|
|
@@ -0,0 +1,102 @@
|
|
|
+From 061795b345aff371df8f71d54ae7c7dc8ae630d0 Mon Sep 17 00:00:00 2001
|
|
|
+From: Mikhail Kshevetskiy <[email protected]>
|
|
|
+Date: Wed, 26 Nov 2025 02:40:45 +0300
|
|
|
+Subject: [PATCH 14/14] spi: airoha-snfi: en7523: workaround flash damaging if
|
|
|
+ UART_TXD was short to GND
|
|
|
+
|
|
|
+Airoha EN7523 specific bug
|
|
|
+--------------------------
|
|
|
+We found that some serial console may pull TX line to GROUND during board
|
|
|
+boot time. Airoha uses TX line as one of its bootstrap pins. On the EN7523
|
|
|
+SoC this may lead to booting in RESERVED boot mode.
|
|
|
+
|
|
|
+It was found that some flashes operates incorrectly in RESERVED mode.
|
|
|
+Micron and Skyhigh flashes are definitely affected by the issue,
|
|
|
+Winbond flashes are not affected.
|
|
|
+
|
|
|
+Details:
|
|
|
+--------
|
|
|
+DMA reading of odd pages on affected flashes operates incorrectly. Page
|
|
|
+reading offset (start of the page) on hardware level is replaced by 0x10.
|
|
|
+Thus results in incorrect data reading. As result OS loading becomes
|
|
|
+impossible.
|
|
|
+
|
|
|
+Usage of UBI make things even worse. On attaching, UBI will detects
|
|
|
+corruptions (because of wrong reading of odd pages) and will try to
|
|
|
+recover. For recovering UBI will erase and write 'damaged' blocks with
|
|
|
+a valid information. This will destroy all UBI data.
|
|
|
+
|
|
|
+Non-DMA reading is OK.
|
|
|
+
|
|
|
+This patch detects booting in reserved mode, turn off DMA and print big
|
|
|
+fat warning.
|
|
|
+
|
|
|
+It's worth noting that the boot configuration is preserved across reboots.
|
|
|
+Therefore, to boot normally, you should do the following:
|
|
|
+- disconnect the serial console from the board,
|
|
|
+- power cycle the board.
|
|
|
+
|
|
|
+Fixes: a403997c12019 ("spi: airoha: add SPI-NAND Flash controller driver")
|
|
|
+Signed-off-by: Mikhail Kshevetskiy <[email protected]>
|
|
|
+Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
|
|
|
+Reviewed-by: Andy Shevchenko <[email protected]>
|
|
|
+Link: https://patch.msgid.link/[email protected]
|
|
|
+Signed-off-by: Mark Brown <[email protected]>
|
|
|
+---
|
|
|
+ drivers/spi/spi-airoha-snfi.c | 25 ++++++++++++++++++++++++-
|
|
|
+ 1 file changed, 24 insertions(+), 1 deletion(-)
|
|
|
+
|
|
|
+--- a/drivers/spi/spi-airoha-snfi.c
|
|
|
++++ b/drivers/spi/spi-airoha-snfi.c
|
|
|
+@@ -1013,6 +1013,11 @@ static const struct spi_controller_mem_o
|
|
|
+ .dirmap_write = airoha_snand_dirmap_write,
|
|
|
+ };
|
|
|
+
|
|
|
++static const struct spi_controller_mem_ops airoha_snand_nodma_mem_ops = {
|
|
|
++ .supports_op = airoha_snand_supports_op,
|
|
|
++ .exec_op = airoha_snand_exec_op,
|
|
|
++};
|
|
|
++
|
|
|
+ static int airoha_snand_setup(struct spi_device *spi)
|
|
|
+ {
|
|
|
+ struct airoha_snand_ctrl *as_ctrl;
|
|
|
+@@ -1057,7 +1062,9 @@ static int airoha_snand_probe(struct pla
|
|
|
+ struct airoha_snand_ctrl *as_ctrl;
|
|
|
+ struct device *dev = &pdev->dev;
|
|
|
+ struct spi_controller *ctrl;
|
|
|
++ bool dma_enable = true;
|
|
|
+ void __iomem *base;
|
|
|
++ u32 sfc_strap;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ ctrl = devm_spi_alloc_host(dev, sizeof(*as_ctrl));
|
|
|
+@@ -1092,12 +1099,28 @@ static int airoha_snand_probe(struct pla
|
|
|
+ return dev_err_probe(dev, PTR_ERR(as_ctrl->spi_clk),
|
|
|
+ "unable to get spi clk\n");
|
|
|
+
|
|
|
++ if (device_is_compatible(dev, "airoha,en7523-snand")) {
|
|
|
++ err = regmap_read(as_ctrl->regmap_ctrl,
|
|
|
++ REG_SPI_CTRL_SFC_STRAP, &sfc_strap);
|
|
|
++ if (err)
|
|
|
++ return err;
|
|
|
++
|
|
|
++ if (!(sfc_strap & 0x04)) {
|
|
|
++ dma_enable = false;
|
|
|
++ dev_warn(dev, "Detected booting in RESERVED mode (UART_TXD was short to GND).\n");
|
|
|
++ dev_warn(dev, "This mode is known for incorrect DMA reading of some flashes.\n");
|
|
|
++ dev_warn(dev, "Much slower PIO mode will be used to prevent flash data damage.\n");
|
|
|
++ dev_warn(dev, "Unplug UART cable and power cycle board to get full performance.\n");
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
+ err = dma_set_mask(as_ctrl->dev, DMA_BIT_MASK(32));
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ ctrl->num_chipselect = 2;
|
|
|
+- ctrl->mem_ops = &airoha_snand_mem_ops;
|
|
|
++ ctrl->mem_ops = dma_enable ? &airoha_snand_mem_ops
|
|
|
++ : &airoha_snand_nodma_mem_ops;
|
|
|
+ ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
|
|
|
+ ctrl->mode_bits = SPI_RX_DUAL;
|
|
|
+ ctrl->setup = airoha_snand_setup;
|