平台设备驱动程序自动加载机制
Platform device driver autoloading mechanism
据我了解,当设备树中的 "compatible" 字段与内核模块中的 "compatible" 字段匹配时,平台设备驱动程序可以自动加载。这是来自 Raspberry Pi 发行版的 pwm-overlay.dts
文件:
/ {
fragment@0 {
target = <&gpio>;
__overlay__ {
pwm_pins: pwm_pins {
brcm,pins = <18>;
brcm,function = <2>; /* Alt5 */
};
};
};
fragment@1 {
target = <&pwm>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&pwm_pins>;
status = "okay";
};
};
fragment@2 {
target = <&clk_pwm>;
frag2: __overlay__ {
clock-frequency = <100000000>;
};
};
__overrides__ {
pin = <&pwm_pins>,"brcm,pins:0";
func = <&pwm_pins>,"brcm,function:0";
clock = <&frag2>,"clock-frequency:0";
};
};
首先,我没有看到任何 "compatible" 字段,但是在 pwm-bcm2835.c
文件中有这样的字符串:
static const struct of_device_id bcm2835_pwm_of_match[] = {
{ .compatible = "brcm,bcm2835-pwm", },
{ /* sentinel */ }
};
此外,当我加载覆盖时,驱动程序也成功自动加载。怎么运行的?它如何知道要加载哪个驱动程序?
关于如何匹配 "compatible" 字段以将驱动程序绑定到设备,你是对的,只是你没有在正确的地方寻找它。
您正在查看的文件是设备树覆盖。它被添加到现有的设备树中,添加、删除或更改一些节点和属性。最终的设备树是将原始设备与一定数量的覆盖相结合的结果。给定的 属性 可能会在任何原始 and/or 覆盖的源文件中被(重新)定义。如何构造设备树源代码是设计者的任意决定。
但是想一想为什么存在叠加层。此覆盖图用于配置 PWM,因为每块板的 PWM 配置都不相同(您可能根本不会使用它)。对可以更改的内容使用覆盖让我们无需构建和从新设备树启动即可进行更改。 SoC 中 PWM 硬件的存在是不变的。即使不使用,它也永远不会不存在。关于它的某些事情,比如设备寄存器的基地址,也不会改变。所以把它放在覆盖层中没有意义,因为它不会改变,而且它很可能在基本设备树源中。
在叠加层中,fragment@1
正在修改标记为 "pwm" 的现有目标节点。如果我们寻找这个节点,我们会在 bcm283x.dtsi
:
中找到它
pwm: pwm@7e20c000 {
compatible = "brcm,bcm2835-pwm";
reg = <0x7e20c000 0x28>;
clocks = <&clocks BCM2835_CLOCK_PWM>;
assigned-clocks = <&clocks BCM2835_CLOCK_PWM>;
assigned-clock-rates = <10000000>;
#pwm-cells = <2>;
status = "disabled";
};
并且您有值 "brcm,bcm2835-pwm" 的兼容 属性。因为它不需要更改,所以它就像我们期望的那样位于基本设备树的源代码中。
据我了解,当设备树中的 "compatible" 字段与内核模块中的 "compatible" 字段匹配时,平台设备驱动程序可以自动加载。这是来自 Raspberry Pi 发行版的 pwm-overlay.dts
文件:
/ {
fragment@0 {
target = <&gpio>;
__overlay__ {
pwm_pins: pwm_pins {
brcm,pins = <18>;
brcm,function = <2>; /* Alt5 */
};
};
};
fragment@1 {
target = <&pwm>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&pwm_pins>;
status = "okay";
};
};
fragment@2 {
target = <&clk_pwm>;
frag2: __overlay__ {
clock-frequency = <100000000>;
};
};
__overrides__ {
pin = <&pwm_pins>,"brcm,pins:0";
func = <&pwm_pins>,"brcm,function:0";
clock = <&frag2>,"clock-frequency:0";
};
};
首先,我没有看到任何 "compatible" 字段,但是在 pwm-bcm2835.c
文件中有这样的字符串:
static const struct of_device_id bcm2835_pwm_of_match[] = {
{ .compatible = "brcm,bcm2835-pwm", },
{ /* sentinel */ }
};
此外,当我加载覆盖时,驱动程序也成功自动加载。怎么运行的?它如何知道要加载哪个驱动程序?
关于如何匹配 "compatible" 字段以将驱动程序绑定到设备,你是对的,只是你没有在正确的地方寻找它。
您正在查看的文件是设备树覆盖。它被添加到现有的设备树中,添加、删除或更改一些节点和属性。最终的设备树是将原始设备与一定数量的覆盖相结合的结果。给定的 属性 可能会在任何原始 and/or 覆盖的源文件中被(重新)定义。如何构造设备树源代码是设计者的任意决定。
但是想一想为什么存在叠加层。此覆盖图用于配置 PWM,因为每块板的 PWM 配置都不相同(您可能根本不会使用它)。对可以更改的内容使用覆盖让我们无需构建和从新设备树启动即可进行更改。 SoC 中 PWM 硬件的存在是不变的。即使不使用,它也永远不会不存在。关于它的某些事情,比如设备寄存器的基地址,也不会改变。所以把它放在覆盖层中没有意义,因为它不会改变,而且它很可能在基本设备树源中。
在叠加层中,fragment@1
正在修改标记为 "pwm" 的现有目标节点。如果我们寻找这个节点,我们会在 bcm283x.dtsi
:
pwm: pwm@7e20c000 {
compatible = "brcm,bcm2835-pwm";
reg = <0x7e20c000 0x28>;
clocks = <&clocks BCM2835_CLOCK_PWM>;
assigned-clocks = <&clocks BCM2835_CLOCK_PWM>;
assigned-clock-rates = <10000000>;
#pwm-cells = <2>;
status = "disabled";
};
并且您有值 "brcm,bcm2835-pwm" 的兼容 属性。因为它不需要更改,所以它就像我们期望的那样位于基本设备树的源代码中。