summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-bitbang.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-bitbang.c')
-rw-r--r--drivers/spi/spi-bitbang.c97
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);