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

Signed-off-by: Christophe Leroy <christophe.le...@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

Reply via email to