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。

相关推荐
cui_win1 小时前
【内存】Linux 内核优化实战 - net.ipv4.tcp_tw_reuse
linux·网络·tcp/ip
CodeWithMe4 小时前
【Note】《深入理解Linux内核》 Chapter 15 :深入理解 Linux 页缓存
linux·spring·缓存
0wioiw04 小时前
Ubuntu基础(监控重启和查找程序)
linux·服务器·ubuntu
Tipriest_4 小时前
Ubuntu常用的软件格式deb, rpm, dmg, AppImage等打包及使用方法
linux·运维·ubuntu
胡斌附体5 小时前
linux测试端口是否可被外部访问
linux·运维·服务器·python·测试·端口测试·临时服务器
愚润求学5 小时前
【Linux】自旋锁和读写锁
linux·运维
大锦终5 小时前
【Linux】常用基本指令
linux·运维·服务器·centos
IT项目管理5 小时前
达梦数据库DMHS介绍及安装部署
linux·数据库
知北游天6 小时前
Linux:多线程---深入互斥&&浅谈同步
linux·运维·服务器
Gappsong8746 小时前
【Linux学习】Linux安装并配置Redis
java·linux·运维·网络安全