慢行者
分类: linux
2013-05-10 20:11:40
一、i2c体系结构
linux的i2c体系结构分为3个组成部分:i2c核心、i2c总线驱动、i2c设备驱动,如下图所示。i2c核心提供总线驱动和设备驱动的注册、注销方法,algorithm;i2c总线驱动对硬件体系结构中适配器的实现,主要包括适配器i2c_adapter、适配器通信算法i2c_algorithm,如果cpu集成了i2c控制器并且linux内核支持这个cpu,那么总线驱动就不用管,比如s3c2440就属于这类情况,在后文中我们将分析它的总线驱动;i2c设备驱动是具体的一个设备(如at24c02),挂接在cpu控制的i2c适配器的设备驱动,有了这部分驱动才能使用控制器操作该设备,设备驱动主要包括i2c_driver 和i2c_client数据结构。
在linux-2.6.32.2的include/linux/i2c.h中定义了i2c_adapter、i2c_algorithm、i2c_driver、i2c_client数据结构如下所示,这4个结构体相互之间的关系。
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结构体也非常关键。
struct i2c_msg {
__u16 addr; /* slave address */
__u16 flags;
#define i2c_m_ten 0x0010 /* this is a ten bit chip address */
#define i2c_m_rd 0x0001 /* read data, from slave to master */
#define i2c_m_nostart 0x4000 /* if i2c_func_protocol_mangling */
#define i2c_m_rev_dir_addr 0x2000 /* if i2c_func_protocol_mangling */
#define i2c_m_ignore_nak 0x1000 /* if i2c_func_protocol_mangling */
#define i2c_m_no_rd_ack 0x0800 /* if i2c_func_protocol_mangling */
#define i2c_m_recv_len 0x0400 /* length will be first received byte */
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */
};
2、i2c_driver 与i2c_client,i2c_driver 对应一套驱动方法,是纯粹的用于辅助作用的数据结构,它不对应于任何的物理实体。i2c_client对应于真实的物理设备,每个i2c设备都需要一个i2c_client来描述。i2c_client一般被包含在i2c字符设备的私有信息结构体中。
3、i2c_adpater 与i2c_client,i2c_adpater 与i2c_client 的关系与i2c 硬件体系中适配器和设备的关系一致,即i2c_client 依附于i2c_adpater。
二、i2c核心
i2c核心是总线驱动和设备驱动的纽带,源码位于drivers/i2c/i2c-core.c,它并不依赖于硬件平台的接口函数,i2c核心中一些重要函数如下:
增加/删除i2c_adapter
int i2c_add_adapter(struct i2c_adapter *adapter)
int i2c_del_adapter(struct i2c_adapter *adapter)
增加/删除i2c_driver
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
int i2c_add_driver(struct i2c_driver *driver) //调用i2c_register_driver
void i2c_del_driver(struct i2c_driver *driver)
增加/删除i2c_client
struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
void i2c_unregister_device(struct i2c_client *client)
注:在2.6.30版本之前使用的是i2c_attach_client()和i2c_detach_client()函数。之后attach被merge到了i2c_new_device中,而detach直接被unresister取代。实际上这两个函数内部都是调用了device_register()和device_unregister()
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_master_send()函数和i2c_master_recv()函数内部会调用i2c_transfer()函数分别完成一条写消息和一条读消息,i2c_transfer()本身不能喝硬件完成消息交互,它寻找i2c_adapter对应的i2c_algorithm,要实现数据传送就要实现i2c_algorithm的master_xfer(),在总线驱动中就是重点。