3—学习笔记.总线设备驱动模型

201 阅读3分钟

2020.12.4

分析总线驱动模型是为了搞清楚总线是如何将driver和device匹配的,即当我们插入我们的设备时,总线是如何找到这个设备对应的驱动,并且调用驱动的probe函数的。不管是先有驱动后有设备、还是先有设备后有驱动。都会调用驱动driver中的probe,而不是设备device。

总线的引入:

首先,驱动设计从直接操作寄存器,每一次修改都要很费劲;到实现驱动程序的第一次

分层,分为了两层,实现了更换单板或芯片时修改更加方便;再到所谓的“分离”,做到

了修改引脚也可以更加的方便。可以说是把分层后的第二层给再细分一下。

在前面,我们为了给硬件分配所谓的“资源”,定义了一个 led_resouce 结构体。很显然,给每个设备都定义一个结构体,太麻烦了,很有重复造轮子的感觉。所以,出现了“平台”这个概念,也就是platform_device结构体,它里面允许我们来定义各种硬件的资源。

到目前为止,都是对硬件的指定的框架在变化,而对硬件的操作,也就是要利用这些硬件达到什么效果,这些并没有什么变化:

  1. 分配\设置\注册 fileoperation结构体

  2. 使用ioremap映射寄存器

  3. 再对寄存器进行操作

因此右侧的driver结构体并没有本质的变化,那么问题来了,这两个平台如何一一对应?这就要交给总线结构了,先放一放,我们先看看platform_device结构体长什么样:

static struct platform_device board_A_led_dev  = {
	.name = "100ask_led",
	.num_resources = ARRAY_SIZE(resources),
	.resource = resources,
};

原来如此,老朋友“资源”被定义在了platform_device结构体的resources里,不过值得注意的是,在结构体的私有数据里也可以定义“资源”。不过在resources里定义时,要遵守一定的规则。

当device和driver配对成功时,driver的probe函数就会被调用,然后依然只是对硬件操作的老三步。

而总线驱动模型的另一个需要注意的地方就是,这个总线的两端连着一堆platform_device和platform_driver,他们是怎么互相找到对方的呢?

所以进入到下一个环节:

总线的配对:

① 最先比较:是否强制选择某个 driver

比较 platform_device. driver_override 和 platform_driver.driver.name

可以设置 platform_device 的 driver_override,强制选择某个 platform_driver。

② 然后比较:设备树信息

比较:platform_device. dev.of_node 和 platform_driver.driver.of_match_table。

由设备树节点转换得来的 platform_device 中,含有一个结构体:of_node。

如果一个 platform_driver 支持设备树,它的 platform_driver.driver.of_match_table 是一个数组。

使用设备树信息来判断 dev 和 drv 是否配对时,

首先,如果 of_match_table 中含有 compatible 值,就跟 dev 的 compatile 属性比较,若

一致则成功,否则返回失败;

其次,如果 of_match_table 中含有 type 值,就跟 dev 的 device_type 属性比较,若一致

则成功,否则返回失败;

最后,如果 of_match_table 中含有 name 值,就跟 dev 的 name 属性比较,若一致则成

功,否则返回失败。

而设备树中建议不再使用 devcie_type 和 name 属性,所以基本上只使用设备节点的

compatible 属性来寻找匹配的 platform_driver。

③ 接下来比较:platform_device_id

比较platform_device. name和platform_driver.id_table[i].name,

id_table中可能有多项。

platform_driver.id_table 是“platform_device_id”指针,表示该 drv 支持若干个 device,它

里面列出了各个 device 的{.name, .driver_data},其中的“name”表示该 drv 支持的设备的名

字,driver_data 是些提供给该 device 的私有数据。

④ 最后比较:platform_device.name 和 platform_driver.driver.name

platform_driver.id_table 可能为空,

这时可以根据 platform_driver.driver.name 来寻找同名的 platform_device。