打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux I2C驱动分析与实现(一)

====本文系本站原创,欢迎转载! 转载请注明出处:http://blog.csdn.net/yyplc====

本文基于内核版本linux-2.6.30.4分析.

Linux中i2c子系统框图如下:

·客户驱动

即I2C设备驱动,每个客户驱动可以为一个或多个I2C设备服务,并向用户空间提供相应的访问接口函数。

客户驱动需要向总线注册并通过i2c-core提供的接口与I2C设备通信。与客户程序相关的数据结构主要有struct i2c_driver和struct i2c_client

添加客户驱动:static inline int i2c_add_driver(struct i2c_driver *driver)

删除客户驱动:extern void i2c_del_driver(struct i2c_driver *);   

·I2C-core核心

I2c-core核心是I2C总线的核心,承上启下,其实现与平台无关。I2C总线的初始化、注册和适配器添加和注销等相关工作均在I2C核心代码中完成,

除此之外,还向上层客户驱动提供相应的API接口函数,使得客户驱动独立于适配器驱动而工作。

· 适配器驱动

负责对I2C控制器的驱动实现,一个总线对应一个适配器。I2C总线上对I2C slave设备的具体

操作是在适配器驱动中完成的。适配器驱动作为platform_driver而注册,在probe()到驱动设

备后,向总线声明并被添加:i2c_add_numbered_adapter(&i2c->adap);

I2c-dev驱动是系统自带的一个通用客户驱动,它不是针对某一个I2C设备(即没有自己驱动设备id-table),它可以使得用户空间的程序通过i2c-tools访问总线上的i2c/SMBUS设备。

I2C子系统主要数据结构

  1. ·struct i2c_msg;             //I2C消息数据结构  
  2.   
  3. ·struct i2c_algorithm;       //算法驱动数据结构  
  4.   
  5. ·struct i2c_adapter;         //I2C适配器数据结构  
  6.   
  7. ·struct i2c_client;          //I2C客户数据结构  
  8.   
  9. ·struct i2c_driver;          //I2C设备驱动数据结构  
  10.   
  11. ·struct i2c_board_info;      //描述板载I2C设备的信息    
  12.    

以上数据结构在include/linux/i2c.h中定义,下面我们结合源码分析一下这些数据结构

I2C算法结构:

  1. struct i2c_algorithm {  
  2.   
  3.    /* If an adapter algorithm can't do I2C-level access, set master_xfer 
  4.  
  5.       to NULL. If an adapter algorithm can do SMBus access, set 
  6.  
  7.       smbus_xfer. If set to NULL, the SMBus protocol is simulated 
  8.  
  9.       using common I2C messages */  
  10.   
  11.    /* master_xfer should return the number of messages successfully 
  12.  
  13.       processed, or a negative value on error */  
  14.   
  15.    int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,  
  16.   
  17.             int num);  
  18.   
  19.    int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,  
  20.   
  21.             unsigned short flags, char read_write,  
  22.   
  23.             u8 command, int size, union i2c_smbus_data *data);  
  24.   
  25.    
  26.   
  27.    /* To determine what the adapter supports */  
  28.   
  29.    u32 (*functionality) (struct i2c_adapter *);  
  30.   
  31. };  

例如:

s3c2440 i2c 适配器驱动是这样实现这个算法结构体:

  1. static const struct i2c_algorithm s3c24xx_i2c_algorithm = {  
  2.   
  3.      .master_xfer            = s3c24xx_i2c_xfer,  
  4.   
  5.      .functionality          = s3c24xx_i2c_func,  
  6.   
  7. };  

s3c24xx_i2c_xfer 是适配器的对I2C设备的读写操作函数

s3c24xx_i2c_func函数决定了该适配器向i2c-core核心支持哪些API函数

I2c_adapter结构标识一个物理I2C总线(适配器),总线通过

算法结构访问到适配器。

  1. struct i2c_adapter {  
  2.   
  3.     struct module *owner;  
  4.   
  5.     unsigned int id;  
  6.   
  7.     unsigned int class;             /* classes to allow probing for */  
  8.   
  9.     const struct i2c_algorithm *algo; /* the algorithm to access the bus */  
  10.   
  11.     void *algo_data;  
  12.   
  13.    
  14.   
  15.     /* --- administration stuff. */  
  16.   
  17.     int (*client_register)(struct i2c_client *) __deprecated;  
  18.   
  19.     int (*client_unregister)(struct i2c_client *) __deprecated;  
  20.   
  21.    
  22.   
  23.     /* data fields that are valid for all devices  */  
  24.   
  25.     u8 level;                /* nesting level for lockdep */  
  26.   
  27.     struct mutex bus_lock;  
  28.   
  29.     struct mutex clist_lock;  
  30.   
  31.    
  32.   
  33.     int timeout;            /* in jiffies */  
  34.   
  35.     int retries;  
  36.   
  37.     struct device dev;      /* the adapter device */  
  38.   
  39.    
  40.   
  41.     int nr;  
  42.   
  43.     struct list_head clients;     /* DEPRECATED */  
  44.   
  45.     char name[48];  
  46.   
  47.     struct completion dev_released;  
  48.   
  49. };  

I2c_msg是I2C消息,I2C通信是以i2c_msg为单位的。

  1. struct i2c_msg {  
  2.   
  3.    __u16 addr;     /* slave address            */  
  4.   
  5.    __u16 flags;  
  6.   
  7. #define I2C_M_TEN      0x0010   /* this is a ten bit chip address */  
  8.   
  9. #define I2C_M_RD       0x0001   /* read data, from slave to master */  
  10.   
  11. #define I2C_M_NOSTART       0x4000   /* if I2C_FUNC_PROTOCOL_MANGLING */  
  12.   
  13. #define I2C_M_REV_DIR_ADDR  0x2000   /* if I2C_FUNC_PROTOCOL_MANGLING */  
  14.   
  15. #define I2C_M_IGNORE_NAK    0x1000   /* if I2C_FUNC_PROTOCOL_MANGLING */  
  16.   
  17. #define I2C_M_NO_RD_ACK 0x0800   /* if I2C_FUNC_PROTOCOL_MANGLING */  
  18.   
  19. #define I2C_M_RECV_LEN 0x0400   /* length will be first received byte */  
  20.   
  21.    __u16 len;      /* msg length               */  
  22.   
  23.    __u8 *buf;      /* pointer to msg data           */  
  24.   
  25. };  

I2c_client描述了一个i2c设备。

  1. struct i2c_client {  
  2.   
  3.      unsigned short flags;        /* div., see below         */  
  4.   
  5.      unsigned short addr;        /* chip address - NOTE: 7bit */  
  6.   
  7.                             /* addresses are stored in the      */  
  8.   
  9.                             /* _LOWER_ 7 bits        */  
  10.   
  11.      char name[I2C_NAME_SIZE];  
  12.   
  13.      struct i2c_adapter *adapter;    /* the adapter we sit on       */  
  14.   
  15.      struct i2c_driver *driver;  /* and our access routines    */  
  16.   
  17.      struct device dev;            /* the device structure          */  
  18.   
  19.      int irq;                     /* irq issued by device          */  
  20.   
  21.      struct list_head list;          /* DEPRECATED */  
  22.   
  23.      struct list_head detected;  
  24.   
  25.      struct completion released;  
  26.   
  27. };  

I2c_driver描述了I2C设备的驱动。

  1. struct i2c_driver {  
  2.   
  3.       int id;  
  4.   
  5.       unsigned int class;  
  6.   
  7.    
  8.   
  9.       /* Notifies the driver that a new bus has appeared. This routine 
  10.  
  11.        * can be used by the driver to test if the bus meets its conditions 
  12.  
  13.        * & seek for the presence of the chip(s) it supports. If found, it 
  14.  
  15.        * registers the client(s) that are on the bus to the i2c admin. via 
  16.  
  17.        * i2c_attach_client.  (LEGACY I2C DRIVERS ONLY) 
  18.  
  19.        */  
  20.   
  21.       int (*attach_adapter)(struct i2c_adapter *);  
  22.   
  23.       int (*detach_adapter)(struct i2c_adapter *);  
  24.   
  25.    
  26.   
  27.       /* tells the driver that a client is about to be deleted & gives it 
  28.  
  29.        * the chance to remove its private data. Also, if the client struct 
  30.  
  31.        * has been dynamically allocated by the driver in the function above, 
  32.  
  33.        * it must be freed here.  (LEGACY I2C DRIVERS ONLY) 
  34.  
  35.        */  
  36.   
  37.       int (*detach_client)(struct i2c_client *) __deprecated;  
  38.   
  39.       。。。  
  40.   
  41. }  

I2C核心提供的API函数

  1. ·      extern int i2c_master_send(struct i2c_client *client, const char *buf,  
  2.   
  3. ·                    int count);  
  4.   
  5. ·      extern int i2c_master_recv(struct i2c_client *client, char *buf, int count);  
  6.   
  7.    
  8.   
  9. <span style="color:#ff6666;">·      extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,  
  10.   
  11. ·                 int num);  
  12. </span>  
  13. ·      extern s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,  
  14.   
  15. ·                   unsigned short flags, char read_write, u8 command,  
  16.   
  17. ·                   int size, union i2c_smbus_data *data);  
  18.   
  19. ·      extern s32 i2c_smbus_read_byte(struct i2c_client *client);  
  20.   
  21. ·      extern s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);  
  22.   
  23. ·      extern s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command);  
  24.   
  25. ·      extern s32 i2c_smbus_write_byte_data(struct i2c_client *client,  
  26.   
  27. ·                           u8 command, u8 value);  
  28.   
  29. ·      extern s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command);  
  30.   
  31. ·      extern s32 i2c_smbus_write_word_data(struct i2c_client *client,  
  32.   
  33. ·                           u8 command, u16 value);  

其中: i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 是实现其他函数的基础,换句话说,其它函数均是通过调用该函数来实现的。

下篇将具体谈谈Linux 中如何实现I2C客户程序。《Linux I2C驱动分析与实现(二)》

 

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
I2C
I2C驱动架构
I2C 总线(适配器) ,核心, 设备驱动
linux内核I2C体系结构(注意结构体原型)
LINUX的IIC驱动从这开始(二)
Linux I2C设备驱动编写(二)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服