drivers/spi/spi-hisi-kunpeng.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-hisi-kunpeng.c
Extension
.c
Size
14408 bytes
Lines
566
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 hisi_chip_data {
	u32 cr;
	u32 speed_hz;	/* baud rate */
	u16 clk_div;	/* baud rate divider */

	/* clk_div = (1 + div_post) * div_pre */
	u8 div_post;	/* value from 0 to 255 */
	u8 div_pre;	/* value from 2 to 254 (even only!) */
};

struct hisi_spi {
	struct device		*dev;

	void __iomem		*regs;
	int			irq;
	u32			fifo_len; /* depth of the FIFO buffer */

	/* Current message transfer state info */
	const void		*tx;
	unsigned int		tx_len;
	void			*rx;
	unsigned int		rx_len;
	u8			n_bytes; /* current is a 1/2/4 bytes op */

	struct dentry *debugfs;
	struct debugfs_regset32 regset;
};

#define HISI_SPI_DBGFS_REG(_name, _off)	\
{					\
	.name = _name,			\
	.offset = _off,			\
}

static const struct debugfs_reg32 hisi_spi_regs[] = {
	HISI_SPI_DBGFS_REG("CSCR", HISI_SPI_CSCR),
	HISI_SPI_DBGFS_REG("CR", HISI_SPI_CR),
	HISI_SPI_DBGFS_REG("ENR", HISI_SPI_ENR),
	HISI_SPI_DBGFS_REG("FIFOC", HISI_SPI_FIFOC),
	HISI_SPI_DBGFS_REG("IMR", HISI_SPI_IMR),
	HISI_SPI_DBGFS_REG("SR", HISI_SPI_SR),
	HISI_SPI_DBGFS_REG("RISR", HISI_SPI_RISR),
	HISI_SPI_DBGFS_REG("ISR", HISI_SPI_ISR),
	HISI_SPI_DBGFS_REG("ICR", HISI_SPI_ICR),
	HISI_SPI_DBGFS_REG("VERSION", HISI_SPI_VERSION),
};

static int hisi_spi_debugfs_init(struct hisi_spi *hs)
{
	char name[32];
	struct spi_controller *host = dev_get_drvdata(hs->dev);

	snprintf(name, 32, "hisi_spi%d", host->bus_num);
	hs->debugfs = debugfs_create_dir(name, NULL);
	if (IS_ERR(hs->debugfs))
		return -ENOMEM;

	hs->regset.regs = hisi_spi_regs;
	hs->regset.nregs = ARRAY_SIZE(hisi_spi_regs);
	hs->regset.base = hs->regs;
	debugfs_create_regset32("registers", 0400, hs->debugfs, &hs->regset);

	return 0;
}

static u32 hisi_spi_busy(struct hisi_spi *hs)
{
	return readl(hs->regs + HISI_SPI_SR) & SR_BUSY;
}

static u32 hisi_spi_rx_not_empty(struct hisi_spi *hs)
{
	return readl(hs->regs + HISI_SPI_SR) & SR_RXNE;
}

static u32 hisi_spi_tx_not_full(struct hisi_spi *hs)
{
	return readl(hs->regs + HISI_SPI_SR) & SR_TXNF;
}

static void hisi_spi_flush_fifo(struct hisi_spi *hs)
{
	unsigned long limit = loops_per_jiffy << 1;

	do {
		unsigned long inner_limit = loops_per_jiffy;

		while (hisi_spi_rx_not_empty(hs) && --inner_limit) {
			readl(hs->regs + HISI_SPI_DOUT);
			cpu_relax();

Annotation

Implementation Notes