linux i2c驱动

1、Linux 的 I2C 体系结构分为 3 个组成部分

( 1) I2C 核心(层)。
I2C 核心提供了 I2C 总线驱动和设备驱动的注册、注销方法, I2C 通信方法(即“ algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。
( 2) I2C 总线驱动(适配器层)。
I2C 总线驱动是对 I2C 硬件体系结构中适配器端的实现,适配器可由 CPU 控制,甚至可以直接集成在 CPU 内部。I2C 总线驱动主要包含了 I2C 适配器数据结构 i2c_adapter、 I2C 适配器的 algorithm 数据结构i2c_algorithm 和控制 I2C 适配器产生通信信号的函数。
经由 I2C 总线驱动的代码,我们可以控制 I2C 适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生 ACK 等。
( 3) I2C 设备驱动(层)。
I2C 设备驱动(也称为客户驱动)是对 I2C 硬件体系结构中设备端的实现,设备一般挂接在受CPU 控制的 I2C 适配器上,通过 I2C 适配器与 CPU 交换数据。I2C 设备驱动主要包含了数据结构 i2c_driver 和 i2c_client,我们需要根据具体设备实现其中的成员函数。
4个重要结构体

i2c_adapter 结构体

1 struct i2c_adapter {
2 struct module *owner;/*所属模块*/
3 unsigned int id; /*algorithm 的类型,定义于 i2c-id.h,以 I2C_ALGO_开始*/
4 unsigned int class;
5 struct i2c_algorithm *algo;/*总线通信方法结构体指针*/
6 void *algo_data;/* algorithm 数据 */
7 int (*client_register)(struct i2c_client *); /*client 注册时调用*/
8 int (*client_unregister)(struct i2c_client *); /*client 注销时调用*/
9 u8 level;
10 struct semaphore bus_lock; /*控制并发访问的自旋锁*/
11 struct semaphore clist_lock;
12 int timeout;
13 int retries; /*重试次数*/
14 struct device dev;/* 适配器设备 */
15 struct class_device class_dev;/* 类设备 */
16 int nr;
17 struct list_head clien; /* client 链表头*/
18 struct list_head list;
19 char name[48]; /*适配器名称*/
20 struct completion dev_released; /*用于同步*/
21};

i2c_algorithm 结构体

1 struct i2c_algorithm {
2 int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,
3 int num); /*i2c 传输函数指针*/
4 int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, /*smbus 传输函数指针*/
5 unsigned short flags, char read_write,
6 u8 command, int size, union i2c_smbus_data * data);
7 u32 (*functionality) (struct i2c_adapter *);/*返回适配器支持的功能*/
8 };
1 struct i2c_driver {
2 int id;
3 unsigned int class;
4 int (*attach_adapter)(struct i2c_adapter *); /*依附 i2c_adapter 函数指针 */
5 int (*detach_adapter)(struct i2c_adapter *); /*脱离 i2c_adapter 函数指针*/
6 int (*detach_client)(struct i2c_client *); /*i2c client 脱离函数指针*/
7 int (*probe)(struct i2c_client *, const struct i2c_device_id *);
8 int (*remove)(struct i2c_client *);
9 void (*shutdown)(struct i2c_client *);
10 int (*suspend)(struct i2c_client *, pm_message_t mesg);
11 int (*resume)(struct i2c_client *);
12 int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
13 struct device_driver driver;
14 const struct i2c_device_id *id_table; /* 该驱动所支持的设备 ID 表 */
15 int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *);
16 const struct i2c_client_address_data *address_data;
17 struct list_head clients;
18 };
1 struct i2c_client {
2 unsigned int flags;/* 标志 */
3 unsigned short addr; /* 低 7 位为芯片地址 */
4 char name[I2C_NAME_SIZE]; /* 设备名称 */
5 struct i2c_adapter *adapter;/*依附的 i2c_adapter*/
6 struct i2c_driver *driver; /*依附的 i2c_driver */
7 struct device dev; /* 设备结构体*/
8 int irq; /* 设备使用的中断号*/
9 struct list_head list; /* 链表头 */
10 struct completion released; /* 用于同步 */
11 };

( 1) i2c_adapter 与 i2c_algorithm

       i2c_adapter 对应于物理上的一个适配器,而 i2c_algorithm 对应一套通信方法。一个 I2C 适配器需要 i2c_algorithm 中提供的通信函数来控制适配器上产生特定的访问周期。缺少 i2c_algorithm的 i2c_adapter 什么也做不了,因此 i2c_adapter 中包含其使用的 i2c_algorithm 的指针。i2c_algorithm 中的关键函数 master_xfer()用于产生 I2C 访问周期需要的信号,以 i2c_msg(即I2C 消息)为单位。 i2c_msg 结构体也非常关键

1 struct i2c_msg {
2 _ _u16 addr;/* 设备地址*/
3 _ _u16 flags;/* 标志 */
4 _ _u16 len;/* 消息长度*/
5 _ _u8 *buf;/* 消息数据*/
6 };

( 2) i2c_driver 与 i2c_client

i2c_driver 对应一套驱动方法,其主要成员函数是 probe()、 remove()、 suspend()、 resume()等,另外 id_table 是该驱动所支持的 I2C 设备的 ID 表。 i2c_client 对应于真实的物理设备,每个 I2C 设备都需要一个 i2c_client 来描述。 i2c_driver 与 i2c_client 的关系是一对多,一个 i2c_driver 上可以支持多个同等类型的 i2c_client。i2c_client 信息通常在 BSP 的板文件中通过 i2c_board_info 填充。
( 3) i2c_adpater 与 i2c_client
i2c_adpater 与 i2c_client 的关系与 I2C 硬件体系中适配器和设备的关系一致,即 i2c_client 依附于 i2c_adpater。由于一个适配器上可以连接多个 I2C 设备,所以一个 i2c_adpater 也可以被多个i2c_client 依附, i2c_adpater 中包括依附于它的 i2c_client 的链表。
一方面,适配器驱动可能是 Linux 内核本身还不包含的;另一方面,挂接在适配器上的具体设备驱动可能也是 Linux 内核还不包含的。因此,工程师要实现的主要工作如下
       提供 I2C 适配器的硬件驱动,探测、初始化 I2C 适配器(如申请 I2C 的 I/O 地址和中断号)、驱动 CPU 控制的 I2C 适配器从硬件上产生各种信号以及处理 I2C 中断等。
       提供 I2C 适配器的 algorithm,用具体适配器的 xxx_xfer()函数填充 i2c_algorithm 的master_xfer 指针,并把 i2c_algorithm 指针赋值给 i2c_adapter 的 algo 指针。
      实现 I2C 设备驱动中的 i2c_driver 接口,用具体设备 yyy 的 yyy_probe()、 yyy_remove()、yyy_suspend()、 yyy_resume()函数指针和 i2c_device_id 设备 ID 表赋值给 i2c_driver 的probe、 remove、 suspend、 resume 和 id_table 指针。
       实现 I2C 设备所对应类型的具体驱动, i2c_driver 只是实现设备与总线的挂接,而挂接在总线上的设备则是千差万别。例如,如果是字符设备,就实现文件操作接口,即实现具体设备 yyy 的 yyy_read()、 yyy_write()和 yyy_ioctl()函数等;如果是声卡,就实现 ALSA驱动。
上述工作中前两个属于 I2C 总线驱动,后两个属于 I2C 设备驱动,做完这些工作,系统会增加两个内核模块。
 

 

 

 

 

 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值