Message ID | 811a2771d93c16b48fb37286e648a03171c8d2bc.1717539384.git.marcelo.schmitt@analog.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Add support for AD4000 series of ADCs | expand |
On Tue, 2024-06-04 at 19:42 -0300, Marcelo Schmitt wrote: > 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() call back > to set MOSI to its idle state. > The MOSI line is kept at its idle state if no tx buffer is provided. > > Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com> > --- Some minor nit below in case a re-spin is needed. Anyways, Acked-by: Nuno Sa <nuno.sa@analog.com> > drivers/spi/spi-bitbang.c | 24 ++++++++++++++++++++++++ > include/linux/spi/spi_bitbang.h | 1 + > 2 files changed, 25 insertions(+) > > diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c > index ca5cc67555c5..3dee085d3570 100644 > --- a/drivers/spi/spi-bitbang.c > +++ b/drivers/spi/spi-bitbang.c > @@ -63,21 +63,28 @@ static unsigned bitbang_txrx_8( > unsigned flags > ) > { > + struct spi_bitbang *bitbang; > unsigned bits = t->bits_per_word; > unsigned 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; no need for () > 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; > } > > @@ -92,21 +99,28 @@ static unsigned bitbang_txrx_16( > unsigned flags > ) > { > + struct spi_bitbang *bitbang; > unsigned bits = t->bits_per_word; > unsigned 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; ditto (and for the txrx8 function) - Nuno Sá
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index ca5cc67555c5..3dee085d3570 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -63,21 +63,28 @@ static unsigned bitbang_txrx_8( unsigned flags ) { + struct spi_bitbang *bitbang; unsigned bits = t->bits_per_word; unsigned 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; } @@ -92,21 +99,28 @@ static unsigned bitbang_txrx_16( unsigned flags ) { + struct spi_bitbang *bitbang; unsigned bits = t->bits_per_word; unsigned 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; } @@ -121,21 +135,28 @@ static unsigned bitbang_txrx_32( unsigned flags ) { + struct spi_bitbang *bitbang; unsigned bits = t->bits_per_word; unsigned 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 +232,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; diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index b930eca2ef7b..1a54b593c691 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -22,6 +22,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 */
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() call back to set MOSI to its idle state. The MOSI line is kept at its idle state if no tx buffer is provided. Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com> --- drivers/spi/spi-bitbang.c | 24 ++++++++++++++++++++++++ include/linux/spi/spi_bitbang.h | 1 + 2 files changed, 25 insertions(+)