Linux 学习笔记:Linux I2C 驱动

一、Linux I2C 驱动框架简介

Linux 内核将 I2C 驱动分为两部分:

  • **I2C 总线驱动:**SOC 的I2C 控制器驱动,也叫做I2C 适配器驱动。一旦编写完成就不再需要再做修改,其他的I2C 设备直接调用主机驱动提供的API 函数完成读写操作即可。
  • **I2C 设备驱动:**I2C 设备驱动就是针对具体的I2C 设备而编写的驱动。

二、I2C 总线驱动

总线驱动用到两个重要的数据结构:

  • i2c_adapter
  • i2c_algorithm

2.1 i2c_adapter

i2c_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	*/
	struct rt_mutex bus_lock;

	int timeout;			/* in jiffies */
	int retries;
	struct device dev;		/* the adapter device */

	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;
};

2.2 i2c_algorithm

i2c_algorithm 就是I2C 适配器与I2C 设备进行通信的方法。

结构体定义如下:

struct i2c_algorithm {
	int (*master_xfer)(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);

	u32 (*functionality) (struct i2c_adapter *);
};
  • master_xfer : 就是 I2C 适配器的传输函数,可以通过此函数来完成与 IIC 设备 之间的通信。
  • smbus_xfer : 就是 SMBUS 总线的传输函数。

2.3 I2C 适配器驱动编写步骤

  • 初始化 i2c_adapter 结构体变量。

  • 设置i2c_algorithm 中的master_xfer 函数 。

  • 向系统注册设置好的i2c_adapter 。注册函数原型如下:

    int i2c_add_adapter(struct i2c_adapter* adapter)
    int i2c_add_numberred_adapter(struct i2c_adapter* adap)
    

    这两个函数的区别在于i2c_add_adapter 使用动态总线号,而i2c_add_numbered_adapter 使用静态总线号

  • 删除I2C 适配器

    void i2c_del_adapter(struct i2c_adapter* adap)
    

一般SOC 的I2C 总线驱动都是由半导体厂商编写的,我们只需要专注于I2C 设备驱动即可。

三、I2C 设备驱动

I2C 设备驱动重点关注两个数据结构体:

  • i2c_client
  • i2c_driver

根据总线、设备、和驱动模型,i2c_client 就是描述设备信息的,i2c_driver 描述设备驱动,类似于platform_driver 。

3.1 i2c_client 结构体

i2c_client 结构体定义在 include/linux/i2c.h 中,内容如下:

struct i2c_client
{
    unsigned short flags;       /* div., see below      */
    unsigned short addr;        /* chip address - NOTE: 7bit addresses are stored in the  _LOWER_ 7 bits        */
    char name[I2C_NAME_SIZE];
    struct i2c_adapter *adapter;    /* the adapter we sit on    */
    struct device dev;      /* the device structure     */
    int irq;            /* irq issued by device     */
    struct list_head detected;
};

一个设备对应一个i2c_client ,每检测到一个I2C 设备就会给这个I2C 设备分配一个i2c_client 。

3.2 i2c_driver 结构体

i2c_driver 类似 platform_driver ,是我们编写I2C 设备驱动重点要处理的内容。

struct i2c_driver
{
    unsigned int class;
    int ( *attach_adapter )( struct i2c_adapter * ) __deprecated;
    int ( *probe )( struct i2c_client *, const struct i2c_device_id * );
    int ( *remove )( struct i2c_client * );
    void ( *shutdown )( 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;
    int ( *detect )( struct i2c_client *, struct i2c_board_info * );
    const unsigned short *address_list;
    struct list_head clients;
};
  • probe : 当i2c 设备和驱动匹配成功以后,probe 函数就会执行,和platform 驱动一样。
  • device_driver : 驱动结构体,如果使用设备树的话,需要设置device_driver 的of_match_table 成员变量,也就是驱动的兼容(compatible) 属性。

对于我们 I2C 设备驱动编写人来说,重点工作就是构建 i2c_driver ,构建完成以后需要向Linux 内核注册这个i2c_driver 。

注册i2c_driver

#define i2c_add_driver (driver) \ i2c_register_driver(THIS_MODULE,driver)

注销 I2C 设备驱动

void i2c_del_driver( struct i2c_driver * driver)

3.3 I2C 设备和驱动匹配过程

I2C 设备和驱动的匹配过程是由I2C 核心来完成的, driver/i2c/i2c-core.c 就是I2C 的核心部分,I2C 核心提供了一些与具体硬件无关的API 函数,比如前面讲过的:

i2c_adapter 注册、注销函数

int i2c_add_adapter(struct i2c_adapter* adapter)
int i2c_add_numbered_adapter(struct i2c_adapter* adap)
void i2c_del_adapter(struct i2c_adapter* adap)

i2c_driver 注册、注销函数

int i2c_register_driver(struct module* owner,struct i2c_driver* driver)
int i2c_add_driver(struct i2c_driver* driver)
int i2c_del_driver(struct i2c_driver* driver)

匹配过程

设备和驱动的匹配过程,具体是由 I2C 总线完成,I2C 总线的数据结构为 i2c_bus_type , 定义在 driver/i2c/i2c-core.c 文件,i2c_bus_type 内容如下:

struct bus_type i2c_bus_type = {
	.name		= "i2c",
	.match		= i2c_device_match,
	.probe		= i2c_device_probe,
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
};

.match 就是I2C 总线的设备和驱动匹配函数,在这里就是i2c_device_match 这个函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gdut_llkkyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值