Commit 92636966 authored by Mark Brown's avatar Mark Brown

Merge tag 'spi-cs-word' into spi-4.20

spi: Provide SPI_CS_WORD

This provides a SPI operation mode which changes chip select after every
word, used by some devices such as ADCs and DACs.
parents 3356d9f4 cbaa62e0
...@@ -2774,8 +2774,10 @@ int spi_setup(struct spi_device *spi) ...@@ -2774,8 +2774,10 @@ int spi_setup(struct spi_device *spi)
return -EINVAL; return -EINVAL;
/* help drivers fail *cleanly* when they need options /* help drivers fail *cleanly* when they need options
* that aren't supported with their current controller * that aren't supported with their current controller
* SPI_CS_WORD has a fallback software implementation,
* so it is ignored here.
*/ */
bad_bits = spi->mode & ~spi->controller->mode_bits; bad_bits = spi->mode & ~(spi->controller->mode_bits | SPI_CS_WORD);
ugly_bits = bad_bits & ugly_bits = bad_bits &
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD); (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD);
if (ugly_bits) { if (ugly_bits) {
...@@ -2829,6 +2831,33 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) ...@@ -2829,6 +2831,33 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
if (list_empty(&message->transfers)) if (list_empty(&message->transfers))
return -EINVAL; return -EINVAL;
/* If an SPI controller does not support toggling the CS line on each
* transfer (indicated by the SPI_CS_WORD flag), we can emulate it by
* splitting transfers into one-word transfers and ensuring that
* cs_change is set for each transfer.
*/
if ((spi->mode & SPI_CS_WORD) && !(ctlr->mode_bits & SPI_CS_WORD)) {
size_t maxsize;
int ret;
maxsize = (spi->bits_per_word + 7) / 8;
/* spi_split_transfers_maxsize() requires message->spi */
message->spi = spi;
ret = spi_split_transfers_maxsize(ctlr, message, maxsize,
GFP_KERNEL);
if (ret)
return ret;
list_for_each_entry(xfer, &message->transfers, transfer_list) {
/* don't change cs_change on the last entry in the list */
if (list_is_last(&xfer->transfer_list, &message->transfers))
break;
xfer->cs_change = 1;
}
}
/* Half-duplex links include original MicroWire, and ones with /* Half-duplex links include original MicroWire, and ones with
* only one data pin like SPI_3WIRE (switches direction) or where * only one data pin like SPI_3WIRE (switches direction) or where
* either MOSI or MISO is missing. They can also be caused by * either MOSI or MISO is missing. They can also be caused by
......
...@@ -163,6 +163,7 @@ struct spi_device { ...@@ -163,6 +163,7 @@ struct spi_device {
#define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */
#define SPI_CS_WORD 0x1000 /* toggle cs after each word */
int irq; int irq;
void *controller_state; void *controller_state;
void *controller_data; void *controller_data;
...@@ -177,7 +178,6 @@ struct spi_device { ...@@ -177,7 +178,6 @@ struct spi_device {
* the controller talks to each chip, like: * the controller talks to each chip, like:
* - memory packing (12 bit samples into low bits, others zeroed) * - memory packing (12 bit samples into low bits, others zeroed)
* - priority * - priority
* - drop chipselect after each word
* - chipselect delays * - chipselect delays
* - ... * - ...
*/ */
......
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