diff options
Diffstat (limited to 'drivers/spi/spi-bitbang.c')
| -rw-r--r-- | drivers/spi/spi-bitbang.c | 97 |
1 files changed, 51 insertions, 46 deletions
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index ca5cc67555c5..ebe18f0b5d23 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -38,104 +38,106 @@ * working quickly, or testing for differences that aren't speed related. */ +typedef unsigned int (*spi_bb_txrx_bufs_fn)(struct spi_device *, spi_bb_txrx_word_fn, + unsigned int, struct spi_transfer *, + unsigned int); + struct spi_bitbang_cs { - unsigned nsecs; /* (clock cycle time)/2 */ - u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, - u32 word, u8 bits, unsigned flags); - unsigned (*txrx_bufs)(struct spi_device *, - u32 (*txrx_word)( - struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), - unsigned, struct spi_transfer *, - unsigned); + unsigned int nsecs; /* (clock cycle time) / 2 */ + spi_bb_txrx_word_fn txrx_word; + spi_bb_txrx_bufs_fn txrx_bufs; }; -static unsigned bitbang_txrx_8( - struct spi_device *spi, - u32 (*txrx_word)(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), - unsigned ns, +static unsigned int bitbang_txrx_8(struct spi_device *spi, + spi_bb_txrx_word_fn txrx_word, + unsigned int ns, struct spi_transfer *t, - unsigned flags -) + unsigned int flags) { - unsigned bits = t->bits_per_word; - unsigned count = t->len; + struct spi_bitbang *bitbang; + unsigned int bits = t->bits_per_word; + unsigned int count = t->len; const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf; + bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 0)) { u8 word = 0; if (tx) word = *tx++; + else + word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFF : 0; word = txrx_word(spi, ns, word, bits, flags); if (rx) *rx++ = word; count -= 1; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + return t->len - count; } -static unsigned bitbang_txrx_16( - struct spi_device *spi, - u32 (*txrx_word)(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), - unsigned ns, +static unsigned int bitbang_txrx_16(struct spi_device *spi, + spi_bb_txrx_word_fn txrx_word, + unsigned int ns, struct spi_transfer *t, - unsigned flags -) + unsigned int flags) { - unsigned bits = t->bits_per_word; - unsigned count = t->len; + struct spi_bitbang *bitbang; + unsigned int bits = t->bits_per_word; + unsigned int count = t->len; const u16 *tx = t->tx_buf; u16 *rx = t->rx_buf; + bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 1)) { u16 word = 0; if (tx) word = *tx++; + else + word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFFFF : 0; word = txrx_word(spi, ns, word, bits, flags); if (rx) *rx++ = word; count -= 2; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + return t->len - count; } -static unsigned bitbang_txrx_32( - struct spi_device *spi, - u32 (*txrx_word)(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits, - unsigned flags), - unsigned ns, +static unsigned int bitbang_txrx_32(struct spi_device *spi, + spi_bb_txrx_word_fn txrx_word, + unsigned int ns, struct spi_transfer *t, - unsigned flags -) + unsigned int flags) { - unsigned bits = t->bits_per_word; - unsigned count = t->len; + struct spi_bitbang *bitbang; + unsigned int bits = t->bits_per_word; + unsigned int count = t->len; const u32 *tx = t->tx_buf; u32 *rx = t->rx_buf; + bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 3)) { u32 word = 0; if (tx) word = *tx++; + else + word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFFFFFFFF : 0; word = txrx_word(spi, ns, word, bits, flags); if (rx) *rx++ = word; count -= 4; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + return t->len - count; } @@ -211,6 +213,9 @@ int spi_bitbang_setup(struct spi_device *spi) goto err_free; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs); return 0; @@ -234,7 +239,7 @@ EXPORT_SYMBOL_GPL(spi_bitbang_cleanup); static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) { struct spi_bitbang_cs *cs = spi->controller_state; - unsigned nsecs = cs->nsecs; + unsigned int nsecs = cs->nsecs; struct spi_bitbang *bitbang; bitbang = spi_controller_get_devdata(spi->controller); @@ -247,7 +252,7 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) } if (spi->mode & SPI_3WIRE) { - unsigned flags; + unsigned int flags; flags = t->tx_buf ? SPI_CONTROLLER_NO_RX : SPI_CONTROLLER_NO_TX; return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, flags); |
