drivers/i2c/busses/i2c-microchip-corei2c.c

Source file repositories/reference/linux-study-clean/drivers/i2c/busses/i2c-microchip-corei2c.c

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-microchip-corei2c.c
Extension
.c
Size
16927 bytes
Lines
650
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 mchp_corei2c_dev {
	void __iomem *base;
	struct device *dev;
	struct clk *i2c_clk;
	struct i2c_msg *msg_queue;
	u8 *buf;
	struct completion msg_complete;
	struct i2c_adapter adapter;
	int msg_err;
	int total_num;
	int current_num;
	u32 bus_clk_rate;
	u32 isr_status;
	u16 msg_len;
	u8 addr;
	bool restart_needed;
};

static void mchp_corei2c_core_disable(struct mchp_corei2c_dev *idev)
{
	u8 ctrl = readb(idev->base + CORE_I2C_CTRL);

	ctrl &= ~CTRL_ENS1;
	writeb(ctrl, idev->base + CORE_I2C_CTRL);
}

static void mchp_corei2c_core_enable(struct mchp_corei2c_dev *idev)
{
	u8 ctrl = readb(idev->base + CORE_I2C_CTRL);

	ctrl |= CTRL_ENS1;
	writeb(ctrl, idev->base + CORE_I2C_CTRL);
}

static void mchp_corei2c_reset(struct mchp_corei2c_dev *idev)
{
	mchp_corei2c_core_disable(idev);
	mchp_corei2c_core_enable(idev);
}

static inline void mchp_corei2c_stop(struct mchp_corei2c_dev *idev)
{
	u8 ctrl = readb(idev->base + CORE_I2C_CTRL);

	ctrl |= CTRL_STO;
	writeb(ctrl, idev->base + CORE_I2C_CTRL);
}

static inline int mchp_corei2c_set_divisor(u32 rate,
					   struct mchp_corei2c_dev *idev)
{
	u8 clkval, ctrl;

	if (rate >= 960)
		clkval = PCLK_DIV_960;
	else if (rate >= 256)
		clkval = PCLK_DIV_256;
	else if (rate >= 224)
		clkval = PCLK_DIV_224;
	else if (rate >= 192)
		clkval = PCLK_DIV_192;
	else if (rate >= 160)
		clkval = PCLK_DIV_160;
	else if (rate >= 120)
		clkval = PCLK_DIV_120;
	else if (rate >= 60)
		clkval = PCLK_DIV_60;
	else if (rate >= 8)
		clkval = BCLK_DIV_8;
	else
		return -EINVAL;

	ctrl = readb(idev->base + CORE_I2C_CTRL);
	ctrl &= ~CLK_MASK;
	ctrl |= clkval;
	writeb(ctrl, idev->base + CORE_I2C_CTRL);

	ctrl = readb(idev->base + CORE_I2C_CTRL);
	if ((ctrl & CLK_MASK) != clkval)
		return -EIO;

	return 0;
}

static int mchp_corei2c_init(struct mchp_corei2c_dev *idev)
{
	u32 clk_rate = clk_get_rate(idev->i2c_clk);
	u32 divisor = clk_rate / idev->bus_clk_rate;
	int ret;

Annotation

Implementation Notes