Problem:
Multiple device drivers (specified in the device tree) are not loading during boot. All built in drivers get loaded with no issue. The drivers successfully load and function if modprobe is used at the command line.
Linux Kernel: 5.4.24 Hardware: Custom board with an iMX6 (ARM), ov5640 Camera, TI WL1831 Wifi chip, and an audio amp tied to a PWM output of the iMX6. Yocto (Dunfell) is used to build an SD card image for this embedded device. Root is only/always mounted read only during the boot of the kernel.
The following device drivers are not loading: wl18xx, wlcore_sdio, wlcore, ov564x_mipi (ov5640_camera_int.ko), mxc_v4l2_capture, pwm-imx. The TI WL18XX drivers are patched into the kernal from Texas Instruments source. The pwm-imx driver is something I wrote. I am using stock ov564x_mipi and mxc_v4l2_capture drivers at the moment. Side Note: This works as desired in an older 3.14 kernel. So I suspect I am missing something that the newer kernels require. The device tree is getting loaded by u-boot. The /proc/device-tree matches the device tree as expected.
My Actions:
- There are no errors or indication that drivers are even attemped to get loaded in the dmesg output.
- Reverse compile device tree to verify all devices are enabled and have a compatible attribute defined. I had to fix the device tree attribute to get these drives to function correctly after loading them with modprobe.
- Checked that all of these kernel modules use the MODULE_DEVICE_TABLE() macro.
- Checked that all the /sys/firmware/devicetree listings have a “compatible” entry that contains a matching of_device_id string that is in the source of each driver.
- Checked that the expected module alias shows up in modinfo
- Checked the depmod database. It lists all modules and the correct dependancies.
- After boot an lsmod shows nothing. No kernel modules are loaded at all.
- I have tried loading these based on info found at https://wiki.archlinux.org/index.php/Kernel_module#Loading
- There is no listing in /sys/bus/*/drivers for any of these drivers after a clean boot. When I manually load each driver with modprobe the an appropriate listing shows up in /sys/bus/*/drivers
- Researching udev has not provided answers. udev handles events that are driven by actions triggered by loading kernel modules. I can not find anything stating how, when, or why udev actually loads kernel modules.
- Tried posting this first at https://stackoverflow.com/questions/66754562/linux-device-drivers-not-loading-during-boot
My Opinions:
- Systemd is capable of running scripts that call modprobe. I do not believe systemd should load kernel modules for hardware that is not removable.
Information:
These kernel modules are present at:
/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
The following sys paths are present upon boot:
/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
Example of changes in /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 files:
/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
Example of udev Events that get fired when a driver is loaded
$> 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)
Relevant sections from reverse compiled device tree:
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";
};
};
};
};