[PATCH v2 12/17] spi: mpc8xx: Allow transfer of more than MAX_BUFFER len

Christophe Leroy
2024-04-15T06:10:02Z

Perform multiple transfer of size MAX_BUFFER when the data to be
transferred is longer than MAX_BUFFER.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
drivers/spi/mpc8xx_spi.c | 48 ++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c
index 0d142f12e9..a193ac711b 100644
--- a/drivers/spi/mpc8xx_spi.c
+++ b/drivers/spi/mpc8xx_spi.c
@@ -143,27 +143,17 @@ static void mpc8xx_spi_cs_deactivate(struct udevice *dev)
dm_gpio_set_value(&priv->gpios[platdata->cs], 0);
}

-static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
- const void *dout, void *din, unsigned long flags)
+static int mpc8xx_spi_xfer_one(struct udevice *dev, size_t count,
+ const void *dout, void *din)
{
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cp = &immr->im_cpm;
cbd_t __iomem *tbdf, *rbdf;
int tm;
- size_t count = (bitlen + 7) / 8;
-
- if (!din && !dout)
- return -EINVAL;
- if (count > MAX_BUFFER)
- return -EINVAL;

tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX];
rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];

- /* Set CS for device */
- if (flags & SPI_XFER_BEGIN)
- mpc8xx_spi_cs_activate(dev);
-
/* Setting tx bd status and data length */
out_be32(&tbdf->cbd_bufaddr, dout ? (ulong)dout : (ulong)dummy_buffer);
out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP);
@@ -196,13 +186,43 @@ static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
}

if (tm >= 1000)
- printf("*** spi_xfer: Time out while xferring to/from SPI!\n");
+ return -ETIMEDOUT;
+
+ return 0;
+}

+static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ size_t count = (bitlen + 7) / 8;
+ size_t offset = 0;
+ int ret = 0;
+
+ if (!din && !dout)
+ return -EINVAL;
+
+ /* Set CS for device */
+ if (flags & SPI_XFER_BEGIN)
+ mpc8xx_spi_cs_activate(dev);
+
+ while (count > 0 && !ret) {
+ size_t chunk = min(count, (size_t)MAX_BUFFER);
+ const void *out = dout ? dout + offset : NULL;
+ void *in = din ? din + offset : NULL;
+
+ ret = mpc8xx_spi_xfer_one(dev, chunk, out, in);
+
+ offset += chunk;
+ count -= chunk;
+ }
/* Clear CS for device */
if (flags & SPI_XFER_END)
mpc8xx_spi_cs_deactivate(dev);

- return 0;
+ if (ret)
+ printf("*** spi_xfer: Time out while xferring to/from SPI!\n");
+
+ return ret;
}

static int mpc8xx_spi_ofdata_to_platdata(struct udevice *dev)
--
2.43.0