drivers/i2c/busses/i2c-digicolor.c

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

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-digicolor.c
Extension
.c
Size
8046 bytes
Lines
377
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 dc_i2c {
	struct i2c_adapter	adap;
	struct device		*dev;
	void __iomem		*regs;
	struct clk		*clk;
	unsigned int		frequency;

	struct i2c_msg		*msg;
	unsigned int		msgbuf_ptr;
	int			last;
	spinlock_t		lock;
	struct completion	done;
	int			state;
	int			error;
};

enum {
	STATE_IDLE,
	STATE_START,
	STATE_ADDR,
	STATE_WRITE,
	STATE_READ,
	STATE_STOP,
};

static void dc_i2c_cmd(struct dc_i2c *i2c, u8 cmd)
{
	writeb_relaxed(cmd | II_COMMAND_GO, i2c->regs + II_COMMAND);
}

static u8 dc_i2c_addr_cmd(struct i2c_msg *msg)
{
	u8 addr = (msg->addr & 0x7f) << 1;

	if (msg->flags & I2C_M_RD)
		addr |= 1;

	return addr;
}

static void dc_i2c_data(struct dc_i2c *i2c, u8 data)
{
	writeb_relaxed(data, i2c->regs + II_DATA);
}

static void dc_i2c_write_byte(struct dc_i2c *i2c, u8 byte)
{
	dc_i2c_data(i2c, byte);
	dc_i2c_cmd(i2c, II_CMD_SEND_ACK);
}

static void dc_i2c_write_buf(struct dc_i2c *i2c)
{
	dc_i2c_write_byte(i2c, i2c->msg->buf[i2c->msgbuf_ptr++]);
}

static void dc_i2c_next_read(struct dc_i2c *i2c)
{
	bool last = (i2c->msgbuf_ptr + 1 == i2c->msg->len);

	dc_i2c_cmd(i2c, last ? II_CMD_GET_NOACK : II_CMD_GET_ACK);
}

static void dc_i2c_stop(struct dc_i2c *i2c)
{
	i2c->state = STATE_STOP;
	if (i2c->last)
		dc_i2c_cmd(i2c, II_CMD_STOP);
	else
		complete(&i2c->done);
}

static u8 dc_i2c_read_byte(struct dc_i2c *i2c)
{
	return readb_relaxed(i2c->regs + II_DATA);
}

static void dc_i2c_read_buf(struct dc_i2c *i2c)
{
	i2c->msg->buf[i2c->msgbuf_ptr++] = dc_i2c_read_byte(i2c);
	dc_i2c_next_read(i2c);
}

static void dc_i2c_set_irq(struct dc_i2c *i2c, int enable)
{
	if (enable)
		writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
	writeb_relaxed(!!enable, i2c->regs + II_INTENABLE);
}

Annotation

Implementation Notes