1.Linux的I2C分3个组成部分:
① i2c 核心: 提供 I2C 总线驱动和设备驱动的注册、注销方法, I2C 通信方法,上层的与具体适配器无关的代码以及探测设备、检测设备地址的层代码。
② i2c总线驱动 : 是对 CPU 内部 I2C 控制器的驱动实现,包含 I2C 适配器数据结构, i2c_adapter,i2c_algorithm 和控制 I2C 适配器产生通信信号的函数,可以设置 I2C 适配器的开始位、停止位,产生 ACK 等。
③ i2c 设备驱动: 对 I2C 设备器件的驱动,包含数据结构 i2c_driver 和 i2c_client, 我们需要根据具体的设备实现其中的成员函数(实际驱动开发需要做的)。
2.I2C驱动代码
Linux2.6中所有i2c设备都在sysfs中显示,存于/sys/bus/i2c目录,以适配器地址和芯片地址的形式列出,tree /sys/bus/i2c/
在内核源码树下,drivers/i2c/目录下,有如下文件:
i2c-core.c--实现i2c核心功能以及/proc/bus/i2c*接口
i2c-dev.c--实现适配器功能,每个i2c适配器都被分配一个设备,通过适配器访问设备时主设备号都为89,此设备号0-255.
i2c-dev.c并没有针对特定的设备而设计,只是提供通用的read(),write(),ioctl()等接口,应用层可借用这些接口访问挂接在适配器上的i2c设备的存储空间和寄存器,并控制i2c设备的工作方式。
chips文件夹---包含特定的i2c芯片驱动
Busses文件夹----包含I2C总线驱动,比如2410的i2c-s3c2410.c
Algos文件夹-- 实现一些i2c总线适配器的algorithm.
3.I2C驱动中重要的数据结构: i2c_adapter 、 i2c_algorithm 、 i2c_client 、 i2c_driver,其关系是
① i2c_adapter 与 i2c_algorithm
i2c_adapter 对应于物理上的一个 适配器 , i2c_algorithm 对应一套 通信方法 。一个适配器需要i2c_algorithm提供的通信函数来控制适配器上产生特定的访问周期,缺少i2c_algorithm,i2c_adapter啥也做不了,i2c_algorithm中包含一个指向i2c_adapter的指针。
i2c_algorithm中的关键函数是 master_xfer ,用于产生i2c访问周期需要的 信号 ,以 i2c_msg 为单位.
② i2c_driver 和 i2c_client
i2c_driver 对应一套 驱动方法 ,纯粹用于辅助作用的数据结构,不对应任何物理实体, i2c_client 对应于真实的 物理设备 (外设), 每个i2c设备都用一个i2c_client描述 ,一般被包含在具体字符设备的私有信息结构体中。
i2c_driver和i2c_client发生关联的时刻是i2c_driver的attach_adapter()函数被运行时。attach_adapter会探测物理设备,当确定一个client存在时,把该client的数据结构的adapter指针指向对应的i2c_adapter,driver指针指向该i2c_driver,并会调用i2c_adapter的client_register()函数,相反过程发生在i2c_driver的detach_client函数被调用时。
③ i2c_adpater 与 i2c_client
i2c_adpater与i2c_client的关系与i2c硬件体系中的适配器与设备的关系一致,即 i2c_client依赖于i2c_adpater , 一个适配器上可连接多个I2C设备 ,所以i2c_adpater中包括依赖于它的i2c_client的链表。
4.I2C接口函数
Linux I2C核心(drivers/i2c/i2c-core.c)提供了一组不依赖于硬件平台的
① 增加/删除i2c_adapter
- int i2c_add_adapter(struct i2c_adapter *adap);
- int i2c_del_adapter(struct i2c_adapter *adap);
② 增加/删除i2c_driver
- nt i2c_register_driver(struct module *owner, struct i2c_driver *driver)
- static inline int i2c_add_driver(struct i2c_driver *driver)
- int i2c_del_driver(struct i2c_driver *driver)
③ i2c_client依附/脱离
- int i2c_attach_client(struct i2c_client *client)
- int i2c_detach_client(struct i2c_client *client)
在i2c_attach_client函数里,当一个具体的client被侦测到并被关联的时候,设备和syffs文件将被注册,相反的在client被取消关联时,sysfs文件和设备也被注销
④ i2c传输、发送和接收
- int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
- int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
- int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
i2c_transfer函数用于进行I2C适配器和I2C设备之间的一组消息交互,i2c_transfer本身不具备驱动适配器物理硬件完成消息交互的能力,他调用i2c_adapter对于的i2c_algorithm,并使用i2c_algorithm的master_xfer()函数真正驱动硬件流程。
⑤ i2c控制命令分配
- int i2c_control(struct i2c_client *client,unsigned int cmd, unsigned long arg)
- void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
将发给I2C适配器设备文件ioctl的命令分配给对应适配器的algorithm的algo_control()函数活i2c_driver()的command()函数