资讯详情

linux GPIO-i2c驱动

  1. 转载链接地址:http://blog.chinaunix.net/uid-27717694-id-3519302.html
  2. 一、I2C概述
  3. Linux的I2C系统结构分为三部分:
  4. 1.I2C核心
  5. I2C 核心提供了I2C注册注销总线驱动和设备驱动的方法,I2C通信方法(即通信方法(即通信方法(即)(即通信方法(即通信方法(即通信方法(即)(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(通信方法通信方法(即通信方法(即通信方法(即通信方法(即通信方法)(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法)(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法)(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法法(即通信方法)(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法)(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法))(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法)(即通信方法(即通信方法(即通信方法(即通信方法)即通信方法))))通信方法(即通信方法(即通信方法(即通信方法方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法(即通信方法)algorithm)与具体适配器无关的上层代码,以及检测设备、检测设备地址的上层代码等。
  6. 2.I2C总线驱动
  7. I2C总线驱动是对的I2C适配器端在硬件系统结构中的实现可以通过CPU控制,甚至直接集成CPU内部。
  8. I2C主要包括总线驱动I2C适配器数据结构i2c_adapter、I2C适配器的algorithm数据结构i2c_algorithm和控制I2C适配器产生通信信号函数。
  9. 经由I2C我们可以控制总线驱动的代码I2C适配器以主控方式产生开始位、停止位、读写周期,以及设备方式的读写ACK等。
  10. 3.I2C设备驱动
  11. I2C设备驱动是正确的I2C设备端在硬件系统结构中的实现,设备一般挂在接收处CPU控制的I2C在适配器上,通过I2C适配器与CPU交换数据。
  12. I2C设备驱动主要包括数据结构i2c_driver和i2c_client,成员函数需要根据具体设备实现。
  13. 二、以下介绍i2c定义核心数据结构及其连接关系。
  14. 1.一个i2c由设备驱动i2c_driver数据结构描述,i2c_driver代表I2C从设备驱动,定义于include/linux/i2c.h:
  15. struct i2c_driver{
  16. unsignedintclass;
  17. / * 这两个接口已经被probe和remove取代  * / 
  18.     int (*attach_adapter)(struct i2c_adapter *);//attach_adapter回调函数在安装i2c设备驱动程序模块时、或者在安装i2c适配器驱动程序模块时被调用,
  19.                                                                                             //用于检测、认领设备并为设备分配i2c_client数据结构。
  20.     int (*detach_adapter)(struct i2c_adapter *);//detach_client方法在卸载适配器或设备驱动程序模块时被调用,用于从总线上注销设备、并释放i2c_client及相应的私有数据结构。
  21.     
  22.     int (*probe)(struct i2c_client *, const struct i2c_device_id *);
  23.     int (*remove)(struct i2c_client *);
  24.     
  25.     void (*shutdown)(struct i2c_client *);
  26.     int (*suspend)(struct i2c_client *, pm_message_t mesg);
  27.     int (*resume)(struct i2c_client *);
  28.     void (*alert)(struct i2c_client *, unsigned int data);
  29.     int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
  30.     struct device_driver driver;/*设备驱动结构体*/
  31.     const struct i2c_device_id *id_table;//该驱动所支持的设备ID表
  32.     int (*detect)(struct i2c_client *, struct i2c_board_info *);
  33.     const unsigned short *address_list;
  34.     struct list_head clients;
  35. };
  36. 2. 一个i2c适配器由i2c_adapter数据结构描述
  37. /*
  38. i2c adapter是软件上抽象出来的i2c总线控制器接口
  39. 物理上一条i2c总线可以挂接多个硬件设备(slave),一个CPU可以挂接多条i2c总线(想象一下PCI总线)
  40. i2c总线控制器就是CPU访问I2C总线的硬件接口,也就是你说的那几个寄存器 .
  41. 简单点了, 你的开发板上有几个I2C接口,就有几个adapter , 也就是有几条I2C bus , I2C CLIENT 对应的就是你的外围I2C 设备,
  42. 有几个就有几个CLIENT , 把这些设备插入开发板, 对应其中的一条BUS, 那么相应的就对应了其中的一个ADAPTER , 
  43. 接下来的就是 CLIENT 与 ADAPTER 勾搭成对了, 后面就是做该做的事了.
  44. */
  45. struct i2c_adapter {
  46.     struct module *owner;/*所属模块*/
  47.     unsigned int id; /*algorithm的类型,定义于i2c-id.h,以I2C_ALGO_开始*/
  48.     unsigned int class;
  49.     struct i2c_algorithm *algo;/*总线通信方法结构体指针,一个i2c适配器上的i2c总线通信方法由其驱动程序提供的i2c_algorithm数据结构描述,由algo指针指向 */
  50.     void *algo_data; /* algorithm数据 */
  51.     int (*client_register)(struct i2c_client *); /*client注册时调用*/
  52.     int (*client_unregister)(struct i2c_client *); /*client注销时调用*/
  53.     struct semaphore bus_lock; /*控制并发访问的自旋*/
  54.     struct semaphore clist_lock;
  55.     int timeout;
  56.     int retries; /*重试次数*/
  57.     struct device dev; /* 适配器设备 */
  58.     struct class_device class_dev; /* 类设备 */
  59.     int nr;
  60.     struct list_head clients; /* client链表头,总线上每个设备的 i2c_client数据结构挂载在这里*/
  61.     struct list_head list;
  62.     char name[I2C_NAME_SIZE]; /*适配器名称*/
  63.     struct completion dev_released; /*用于同步*/
  64.     struct completion class_dev_released;
  65. };
  66. 3.具体i2c适配器的通信方法由i2c_algorithm数据结构进行描述:
  67. struct i2c_algorithm {
  68.     int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);//I2C传输函数指针
  69.     int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write,u8 command, int size, union i2c_smbus_data *data);//SMbus传输函数指针
  70.     u32 (*functionality) (struct i2c_adapter *);//返回适配器支持的功能
  71. };
  72. 4.一个i2c设备由i2c_client数据结构进行描述:
  73. struct i2c_client {
  74.     unsigned int flags; /* 标志 */
  75.     /*需要说明的是,i2c设备的7位地址是就当前i2c总线而言的,是“相对地址”。不同的i2c总线上的设备
  76.     可以使用相同的7位地址,但是它们所在的i2c总线不同。所以在系统中一个i2c设备的“绝对地址”由二
  77.     元组(i2c适配器的ID和设备在该总线上的7位地址)表示。
  78.     */
  79.     unsigned short addr; /* 低7位为芯片地址 */
  80.     struct i2c_adapter *adapter; /*依附的i2c_adapter*/
  81.     struct i2c_driver *driver; /*依附的i2c_driver */
  82.     int usage_count; /* 访问计数 */
  83.     struct device dev; /* 设备结构体 */
  84.     struct list_head list; /* 链表头 */ 
  85.     char name[I2C_NAME_SIZE]; /* 设备名称 */
  86.     struct completion released; /* 用于同步 */
  87. };
  88. 5.下面分析一下i2c_driver、i2c_client、i2c_adapter和i2c_algorithm这4个数据结构的作用及其盘根错节的关系。
  89. 5.1 i2c_adapter与i2c_algorithm
  90. i2c_adapter 对应于物理上的一个适配器,而i2c_algorithm对应一套通信方法。一个I2C适配器需要i2c_algorithm中提供的通信函数来控制适配器上产生特定的访问周期。缺少i2c_algorithm的i2c_adapter什么也做不了,因此i2c_adapter中包含其使用的 i2c_algorithm的指针。
  91. i2c_algorithm中的关键函数master_xfer()用于产生I2C访问周期需要的信号,以i2c_msg(即I2C消息)为单位。i2c_msg结构体也非常关键。
  92. //i2c_msg结构体:
  93. struct i2c_msg {
  94.     __u16 addr; /* 设备地址*/
  95.     __u16 flags; /* 标志 */ 
  96.     __u16 len; /* 消息长度*/
  97.     __u8 *buf; /* 消息数据*/
  98. };
  99. 5.2 i2c_driver与i2c_client
  100. i2c_driver对应一套驱动方法,是纯粹的用于辅助作用的数据结构,它不对应于任何的物理实体。i2c_client对应于真实的物理设备,每个I2C设备都需要一个i2c_client来描述。i2c_client一般被包含在i2c字符设备的私有信息结构体中。
  101. i2c_driver 与i2c_client发生关联的时刻在i2c_driver的attach_adapter()函数被运行时。attach_adapter()会探测物理设备,当确定一个client存在时,把该client使用的i2c_client数据结构的adapter指针指向对应的i2c_adapter, driver指针指向该i2c_driver,并会调用i2c_adapter的client_register()函数。相反的过程发生在 i2c_driver 的detach_client()函数被调用的时候。
  102. 5.3 i2c_adpater与i2c_client
  103. i2c_adpater 与i2c_client的关系与I2C硬件体系中适配器和设备的关系一致,即i2c_client依附于i2c_adpater。由于一个适配器上可以连 接多个I2C设备,所以一个i2c_adpater也可以被多个i2c_client依附,i2c_adpater中包括依附于它的i2c_client 的链表。
  104. 三、I2C驱动的实现工作
  105. 一方面,适配器驱动可能是Linux内核本身还不包含的。另一方面,挂接在适配器上的具体设备驱动可能也是Linux不存在的。即便上述设备驱动都存在于Linux内核中,其基于的平台也可能与我们的电路板不一样。因此,工程师要实现的主要工作将包括:
  106. 6.1 提供I2C适配器的硬件驱动,探测、初始化I2C适配器(如申请I2C的I/O地址和中断号)、驱动CPU控制的I2C适配器从硬件上产生各种信号以及处理I2C中断等。
  107. 6.2 提供I2C适配器的algorithm,用具体适配器的xxx_xfer()函数填充i2c_algorithm的master_xfer指针,并把i2c_algorithm指针赋值给i2c_adapter的algo指针。
  108. 6.3 实现I2C设备驱动与i2c_driver接口,用具体设备yyy的yyy_attach_adapter()函数指针、 yyy_detach_client()函数指针和yyy_command()函数指针的赋值给i2c_driver的attach_adapter、 detach_adapter和detach_client指针。
  109. 6.4 实现I2C设备驱动的文件操作接口,即实现具体设备yyy的yyy_read()、yyy_write()和yyy_ioctl()函数等。
  110. 四、核心层提供的接口函数
  111. 1、增加/删除I2C适配器
  112. int i2c_add_adapter(struct i2c_adapter *adapter) 
  113. int i2c_del_adapter(struct i2c_adapter *adap) 
  114. 2、增加/删除I2C从设备驱动
  115. int i2c_register_driver(struct module *owner, structi2c_driver *driver) 
  116. static inline int i2c_add_driver(struct i2c_driver *driver) 
  117. void i2c_del_driver(struct i2c_driver *driver) 
  118. //i2c_add_driver是对i2c_register_driver简单的封装
  119. 3、i2c传输,发送和接收
  120. int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg*msgs, int num) 
  121. int i2c_master_send(const struct i2c_client *client, constchar *buf, int count) 
  122. int i2c_master_recv(const struct i2c_client *client, char*buf, int count) 
  123. //i2c_master_send和i2c_master_recv是i2c_transfer的封装
  124. //3.1.0的内核中已经没有i2c_attach_client和i2c_detach_client接口
  125. 4、I2C总线通信方法
  126. 我们需要为特定的I2C适配器实现其通信方法,主要实现i2c_algorithm结构体中的两个函数:
  127. struct i2c_algorithm  标签: rt5067aic集成电路

    锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台