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.
This commit is contained in:
@@ -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)
|
|||||||
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 {
|
|||||||
#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 {
|
|||||||
* 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
|
||||||
* - ...
|
* - ...
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user