summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>2025-11-26 02:40:45 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-12-18 13:55:10 +0100
commit7be679104357439ff6eab076975f5f74368acd69 (patch)
tree80f91f03dfd2d2a50fddf01ecb7e24853b7b2568 /drivers
parent9ff7ef2efae3386a1d909e89809faff47529bc62 (diff)
downloadlinux-7be679104357439ff6eab076975f5f74368acd69.tar.gz
linux-7be679104357439ff6eab076975f5f74368acd69.tar.bz2
linux-7be679104357439ff6eab076975f5f74368acd69.zip
spi: airoha-snfi: en7523: workaround flash damaging if UART_TXD was short to GND
[ Upstream commit 061795b345aff371df8f71d54ae7c7dc8ae630d0 ] 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 <mikhail.kshevetskiy@iopsys.eu> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com> Link: https://patch.msgid.link/20251125234047.1101985-2-mikhail.kshevetskiy@iopsys.eu Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/spi-airoha-snfi.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c
index b78163eaed61..20b5d469d519 100644
--- a/drivers/spi/spi-airoha-snfi.c
+++ b/drivers/spi/spi-airoha-snfi.c
@@ -1030,6 +1030,11 @@ static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
.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;
@@ -1104,7 +1109,9 @@ static int airoha_snand_probe(struct platform_device *pdev)
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));
@@ -1139,12 +1146,28 @@ static int airoha_snand_probe(struct platform_device *pdev)
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;