drivers/spi/spi-altera-core.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-altera-core.c
Extension
.c
Size
5234 bytes
Lines
224
Domain
Driver Families
Bucket
drivers/spi
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

switch (hw->bytes_per_word) {
		case 1:
			txd = hw->tx[hw->count];
			break;
		case 2:
			txd = (hw->tx[hw->count * 2]
				| (hw->tx[hw->count * 2 + 1] << 8));
			break;
		case 4:
			txd = (hw->tx[hw->count * 4]
				| (hw->tx[hw->count * 4 + 1] << 8)
				| (hw->tx[hw->count * 4 + 2] << 16)
				| (hw->tx[hw->count * 4 + 3] << 24));
			break;

		}
	}

	altr_spi_writel(hw, ALTERA_SPI_TXDATA, txd);
}

static void altera_spi_rx_word(struct altera_spi *hw)
{
	unsigned int rxd;

	altr_spi_readl(hw, ALTERA_SPI_RXDATA, &rxd);
	if (hw->rx) {
		switch (hw->bytes_per_word) {
		case 1:
			hw->rx[hw->count] = rxd;
			break;
		case 2:
			hw->rx[hw->count * 2] = rxd;
			hw->rx[hw->count * 2 + 1] = rxd >> 8;
			break;
		case 4:
			hw->rx[hw->count * 4] = rxd;
			hw->rx[hw->count * 4 + 1] = rxd >> 8;
			hw->rx[hw->count * 4 + 2] = rxd >> 16;
			hw->rx[hw->count * 4 + 3] = rxd >> 24;
			break;

		}
	}

	hw->count++;
}

static int altera_spi_txrx(struct spi_controller *host,
	struct spi_device *spi, struct spi_transfer *t)
{
	struct altera_spi *hw = spi_controller_get_devdata(host);
	u32 val;

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->count = 0;
	hw->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
	hw->len = t->len / hw->bytes_per_word;

	if (hw->irq >= 0) {
		/* enable receive interrupt */
		hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
		altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);

		/* send the first byte */
		altera_spi_tx_word(hw);

		return 1;
	}

	while (hw->count < hw->len) {
		altera_spi_tx_word(hw);

		for (;;) {
			altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
			if (val & ALTERA_SPI_STATUS_RRDY_MSK)
				break;

			cpu_relax();
		}

		altera_spi_rx_word(hw);
	}
	spi_finalize_current_transfer(host);

	return 0;
}

irqreturn_t altera_spi_irq(int irq, void *dev)

Annotation

Implementation Notes