Unverified Commit 25d28471 authored by Chris Packham's avatar Chris Packham Committed by Mark Brown
Browse files

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: 42d20a6a ("spi: spi-mem: Add Realtek SPI-NAND controller")
Signed-off-by: default avatarChris Packham <chris.packham@alliedtelesis.co.nz>
Link: https://patch.msgid.link/20241030194920.3202282-1-chris.packham@alliedtelesis.co.nz


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent f399051e
Loading
Loading
Loading
Loading
+30 −16
Original line number Diff line number Diff line
@@ -231,19 +231,22 @@ static int rtl_snand_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_

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,14 +267,24 @@ static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_
	if (ret)
		goto out_unmap;

	pos = 0;
	len = op->data.nbytes;

	while (pos < len) {
		nbytes = len - pos;
		if (nbytes > maxlen)
			nbytes = maxlen;

		reinit_completion(&snand->comp);

	ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma);
		ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma + pos);
		if (ret)
			goto out_disable_int;

		pos += nbytes;

		ret = regmap_write(snand->regmap, SNAFDLR,
			   CMR_WID(op->data.buswidth) | (op->data.nbytes & 0xffff));
				CMR_WID(op->data.buswidth) | nbytes);
		if (ret)
			goto out_disable_int;

@@ -284,6 +297,7 @@ static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_

		if (ret)
			goto out_disable_int;
	}

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