Fix 8 and 16-bit transfers in mxc_spi driver and a wrong pointer in the 
free routine.

Signed-off-by: Guennadi Liakhovetski <l...@denx.de>
---

No SPI custodian, so, Jean-Christophe will have to Ack it?

 drivers/spi/mxc_spi.c |   62 +++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index 5957ada..9267341 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -85,17 +85,12 @@ static inline void reg_write(unsigned long addr, u32 val)
        *(volatile unsigned long*)addr = val;
 }
 
-static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen)
+static u32 spi_xchg_single(struct spi_slave *slave, u32 data,
+                          unsigned long flags)
 {
        struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
        unsigned int cfg_reg = reg_read(mxcs->base + MXC_CSPICTRL);
 
-       if (MXC_CSPICTRL_BITCOUNT(bitlen - 1) != (cfg_reg & 
MXC_CSPICTRL_BITCOUNT(31))) {
-               cfg_reg = (cfg_reg & ~MXC_CSPICTRL_BITCOUNT(31)) |
-                       MXC_CSPICTRL_BITCOUNT(bitlen - 1);
-               reg_write(mxcs->base + MXC_CSPICTRL, cfg_reg);
-       }
-
        reg_write(mxcs->base + MXC_CSPITXDATA, data);
 
        cfg_reg |= MXC_CSPICTRL_XCH;
@@ -108,13 +103,46 @@ static u32 spi_xchg_single(struct spi_slave *slave, u32 
data, int bitlen)
        return reg_read(mxcs->base + MXC_CSPIRXDATA);
 }
 
+/*
+ * bitlen is the total number of bits to be sent. Therefore, if you have to 
send
+ * using < 32-bit words, you have to send each single word individually. If
+ * bitlen > 32 we assume you meant to send 32-bit words...
+ */
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-               void *din, unsigned long flags)
+            void *din, unsigned long flags)
 {
-       int n_blks = (bitlen + 31) / 32;
+       struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+       int n_blks = bitlen / 32;
        u32 *out_l, *in_l;
        int i;
 
+       mxcs->ctrl_reg = (mxcs->ctrl_reg & ~MXC_CSPICTRL_BITCOUNT(31)) |
+               MXC_CSPICTRL_BITCOUNT(bitlen - 1);
+
+       reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg);
+
+       if (bitlen <= 8) {
+               u32 iword, oword = *(const u8 *)dout;
+
+               iword = spi_xchg_single(slave, oword, flags);
+               *(u8 *)din = iword;
+               return 0;
+       }
+
+       if (bitlen <= 16) {
+               u32 iword, oword = *(const u16 *)dout;
+
+               if ((int)dout & 1 || (int)din & 1) {
+                       printf("Error: unaligned buffers in: %p, out: %p\n",
+                              din, dout);
+                       return 1;
+               }
+
+               iword = spi_xchg_single(slave, oword, flags);
+               *(u16 *)din = iword;
+               return 0;
+       }
+
        if ((int)dout & 3 || (int)din & 3) {
                printf("Error: unaligned buffers in: %p, out: %p\n", din, dout);
                return 1;
@@ -122,8 +150,17 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, 
const void *dout,
 
        for (i = 0, in_l = (u32 *)din, out_l = (u32 *)dout;
             i < n_blks;
-            i++, in_l++, out_l++, bitlen -= 32)
-               *in_l = spi_xchg_single(slave, *out_l, bitlen);
+            i++, in_l++, out_l++)
+               *in_l = spi_xchg_single(slave, *out_l, flags);
+
+       if (bitlen & 31) {
+               /* Exchange the residue, treat data as 32 bits */
+               mxcs->ctrl_reg = (mxcs->ctrl_reg & ~MXC_CSPICTRL_BITCOUNT(31)) |
+                       MXC_CSPICTRL_BITCOUNT((bitlen & 31) - 1);
+               reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg);
+
+               *in_l = spi_xchg_single(slave, *out_l, flags);
+       }
 
        return 0;
 }
@@ -169,7 +206,8 @@ struct spi_slave *spi_setup_slave(unsigned int bus, 
unsigned int cs,
 
 void spi_free_slave(struct spi_slave *slave)
 {
-       free(slave);
+       struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+       free(mxcs);
 }
 
 int spi_claim_bus(struct spi_slave *slave)
-- 
1.5.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to