Linux下I2C驱动框架:I2C 设备驱动

一. 简介

前面一篇文章学习了 Linux下 I2C 驱动框架与 I2C总线驱动(即I2C控制器驱动),文章如下:

Linux下I2C驱动实验: I2C驱动框架与I2C总线驱动-CSDN博客

Linux 内核也将 I2C 驱动分为两部分:
(1) I2C 总线驱动, I2C 总线驱动就是 SOC 的 I2C 控制器驱动,也叫做 I2C 适配器驱动。
(2) I2C 设备驱动, I2C 设备驱动就是针对具体的 I2C 设备而编写的驱动。

本文来学习一下 I2C 设备驱动。

二. Linux下I2C驱动实验:I2C设备驱动

I2C 设备驱动重点关注两个数据结构:i2c_client 和 i2c_driver,i2c_client 就是描述设备信息的,i2c_driver 描述驱动内容,类似于 platform_driver。

1. I2C 设备驱动涉及的结构体

(1)i2c_client 结构体

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

复制代码
struct i2c_client {
    unsigned short flags; /* 标志 */
    unsigned short addr; /* 芯片地址,7 位,存在低 7 位*/
......
    char name[I2C_NAME_SIZE]; /* 名字 */
    struct i2c_adapter *adapter; /* 对应的 I2C 适配器 */
    struct device dev; /* 设备结构体 */
    int irq; /* 中断 */
    struct list_head detected;
......
};

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

(2)i2c_driver结构体

i2c_driver 类似 platform_driver,是我们编写 I2C 设备驱动重点要处理的内容,i2c_driver 结构体定义在 include/linux/i2c.h 文件中,内容如下:

复制代码
struct i2c_driver {
	unsigned int class;

	/* Notifies the driver that a new bus has appeared. You should avoid
	 * using this, it will be removed in a near future.
	 */
	int (*attach_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 *);

	/* Alert callback, for example for the SMBus alert protocol.
	 * The format and meaning of the data value depends on the protocol.
	 * For the SMBus alert protocol, there is a single bit of data passed
	 * as the alert response's low bit ("event flag").
	 */
	void (*alert)(struct i2c_client *, unsigned int data);

	/* a ioctl like command that can be used to perform specific functions
	 * with the device.
	 */
	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);

	struct device_driver driver;
	const struct i2c_device_id *id_table;

	/* Device detection callback for automatic device creation */
	int (*detect)(struct i2c_client *, struct i2c_board_info *);
	const unsigned short *address_list;
	struct list_head clients;
};

第 10 行,当 I2C 设备和驱动匹配成功以后, probe 函数就会执行,和 platform 驱动一样。
第 28 行,device_driver 驱动结构体,如果使用设备树的话,需要设置 device_driver 的
of_match_table 成员变量,也就是驱动的兼容(compatible)属性。
第 29 行,id_table 是传统的、未使用设备树的设备匹配 ID 表。

对于我们 I2C 设备驱动编写人来说,重点工作就是构建 i2c_driver。

2. I2C 设备驱动注册与删除

构建完成 i2c_driver 结构体 以后,需要向Linux 内核注册这个 i2c_driver 。 i2c_driver 注册函数为 i2c_register_driver函数 ,此函数原型如下:

复制代码
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)

函数参数和返回值含义如下:
owner : 一般为 THIS_MODULE 。
driver :要注册的 i2c_driver 。
返回值: 0 ,成功;负值,失败。

i2c_add_driver 也常常用于注册 i2c_driver , i2c_add_driver 是一个宏,定义如下:

复制代码
#define i2c_add_driver(driver) \
	i2c_register_driver(THIS_MODULE, driver)

i2c_add_driver 就是对 i2c_register_driver 做了一个简单的封装,只有一个参数,就是要注册的 i2c_driver 。

注销 I2C 设备驱动的时候需要将前面注册的 i2c_driver 从 Linux 内核中注销掉,需要用到
i2c_del_driver 函数,此函数原型如下:

复制代码
void i2c_del_driver(struct i2c_driver *driver)

函数参数和返回值含义如下:
driver :要注销的 i2c_driver 。
返回值: 无。

三. 总结

**i2c_client结构体:**表示I2C设备,不需要我们自己创建 i2c_client,我们一般在设备树里面添加具体的I2C芯片,比如 fxls8471,系统在解析设备树的时候,就会知道有这个I2C设备,然后会创建对应的i2c_client。

**i2c设备驱动框架:**i2c_driver初始化与注册,需要II2C设备驱动编写人员编写的,IIC驱动程序就是初始化i2c_driver,然后向系统注册。注册使用i2c_register_driver、i2c_add_driver,如果注销i2c_driver使用i2c_del_driver。

相关推荐
牢姐与蒯14 分钟前
Linux信号(一).信号产生
linux·运维·服务器·ubuntu
雯宝6 小时前
mnt_init 函数
linux
律宏阔12 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔12 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴12 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千12 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei3712 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei3712 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei3712 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
GeW13 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux