Files
openwrt-R7800-nss/target/linux/realtek/patches-6.12/002-v6.13-spi-mem-rtl-snand-correctly-handle-dma-transfers.patch
Markus Stockhausen 41b0340ff0 realtek: backport NAND driver for RTL93xx
RTL93xx devices have a NAND controller built in. Upstream already
has a driver in place. Include it downstream. Activate it in the
RTL93xx builds and disable it for the RTL83xx builds.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/19583
Signed-off-by: Robert Marko <robimarko@gmail.com>
2025-07-30 23:22:24 +02:00

97 lines
2.8 KiB
Diff

From 25d284715845a465a1a3693a09cf8b6ab8bd9caf Mon Sep 17 00:00:00 2001
From: Chris Packham <chris.packham@alliedtelesis.co.nz>
Date: Thu, 31 Oct 2024 08:49:20 +1300
Subject: [PATCH] spi: spi-mem: rtl-snand: Correctly handle DMA transfers
The RTL9300 has some limitations on the maximum DMA transfers possible.
For reads this is 2080 bytes (520*4) for writes this is 520 bytes. Deal
with this by splitting transfers into appropriately sized parts.
Fixes: 42d20a6a61b8 ("spi: spi-mem: Add Realtek SPI-NAND controller")
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Link: https://patch.msgid.link/20241030194920.3202282-1-chris.packham@alliedtelesis.co.nz
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/spi/spi-realtek-rtl-snand.c | 46 +++++++++++++++++++----------
1 file changed, 30 insertions(+), 16 deletions(-)
--- a/drivers/spi/spi-realtek-rtl-snand.c
+++ b/drivers/spi/spi-realtek-rtl-snand.c
@@ -231,19 +231,22 @@ out_deselect:
static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_op *op)
{
+ unsigned int pos, nbytes;
int ret;
dma_addr_t buf_dma;
enum dma_data_direction dir;
- u32 trig;
+ u32 trig, len, maxlen;
ret = rtl_snand_xfer_head(snand, cs, op);
if (ret)
goto out_deselect;
if (op->data.dir == SPI_MEM_DATA_IN) {
+ maxlen = 2080;
dir = DMA_FROM_DEVICE;
trig = 0;
} else if (op->data.dir == SPI_MEM_DATA_OUT) {
+ maxlen = 520;
dir = DMA_TO_DEVICE;
trig = 1;
} else {
@@ -264,26 +267,37 @@ static int rtl_snand_dma_xfer(struct rtl
if (ret)
goto out_unmap;
- reinit_completion(&snand->comp);
+ pos = 0;
+ len = op->data.nbytes;
- ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma);
- if (ret)
- goto out_disable_int;
+ while (pos < len) {
+ nbytes = len - pos;
+ if (nbytes > maxlen)
+ nbytes = maxlen;
- ret = regmap_write(snand->regmap, SNAFDLR,
- CMR_WID(op->data.buswidth) | (op->data.nbytes & 0xffff));
- if (ret)
- goto out_disable_int;
+ reinit_completion(&snand->comp);
- ret = regmap_write(snand->regmap, SNAFDTR, trig);
- if (ret)
- goto out_disable_int;
+ ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma + pos);
+ if (ret)
+ goto out_disable_int;
- if (!wait_for_completion_timeout(&snand->comp, usecs_to_jiffies(20000)))
- ret = -ETIMEDOUT;
+ pos += nbytes;
- if (ret)
- goto out_disable_int;
+ ret = regmap_write(snand->regmap, SNAFDLR,
+ CMR_WID(op->data.buswidth) | nbytes);
+ if (ret)
+ goto out_disable_int;
+
+ ret = regmap_write(snand->regmap, SNAFDTR, trig);
+ if (ret)
+ goto out_disable_int;
+
+ if (!wait_for_completion_timeout(&snand->comp, usecs_to_jiffies(20000)))
+ ret = -ETIMEDOUT;
+
+ if (ret)
+ goto out_disable_int;
+ }
out_disable_int:
regmap_update_bits(snand->regmap, SNAFCFR, SNAFCFR_DMA_IE, 0);