问题:
多个设备驱动程序(在设备树中指定)在启动期间未加载。所有内置驱动程序均已加载,没有任何问题。如果在命令行中使用 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";
};
};
};
};