Skip to content

Commit 25d2847

Browse files
cpackham-atlnzbroonie
authored andcommitted
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: 42d20a6 ("spi: spi-mem: Add Realtek SPI-NAND controller") Signed-off-by: Chris Packham <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent f399051 commit 25d2847

File tree

1 file changed

+30
-16
lines changed

1 file changed

+30
-16
lines changed

drivers/spi/spi-realtek-rtl-snand.c

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -231,19 +231,22 @@ static int rtl_snand_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_
231231

232232
static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_op *op)
233233
{
234+
unsigned int pos, nbytes;
234235
int ret;
235236
dma_addr_t buf_dma;
236237
enum dma_data_direction dir;
237-
u32 trig;
238+
u32 trig, len, maxlen;
238239

239240
ret = rtl_snand_xfer_head(snand, cs, op);
240241
if (ret)
241242
goto out_deselect;
242243

243244
if (op->data.dir == SPI_MEM_DATA_IN) {
245+
maxlen = 2080;
244246
dir = DMA_FROM_DEVICE;
245247
trig = 0;
246248
} else if (op->data.dir == SPI_MEM_DATA_OUT) {
249+
maxlen = 520;
247250
dir = DMA_TO_DEVICE;
248251
trig = 1;
249252
} else {
@@ -264,26 +267,37 @@ static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_
264267
if (ret)
265268
goto out_unmap;
266269

267-
reinit_completion(&snand->comp);
270+
pos = 0;
271+
len = op->data.nbytes;
268272

269-
ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma);
270-
if (ret)
271-
goto out_disable_int;
273+
while (pos < len) {
274+
nbytes = len - pos;
275+
if (nbytes > maxlen)
276+
nbytes = maxlen;
272277

273-
ret = regmap_write(snand->regmap, SNAFDLR,
274-
CMR_WID(op->data.buswidth) | (op->data.nbytes & 0xffff));
275-
if (ret)
276-
goto out_disable_int;
278+
reinit_completion(&snand->comp);
277279

278-
ret = regmap_write(snand->regmap, SNAFDTR, trig);
279-
if (ret)
280-
goto out_disable_int;
280+
ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma + pos);
281+
if (ret)
282+
goto out_disable_int;
281283

282-
if (!wait_for_completion_timeout(&snand->comp, usecs_to_jiffies(20000)))
283-
ret = -ETIMEDOUT;
284+
pos += nbytes;
284285

285-
if (ret)
286-
goto out_disable_int;
286+
ret = regmap_write(snand->regmap, SNAFDLR,
287+
CMR_WID(op->data.buswidth) | nbytes);
288+
if (ret)
289+
goto out_disable_int;
290+
291+
ret = regmap_write(snand->regmap, SNAFDTR, trig);
292+
if (ret)
293+
goto out_disable_int;
294+
295+
if (!wait_for_completion_timeout(&snand->comp, usecs_to_jiffies(20000)))
296+
ret = -ETIMEDOUT;
297+
298+
if (ret)
299+
goto out_disable_int;
300+
}
287301

288302
out_disable_int:
289303
regmap_update_bits(snand->regmap, SNAFCFR, SNAFCFR_DMA_IE, 0);

0 commit comments

Comments
 (0)