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 interrupt 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 { /* we need to tighten the transfer loop */ writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA); for (i = 1; i < t->len; i++) { writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA); if (rxp || (i != t->len - 1)) tiny_spi_wait_txr(hw); if (rxp) *rxp++ = readb(hw->base + TINY_SPI_TXDATA); } tiny_spi_wait_txe(hw); if (rxp) *rxp++ = readb(hw->base + TINY_SPI_RXDATA); } return t->len; }
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) { hw->len = t->len; hw->txp = t->tx_buf; hw->rxp = t->rx_buf; hw->txc = 0; hw->rxc = 0; 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) { 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++; tiny_spi_wait_txr(hw); rx = readb(hw->base + TINY_SPI_TXDATA); writeb(tx, hw->base + TINY_SPI_TXDATA); *rxp++ = rx; } tiny_spi_wait_txr(hw); *rxp++ = readb(hw->base + TINY_SPI_TXDATA); } tiny_spi_wait_txe(hw); *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; tiny_spi_wait_txr(hw); rx = readb(hw->base + TINY_SPI_TXDATA); writeb(0, hw->base + TINY_SPI_TXDATA); *rxp++ = rx; } tiny_spi_wait_txr(hw); *rxp++ = readb(hw->base + TINY_SPI_TXDATA); } tiny_spi_wait_txe(hw); *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++; tiny_spi_wait_txr(hw); writeb(tx, hw->base + TINY_SPI_TXDATA); } } tiny_spi_wait_txe(hw); } 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++) { tiny_spi_wait_txr(hw); writeb(0, hw->base + TINY_SPI_TXDATA); } } tiny_spi_wait_txe(hw); } return t->len; }