drivers/spi/spi-cadence.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-cadence.c
Extension
.c
Size
27077 bytes
Lines
906
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 cdns_spi {
	void __iomem *regs;
	struct clk *ref_clk;
	struct clk *pclk;
	unsigned int clk_rate;
	u32 speed_hz;
	const void *txbuf;
	void *rxbuf;
	int tx_bytes;
	int rx_bytes;
	u8 n_bytes;
	u8 dev_busy;
	u32 is_decoded_cs;
	unsigned int tx_fifo_depth;
	struct reset_control *rstc;
};

enum cdns_spi_frame_n_bytes {
	CDNS_SPI_N_BYTES_NULL = 0,
	CDNS_SPI_N_BYTES_U8 = 1,
	CDNS_SPI_N_BYTES_U16 = 2,
	CDNS_SPI_N_BYTES_U32 = 4
};

/* Macros for the SPI controller read/write */
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
{
	return readl_relaxed(xspi->regs + offset);
}

static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val)
{
	writel_relaxed(val, xspi->regs + offset);
}

/**
 * cdns_spi_init_hw - Initialize the hardware and configure the SPI controller
 * @xspi:	Pointer to the cdns_spi structure
 * @is_target:	Flag to indicate target or host mode
 * * On reset the SPI controller is configured to target or host mode.
 * In host mode baud rate divisor is set to 4, threshold value for TX FIFO
 * not full interrupt is set to 1 and size of the word to be transferred as 8 bit.
 *
 * This function initializes the SPI controller to disable and clear all the
 * interrupts, enable manual target select and manual start, deselect all the
 * chip select lines, and enable the SPI controller.
 */
static void cdns_spi_init_hw(struct cdns_spi *xspi, bool is_target)
{
	u32 ctrl_reg = 0;

	if (!is_target)
		ctrl_reg |= CDNS_SPI_CR_DEFAULT;

	if (xspi->is_decoded_cs)
		ctrl_reg |= CDNS_SPI_CR_PERI_SEL;

	cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
	cdns_spi_write(xspi, CDNS_SPI_IDR, CDNS_SPI_IXR_ALL);

	/* Clear the RX FIFO */
	while (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_RXNEMTY)
		cdns_spi_read(xspi, CDNS_SPI_RXD);

	cdns_spi_write(xspi, CDNS_SPI_ISR, CDNS_SPI_IXR_ALL);
	cdns_spi_write(xspi, CDNS_SPI_CR, ctrl_reg);
	cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_ENABLE);
}

/**
 * cdns_spi_chipselect - Select or deselect the chip select line
 * @spi:	Pointer to the spi_device structure
 * @is_high:	Select(0) or deselect (1) the chip select line
 */
static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
{
	struct cdns_spi *xspi = spi_controller_get_devdata(spi->controller);
	u32 ctrl_reg;

	ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);

	if (is_high) {
		/* Deselect the target */
		ctrl_reg |= CDNS_SPI_CR_SSCTRL;
	} else {
		/* Select the target */
		ctrl_reg &= ~CDNS_SPI_CR_SSCTRL;
		if (!(xspi->is_decoded_cs))
			ctrl_reg |= ((~(CDNS_SPI_SS0 << spi_get_chipselect(spi, 0))) <<
				     CDNS_SPI_SS_SHIFT) &

Annotation

Implementation Notes