较新的 Linux 内核如何在启动期间加载不可移动硬件设备驱动程序?

较新的 Linux 内核如何在启动期间加载不可移动硬件设备驱动程序?

问题:

多个设备驱动程序(在设备树中指定)在启动期间未加载。所有内置驱动程序均已加载,没有任何问题。如果在命令行中使用 modprobe,驱动程序将成功加载并运行。

Linux 内核:5.4.24 硬件:定制主板,带有 iMX6 (ARM)、ov5640 摄像头、TI WL1831 Wifi 芯片和与 iMX6 的 PWM 输出绑定的音频放大器。Yocto (Dunfell) 用于为该嵌入式设备构建 SD 卡映像。在内核启动期间,Root 仅/始终以只读方式安装。

以下设备驱动程序未加载:wl18xx、wlcore_sdio、wlcore、ov564x_mipi (ov5640_camera_int.ko)、mxc_v4l2_capture、pwm-imx。TI WL18XX 驱动程序已从德州仪器源修补到内核中。pwm-imx 驱动程序是我编写的。我目前使用的是原装 ov564x_mipi 和 mxc_v4l2_capture 驱动程序。附注:这在较旧的 3.14 内核中按预期工作。所以我怀疑我缺少了较新内核所需的某些东西。设备树正在由 u-boot 加载。/proc/device-tree 与设备树匹配,正如预期的那样。

我的行动:

  • 在 dmesg 输出中没有错误或迹象表明驱动程序甚至尝试加载。
  • 反向编译设备树以验证所有设备均已启用并定义了兼容属性。在使用 modprobe 加载这些驱动器后,我必须修复设备树属性才能使它们正常运行。
  • 检查所有这些内核模块是否使用 MODULE_DEVICE_TABLE() 宏。
  • 检查所有 /sys/firmware/devicetree 列表都有一个“兼容”条目,其中包含每个驱动程序源中的匹配的 of_device_id 字符串。
  • 检查预期的模块别名是否显示在 modinfo 中
  • 检查了 depmod 数据库。它列出了所有模块和正确的依赖项。
  • 启动后,lsmod 什么也没显示。根本没有加载任何内核模块。
  • 我曾尝试根据在以下位置找到的信息加载这些内容https://wiki.archlinux.org/index.php/Kernel_module#Loading
  • 干净启动后,/sys/bus/*/drivers 中没有任何这些驱动程序的列表。当我使用 modprobe 手动加载每个驱动程序时,/sys/bus/*/drivers 中会显示相应的列表
  • 研究 udev 并没有给出答案。udev 处理由加载内核模块触发的操作驱动的事件。我找不到任何说明 udev 实际如何、何时或为何加载内核模块的内容。
  • 尝试先发布此内容https://stackoverflow.com/questions/66754562/linux-device-drivers-not-loading-during-boot

我的观点:

  • Systemd 能够运行调用 modprobe 的脚本。我不认为 systemd 应该为不可移动的硬件加载内核模块。

信息:

这些内核模块位于:

/lib/modules/5.4.24+g5303049bda95/kernel/drivers/media/platform/mxc/capture/ov5640_camera_mipi_int.ko
/lib/modules/5.4.24+g5303049bda95/extra/pwm-imx.ko
/lib/modules/5.4.24+g5303049bda95/kernel/drivers/media/platform/mxc/capture/mxc_v4l2_capture.ko
/lib/modules/5.4.24+g5303049bda95/kernel/drivers/net/wireless/ti/wl18xx/wl18xx.ko
/lib/modules/5.4.24+g5303049bda95/kernel/drivers/net/wireless/ti/wlcore/wlcore.ko
/lib/modules/5.4.24+g5303049bda95/kernel/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko

启动时会出现以下系统路径:

/sys/bus/platform/devices/2080000.pwm
/sys/bus/platform/devices/20d4000.v4l2_cap_0
/sys/bus/platform/devices/21a0000.i2c
/sys/bus/platform/devices/2190000.usdhc
/sys/devices/soc0/soc/2000000.aips-bus/2080000.pwm
/sys/devices/soc0/soc/2000000.aips-bus/20d4000.v4l2_cap_0
/sys/devices/soc0/soc/2100000.aips-bus/21a0000.i2c
/sys/devices/soc0/soc/2100000.aips-bus/2190000.usdhc
/sys/firmware/devicetree/base/soc/aips-bus@2000000/pwm@2080000
/sys/firmware/devicetree/base/soc/aips-bus@2000000/v4l2_cap_0@20d4000
/sys/firmware/devicetree/base/soc/aips-bus@2100000/i2c@21a0000/ov5640_mipi@3c
/sys/firmware/devicetree/base/soc/aips-bus@2100000/usdhc@2190000/wlcore@0

/sys 中更改的示例:

$> find / -name *ov564*
/sys/firmware/devicetree/base/soc/aips-bus@2100000/i2c@21a0000/ov5640_mipi@3c
/lib/modules/5.4.24+g5303049bda95/kernel/drivers/media/platform/mxc/capture/ov5640_camera_mipi_int.ko

$> modprobe ov5640_camera_mipi_int

$> find / -name *ov564*
/sys/firmware/devicetree/base/soc/aips-bus@2100000/i2c@21a0000/ov5640_mipi@3c
/sys/bus/i2c/drivers/ov564x_mipi
/sys/module/ov5640_camera_mipi_int
/sys/module/ov5640_camera_mipi_int/drivers/i2c:ov564x_mipi
/sys/module/v4l2_int_device/holders/ov5640_camera_mipi_int
/lib/modules/5.4.24+g5303049bda95/kernel/drivers/media/platform/mxc/capture/ov5640_camera_mipi_int.ko

udev / systemd 文件:

/usr/lib/modprobe.d/ does not exist
/etc/conf.d/modules does not exist

$> ls -als /lib/modprobe.d
total 12
4 drwxr-xr-x 2 root root 4096 Mar  9 12:34 .
4 drwxr-xr-x 9 root root 4096 Mar  9 12:34 ..
4 -rw-r--r-- 1 root root  765 Mar  9 12:34 systemd.conf

$> ls -als /etc/modprobe.d/
total 12
4 drwxr-xr-x  2 root root 4096 Mar  9 12:36 .
4 drwxr-xr-x 39 root root 4096 Mar  9  2018 ..
4 -rw-r--r--  1 root root   70 Mar  9 12:38 ov564x-mipi.conf

cat /etc/modprobe.d/ov564x-mipi.conf 
# Load ov5640_camera_mipi_int at boot
options ov5640_camera_mipi_int

$> ls -als /etc/modules-load.d/
total 12
4 drwxr-xr-x  2 root root 4096 Mar  9  2018 .
4 drwxr-xr-x 39 root root 4096 Mar  9  2018 ..
4 -rw-r--r--  1 root root   62 Mar  9  2018 ov564x-mipi.conf

cat /etc/modules-load.d/ov564x-mipi.conf 
# Load ov5640_camera_mipi_int at boot
ov5640_camera_mipi_int

加载驱动程序时触发的 udev 事件示例

$> udevadm monitor &

$>modprobe ov5640_camera_int
KERNEL[225.175451] add      /module/v4l2_int_device (module)
UDEV  [225.181252] add      /module/v4l2_int_device (module)
KERNEL[225.183581] add      /module/ov5640_camera_int (module)
KERNEL[225.183956] add      /bus/i2c/drivers/ov564x (drivers)
UDEV  [225.186825] add      /module/ov5640_camera_int (module)
UDEV  [225.190633] add      /bus/i2c/drivers/ov564x (drivers)

$>modprobe mxc_v4l2_capture
KERNEL[267.876151] add      /module/ipu_fg_overlay_sdc (module)
KERNEL[267.880571] add      /module/ipu_csi_enc (module)
UDEV  [267.882058] add      /module/ipu_fg_overlay_sdc (module)
KERNEL[267.885927] add      /module/ipu_prp_enc (module)
UDEV  [267.887871] add      /module/ipu_csi_enc (module)
UDEV  [267.888047] add      /module/ipu_prp_enc (module)
KERNEL[267.889285] add      /module/ipu_still (module)
UDEV  [267.890705] add      /module/ipu_still (module)
KERNEL[267.891847] add      /module/ipu_bg_overlay_sdc (module)
UDEV  [267.894052] add      /module/ipu_bg_overlay_sdc (module)
KERNEL[267.901998] add      /module/mxc_v4l2_capture (module)
UDEV  [267.903648] add      /module/mxc_v4l2_capture (module)
KERNEL[267.904599] add      /devices/soc0/soc/2000000.aips-bus/20d4000.v4l2_cap_0/video4linux/video0 (video4linux)
KERNEL[267.906944] bind     /devices/soc0/soc/2000000.aips-bus/20d4000.v4l2_cap_0 (platform)
KERNEL[267.907472] add      /bus/platform/drivers/mxc_v4l2_capture (drivers)
UDEV  [267.910128] add      /bus/platform/drivers/mxc_v4l2_capture (drivers)
UDEV  [267.924422] add      /devices/soc0/soc/2000000.aips-bus/20d4000.v4l2_cap_0/video4linux/video0 (video4linux)
UDEV  [267.927830] bind     /devices/soc0/soc/2000000.aips-bus/20d4000.v4l2_cap_0 (platform)

逆向编译的设备树的相关部分:

soc {
    #address-cells = <0x1>;
    #size-cells = <0x1>;
    compatible = "simple-bus";
    interrupt-parent = <0x1>;
    ranges;

    aips-bus@2000000 {
        compatible = "fsl,aips-bus", "simple-bus";
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        reg = <0x2000000 0x100000>;
        ranges;

        pwm@2080000 {
            #pwm-cells = <0x2>;
            compatible = "fsl,pwm-imx";
            reg = <0x2080000 0x4000>;
            interrupts = <0x0 0x53 0x4>;
            clocks = <0x4 0x3e 0x4 0x91>;
            clock-names = "ipg", "per";
            status = "okay";
            pinctrl-names = "default";
            pinctrl-0 = <0x15>;
        };

        v4l2_cap_0@20d4000 {
            compatible = "fsl,imx6q-v4l2-capture";
            reg = <0x20d4000 0x4000>;
            interrupts = <0x0 0x39 0x4>;
            interrupt-names = "epit2";
            clocks = <0x4 0x3e 0x4 0x106>;
            clock-names = "ipg", "per";
            ipu_id = <0x0>;
            csi_id = <0x0>;
            mclk_source = <0x0>;
            mipi_camera = <0x1>;
            default_input = <0x1>;
            io3-gpios = <0x18 0xa 0x0>;
            io4-gpios = <0x18 0xb 0x0>;
            HREF-gpios = <0x19 0x9 0x0>;
            LED_EN-gpios = <0x1a 0x6 0x0>;
            LASER2-gpios = <0x1b 0x10 0x0>;
            LASER3-gpios = <0x1b 0x11 0x0>;
            LED2_EN-gpios = <0x1b 0x13 0x0>;
            LASER1-gpios = <0x1b 0x14 0x0>;
            LED1_EN-gpios = <0x1b 0x15 0x0>;
            FLEN-gpios = <0x1b 0x16 0x0>;
            LED_CUR1-gpios = <0x18 0xc 0x0>;
            LED_CUR2-gpios = <0x18 0xf 0x0>;
            CHARGE_EN-gpios = <0x18 0x2 0x0>;
            FLASH_FLAG-gpios = <0x18 0x1a 0x1>;
            status = "okay";
        };
    };

    aips-bus@2100000 {
            compatible = "fsl,aips-bus", "simple-bus";
            #address-cells = <0x1>;
            #size-cells = <0x1>;
            reg = <0x2100000 0x100000>;
            ranges;

        usdhc@2190000 {
                compatible = "fsl,imx6q-usdhc";
                reg = <0x2190000 0x4000>;
                interrupts = <0x0 0x16 0x4>;
                clocks = <0x4 0xa3 0x4 0xa3 0x4 0xa3>;
                clock-names = "ipg", "ahb", "per";
                bus-width = <0x4>;
                status = "okay";
                pinctrl-names = "default";
                pinctrl-0 = <0x36 0x37>;
                vmmc-supply = <0x38>;
                mmc-pwrseq = <0x39>;
                no-1-8-v;
                enable-sdio-wakeup;
                non-removable;
                ti,non-removable;
                ti,needs-special-hs-handling;
                cap-power-off-card;
                keep-power-in-suspend;
                #address-cells = <0x1>;
                #size-cells = <0x0>;

                wlcore@0 {
                    compatible = "ti,wl1831";
                    reg = <0x2>;
                    interrupts = <0x4 0x4>;
                    interrupt-parent = <0x1a>;
                    platform-quirks = <0x1>;
                };
            };

i2c@21a0000 {
    #address-cells = <0x1>;
    #size-cells = <0x0>;
    compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
    reg = <0x21a0000 0x4000>;
    interrupts = <0x0 0x24 0x4>;
    clocks = <0x4 0x7d>;
    status = "okay";
    clock-frequency = <0x186a0>;
    pinctrl-names = "default";
    pinctrl-0 = <0x3d>;

    ov5640_mipi@3c {
        compatible = "ovti,ov564x_mipi";
        reg = <0x3c>;
        pintctrl-names = "default";
        pinctrl-0 = <0x2e>;
        clocks = <0x4 0xc8>;
        clock-names = "csi_mclk";
        clock-rates = <0x16e3600>;
        DOVDD-supply = <0x3e>;
        AVDD-supply = <0x3e>;
        DVDD-supply = <0x3e>;
        pwn-gpios = <0x1b 0x8 0x0>;
        rst-gpios = <0x19 0xa 0x0>;
        ipu_id = <0x0>;
        csi_id = <0x0>;
        default_input = <0x1>;
        mclk = <0x16e3600>;
        mclk_source = <0x0>;
        status = "okay";
    };
};
    };
};

相关内容