• Linux ARM平台开发系列讲解(IIC) 2.7.1 IIC总线驱动框架分析


    1. 概述

    对于 I2C 主机驱动,一旦编写完成就不需要再做修改,其他的 I2C 设备直接调用主机驱动提供的 API 函数完成读写操作即可。这个正好符合 Linux 的驱动分离与分层的思想,因此 Linux内核也将 I2C 驱动分为两部分:
    ①、I2C 总线驱动,I2C 总线驱动就是 SOCI2C 控制器驱动,也叫做 I2C 适配器驱动。
    ②、I2C 设备驱动,I2C 设备驱动就是针对具体的 I2C 设备而编写的驱动。

    2. IIC总线驱动

    相比platform总线而言,I2C不需要虚拟出一条总线,直接使用 I2C总线即可。I2C 总线驱动重点是 I2C 适配器(也就是 SOCI2C 接口控制器)驱动,这里要用到两个重要的数据结构:i2c_adapteri2c_algorithmLinux 内核将 SOCI2C 适配器(控制器)抽象成 i2c_adapteri2c_adapter 结构体定义在 include/linux/i2c.h 文件中,结构体内容如下:

    struct i2c_adapter {
    	struct module *owner;
    	unsigned int class;		  /* classes to allow probing for */
    	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
    	void *algo_data;
    
    	/* data fields that are valid for all devices	*/
    	const struct i2c_lock_operations *lock_ops;
    	struct rt_mutex bus_lock;
    	struct rt_mutex mux_lock;
    
    	int timeout;			/* in jiffies */
    	int retries;
    	struct device dev;		/* the adapter device */
    	unsigned long locked_flags;	/* owned by the I2C core */
    #define I2C_ALF_IS_SUSPENDED		0
    #define I2C_ALF_SUSPEND_REPORTED	1
    
    	int nr;
    	char name[48];
    	struct completion dev_released;
    
    	struct mutex userspace_clients_lock;
    	struct list_head userspace_clients;
    
    	struct i2c_bus_recovery_info *bus_recovery_info;
    	const struct i2c_adapter_quirks *quirks;
    
    	struct irq_domain *host_notify_domain;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2. IIC总线驱动中的读写算法

    struct i2c_adapter结构体中,有一个IIC总线访问算法,该算法的作用是用于提供IIC总线对外读写的APIi2c_algorithm 就是 I2C 适配器与 IIC 设备进行通信的方法,i2c_algorithm 结构体定义在 include/linux/i2c.h 文件中,内容如下:

    struct i2c_algorithm {
    	/*
    	 * If an adapter algorithm can't do I2C-level access, set master_xfer
    	 * to NULL. If an adapter algorithm can do SMBus access, set
    	 * smbus_xfer. If set to NULL, the SMBus protocol is simulated
    	 * using common I2C messages.
    	 *
    	 * master_xfer should return the number of messages successfully
    	 * processed, or a negative value on error
    	 */
    	int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
    			   int num);
    	int (*master_xfer_atomic)(struct i2c_adapter *adap,
    				   struct i2c_msg *msgs, int num);
    	int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr,
    			  unsigned short flags, char read_write,
    			  u8 command, int size, union i2c_smbus_data *data);
    	int (*smbus_xfer_atomic)(struct i2c_adapter *adap, u16 addr,
    				 unsigned short flags, char read_write,
    				 u8 command, int size, union i2c_smbus_data *data);
    
    	/* To determine what the adapter supports */
    	u32 (*functionality)(struct i2c_adapter *adap);
    
    #if IS_ENABLED(CONFIG_I2C_SLAVE)
    	int (*reg_slave)(struct i2c_client *client);
    	int (*unreg_slave)(struct i2c_client *client);
    #endif
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • master_xfer: 就是 I2C 适配器的传输函数,可以通过此函数来完成与 IIC 设备之间的通信。
    • smbus_xfer: 就是 SMBUS 总线的传输函数。

    综上所述,I2C 总线驱动,或者说 I2C 适配器驱动的主要工作就是初始化 i2c_adapter 结构体变量,然后设置 i2c_algorithm 中的 master_xfer 函数。完成以后通过 i2c_add_numbered_adapteri2c_add_adapter 这两个函数向系统注册设置好的 i2c_adapter,这两个函数的原型如下:

    int i2c_add_adapter(struct i2c_adapter *adapter)
    int i2c_add_numbered_adapter(struct i2c_adapter *adap)
    
    • 1
    • 2

    这两个函数的区别在于 i2c_add_adapter 使用动态的总线号,而 i2c_add_numbered_adapter
    使用静态总线号。函数参数和返回值含义如下:

    • adapteradap:要添加到 Linux 内核中的 i2c_adapter,也就是 I2C 适配器。
    • 返回值0,成功;负值,失败。

    如果要删除 I2C 适配器的话使用 i2c_del_adapter 函数即可,函数原型如下:

    void i2c_del_adapter(struct i2c_adapter * adap)
    
    • 1

    函数参数和返回值含义如下:

    • adap:要删除的 I2C 适配器。
    • 返回值:无。

    返回总目录

  • 相关阅读:
    《HelloGitHub》第 97 期
    CS224W2.2——传统基于特征的方法(边层级特征)
    DDoS攻击频发,科普防御DDoS攻击的几大有效方法
    零基础快速自学SQL,2天足矣。
    item_review-获得商品评论
    提升 Python 执行速度:Codon、C/C++、Rust、Numba(JIT)、Taichi、Nuitka、MatxScript
    聚观早报 | 华为Mate 50系列9月7日发布;Meta使用算法随机裁员
    TSINGSEE智能分析网关V4车辆结构化数据检测算法及车辆布控
    PT_参数估计/点估计_矩估计法
    SVA断言总结
  • 原文地址:https://blog.csdn.net/DSMGUOGUO/article/details/125143404