[Beijing Xunwei] i.MX6ULL Terminator Linux I2C Driver Experiment Introduction to Linux I2C Driver Framework

The I2C architecture in the Linux kernel is divided into three parts:
① I2C core: I2C core provides I2C bus driver and device driver registration and deregistration methods.
② I2C bus driver: I2C bus driver is the realization of the adapter end in the I2C hardware architecture. The adapter can be controlled by the CPU, and can even be directly integrated inside the CPU.
③ I2C device driver: I2C device driver is the realization of the device side in the I2C hardware architecture. The device is generally connected to an I2C adapter controlled by the CPU, and exchanges data with the CPU through the I2C adapter.

1 I2C bus driver

The I2C bus is similar to the platform bus, except that the platform bus is a virtual bus, and the I2C bus actually exists. For devices that use I2C communication, just use I2C summary directly in the driver. The focus of the I2C bus driver is the I2C adapter driver, which mainly involves two structures: i2c_adapter and i2c_algorithm. The i2c_adapter structure is used to represent the I2C adapter in the Linux kernel. The i2c_adapter structure is defined in the include/linux/i2c.h file, and the structure content is as follows:

498 struct i2c_adapter {
    
     
499        struct module *owner; 
500        unsigned int class; /* classes to allow probing for */ 
501        const struct i2c_algorithm *algo; /* 总线访问算法 */ 
502        void *algo_data; 
503 
504        /* data fields that are valid for all devices */ 
505        struct rt_mutex bus_lock; 
506 
507        int timeout; /* in jiffies */ 
508        int retries; 
509        struct device dev; /* the adapter device */ 
510 
511        int nr; 
512        char name[48]; 
513        struct completion dev_released; 
514 
515        struct mutex userspace_clients_lock; 
516        struct list_head userspace_clients; 
517 
518        struct i2c_bus_recovery_info *bus_recovery_info; 
519        const struct i2c_adapter_quirks *quirks; 
520 };

Line 501, i2c_algorithm type pointer variable algo, for an I2C adapter, must provide read and write API functions externally, the device driver can use these API functions to complete read and write operations. i2c_algorithm is the method for the I2C adapter to communicate with the IIC device.
The i2c_algorithm structure is defined in the include/linux/i2c.h file, and part of the content is as follows:

391 struct i2c_algorithm {
    
     
...... 
398        int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, 
399                        int num); 
400        int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, 
401        unsigned short flags, char read_write, 
402        u8 command, int size, union i2c_smbus_data *data); 
403 
404        /* To determine what the adapter supports */ 
405        u32 (*functionality) (struct i2c_adapter *); 
...... 
411 }; 

On line 398, master_xfer is the transfer function of the I2C adapter, which can be used to complete the communication with the IIC device.
In line 400, smbus_xfer is the transfer function of SMBUS.
In summary, the main work of the I2C bus driver, or I2C adapter driver, is to initialize the i2c_adapter structure variable, and then set the master_xfer function in i2c_algorithm. After completion, register the set i2c_adapter with the system through the two functions i2c_add_numbered_adapter or i2c_add_adapter. The prototypes of these two functions are as follows:

int i2c_add_adapter(struct i2c_adapter *adapter) 
int i2c_add_numbered_adapter(struct i2c_adapter *adap)

The difference between these two functions is that i2c_add_adapter uses a dynamic bus number, while i2c_add_numbered_adapter uses a static bus number. The meanings of function parameters and return values ​​are as follows:
adapter or adap: i2c_adapter to be added to the Linux kernel, that is, the I2C adapter.
Return value: 0, success; negative value, failure.
If you want to delete the I2C adapter, use the i2c_del_adapter function. The function prototype is as follows:
void i2c_del_adapter(struct i2c_adapter * adap) The
meaning of the function parameters and return values ​​are as follows:
adap: the I2C adapter to be deleted.
Return value: None.
The I2C bus (controller or adapter) driver is explained here. Generally, the I2C bus driver of SOC is written by semiconductor manufacturers. For example, I.MX6U I2C adapter driver NXP has been written, and this does not require users to write . So we don't need to care about how the I2C bus driver is implemented, we just need to focus on the I2C device driver.

2 I2C device driver

There are two important structures in the I2C device driver: i2c_client and i2c_driver. i2c_client describes the device information, i2c_driver describes the drive content, similar to platform_driver.
The i2c_client structure is defined in the include/linux/i2c.h file, and the content is as follows:

217 struct i2c_client {
    
     
218        unsigned short flags; /* 标志 */ 
219        unsigned short addr; /* 芯片地址,7 位,存在低 7 位*/ 
...... 
222        char name[I2C_NAME_SIZE]; /* 名字 */ 
223        struct i2c_adapter *adapter; /* 对应的 I2C 适配器 */ 
224        struct device dev; /* 设备结构体 */ 
225        int irq; /* 中断 */ 
226        struct list_head detected; 
...... 
230 };

One device corresponds to one i2c_client, and every time an I2C device is detected, an i2c_client is assigned to the I2C device.
i2c_driver is similar to platform_driver and is the key content of I2C driver writing. The i2c_driver structure is defined in the include/linux/i2c.h file, and the content is as follows:

161 struct i2c_driver {
    
     
162        unsigned int class; 
163 
164        /* Notifies the driver that a new bus has appeared. You should 
165        * avoid using this, it will be removed in a near future. 
166        */ 
167        int (*attach_adapter)(struct i2c_adapter *) __deprecated; 
168 
169        /* Standard driver model interfaces */ 
170        int (*probe)(struct i2c_client *, const struct i2c_device_id *); 
171      int (*remove)(struct i2c_client *); 
172 
173        /* driver model interfaces that don't relate to enumeration */ 
174        void (*shutdown)(struct i2c_client *); 
175 
176        /* Alert callback, for example for the SMBus alert protocol. 
177        * The format and meaning of the data value depends on the 
178        * protocol.For the SMBus alert protocol, there is a single bit 
179        * of data passed as the alert response's low bit ("event 
180     flag"). */ 
181        void (*alert)(struct i2c_client *, unsigned int data);
182 
183        /* a ioctl like command that can be used to perform specific 
184        * functions with the device. 
185        */ 
186        int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); 
187 
188        struct device_driver driver; 
189        const struct i2c_device_id *id_table; 
190 
191        /* Device detection callback for automatic device creation */ 
192        int (*detect)(struct i2c_client *, struct i2c_board_info *); 
193        const unsigned short *address_list; 
194        struct list_head clients; 
195 };

On line 170, when the I2C device and the driver match successfully, the probe function will be executed, just like the platform driver.
Line 188, device_driver driver structure. If you use the device tree, you need to set the
of_match_table member variable of device_driver, which is the compatible attribute of the driver.
In line 189, id_table is a traditional, unused device tree matching ID table.

When writing a driver for an I2C device, the main thing is to create an i2c_driver structure and implement the content inside.
After the i2c_driver structure is created, use the int i2c_register_driver function to register the i2c device in the Linux kernel. The function prototype is as follows:

int i2c_register_driver(struct module *owner,  
struct i2c_driver *driver) 

The meanings of function parameters and return values ​​are as follows:
owner: generally THIS_MODULE.
driver: i2c_driver to be registered.
Return value: 0, success; negative value, failure.
In addition, i2c_add_driver is also often used to register i2c_driver, i2c_add_driver is a macro, defined as follows:
587 #define i2c_add_driver(driver) \
588 i2c_register_driver(THIS_MODULE, driver) It
can be seen that i2c_add_driver is a simple package for i2c_register_driver. It is the i2c_driver to be registered.
At the same time as the mainline I2C device driver, the previously registered i2c_driver needs to be unregistered from the Linux kernel. Use the i2c_del_driver function, the prototype of this function is as follows: the
void i2c_del_driver(struct i2c_driver *driver)
meaning of the function parameters and return values ​​are as follows:
driver: i2c_driver to be cancelled.
Return value: None.
The registration sample code of i2c_driver is as follows:

1 /* i2c 驱动的 probe 函数 */ 
2 static int xxx_probe(struct i2c_client *client, const struct i2c_device_id *id) 
3 {
    
     
4      /* 函数具体程序 */ 
5        return 0; 
6 } 
7 
8 /* i2c 驱动的 remove 函数 */ 
9 static int ap3216c_remove(struct i2c_client *client) 
10 {
    
     
11      /* 函数具体程序 */ 
12         return 0; 
13 } 
14 
15 /* 传统匹配方式 ID 列表 */ 
16 static const struct i2c_device_id xxx_id[] = {
    
     
17         {
    
    "xxx", 0}, 
18         {
    
    } 
19 }; 
20 
21 /* 设备树匹配列表 */ 
22 static const struct of_device_id xxx_of_match[] = {
    
     
23         {
    
     .compatible = "xxx" }, 
24         {
    
     /* Sentinel */ } 
25 }; 
26 
27 /* i2c 驱动结构体 */ 
28 static struct i2c_driver xxx_driver = {
    
     
29         .probe = xxx_probe, 
30         .remove = xxx_remove, 
31      .driver = {
    
     
32             .owner = THIS_MODULE, 
33             .name = "xxx", 
34             .of_match_table = xxx_of_match, 
35         }, 
36         .id_table = xxx_id, 
37 }; 
38 
39 /* 驱动入口函数 */ 
40 static int __init xxx_init(void) 
41 {
    
     
42     int ret = 0; 
43 
44     ret = i2c_add_driver(&xxx_driver);
45     return ret; 
46 } 
47 
48 /* 驱动出口函数 */ 
49 static void __exit xxx_exit(void) 
50 {
    
     
51     i2c_del_driver(&xxx_driver); 
52 } 
53 
54 module_init(xxx_init); 
55 module_exit(xxx_exit); 

Lines 16-19, i2c_device_id, match the ID table when there is no device tree.
Lines 22~25, of_device_id, the matching table used by the device tree.
Lines 28~37, i2c_driver, the probe function will be executed when the I2C device and I2C driver match successfully. These are the same as the platform driver. The probe function is basically the standard character device driver.

3 I2C core

What is done at the I2C core layer is the matching process between I2C devices and I2C drivers. The I2C core file is drivers/i2c/i2c-core.c, and the I2C core layer provides some API functions that are not related to hardware.
1. i2c_adapter registration/deregistration function
int i2c_add_adapter(struct i2c_adapter *adapter)
int i2c_add_numbered_adapter(struct i2c_adapter *adap)
void i2c_del_adapter(struct i2c_adapter * adap)
register/deregistration function
i2c_driver i2c_driver struct i2c_driver (struct i2c_driver *adap) module *adap) )
int i2c_add_driver (struct i2c_driver *driver)
void i2c_del_driver(struct i2c_driver *driver)
The matching process of the device and the driver is also done on the I2C bus. The data structure of the I2C bus is i2c_bus_type, which is defined in the drivers/i2c/i2c-core.c file , The content of i2c_bus_type is as follows:

736 struct bus_type i2c_bus_type = {
    
     
737 		.name = "i2c", 
738 		.match = i2c_device_match, 
739 		.probe = i2c_device_probe, 
740 		.remove = i2c_device_remove, 
741 		.shutdown = i2c_device_shutdown, 
742 };

The match member variable is the device and driver matching function on the I2C bus, that is, the function i2c_device_match. The content of this function is as follows:

457 static int i2c_device_match(struct device *dev, struct device_driver *drv)
458 {
    
     
459        struct i2c_client *client = i2c_verify_client(dev); 
460        struct i2c_driver *driver; 
461 
462      if (!client) 
463            return 0; 
464 
465        /* Attempt an OF style match */ 
466        if (of_driver_match_device(dev, drv)) 
467        return 1; 
468 
469        /* Then ACPI style match */ 
470        if (acpi_driver_match_device(dev, drv)) 
471            return 1; 
472 
473        driver = to_i2c_driver(drv); 
474        /* match on an id table if there is one */ 
475        if (driver->id_table) 
476            return i2c_match_id(driver->id_table, client) != NULL; 
477 
478        return 0; 
479 }

In line 466, the of_driver_match_device function is used to complete the device tree device and driver matching. Compare whether the compatible attribute of the I2C device node is equal to the compatible attribute in of_device_id. If they are equivalent, it means that the I2C device and the driver match.
In line 470, the acpi_driver_match_device function is used for ACPI matching.
In line 476, the i2c_match_id function is used in the traditional I2C device and driver matching process without a device tree. Compare the name of the I2C device with the name field of i2c_device_id. If they are equal, it means that the I2C device matches the driver.

Insert picture description here

Guess you like

Origin blog.csdn.net/BeiJingXunWei/article/details/112481632