drivers/i2c/busses/i2c-mv64xxx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-mv64xxx.c
Extension
.c
Size
30977 bytes
Lines
1113
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 mv64xxx_i2c_regs {
	u8	addr;
	u8	ext_addr;
	u8	data;
	u8	control;
	u8	status;
	u8	clock;
	u8	soft_reset;
};

struct mv64xxx_i2c_data {
	struct i2c_msg		*msgs;
	int			num_msgs;
	int			irq;
	u32			state;
	u32			action;
	u32			aborting;
	u32			cntl_bits;
	void __iomem		*reg_base;
	struct mv64xxx_i2c_regs	reg_offsets;
	u32			addr1;
	u32			addr2;
	u32			bytes_left;
	u32			byte_posn;
	u32			send_stop;
	u32			block;
	int			rc;
	u32			freq_m;
	u32			freq_n;
	struct clk              *clk;
	struct clk              *reg_clk;
	wait_queue_head_t	waitq;
	spinlock_t		lock;
	struct i2c_msg		*msg;
	struct i2c_adapter	adapter;
	bool			offload_enabled;
/* 5us delay in order to avoid repeated start timing violation */
	bool			errata_delay;
	struct reset_control	*rstc;
	bool			irq_clear_inverted;
	/* Clk div is 2 to the power n, not 2 to the power n + 1 */
	bool			clk_n_base_0;
	struct i2c_bus_recovery_info	rinfo;
	bool			atomic;
};

static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
	.addr		= 0x00,
	.ext_addr	= 0x10,
	.data		= 0x04,
	.control	= 0x08,
	.status		= 0x0c,
	.clock		= 0x0c,
	.soft_reset	= 0x1c,
};

static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_sun4i = {
	.addr		= 0x00,
	.ext_addr	= 0x04,
	.data		= 0x08,
	.control	= 0x0c,
	.status		= 0x10,
	.clock		= 0x14,
	.soft_reset	= 0x18,
};

static void
mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
	struct i2c_msg *msg)
{
	drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
			      MV64XXX_I2C_REG_CONTROL_TWSIEN;

	if (!drv_data->atomic)
		drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_INTEN;

	if (msg->flags & I2C_M_TEN) {
		drv_data->addr1 = i2c_10bit_addr_hi_from_msg(msg);
		drv_data->addr2 = i2c_10bit_addr_lo_from_msg(msg);
	} else {
		drv_data->addr1 = i2c_8bit_addr_from_msg(msg);
		drv_data->addr2 = 0;
	}
}

/*
 *****************************************************************************
 *
 *	Finite State Machine & Interrupt Routines
 *

Annotation

Implementation Notes