Commit cfad60d4 authored by Attie Grande's avatar Attie Grande Committed by Martí Bolívar
Browse files

spi: sam0: fix fast-rx path, and refresh comments



The SAM0 fast-path implementation was broken, and partially fixed in
commits 8181eede and 8a99bd0d...

This patch resolves an issue where the MSB is always zero on SAML21
parts, and appears to follow suit with the previous patches.

This patch also refreshes the commentary, and removes mention of the
"interleaved" operation that is no longer used - which appears to have
been problematic in the past.

In addition to this, it also resolves an off-by-one error in both the
fast_rx and fast_rxrx paths, which would have been tripped when
transmitting a zero-byte buffer.

Signed-off-by: default avatarAttie Grande <attie.grande@argentum-systems.co.uk>
parent b15ac058
Loading
Loading
Loading
Loading
+5 −48
Original line number Diff line number Diff line
@@ -219,37 +219,17 @@ static void spi_sam0_fast_rx(SercomSpi *regs, const struct spi_buf *rx_buf)
		return;
	}

	/* See the comment in spi_sam0_fast_txrx re: interleaving. */

	/* Write the first byte */
	regs->DATA.reg = 0;
	len--;

	/* Ensure the data register has shifted to the shift register before
	 * continuing.	Later writes are synchronised by waiting for the receive
	 * to complete.
	 */
	while (!regs->INTFLAG.bit.DRE) {
	}

	while (len) {
		/* Load byte N+1 into the transmit register */
		/* Send the next byte */
		regs->DATA.reg = 0;
		len--;

		/* Read byte N+0 from the receive register */
		/* Wait for completion, and read */
		while (!regs->INTFLAG.bit.RXC) {
		}

		*rx++ = regs->DATA.reg;
	}

	/* Read the final incoming byte */
	while (!regs->INTFLAG.bit.RXC) {
	}

	*rx = regs->DATA.reg;

	spi_sam0_finish(regs);
}

@@ -267,39 +247,16 @@ static void spi_sam0_fast_txrx(SercomSpi *regs,
		return;
	}

	/*
	 * The code below interleaves the transmit writes with the
	 * receive reads to keep the bus fully utilised.  The code is
	 * equivalent to:
	 *
	 * Transmit byte 0
	 * Loop:
	 * - Transmit byte n+1
	 * - Receive byte n
	 * Receive the final byte
	 */

	/* Write the first byte */
	regs->DATA.reg = *tx++;

	while (tx != txend) {
		/* Send the next byte */
		regs->DATA.reg = *tx++;

		/* Read byte N+0 from the receive register */
		/* Wait for completion, and read */
		while (!regs->INTFLAG.bit.RXC) {
		}

		*rx++ = regs->DATA.reg;

		/* We just received the response, send the next byte */
		regs->DATA.reg = *tx++;
	}

	/* Read the final incoming byte */
	while (!regs->INTFLAG.bit.RXC) {
	}

	*rx = regs->DATA.reg;

	spi_sam0_finish(regs);
}