Re: [PATCH v4] spi: add OpenCores tiny SPI driver

From: Dirk Brandewie
Date: Thu Feb 03 2011 - 10:20:41 EST


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;
+}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/