Linux IIC驱动

Linux IIC驱动

层次关系

这里写图片描述

  • I2C core:对I2C总线、I2C adapter及I2C driver管理
  • I2C adapter :针对不同类型的I2C控制器,实现对总线访问的具体方法
  • I2C driver:针对特定I2C设备的具体操作,read、write、ioctl……

这里写图片描述

core 简化对设备编程,不用考虑硬件的接口,提高驱动的移植性。I2C的core层的代码,就是一堆的标准的API,驱动可以调用,具体的硬件的操作,是由特定的硬件相关的代码实现。

关键结构体
  • i2c_driver

    struct i2c_driver {
    unsigned int class;//用探测的一种类型的I2C设备
    int (*attach_adapter)(struct i2c_adapter *) __deprecated; //关联适配器不推荐使用
    int (*detach_adapter)(struct i2c_adapter *) __deprecated;//分离适配器不推荐使用
    
    /* Standard driver model interfaces */
    int (*probe)(struct i2c_client *, const struct i2c_device_id *);
    int (*remove)(struct i2c_client *);
    
    /* driver model interfaces that don't relate to enumeration  */
    void (*shutdown)(struct i2c_client *);//关机
    int (*suspend)(struct i2c_client *, pm_message_t mesg);//暂停
    int (*resume)(struct i2c_client *);//恢复
    void (*alert)(struct i2c_client *, unsigned int data);//警报回调
    int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);//总线信号。
    struct device_driver driver;//设备驱动模型的驱动
    const struct i2c_device_id *id_table;//I2C设备支持的驱动程序列表
    /* Device detection callback for automatic device creation */
    int (*detect)(struct i2c_client *, struct i2c_board_info *);//设备检测的回调
    const unsigned short *address_list;//I2C地址探测(检测)
    struct list_head clients;//我们创建的clients的探测列表(I2C核心使用的)
    };

    i2c_driver 对应一套驱动方法,其主要成员函数是 probe()、remove()、 suspend()、resume()等,另外id_table是该驱动所支持的I2C设备的ID表。i2c_driver 与 i2c_client 的关系是一对多,一个 i2c_driver 上可以支持多个同等类型的 i2c_client。

  • i2c_client

    struct i2c_client {
    unsigned short flags; /* 标志 */ 
    unsigned short addr; /* 低 7 位的芯片地址 */ 
    char name[I2C_NAME_SIZE];  /* 设备名称 */ 
    struct i2c_adapter *adapter; /* 依附的 i2c_adapter */ 
    struct i2c_driver *driver; /* 依附的 i2c_driver */ 
    struct device dev;  
    int irq;  /* 设备使用的中断号 */ 
    struct list_head detected;
    };

    i2c_client 对应于真实的物理设备,每个 I2C 设备都需要一个 i2c_client 来描述

  • i2c_adapter

    struct i2c_adapter {
    struct module *owner; /* 所属模块 */ 
    unsigned int id; /* algorithm 的类型,定义于 i2c-id.h,以 I2C_ALGO_开始 */ 
    unsigned int class;
    const struct i2c_algorithm *algo; /* 总线通信方法结构体指针 */
    void *algo_data;  /* algorithm 数据 */ 
    struct rt_mutex bus_lock;
    int timeout;  /* 超时时间,以 jiffies 为单位 */ 
    int retries;  /* 重试次数 */ 
    struct device dev;  /* 控制器设备 */ 
    int nr;
    char name[48]; /* 控制器名称 */ 
    struct completion dev_released; /* 用于同步 */ 
    struct mutex userspace_clients_lock;
    struct list_head userspace_clients;
    };

    i2c_adapter 对应于物理上的一个控制器。一个 I2C 控制器需要 i2c_algorithm 中提供的通信函数来控制控制器上产生特定的访问周期。

  • i2c_algorithm

    struct i2c_algorithm {
    /* I2C 传输函数指针 */
    int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
    /* smbus 传输函数指针 */
    int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write,  u8 command, int size, union i2c_smbus_data *data); 
    /* 返回控制器支持的功能 */
    u32 (*functionality) (struct i2c_adapter *);
    };

    一个 I2C 控制器需要 i2c_algorithm 中提供的通信函数来控制控制器上产生特定的访问周期。 master_xfer()用于产生i2c访问周期需要的start stop ack信号,以i2c_msg(即i2c消息)为单位发送和接收通信数据。i2c_algorithm是与芯片的i2c_adapter适配器是唯一配对的

  • i2c_msg

    struct i2c_msg {
    __u16 addr; /* 从设备地址 */ 
    __u16 flags; /* 消息类型 */ 
    __u16 len; /* 消息长度 */ 
    __u8 *buf; /* 消息数据 */ 
    };

    i2c_msg 是 I2C 传输的基本单位,它包含了从设备的具体地址,消息的类型 以及要传输的具体数据信息。每个 I2C 消息传输前,都会产生一个开始位,紧接 着传送从设备地址,然后开始数据的发送或接收,对最后的消息还需产生一个停止位。

各数据结构之间的关系
  • i2c_driver就是一套驱动方法,与硬件接口无关,主要函数attach_adapter()、适配适配器,detach_client(),探测client

  • i2c_client对应一个真实的物理设备,一个i2c_driver可以支持多个同等类型i2c_client

  • i2c_adapter,适配器操作的是真实硬件,和真实硬件一一对应,一个适配器可以为多个i2c_client服务

  • i2c驱动与具体i2c设备对应,通过具体设备描述让core层对接适配器

  • i2c总线在注册时已经将适配器和相应算法绑定,i2c_transfer()寻找到i2c_adapter对应的i2c_algorithm,并使用i2c_algorithm的master_xfer()函数真正的驱动硬件流程,其本身没有和硬件的交互能力

    int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)  
      {  
          int ret;  
          if (adap->algo->master_xfer) {//如果master_xfer函数存在,则调用,否则返回错误  
              ret = adap->algo->master_xfer(adap,msgs,num);//这个函数在硬件相关的代码中给algorithm赋值  
              return ret;  
          } else {  
              return -ENOSYS;  
          }  
      }  
I2C流程

总线上先添加好IIC驱动,i2c.c遍历i2c_boardinfo链表,依次建立i2c_client,并对每一个i2c_client与所有在在这个线上的驱动匹配match,匹配上就调用该驱动的probe函数完成设备文件创建,操作接口注册。

  • 总线驱动需要填充core层i2c_add_adapter()和i2c_del_adapter()
  • i2c驱动需要i2c_attach_client()关联I2C总线设备
  • 算法在总线I2C设备probe时填充,同时probe也完成了对设备文件的创建

这里写图片描述

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值