drivers/spi/spi-pic32-sqi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-pic32-sqi.c
Extension
.c
Size
17849 bytes
Lines
687
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 buf_desc {
	u32 bd_ctrl;	/* control */
	u32 bd_status;	/* reserved */
	u32 bd_addr;	/* DMA buffer addr */
	u32 bd_nextp;	/* next item in chain */
};

/* bd_ctrl */
#define BD_BUFLEN		0x1ff
#define BD_CBD_INT_EN		BIT(16)	/* Current BD is processed */
#define BD_PKT_INT_EN		BIT(17) /* All BDs of PKT processed */
#define BD_LIFM			BIT(18) /* last data of pkt */
#define BD_LAST			BIT(19) /* end of list */
#define BD_DATA_RECV		BIT(20) /* receive data */
#define BD_DDR			BIT(21) /* DDR mode */
#define BD_DUAL			BIT(22)	/* Dual SPI */
#define BD_QUAD			BIT(23) /* Quad SPI */
#define BD_LSBF			BIT(25)	/* LSB First */
#define BD_STAT_CHECK		BIT(27) /* Status poll */
#define BD_DEVSEL_SHIFT		28	/* CS */
#define BD_CS_DEASSERT		BIT(30) /* de-assert CS after current BD */
#define BD_EN			BIT(31) /* BD owned by H/W */

/**
 * struct ring_desc - Representation of SQI ring descriptor
 * @list:	list element to add to free or used list.
 * @bd:		PESQI controller buffer descriptor
 * @bd_dma:	DMA address of PESQI controller buffer descriptor
 * @xfer_len:	transfer length
 */
struct ring_desc {
	struct list_head list;
	struct buf_desc *bd;
	dma_addr_t bd_dma;
	u32 xfer_len;
};

/* Global constants */
#define PESQI_BD_BUF_LEN_MAX	256
#define PESQI_BD_COUNT		256 /* max 64KB data per spi message */

struct pic32_sqi {
	void __iomem		*regs;
	struct clk		*sys_clk;
	struct clk		*base_clk; /* drives spi clock */
	struct spi_controller	*host;
	int			irq;
	struct completion	xfer_done;
	struct ring_desc	*ring;
	void			*bd;
	dma_addr_t		bd_dma;
	struct list_head	bd_list_free; /* free */
	struct list_head	bd_list_used; /* allocated */
	struct spi_device	*cur_spi;
	u32			cur_speed;
	u8			cur_mode;
};

static inline void pic32_setbits(void __iomem *reg, u32 set)
{
	writel(readl(reg) | set, reg);
}

static inline void pic32_clrbits(void __iomem *reg, u32 clr)
{
	writel(readl(reg) & ~clr, reg);
}

static int pic32_sqi_set_clk_rate(struct pic32_sqi *sqi, u32 sck)
{
	u32 val, div;

	/* div = base_clk / (2 * spi_clk) */
	div = clk_get_rate(sqi->base_clk) / (2 * sck);
	div &= PESQI_CLKDIV;

	val = readl(sqi->regs + PESQI_CLK_CTRL_REG);
	/* apply new divider */
	val &= ~(PESQI_CLK_STABLE | (PESQI_CLKDIV << PESQI_CLKDIV_SHIFT));
	val |= div << PESQI_CLKDIV_SHIFT;
	writel(val, sqi->regs + PESQI_CLK_CTRL_REG);

	/* wait for stability */
	return readl_poll_timeout(sqi->regs + PESQI_CLK_CTRL_REG, val,
				  val & PESQI_CLK_STABLE, 1, 5000);
}

static inline void pic32_sqi_enable_int(struct pic32_sqi *sqi)
{
	u32 mask = PESQI_DMAERR | PESQI_BDDONE | PESQI_PKTCOMP;

Annotation

Implementation Notes