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. -----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlugGWgTHGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0OAqB/99Zk/yjUqw3q8mQ9TcDyurMrllpNYm n9KshwKOc1wyfHsbPMke+ytCJHmMpNDKbv80Dk5aTNBvbeNN9OZdcqonGfVfulEB hhZy6X4wN6QwX6HpIeWl52o4V4zLd0skeZOqMod/4RQKQvG7kCVVetKFfzMBxYpP 4B+jVLg/L/lVsbNqXe53A59C0myg/lkCBFL9uWmiUaAScS/eeWmHX/Z+Guf3DTjo eR0ZoB55HeovL8AsTV0xAwjae+YM6LMElptXLF/+AlaFmW4WmuRGuU2tCXh+SaHU /VzwLgekzd1hplHc8tX1Nhdr4qJhI6tcpQOu+IelTqZ/Z/JlpIruaJVB =sMBd -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlugGesTHGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0LpbB/9eeBHjpAthphCZ1Q87oUtqn0dbhV9j +djnjM3BgJX+3T3vl6fnOtyD2MPg/sGX8pMePEcVqUSRp+StY5tCO++zbR7maMxs Czw5GslnJJ9CG6T7xx1ZE1vWAIeWywH7Pw98daFJpQkj17BEhGrrqSbpctJaRdSy 3e5nZvc3mWQ5k4ttmK+C9MTa6XV3ReaHDfJaagXWM7bykV6mDwVh6dyx4QJ7kwht Ti+MQ+SYZndySXTFoborSss+5zgYIJ5nKr07PvOsNrjlk2p3hoU+y7MuU+RB9zzs XP9dgZKSoLWbFdCspaC6DtcT1P2HLQRi5kBfdc8xlUCupa6Y2Jt3Hms1 =TFpo -----END PGP SIGNATURE----- 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:
commit
9263696677
|
@ -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
|
||||||
* - ...
|
* - ...
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue