drivers/spi/spi-st-ssc4.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-st-ssc4.c
Extension
.c
Size
10624 bytes
Lines
455
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

struct spi_st {
	/* SSC SPI Controller */
	void __iomem		*base;
	struct clk		*clk;
	struct device		*dev;

	/* SSC SPI current transaction */
	const u8		*tx_ptr;
	u8			*rx_ptr;
	u16			bytes_per_word;
	unsigned int		words_remaining;
	unsigned int		baud;
	struct completion	done;
};

/* Load the TX FIFO */
static void ssc_write_tx_fifo(struct spi_st *spi_st)
{
	unsigned int count, i;
	uint32_t word = 0;

	if (spi_st->words_remaining > FIFO_SIZE)
		count = FIFO_SIZE;
	else
		count = spi_st->words_remaining;

	for (i = 0; i < count; i++) {
		if (spi_st->tx_ptr) {
			if (spi_st->bytes_per_word == 1) {
				word = *spi_st->tx_ptr++;
			} else {
				word = *spi_st->tx_ptr++;
				word = *spi_st->tx_ptr++ | (word << 8);
			}
		}
		writel_relaxed(word, spi_st->base + SSC_TBUF);
	}
}

/* Read the RX FIFO */
static void ssc_read_rx_fifo(struct spi_st *spi_st)
{
	unsigned int count, i;
	uint32_t word = 0;

	if (spi_st->words_remaining > FIFO_SIZE)
		count = FIFO_SIZE;
	else
		count = spi_st->words_remaining;

	for (i = 0; i < count; i++) {
		word = readl_relaxed(spi_st->base + SSC_RBUF);

		if (spi_st->rx_ptr) {
			if (spi_st->bytes_per_word == 1) {
				*spi_st->rx_ptr++ = (uint8_t)word;
			} else {
				*spi_st->rx_ptr++ = (word >> 8);
				*spi_st->rx_ptr++ = word & 0xff;
			}
		}
	}
	spi_st->words_remaining -= count;
}

static int spi_st_transfer_one(struct spi_controller *host,
			       struct spi_device *spi, struct spi_transfer *t)
{
	struct spi_st *spi_st = spi_controller_get_devdata(host);
	uint32_t ctl = 0;

	/* Setup transfer */
	spi_st->tx_ptr = t->tx_buf;
	spi_st->rx_ptr = t->rx_buf;

	if (spi->bits_per_word > 8) {
		/*
		 * Anything greater than 8 bits-per-word requires 2
		 * bytes-per-word in the RX/TX buffers
		 */
		spi_st->bytes_per_word = 2;
		spi_st->words_remaining = t->len / 2;

	} else if (spi->bits_per_word == 8 && !(t->len & 0x1)) {
		/*
		 * If transfer is even-length, and 8 bits-per-word, then
		 * implement as half-length 16 bits-per-word transfer
		 */
		spi_st->bytes_per_word = 2;
		spi_st->words_remaining = t->len / 2;

Annotation

Implementation Notes