Commit 320f6693 authored by Marcelo Schmitt's avatar Marcelo Schmitt Committed by Mark Brown

spi: bitbang: Implement support for MOSI idle state configuration

Some SPI peripherals may require strict MOSI line state when the controller
is not clocking out data. Implement support for MOSI idle state
configuration (low or high) by setting the data output line level on
controller setup and after transfers. Bitbang operations now call
controller specific set_mosi_idle() callback to set MOSI to its idle state.
The MOSI line is kept at its idle state if no tx buffer is provided.
Acked-by: default avatarNuno Sa <nuno.sa@analog.com>
Reviewed-by: default avatarDavid Lechner <dlechner@baylibre.com>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: default avatarMarcelo Schmitt <marcelo.schmitt@analog.com>
Link: https://patch.msgid.link/de61a600b56ed9cb714d5ea87afa88948e70041e.1720810545.git.marcelo.schmitt@analog.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent f58872f4
......@@ -54,21 +54,28 @@ static unsigned int bitbang_txrx_8(struct spi_device *spi,
struct spi_transfer *t,
unsigned int flags)
{
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;
}
......@@ -78,21 +85,28 @@ static unsigned int bitbang_txrx_16(struct spi_device *spi,
struct spi_transfer *t,
unsigned int flags)
{
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;
}
......@@ -102,21 +116,28 @@ static unsigned int bitbang_txrx_32(struct spi_device *spi,
struct spi_transfer *t,
unsigned int flags)
{
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;
}
......@@ -192,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;
......
......@@ -24,6 +24,7 @@ struct spi_bitbang {
#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
#define BITBANG_CS_INACTIVE 0
void (*set_mosi_idle)(struct spi_device *spi);
/* txrx_bufs() may handle dma mapping for transfers that don't
* already have one (transfer.{tx,rx}_dma is zero), or use PIO
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment