drivers/spi/spi-axiado.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-axiado.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-axiado.c
Extension
.c
Size
30468 bytes
Lines
1005
Domain
Driver Families
Bucket
drivers/spi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (xspi->rx_discard) {
			xspi->rx_discard--;
		} else {
			*xspi->rx_buf++ = b;
			xspi->rx_copy_remaining--;
		}
	}

	/* This loop processes new words directly from the FIFO */
	while (avail_bytes >= 4 && (xspi->rx_copy_remaining || xspi->rx_discard)) {
		/* This function should handle reading from the FIFO */
		u8 b = ax_spi_get_rx_byte_for_irq(xspi);

		if (xspi->rx_discard) {
			xspi->rx_discard--;
		} else {
			*xspi->rx_buf++ = b;
			xspi->rx_copy_remaining--;
		}
		/* ax_spi_get_rx_byte_for_irq fetches a new word when needed
		 * and updates internal state.
		 */
		if (xspi->bytes_left_in_current_rx_word_for_irq == 3)
			avail_bytes -= 4;
	}

	/* Completion Check: The transfer is truly complete if all expected
	 * RX bytes have been copied or discarded.
	 */
	if (xspi->rx_copy_remaining == 0 && xspi->rx_discard == 0) {
		/* Defensive drain: If for some reason there are leftover bytes
		 * in the HW FIFO after we've logically finished,
		 * read and discard them to prevent them from corrupting the next transfer.
		 * This should be a bounded operation.
		 */
		int safety_words = AX_SPI_RX_FIFO_DRAIN_LIMIT; // Limit to avoid getting stuck

		while (ax_spi_read(xspi, AX_SPI_RX_FBCAR) > 0 && safety_words-- > 0)
			ax_spi_read(xspi, AX_SPI_RXFIFO);

		/* Disable all interrupts for this transfer and finalize. */
		ax_spi_write(xspi, AX_SPI_IMR, 0x00);
		spi_finalize_current_transfer(ctlr);
		return true;
	}

	return false;
}

/**
 * ax_spi_irq - Interrupt service routine of the SPI controller
 * @irq:	IRQ number
 * @dev_id:	Pointer to the xspi structure
 *
 * This function handles RX FIFO almost full and Host Transfer Completed interrupts only.
 * On RX FIFO amlost full interrupt this function reads the received data from RX FIFO and
 * fills the TX FIFO if there is any data remaining to be transferred.
 * On Host Transfer Completed interrupt this function indicates that transfer is completed,
 * the SPI subsystem will clear MTC bit.
 *
 * Return:	IRQ_HANDLED when handled; IRQ_NONE otherwise.
 */
static irqreturn_t ax_spi_irq(int irq, void *dev_id)
{
	struct spi_controller *ctlr = dev_id;
	struct ax_spi *xspi = spi_controller_get_devdata(ctlr);
	u32 intr_status;

	intr_status = ax_spi_read(xspi, AX_SPI_IVR);
	if (!intr_status)
		return IRQ_NONE;

	/* Handle "Message Transfer Complete" interrupt.
	 * This means all bytes have been shifted out of the TX FIFO.
	 * It's time to harvest the final incoming bytes from the RX FIFO.
	 */
	if (intr_status & AX_SPI_IVR_MTCV) {
		/* Clear the MTC interrupt flag immediately. */
		ax_spi_write(xspi, AX_SPI_ISR, AX_SPI_ISR_MTC);

		/* For a TX-only transfer, rx_buf would be NULL.
		 * In the spi-core, rx_copy_remaining would be 0.
		 * So we can finalize immediately.
		 */
		if (!xspi->rx_buf) {
			ax_spi_write(xspi, AX_SPI_IMR, 0x00);
			spi_finalize_current_transfer(ctlr);
			return IRQ_HANDLED;
		}
		/* For a full-duplex transfer, process any remaining RX data.

Annotation

Implementation Notes