Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a5f0b3a authored by Jonathan Cameron's avatar Jonathan Cameron
Browse files

Merge tag 'spi-cs-word' into togreg

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 c8d5b996 cbaa62e0
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -2774,8 +2774,10 @@ int spi_setup(struct spi_device *spi)
		return -EINVAL;
	/* help drivers fail *cleanly* when they need options
	 * 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 &
		    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD);
	if (ugly_bits) {
@@ -2829,6 +2831,33 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
	if (list_empty(&message->transfers))
		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
	 * only one data pin like SPI_3WIRE (switches direction) or where
	 * either MOSI or MISO is missing.  They can also be caused by
+1 −1
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ struct spi_device {
#define	SPI_TX_QUAD	0x200			/* transmit with 4 wires */
#define	SPI_RX_DUAL	0x400			/* receive with 2 wires */
#define	SPI_RX_QUAD	0x800			/* receive with 4 wires */
#define SPI_CS_WORD	0x1000			/* toggle cs after each word */
	int			irq;
	void			*controller_state;
	void			*controller_data;
@@ -177,7 +178,6 @@ struct spi_device {
	 * the controller talks to each chip, like:
	 *  - memory packing (12 bit samples into low bits, others zeroed)
	 *  - priority
	 *  - drop chipselect after each word
	 *  - chipselect delays
	 *  - ...
	 */