针对Linux,RK3568平台下,I2C驱动的一点小小的领悟

总结:

I2C驱动子系统的实现是如下说明:以下说明仅针对硬件I2C;若所需为软件I2C的设备、驱动都需要我们自己编写

I2C驱动由:

i2c_client(i2c设备)、i2c_driver(i2c驱动)

i2c core:i2c核心层

i2c_adapter(i2c控制器/i2c适配器)、i2c_algorithm(i2c算法/i2c通信协议/i2c通信时序构成)

其中:i2c_client(i2c设备)、i2c_driver(i2c驱动),由我们驱动工程师做

i2c core:为硬件无关代码,主要作用是将i2c_client(i2c设备)、i2c_driver(i2c驱动)等的操作转换为i2c_adapter所需要的:简单理解为中间件/翻译等

i2c_adapter(i2c控制器/i2c适配器)、i2c_algorithm(i2c算法/i2c通信协议/i2c通信时序构成):由原厂工程师编写,也就是SOC的工程师:瑞芯微、海思等

其中I2C是具有自己的总线的,i2c_client、i2c_driver注册在I2C总线上

总线结构体如下:

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

但反直觉的是,i2c_adapter并不是直接通过i2c总线去匹配注册的,而是转了一道,通过platform里面的probe去进行的注册

c 复制代码
static struct platform_driver rk3x_i2c_driver = {
	.probe   = rk3x_i2c_probe,
	.remove  = rk3x_i2c_remove,
	.driver  = {
		.name  = "rk3x-i2c",
		.of_match_table = rk3x_i2c_match,
		.pm = &rk3x_i2c_pm_ops,
	},
};

#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
static int __init rk3x_i2c_driver_init(void)
{
	return platform_driver_register(&rk3x_i2c_driver);
}
subsys_initcall_sync(rk3x_i2c_driver_init);

static void __exit rk3x_i2c_driver_exit(void)
{
	platform_driver_unregister(&rk3x_i2c_driver);
}
module_exit(rk3x_i2c_driver_exit);
#else
module_platform_driver(rk3x_i2c_driver);
#endif

不过也不难以理解,设备树中指定了硬件i2c的设备,然后编写驱动,通过platform_driver去匹配注册,然后再在对应的Probe内进行i2c_adapter、i2c_client的注册

i2c_adapter的注册在i2c_add_adapter申请空间,剩下的位置填充,最后赋给旗下的i2c_client

i2c_client的注册:i2c_add_adapter->i2c_register_adapter->of_i2c_register_devices->...->i2c_new_device

也就是说i2c_client的注册是随着i2c_adapter的注册一同完成的,不过也不难以理解,i2c_adapter是用来控制i2c设备的

误区:误以为i2c-core-base.c文件中的dummy:

c 复制代码
static struct i2c_driver dummy_driver = {
	.driver.name	= "dummy",
	.probe		= dummy_probe,
	.remove		= dummy_remove,
	.id_table	= dummy_id,
};

是注册的i2c驱动,实际上并不是,这个只是针对同一设备具有多地址时的一个优化,具体作用还没理解清楚。

误区2:i2c-dev.c文件中的const struct file_operations i2cdev_fops以为是注册了实际的设备

实际并不是,稍微追一下就可以发现是直接调用了i2c_adapter,可以很简单的理解为,通过这个玩意可以跳过编写i2c的驱动,在启动了对于管脚的i2c_adapter后,就可以在应用层编写应用,进行一定的处理,不需要在内核里面增加新的i2c_client、i2c_driver。

总结,对于非soc驱动工程师来说,针对硬件I2C,只需要关注i2c_client、i2c_driver的编写即可,甚至i2c_client直接使用设备树,而去编写i2c_driver就行。

核心思想依然是:总线、驱动、设备模型;
i2c_bus_type(总线)、i2c_driver(驱动)、i2c_client(设备)
platform_bus_type(总线)、platform_driver rk3x_i2c_driver(驱动)、rk3x_i2c_match/设备树中指定的i2c节点(设备)

相关推荐
chlk12315 小时前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑15 小时前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件16 小时前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号1 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash1 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI2 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行2 天前
Linux和window共享文件夹
linux
木心月转码ing3 天前
WSL+Cpp开发环境配置
linux
崔小汤呀4 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
何中应4 天前
vi编辑器使用
linux·后端·操作系统