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。

相关推荐
冷崖25 分钟前
定时器的学习(二)
linux·c++·学习
馨谙1 小时前
chage -d 0 强制密码修改的完整流程
linux·运维
爱技术的小伙子1 小时前
【Linux运维】 Prometheus + Grafana + Alertmanager 监控系统部署指南(CentOS & Ubuntu 通用版)
linux·运维·prometheus
Zach_yuan1 小时前
Linux编辑器vim
linux·编辑器·vim
hweiyu002 小时前
Linux运维实战:云原生设计与实施Docker&K8S(视频教程)
linux·运维·云原生
海棠蚀omo2 小时前
Linux操作系统-命令行参数及环境变量
linux·操作系统
小白不想白a3 小时前
【shell】每日shell练习(系统用户安全审计/系统日志错误分析)
linux·运维·云原生
码猫Mrr3 小时前
创维E900V22D刷入armbian hdmi开机花屏和网络无法使用 解决方式【亲测】
linux·armbian·e900v22d
Cx330❀3 小时前
《Linux基础入门指令(二)》:从零开始理解Linux系统
linux·运维·服务器·网络·经验分享
武文斌774 小时前
项目学习总结:CAN总线、摄像头、STM32概述
linux·arm开发·stm32·单片机·嵌入式硬件·学习·c#