drivers/i2c/busses/i2c-riic.c

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

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-riic.c
Extension
.c
Size
20091 bytes
Lines
778
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 riic_of_data {
	const u8 *regs;
	const struct riic_irq_desc *irqs;
	u8 num_irqs;
	bool fast_mode_plus;
};

struct riic_dev {
	void __iomem *base;
	u8 *buf;
	struct i2c_msg *msg;
	int bytes_left;
	int err;
	int is_last;
	const struct riic_of_data *info;
	struct completion msg_done;
	struct i2c_adapter adapter;
	struct clk *clk;
	struct reset_control *rstc;
	struct i2c_timings i2c_t;
};

struct riic_irq_desc {
	int res_num;
	irq_handler_t isr;
	char *name;
};

static inline void riic_writeb(struct riic_dev *riic, u8 val, u8 offset)
{
	writeb(val, riic->base + riic->info->regs[offset]);
}

static inline u8 riic_readb(struct riic_dev *riic, u8 offset)
{
	return readb(riic->base + riic->info->regs[offset]);
}

static inline void riic_clear_set_bit(struct riic_dev *riic, u8 clear, u8 set, u8 reg)
{
	riic_writeb(riic, (riic_readb(riic, reg) & ~clear) | set, reg);
}

static int riic_bus_barrier(struct riic_dev *riic)
{
	int ret;
	u8 val;

	/*
	 * The SDA line can still be low even when BBSY = 0. Therefore, after checking
	 * the BBSY flag, also verify that the SDA and SCL lines are not being held low.
	 */
	ret = readb_poll_timeout(riic->base + riic->info->regs[RIIC_ICCR2], val,
				 !(val & ICCR2_BBSY), 10, riic->adapter.timeout);
	if (ret)
		return i2c_recover_bus(&riic->adapter);

	if ((riic_readb(riic, RIIC_ICCR1) & (ICCR1_SDAI | ICCR1_SCLI)) !=
	     (ICCR1_SDAI | ICCR1_SCLI))
		return i2c_recover_bus(&riic->adapter);

	return 0;
}

static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
	struct riic_dev *riic = i2c_get_adapdata(adap);
	struct device *dev = adap->dev.parent;
	unsigned long time_left;
	int i, ret;
	u8 start_bit;

	ret = pm_runtime_resume_and_get(dev);
	if (ret)
		return ret;

	riic->err = riic_bus_barrier(riic);
	if (riic->err)
		goto out;

	reinit_completion(&riic->msg_done);

	riic_writeb(riic, 0, RIIC_ICSR2);

	for (i = 0, start_bit = ICCR2_ST; i < num; i++) {
		riic->bytes_left = RIIC_INIT_MSG;
		riic->buf = msgs[i].buf;
		riic->msg = &msgs[i];
		riic->is_last = (i == num - 1);

Annotation

Implementation Notes