I2C总线驱动框架详解
i2c的驱动主要分为三个部分:设备驱动层,核心驱动层和总线驱动层
设备驱动层(i2c-dev.c)是用户的接口,主要作用就是定义数据传输的内容,但是不知道传输数据的机制
核心区动层(i2c-core.c)是开发编程的接口,I2C核心提供了I2C总线驱动(适配器)和设备驱动的注册、注销方法,I2C通信方法(”algorithm”)上层的,与具体硬件无关的代码以及探测设备检测设备地址的上层代码等。
总线驱动层(i2c-xxx.c), 他的主要作用就是初始化硬件,同时定义数据传输机制
1、三大组成部分
(1)I2C核心(i2c-core):I2C核心提供了I2C总线驱动(适配器)和设备驱动的注册、注销方法,I2C通信方法(”algorithm”)上层的,与具体硬件无关的代码以及探测设备检测设备地址的上层代码等。。
(2)I2C总线驱动(I2Cadapter):I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力。I2C总线驱动由i2c_adapter和i2c_algorithm来描述I2C适配器是SoC中内置i2c控制器的软件抽象,可以理解为他所代表的是一个I2C主机。
(3)I2C设备驱动(I2Cclient driver):包括两部分:设备的注册和设备驱动的注册
2、I2C子系统的主要目标是:让驱动开发者可以在内核中方便的添加自己的I2C设备的驱动程序,让内核统一管理I2C设备,从而可以更容易的在linux下驱动自己的I2C接口硬件。
=相关结构体===========
struct i2c_adapter是用来描述一个I2C适配器,在SoC中的指的就是内部外设I2C控制器,当向I2C核心层注册一个I2C适配器时就需要提供这样的一个结构体变量。
1 struct i2c_adapter {
2 struct module *owner; // 所有者
3 unsigned int id;
4 unsigned int class; // 该适配器支持的从设备的类型
5 const struct i2c_algorithm *algo; // 该适配器与从设备的通信算法
6 void *algo_data;
7
8 /* data fields that are valid for all devices */
9 struct rt_mutex bus_lock;
10
11 int timeout; // 超时时间
12 int retries;
13 struct device dev; // 该适配器设备对应的device
14
15 int nr; // 适配器的编号
16 char name[48]; // 适配器的名字
17 struct completion dev_released;
18
19 struct list_head userspace_clients; // 用来挂接与适配器匹配成功的从设备i2c_client的一个链表头
20 }
;
struct i2c_algorithm结构体代表的是适配器的通信算法,在构建i2c_adapter结构体变量的时候会去填充这个元素。
1 struct i2c_algorithm {
2 /* If an adapter algorithm can't do I2C-level access, set master_xfer
3 to NULL. If an adapter algorithm can do SMBus access, set
4 smbus_xfer. If set to NULL, the SMBus protocol is simulated
5 using common I2C messages */
6 /* master_xfer should return the number of messages successfully
7 processed, or a negative value on error */
8 int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
9 int num);
10 int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
11 unsigned short flags, char read_write,
12 u8 command, int size, union i2c_smbus_data *data);
13
14 /* To determine what the adapter supports */
15 u32 (*functionality) (struct i2c_adapter *);
16 };
1 struct i2c_client { // 用来描述一个i2c次设备
2 unsigned short flags; // 描述i2c次设备特性的标志位
3 unsigned short addr; // i2c 次设备的地址
4
5 char name[I2C_NAME_SIZE]; // i2c次设备的名字
6 struct i2c_adapter *adapter; // 指向与次设备匹配成功的适配器
7 struct i2c_driver *driver; // 指向与次设备匹配成功的设备驱动
8 struct device dev; // 该次设备对应的device
9 int irq; // 次设备的中断引脚
10 struct list_head detected; // 作为一个链表节点挂接到与他匹配成功的i2c_driver 相应的链表头上
11 };
1 struct i2c_driver { // 代表一个i2c设备驱动
2 unsigned int class; // i2c设备驱动所支持的i2c设备的类型
3
4 /* Notifies the driver that a new bus has appeared or is about to be
5 * removed. You should avoid using this if you can, it will probably
6 * be removed in a near future.
7 */
8 int (*attach_adapter)(struct i2c_adapter *); // 用来匹配适配器的函数 adapter
9 int (*detach_adapter)(struct i2c_adapter *);
10
11 /* Standard driver model interfaces */
12 int (*probe)(struct i2c_client *, const struct i2c_device_id *); // 设备驱动层的probe函数
13 int (*remove)(struct i2c_client *); // 设备驱动层卸载函数
14
15 /* driver model interfaces that don't relate to enumeration */
16 void (*shutdown)(struct i2c_client *);
17 int (*suspend)(struct i2c_client *, pm_message_t mesg);
18 int (*resume)(struct i2c_client *);
19
20 /* Alert callback, for example for the SMBus alert protocol.
21 * The format and meaning of the data value depends on the protocol.
22 * For the SMBus alert protocol, there is a single bit of data passed
23 * as the alert response's low bit ("event flag").
24 */
25 void (*alert)(struct i2c_client *, unsigned int data);
26
27 /* a ioctl like command that can be used to perform specific functions
28 * with the device.
29 */
30 int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
31
32 struct device_driver driver; // 该i2c设备驱动所对应的device_driver
33 const struct i2c_device_id *id_table; // 设备驱动层用来匹配设备的id_table
34
35 /* Device detection callback for automatic device creation */
36 int (*detect)(struct i2c_client *, struct i2c_board_info *);
37 const unsigned short *address_list; // 该设备驱动支持的所有次设备的地址数组
38 struct list_head clients; // 用来挂接与该i2c_driver匹配成功的i2c_client (次设备)的一个链表头
39 };
1 struct i2c_board_info { // 这个结构体是用来描述板子上的一个i2c设备的信息
2 char type[I2C_NAME_SIZE]; // i2c 设备的名字,用来初始化i2c_client.name
3 unsigned short flags; // 用来初始化i2c_client.flags
4 unsigned short addr; // 用来初始化 i2c_client.addr
5 void *platform_data; // 用来初始化 i2c_client.dev.platform_data
6 struct dev_archdata *archdata; // 用来初始化i2c_client.dev.archdata
7 #ifdef CONFIG_OF
8 struct device_node *of_node;
9 #endif
10 int irq; // 用来初始化i2c_client.irq
11 };
12
13
14
15 struct i2c_devinfo {
16 struct list_head list; // 作为一个链表节点挂接到__i2c_board_list 链表上去
17 int busnum; // 适配器的编号
18 struct i2c_board_info board_info; // 内置的i2c_board_info 结构体
19 };
调用框架:
i2c_add_driver()
└── i2c_register_driver
└── driver_register
├── driver_find
│ ├── kset_find_obj
│ ├── kobject_put
│ └── to_driver
└── bus_add_driver
└── driver_attach
└── bus_for_each_dev
├── next_device
└── __driver_attach
└─ driver_match_device
└── i2c_device_match
├── acpi_driver_match_device
├── i2c_match_id
└── of_driver_match_device
└── of_match_device
└── of_match_node
└── __of_match_node
└── __of_device_is_compatible
i2c_add_driver()
└── i2c_register_driver
└── driver_register
├── driver_find
│ ├── kset_find_obj
│ ├── kobject_put
│ └── to_driver
└── bus_add_driver
└── driver_attach
└── bus_for_each_dev
├── next_device
└── __driver_attach
├── driver_match_device
└── driver_probe_device
└── really_probe
└── i2c_device_probe
└── i2c_match_id