OMAP3630 Linux I2C总线驱动分析

1 Linux I2C驱动架构
Linux下I2C驱动的架构图如下:


 OMAP3630 Linux I2C总线驱动分析
图1.1 Linux下I2C驱动架构


    如上图所示,每条I2C总线会对应一个adapter,而每条I2C总线上则可以有多个 client,在linux kernel中,通过I2C core层将I2C client与I2C adapter关联起来,Linux 中I2C驱动代码位于drivers/i2c目录。
    Linux中I2C可以分为三个层次,分别为I2C core层、I2C adapter driver层、I2C device driver层。

1.1 I2C core层
    I2C core是用于维护Linux的I2C核心部分,提供了核心的数据结构,I2C适配器驱动和设备驱动的注册、注销管理等API,同时还提供了I2C总线读写访问的一般接口(具体的实现在与I2C控制器相关的I2C adapter中实现)。
    该层为硬件平台无关层,向下屏蔽了物理总线适配器的差异,定义了统一的访问策略和接口;向上则提供了统一的接口,以便I2C设备驱动可以通过总线适配器进行数据收发。
    Linux中,I2C core层的代码位于driver/i2c/ i2c-core.c。由于该层是平台无关层,本文将不再叙述,有兴趣可以查阅相关资料。

 

1.2 I2C adapter driver层
    I2C adapter driver层即I2C适配器驱动层,每种处理器平台都有自己的适配器驱动,属于平台移植相关层。它的职责是为系统中每条I2C总线实现相应的读写方法。但是适配器驱动本身并不会进行任何的通讯,而是等待设备驱动调用其函数。
    在系统开机时,I2C适配器驱动被首先装载。一个适配器驱动用于支持一条特定的I2C总线的读写。一个适配器驱动通常需要两个模块,一个struct i2c_adapter和一个struct i2c_algorithm来描述。
    i2c adapter 构造一个对I2C core层接口的数据结构,并通过相应的接口函数向I2C core注册一个适配器。i2c_algorithm主要实现对I2C总线访问的算法,master_xfer和smbus_xfer即I2C adapter底层对I2C总线读写方法的实现,相关的数据结构如下:

  1. /*  
  2.  * The following structs are for those who like to implement new bus drivers:  
  3.  * i2c_algorithm is the interface to a class of hardware solutions which can  
  4.  * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584  
  5.  * to name two of the most common.  
  6.  */  
  7. struct i2c_algorithm {   
  8.     /* If an adapter algorithm can't do I2C-level access, set master_xfer  
  9.        to NULL. If an adapter algorithm can do SMBus access, set  
  10.        smbus_xfer. If set to NULL, the SMBus protocol is simulated  
  11.        using common I2C messages */  
  12.     /* master_xfer should return the number of messages successfully  
  13.        processed, or a negative value on error */  
  14.     int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,   
  15.                int num);   
  16.     int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,   
  17.                unsigned short flags, char read_write,   
  18.                u8 command, int size, union i2c_smbus_data *data);   
  19.     /* To determine what the adapter supports */  
  20.     u32 (*functionality) (struct i2c_adapter *);   
  21. };  

    主要就是master_xfer方法,其和具体的总线控制器相关,不同的CPU在实现上会有差异。

  1. /*  
  2.  * i2c_adapter is the structure used to identify a physical i2c bus along  
  3.  * with the access algorithms necessary to access it.  
  4.  */  
  5. struct i2c_adapter {   
  6.     struct module *owner;   
  7.     unsigned int id;   
  8.     unsigned int class;       /* classes to allow probing for */  
  9.     const struct i2c_algorithm *algo; /* the algorithm to access the bus */  
  10.     void *algo_data;   
  11.     /* data fields that are valid for all devices   */  
  12.     struct rt_mutex bus_lock;   
  13.     int timeout;            /* in jiffies */  
  14.     int retries;   
  15.     struct device dev;      /* the adapter device */  
  16.     int nr;   
  17.     char name[48];   
  18.     struct completion dev_released;   
  19.     struct list_head userspace_clients;   
  20. };  

    Algo是和底层硬件的接口,标识了具体的物理总线传输的实现。
    Userspace_clients为使用该总线的client链表。
    Nr为该适配器也就是某条I2C总线占据的全局编号。
    bus_lock总线的互斥锁,防止总线冲突。
    Linux中,I2C adapter driver层的代码位于drivers/i2c/busses目录,第3章会详细介绍该层的内容。

相关推荐