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>
97 lines
2.8 KiB
Diff
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);
|