On 02/03/2011 02:37 AM, Thomas Chou wrote:
This patch adds support of OpenCores tiny SPI driver.

http://opencores.org/project,tiny_spi


+static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct tiny_spi *hw = tiny_spi_to_hw(spi);
+       const u8 *txp = t->tx_buf;
+       u8 *rxp = t->rx_buf;
+       unsigned int i;
+
+       if (hw->irq>= 0) {
+               /* use intrrupt driven data transfer */
+               hw->len = t->len;
+               hw->txp = t->tx_buf;
+               hw->rxp = t->rx_buf;
+               hw->txc = 0;
+               hw->rxc = 0;
+
+               /* send the first byte */
+               if (t->len>  1) {
+                       writeb(hw->txp ? *hw->txp++ : 0,
+                              hw->base + TINY_SPI_TXDATA);
+                       hw->txc++;
+                       writeb(hw->txp ? *hw->txp++ : 0,
+                              hw->base + TINY_SPI_TXDATA);
+                       hw->txc++;
+                       writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
+               } else {
+                       writeb(hw->txp ? *hw->txp++ : 0,
+                              hw->base + TINY_SPI_TXDATA);
+                       hw->txc++;
+                       writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
+               }
+
+               wait_for_completion(&hw->done);
+       } else if (txp&&  rxp) {
+               /* we need to tighten the transfer loop */
+               writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+               if (t->len>  1) {
+                       writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+                       for (i = 2; i<  t->len; i++) {
+                               u8 rx, tx = *txp++;
+                               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                                        TINY_SPI_STATUS_TXR))
+                                       cpu_relax();

Putting the read status, cpu releax in an inline function would make this function a lot easier to read.

+                               rx = readb(hw->base + TINY_SPI_TXDATA);
+                               writeb(tx, hw->base + TINY_SPI_TXDATA);
+                               *rxp++ = rx;
+                       }
+                       while (!(readb(hw->base + TINY_SPI_STATUS)&
+                                TINY_SPI_STATUS_TXR))
+                               cpu_relax();
+                       *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+               }
+               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                        TINY_SPI_STATUS_TXE))
+                       cpu_relax();
+               *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+       } else if (rxp) {
+               writeb(0, hw->base + TINY_SPI_TXDATA);
+               if (t->len>  1) {
+                       writeb(0,
+                              hw->base + TINY_SPI_TXDATA);
+                       for (i = 2; i<  t->len; i++) {
+                               u8 rx;
+                               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                                        TINY_SPI_STATUS_TXR))
+                                       cpu_relax();
+                               rx = readb(hw->base + TINY_SPI_TXDATA);
+                               writeb(0,
+                                      hw->base + TINY_SPI_TXDATA);
+                               *rxp++ = rx;
+                       }
+                       while (!(readb(hw->base + TINY_SPI_STATUS)&
+                                TINY_SPI_STATUS_TXR))
+                               cpu_relax();
+                       *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+               }
+               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                        TINY_SPI_STATUS_TXE))
+                       cpu_relax();
+               *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+       } else if (txp) {
+               writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+               if (t->len>  1) {
+                       writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+                       for (i = 2; i<  t->len; i++) {
+                               u8 tx = *txp++;
+                               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                                        TINY_SPI_STATUS_TXR))
+                                       cpu_relax();
+                               writeb(tx, hw->base + TINY_SPI_TXDATA);
+                       }
+               }
+               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                        TINY_SPI_STATUS_TXE))
+                       cpu_relax();
+       } else {
+               writeb(0, hw->base + TINY_SPI_TXDATA);
+               if (t->len>  1) {
+                       writeb(0,
+                              hw->base + TINY_SPI_TXDATA);
+                       for (i = 2; i<  t->len; i++) {
+                               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                                        TINY_SPI_STATUS_TXR))
+                                       cpu_relax();
+                               writeb(0,
+                                      hw->base + TINY_SPI_TXDATA);
+                       }
+               }
+               while (!(readb(hw->base + TINY_SPI_STATUS)&
+                        TINY_SPI_STATUS_TXE))
+                       cpu_relax();
+       }
+       return t->len;
+}
_______________________________________________
devicetree-discuss mailing list
[email protected]
https://lists.ozlabs.org/listinfo/devicetree-discuss

Reply via email to