]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/spi/mxs_spi.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / drivers / spi / mxs_spi.c
index c3997070019f7686b0bfcea78187a964ee3f2c64..bb865b7f4c30eb71f9dfda6b5e4c277e8b7717b7 100644 (file)
@@ -80,7 +80,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                                  unsigned int max_hz, unsigned int mode)
 {
        struct mxs_spi_slave *mxs_slave;
-       uint32_t addr;
        struct mxs_ssp_regs *ssp_regs;
        int reg;
 
@@ -96,13 +95,11 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
        if (mxs_dma_init_channel(bus))
                goto err_init;
 
-       addr = MXS_SSP0_BASE + (bus * MXS_SPI_PORT_OFFSET);
-
        mxs_slave->slave.bus = bus;
        mxs_slave->slave.cs = cs;
        mxs_slave->max_khz = max_hz / 1000;
        mxs_slave->mode = mode;
-       mxs_slave->regs = (struct mxs_ssp_regs *)addr;
+       mxs_slave->regs = mxs_ssp_regs_by_bus(bus);
        ssp_regs = mxs_slave->regs;
 
        reg = readl(&ssp_regs->hw_ssp_ctrl0);
@@ -140,7 +137,7 @@ int spi_claim_bus(struct spi_slave *slave)
 
        writel(0, &ssp_regs->hw_ssp_cmd0);
 
-       mx28_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
+       mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
 
        return 0;
 }
@@ -227,6 +224,7 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
        const uint32_t dstart = (uint32_t)data;
        int dmach;
        int tl;
+       int ret = 0;
 
        ALLOC_CACHE_ALIGN_BUFFER(struct mxs_dma_desc, desc, desc_count);
 
@@ -240,8 +238,6 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
        if (!write)
                ctrl0 |= SSP_CTRL0_READ;
 
-       writel(length, &ssp_regs->hw_ssp_xfer_size);
-
        if (length % ARCH_DMA_MINALIGN)
                cache_data_count = roundup(length, ARCH_DMA_MINALIGN);
        else
@@ -284,39 +280,47 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
                        tl = min(length, xfer_max_sz);
 
                dp->cmd.data |=
-                       (tl << MXS_DMA_DESC_BYTES_OFFSET) |
-                       (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+                       ((tl & 0xffff) << MXS_DMA_DESC_BYTES_OFFSET) |
+                       (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
                        MXS_DMA_DESC_HALT_ON_TERMINATE |
                        MXS_DMA_DESC_TERMINATE_FLUSH;
-               dp->cmd.pio_words[0] = ctrl0;
 
                data += tl;
                length -= tl;
 
+               if (!length) {
+                       dp->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
+
+                       if (flags & SPI_XFER_END) {
+                               ctrl0 &= ~SSP_CTRL0_LOCK_CS;
+                               ctrl0 |= SSP_CTRL0_IGNORE_CRC;
+                       }
+               }
+
+               /*
+                * Write CTRL0, CMD0, CMD1, XFER_SIZE registers. It is
+                * essential that the XFER_SIZE register is written on
+                * a per-descriptor basis with the same size as is the
+                * descriptor!
+                */
+               dp->cmd.pio_words[0] = ctrl0;
+               dp->cmd.pio_words[1] = 0;
+               dp->cmd.pio_words[2] = 0;
+               dp->cmd.pio_words[3] = tl;
+
                mxs_dma_desc_append(dmach, dp);
 
                dp++;
        }
 
-       dp->address = (dma_addr_t)dp;
-       dp->cmd.address = (dma_addr_t)0;
-       dp->cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER |
-                       (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
-                       MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
-       if (flags & SPI_XFER_END) {
-               ctrl0 &= ~SSP_CTRL0_LOCK_CS;
-               dp->cmd.pio_words[0] = ctrl0 | SSP_CTRL0_IGNORE_CRC;
-       }
-       mxs_dma_desc_append(dmach, dp);
-
        if (mxs_dma_go(dmach))
-               return -EINVAL;
+               ret = -EINVAL;
 
        /* The data arrived into DRAM, invalidate cache over them */
        if (!write)
                invalidate_dcache_range(dstart, dstart + cache_data_count);
 
-       return 0;
+       return ret;
 }
 
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,