]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/spi/atmel_spi.c
atmel_spi: support zero length transfer
[linux-2.6-omap-h63xx.git] / drivers / spi / atmel_spi.c
index 545519a063b803ab80936397c4f44134b6ac46c3..02c8e305b14fd783e3b94a71d3c8b4d9c4ed9c68 100644 (file)
@@ -87,6 +87,16 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
        unsigned gpio = (unsigned) spi->controller_data;
        unsigned active = spi->mode & SPI_CS_HIGH;
        u32 mr;
+       int i;
+       u32 csr;
+       u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
+
+       /* Make sure clock polarity is correct */
+       for (i = 0; i < spi->master->num_chipselect; i++) {
+               csr = spi_readl(as, CSR0 + 4 * i);
+               if ((csr ^ cpol) & SPI_BIT(CPOL))
+                       spi_writel(as, CSR0 + 4 * i, csr ^ SPI_BIT(CPOL));
+       }
 
        mr = spi_readl(as, MR);
        mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
@@ -198,6 +208,11 @@ static void atmel_spi_next_xfer(struct spi_master *master,
                        len >>= 1;
                spi_writel(as, RCR, len);
                spi_writel(as, TCR, len);
+
+               dev_dbg(&msg->spi->dev,
+                       "  start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+                       xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+                       xfer->rx_buf, xfer->rx_dma);
        } else {
                xfer = as->next_transfer;
                remaining = as->next_remaining_bytes;
@@ -208,8 +223,8 @@ static void atmel_spi_next_xfer(struct spi_master *master,
 
        if (remaining > 0)
                len = remaining;
-       else if (!atmel_spi_xfer_is_last(msg, xfer) &&
-               atmel_spi_xfer_can_be_chained(xfer)) {
+       else if (!atmel_spi_xfer_is_last(msg, xfer)
+                       && atmel_spi_xfer_can_be_chained(xfer)) {
                xfer = list_entry(xfer->transfer_list.next,
                                struct spi_transfer, transfer_list);
                len = xfer->len;
@@ -230,6 +245,11 @@ static void atmel_spi_next_xfer(struct spi_master *master,
                        len >>= 1;
                spi_writel(as, RNCR, len);
                spi_writel(as, TNCR, len);
+
+               dev_dbg(&msg->spi->dev,
+                       "  next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+                       xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+                       xfer->rx_buf, xfer->rx_dma);
        } else {
                spi_writel(as, RNCR, 0);
                spi_writel(as, TNCR, 0);
@@ -246,12 +266,6 @@ static void atmel_spi_next_xfer(struct spi_master *master,
         * It should be doable, though. Just not now...
         */
        spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
-
-       dev_dbg(&msg->spi->dev,
-               "  start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n",
-               xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-               xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR));
-
        spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
 }
 
@@ -602,7 +616,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
                return -ESHUTDOWN;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               if (!(xfer->tx_buf || xfer->rx_buf)) {
+               if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
                        dev_dbg(&spi->dev, "missing rx or tx buf\n");
                        return -EINVAL;
                }
@@ -849,3 +863,4 @@ module_exit(atmel_spi_exit);
 MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
 MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:atmel_spi");