本帖最后由 robe.zhang 于 2021-8-30 00:37 编辑
【米尔MYS-8MMX试用】如何向设备树添加节点
本文重点内容有三个:
1,驱动模型如何建立
2,设备树如何被解析
3,在理解 1 和 2 基础上,会很自然的理解如何向设备树添加节点
platform 驱动模型建立
内核驱动模型中有 bus,device,driver,分别对应 struct bus_type,struct device,struct device_driver 三个结构体,或者说三个对象也行,platform_bus , platform_device, platform_driver 是对 struct bus_type,struct device,struct device_driver 的继承,可以把 platform 平台看作是bus,device,driver的更高一级对象。
Platform 驱动中的 bus 和 device 是内核创建的,比如以下代码,注册了 platform_bus 有了 platform_bus 之后,需要有 platform_device ,platform_device 也是内核模块的形式注册的 of_platform_default_populate_init 这个函数解析设备树,解析时有规则的,结合imx8mm 平台来说,解析了以下所有节点及其一级子节点,也就是设备书中的以下节点创建了 device 设备,并且创建他们子节点的 device 设备,子节点再往下的节点,不解析不创建device,留作 platform_driver 去解析创建。(设备树如何被解析) 有了 platform_bus 也创建了 platform_device 设备,还差 platform_driver,platform_driver 就是驱动,并且是 SoC 芯片级别的驱动,这个有芯片原厂搞定,比如imx8mm 有以下 platform_driver:这个是 sdma 的驱动,以此为例,其他类同。 Platform 平台 bus,device,driver 几乎全部有厂商提供,用户基本是无感的。他默默在背后工作,但是初学者根本不知道他的存在。这是platform 平台完整的驱动模型。
理解此文基础上,再继续看笔者往期文章才能理解 IIC 总线框架: https://www.cirmall.com/bbs/thread-208032-1-1.html
深入看 IIC 设备树,i2c1 位于aips3 的一级子节点,i2c1 会被创建 platform_device,
I2c 驱动注册为platform_driver:
内核一开始注册了 platform_bus,也创建了 i2c1 的 platform_device,也注册了i2c1的 platform_driver,组成一个完整的 platform 驱动模型,他们就会工作了,i2c 适配器/主机能正常工作了。 (文章中的 i2c 适配器,就是 i2c 主机,i2c 控制器,对应驱动中的 i2c adapter;文章中的 i2c 设备,是 i2c 从机,对应驱动中的 i2c client)
i2c 驱动模型建立
I2c 适配器用的 platform 平台驱动模型,对你没有看错,笔者也么有写错,i2c 适配器用的 platform 平台驱动模型,和 i2c 总线没有半毛钱关系。 i2c 总线用在哪呢?用在 i2c 设备上。
I2c 适配器的 platform_driver 会去注册 adapter
解析 adapter 所有子节点注册为 i2c client 设备 (i2c device),现在有了 i2c device
内核会注册创建 i2c 总线
内核也会注册 client 驱动(i2c driver)注册,如下;
有 i2c 总线,有 i2c device设备(i2c client 设备),有 i2c driver (i2c client 驱动),组成一个完整的 i2c 总线模型,这个总线主要为 i2c 设备服务。
i2c 主机使用 platform 平台总线,i2c 从机使用 i2c 总线,是不是很难理解?驱动源码就是这样的。 linux 内核驱动中的总线,并不是硬件中的总线,也不是传输信息的,而是为了设备和驱动更容易的适配的,是设备和驱动的一种组织形式。
最难理解的地方就是 i2c 主机和 i2c 从机没使用同一个总线,分别使用了 platform 总线和 i2c 总线,能问出这个问题的根源是用硬件总线的概念去想当然的理解驱动中的总线,潜意识完全错误,硬件总线和驱动中的总线,完全是两个东西,应该这么去理解:
1,硬件中的总线,是传输信息的,硬件上主从机位于同一条 i2c 总线,主从机是可以通信的。 2,驱动中的总线仅仅是设备和驱动的组织形式,方便设备和驱动适配的。只要 i2c 主机设备和驱动适配 ok 主机就会工作,i2c 从机设备和驱动适配 ok 从机就会工作。分别使用了 platform 总线和 i2c 总线,并不影响 i2c 主机和 i2c 从机正常适配,正常工作。 结果就是 linux 驱动让 i2c 主从机都可以正常工作,硬件让主从机又能相互通信,那就可以了。
linux 驱动仅仅是让硬件工作起来,别强求 i2c 主从机必须位于同一条总线,不在同一条总线没关系;硬件的总线是通信的,i2c 主从机要想通信必须位于同一条总线,没的商量。
platform 是 arm linux 驱动中最基础的平台,用的多,也最容易追踪分析,是软件中驱动模块部分抽象出来的一种模型,用于组织设备和驱动的一种方式,其他 i2c ,spi 总线和 platform 平台驱动模型类似各有差异,i2c 和 spi 驱动模型都是在 platform 平台驱动中再次建立起来的,platform 平台驱动注册 i2c / spi 设备,和内核注册的 i2c 总线、i2c driver 组成 i2c 驱动模型。
没有 设备树 对应的节点,就没有 platform device,没有 platform device 仅有 platform bus 和 platform driver 不能组成完整的驱动模型,就无法工作。无法工作,platform driver 就不能 match 就无法 probe,无法 probe 就不能添加 i2c device,仅有 i2c 总线和 i2c driver 不能组成i2c 总线完整的驱动模型,i2c 也就不能工作。所以向设备树添加节点,很重要,相当于给驱动模型添加 device。
如何向设备树添加节点
设备树,这个名字说明他的数据结构是树,树中的每个节点是设备。
向设备树中添加节点,就是向 linux 中添加设备,树,就要求你添加到合适的位置,合适的层级。
向设备树添加节点是有规则的,规则是由设备树被解析的规则决定的,内核怎么解析设备树你就怎么添加
添加设备节点,必须添加到指定位置
添加自己的设备节点,必须添加到文中图片列出的节点的一级子节点,二级和再深的节点,添加了也没用,因为内核根本不去创建更深层次节点设备。
也不是完全不可以,你添加后节点还是存在的,只存在设备树中,驱动模型中是不存在,需要你自己去建立驱动模型。
接下来笔者运用设备树等不同的方法自己创建一条总线,建立起这个总线的驱动模型,让设备和驱动正常适配、probe、正常工作起来。
|