drivers/i2c/busses/i2c-imx-lpi2c.c

Source file repositories/reference/linux-study-clean/drivers/i2c/busses/i2c-imx-lpi2c.c

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-imx-lpi2c.c
Extension
.c
Size
46993 bytes
Lines
1740
Domain
Driver Families
Bucket
drivers/i2c
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 imx_lpi2c_hwdata {
	bool	need_request_free_irq;		/* Needed by irqsteer */
	bool	need_prepare_unprepare_clk;	/* Needed by LPCG */
};

struct lpi2c_imx_dma {
	bool		using_pio_mode;
	u8		rx_cmd_buf_len;
	u8		*dma_buf;
	u16		*rx_cmd_buf;
	unsigned int	dma_len;
	unsigned int	tx_burst_num;
	unsigned int	rx_burst_num;
	unsigned long	dma_msg_flag;
	resource_size_t	phy_addr;
	dma_addr_t	dma_tx_addr;
	dma_addr_t	dma_addr;
	enum dma_data_direction dma_data_dir;
	enum dma_transfer_direction dma_transfer_dir;
	struct dma_chan	*chan_tx;
	struct dma_chan	*chan_rx;
};

struct lpi2c_imx_struct {
	struct i2c_adapter	adapter;
	int			num_clks;
	struct clk_bulk_data	*clks;
	void __iomem		*base;
	__u8			*rx_buf;
	__u8			*tx_buf;
	struct completion	complete;
	unsigned long		rate_per;
	unsigned int		msglen;
	unsigned int		delivered;
	unsigned int		block_data;
	unsigned int		bitrate;
	unsigned int		txfifosize;
	unsigned int		rxfifosize;
	enum lpi2c_imx_mode	mode;
	struct i2c_bus_recovery_info rinfo;
	bool			can_use_dma;
	struct lpi2c_imx_dma	*dma;
	struct i2c_client	*target;
	int			irq;
	const struct imx_lpi2c_hwdata *hwdata;
};

static const struct imx_lpi2c_hwdata imx7ulp_lpi2c_hwdata = {
};

static const struct imx_lpi2c_hwdata imx8qxp_lpi2c_hwdata = {
	.need_request_free_irq		= true,
	.need_prepare_unprepare_clk	= true,
};

static const struct imx_lpi2c_hwdata imx8qm_lpi2c_hwdata = {
	.need_request_free_irq		= true,
	.need_prepare_unprepare_clk	= true,
};

#define lpi2c_imx_read_msr_poll_timeout(atomic, val, cond)                    \
	(atomic ? readl_poll_timeout_atomic(lpi2c_imx->base + LPI2C_MSR, val, \
					    cond, 0, 500000) :                \
		  readl_poll_timeout(lpi2c_imx->base + LPI2C_MSR, val, cond,  \
				     0, 500000))

static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
			      unsigned int enable)
{
	writel(enable, lpi2c_imx->base + LPI2C_MIER);
}

static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx, bool atomic)
{
	unsigned int temp;
	int err;

	err = lpi2c_imx_read_msr_poll_timeout(atomic, temp,
					      temp & (MSR_ALF | MSR_BBF | MSR_MBF));

	/* check for arbitration lost, clear if set */
	if (temp & MSR_ALF) {
		writel(temp, lpi2c_imx->base + LPI2C_MSR);
		return -EAGAIN;
	}

	/* check for bus not busy */
	if (err) {
		dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
		if (lpi2c_imx->adapter.bus_recovery_info)

Annotation

Implementation Notes