Linux driver development (IIC subsystem)

Posted by bluetonic on Sun, 26 Dec 2021 15:23:01 +0100

1. Introduction to IIC protocol

In the previous bare metal ARM, we introduced: https://blog.csdn.net/weixin_49303682/article/details/119305227

2. IIC subsystem framework of Linux

I2C host driver: the driver of I2C host controller is generally designed and implemented by SoC chip manufacturers to control the timing signal sent by II2C host controller.

I2C Core: provides a unified API interface for the upper layer and manages the registration and cancellation of other modules.

The I2C driver is very similar to the platform bus device driver we came into contact with before. There are bus, device and driver.

The main goal of I2C driver framework is to enable driver developers to easily add their own I2C device drivers in the kernel, so that they can more easily drive their own I2C interface hardware under linux.

The I2C related drivers in the source code are located in the drivers/i2c directory.

3. Source code analysis of I2C subsystem of Linux kernel

Four key structures of I2C subsystem:

struct i2c_adapter: I2C adapter

struct i2c_adapter {
	struct module *owner;
	unsigned int id;
	unsigned int class;		          /* classes to allow probing for */
	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
	void *algo_data;

	/* data fields that are valid for all devices	*/
	struct rt_mutex bus_lock;
	int timeout;		         	 /* in jiffies */
	int retries;
	struct device dev;		         /* the adapter device */

	int nr;
	char name[48];
	struct completion dev_released;
	struct list_head userspace_clients;
};

struct i2c_algorithm: I2C algorithm

struct i2c_algorithm {
int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,  int num);
int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data);

/* To determine what the adapter supports */
u32 (*functionality) (struct i2c_adapter *);
};

struct i2c_client: I2C (slave) device information

struct i2c_client {
	unsigned short flags;		/* div., see below		*/
	unsigned short addr;		/* chip address - NOTE: 7bit	*/
					            /* addresses are stored in the	*/
				             	/* _LOWER_ 7 bits		*/
	char name[I2C_NAME_SIZE];
	struct i2c_adapter *adapter;/* the adapter we sit on	*/
	struct i2c_driver *driver;	/* and our access routines	*/
	struct device dev;		    /* the device structure		*/
	int irq;			        /* irq issued by device		*/
	struct list_head detected;
};

struct i2c_driver: I2C (slave) device driver

struct i2c_driver {
	unsigned int class;
	int (*attach_adapter)(struct i2c_adapter *);
	int (*detach_adapter)(struct i2c_adapter *);

	/* Standard driver model interfaces */
	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
	int (*remove)(struct i2c_client *);

	/* driver model interfaces that don't relate to enumeration  */
	void (*shutdown)(struct i2c_client *);
	int (*suspend)(struct i2c_client *, pm_message_t mesg);
	int (*resume)(struct i2c_client *);
	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);

	struct device_driver driver;
	const struct i2c_device_id *id_table;

	/* Device detection callback for automatic device creation */
	int (*detect)(struct i2c_client *, struct i2c_board_info *);
	const unsigned short *address_list;
	struct list_head clients;
};

4.i2c-core.c analysis

match function:

probe function:

There are two branches on the I2C bus: i2c_client chain and i2c_driver chain. When any driver or client registers, the I2C bus will call the match function to register the client Name and driver id_ table. Name for circular matching. If driver id_ If all IDS in the table do not match, the client does not find a corresponding driver.
 

5.i2c_s3c2410.c analysis

driver and device pairing process:

probe function:

Fill an I2C_ The adapter structure and call the interface to register it.

From platform_device receives hardware information and performs necessary processing (request_mem_region & ioremap, request_irq, etc.).

Initialize the hardware (directly operate the registers of the internal I2C controller of 210).

6. Take the drive of gslx680 as an example ----- i2c_driver and i2c_client 

i2c_driver:

i2c_client implementation principle:

The kernel maintains a linked list__ i2c_board_list, which links the information structures of all hardware devices attached to the I2C bus. In other words, the linked list maintains a struct i2c_board_info structure linked list.

 

 

 

 

 

Topics: Linux Driver