1

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";
    };
};
    };
};
4
  • 1
    "All built in drivers get loaded" -- You're misusing the word "loading", which simply means transferred into memory. So of course built-in drivers get loaded into memory as part of the kernel image. You seem to misuse "loaded" in place of "initialized" or "installed". "The drivers successfully load and function .." -- You need to understand the difference between "loading" and driver initialization. BTW driver modules typically get installed by the kernel using request_module(), and then a userspace application (e.g. [e]udev). assists in performing the load.
    – sawdust
    Mar 24, 2021 at 4:47
  • 1
    Try building a kernel where these drivers that "are not loading" are instead built-in drivers.
    – sawdust
    Mar 24, 2021 at 4:56
  • I have tried building some of them in and I get a lot of build errors that do not happen when they are built as a module. This may be do to a Yocto build environment issue or a cross compile issue.
    – schustercp
    Mar 24, 2021 at 15:47
  • To be very specific all drivers that are built into the kernel that are referenced in the device tree "successfully load and function". Any drivers built as a module "successfully load and function" when called with modprobe from the command line. After I load them manualy, the device works as expected. I can connect and use WIFI networks (wlan0 shows up). /dev/video0 shows up and an open call succeeds for that device. I can see messages from the modules show up in the log (dmesg). I have all kernel log levels set to 8. I will research into request_module().
    – schustercp
    Mar 24, 2021 at 15:47

0

You must log in to answer this question.

Browse other questions tagged .