I2C子系统框架

1 I2C子系统框架概述:

1.1 I2C驱动有4个重要的名词

I2C总线、I2C驱动、I2C设备、I2C设备器,对应的解释如下:
1)、I2C总线:维护着两个链表(I2C驱动、I2C设备),管理I2C设备和I2C驱动的匹配和删除等
2)、I2C驱动:对应的就是I2C设备的驱动程序
3)、I2C设备:是具体硬件设备的一个抽象
4)、I2C设配器:用于I2C驱动和I2C设备间的通用,是SOC上I2C控制器的一个抽象
1.2 I2C子系统框架概述
(1)内核初始化platform_bus和i2c_bus。
(2)注册总线驱动xxx_i2c_driver,遍历platform_bus中设备链表的每个平台设备(dts展开得到),以找到与该驱动匹配的设备。匹配成功以后,在probe函数中,向内核注册该设备(eg:I2C 1节点)。实质就是将这个设备节点添加到I2C总线的设备链表(也就是i2c_adapter和i2c_client都在I2C的设备链表中)中。此时,i2c_adapter与I2C总线驱动被关联起来。
(3)将i2c_client(一级节点下的子节点,也就是挂在I2C1下的设备)和adapter(一级节点,eg:I2C 1)关联起来;然后遍历i2c_bus上驱动链表,也就是通过i2c总线,将I2C_driver和设备树总线节点(eg:I2C 1)下的子节点进行匹配,匹配成功后,就实现了i2c_driver和i2c_client的关联起来;
(4)这时驱动driver通过client,就可以访问到adapter,进而使用到相应的通信函数,实现对I2C硬件的数据收发。

我的总结,整个I2C框架,有两次匹配过程:
1、I2C 设备和驱动的匹配过程是通过I2C 总线完成的:
简单的概括,就是I2C总线一头是i2c_client链表,一头是i2c_driver链表。通过match函数进行匹配,匹配之后,执行probe函数。至于在probe函数中,做什么,有自己根据之际情况而定。
匹配的方法和platform总线的匹配方法类似:
1)、利用设备树设备和驱动匹配。比较 I2C 设备节点的 compatible 属性和 of_device_id 中的 compatible 属性是否相等,如果相当的话就表示 I2C设备和驱动匹配。
2)、ACPI 形式的匹配。
3)、用于传统的、无设备树的 I2C 设备和驱动匹配过程。通过 I2C设备名字和 i2c_device_id 的 name 字段进行匹配。
2、设备控制器驱动和设备树下对应设备节点的匹配的。这个过程,是基于platform驱动框架进行匹配的,通过compatible属性值进行匹配。

2、I2C子系统具体的实现流程解析

linux内核将I2C驱动分为两部分:I2C总线驱动和I2C设备驱动。
I2C总线驱动:就是SOC的I2C控制器驱动,也叫做适配器驱动。(这部分驱动,是芯片原厂写好的,一经写好,就不需要再修改。在编写I2C设备驱动的时候,可以直接调用I2C总线驱动提供的API函数)
I2C设备驱动:集体的设备驱动,eg:AP32164.这部分,需要用户自行编写。
在这里插入图片描述

2.1 I2C总线驱动的编写(包括核心层和总线驱动层)

I2C总线驱动的编写需要用到两个重要的结构体:
(1)i2c_adapter
linux将SOC的I2C适配器驱动抽象成i2c_adapter结构体。
(2)i2c_algorithm
对于每个I2C适配器(也叫做I2C控制器),要对外提供读写的API函数,驱动程序可以使用这些API函数来完成读写操作(就好比Input子系统的核心层要向设备驱动层提供API函数,用来让设备驱动层将获取到的设备数据上传一样)。i2c_algorithm结构体里面存放着I2C控制器和I2C设备进行通信的方法。
因此:
I2C适配器驱动的核心就是申请并初始化i2c_adapter结构体,设置i2c_algorithm结构体里面的master_xfer函数—》此函数就是I2C控制器最终进行数据收发的函数(i2c_algorithm结构体是i2c_adapter结构体的成员),最后,注册i2c_adapter结构体。

2.2 I2C总线驱动编写流程:

说明:
i2c总线为I2C设备提供了一整套总线驱动框架,但是I2C适配器却是platform驱动(驱动-总线-设备框架),在这里,设备树下的设备节点与驱动的匹配时通过compatibie属性值来进行匹配的)。
这就好比是,I2C总线是你们部门的老大,具体的I2C设备是他的下属。但是,从整个公司来看(platform驱动),I2C总线就是下属。
设备和驱动匹配成功以后,probe函数就会执行,在这个函数里面,我们要做的就是从获取(我们是从设备树获取)I2C控制器所使用的寄存器信息,申请并初始化i2c_adapter结构体,设置i2c_algorithm结构体里面的master_xfer函数,最后,注册i2c_adapter结构体,注册到核心层。

2.3 I2C的读写流程:

在这里插入图片描述
解析:
从用户层开始,应用程序会通过我们自己写的设备驱动(文件操作结构体中的.read/.write……)来促使I2C通讯的发生。在linux操作系统中,对任何设备的访问,都可以通过设备文件节点来进行。因此,应用程序会通过i2c_client来访问设备驱动i2c_driver。设备驱动i2c_driver会将自己注册到一个具体的I2C总线上,而一个I2C总线会对应一个I2C控制器i2c_adapter,eg:I2C 1->I2C_adapter 1; I2C 2->I2C_adapter 2。
设备驱动在调用I2C内核提供的数据收发函数i2c_master_send/i2c_master_recv或者是直接调用数据传输函数i2c_transfer的过程中,都会导致对应的I2C控制器发生动作,而不会让另一个I2c控制器发生动作,这些绑定动作都是由i2c核心层实现的。具体的实现思路:
i2c控制器驱动和i2c设备驱动在注册的时候,都会调用i2c内核的相关函数来实现彼此之间的绑定。
最终,i2c控制器的数据发送动作有i2c控制器驱动中的xxx_i2c_xfer函数来实现。

3 I2C设备驱动的编写

(1)i2c_client
其实就是i2c_device,跟i2c_driver配对。描述设备信息 。这个结构体不是我们自己创建的,是自动改创建的。内核在解析设备树的时候,在i2c_adapter对应的节点下,每检测到一个子设备节点,就会自动创建一个i2c_client。所以,这块我们只要配置设备树即可!!i2c_client会保存他所述的i2c_adapter。
(2)i2c_driver 完全需要我们自己创建
描述驱动内容,类似于platform_driver。实现与用户层交互的文件操作集合fops等。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

One Piece&

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

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

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

打赏作者

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

抵扣说明:

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

余额充值