How to debug a driver failing to bind to a device on Linux?
A working solution to get the driver to bind to the device is:
cgublock: jz4780-cgublock@10000000 {
compatible = "simple-bus", "syscon";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x10000000 0x100>;
ranges;
cgu: jz4780-cgu@10000000 {
compatible = "ingenic,jz4780-cgu";
reg = <0x10000000 0x100>;
clocks = <&ext>, <&rtc>;
clock-names = "ext", "rtc";
#clock-cells = <1>;
};
rng: rng@d8 {
compatible = "ingenic,jz4780-rng";
reg = <0x100000d8 0x8>;
};
};
This was found by staring at other examples. I would prefer a solution where I get a proper diagnosis why the previous attempt is incorrect.
Related videos on Youtube
Fakt7
Updated on September 18, 2022Comments
-
Fakt7 over 1 year
I am trying to figure out why the following device is not setup to its driver on my Creator CI20. For reference I am using a Linux kernel v4.13.0 and doing the compilation locally:
make ARCH=mips ci20_defconfig make -j8 ARCH=mips CROSS_COMPILE=mipsel-linux-gnu- uImage
From the running system I can see:
ci20@ci20:~# find /sys | grep rng /sys/firmware/devicetree/base/jz4780-cgu@10000000/rng@d8 /sys/firmware/devicetree/base/jz4780-cgu@10000000/rng@d8/compatible /sys/firmware/devicetree/base/jz4780-cgu@10000000/rng@d8/name /sys/bus/platform/drivers/jz4780-rng /sys/bus/platform/drivers/jz4780-rng/bind /sys/bus/platform/drivers/jz4780-rng/unbind /sys/bus/platform/drivers/jz4780-rng/uevent
So the device is seen by the kernel at runtime, now the missing piece is why the driver is never binded ? I would have expected something like this:
/sys/bus/platform/drivers/jz4780-rng/100000d8.rng
I did find some other posts explaining how to debug a running system, such as:
- https://stackoverflow.com/questions/28406776/driver-binding-using-device-tree-without-compatible-string-in-the-driver
- https://stackoverflow.com/questions/35580862/device-tree-mismatch-probe-never-called
- https://stackoverflow.com/questions/41446737/platform-device-driver-autoloading-mechanism
- Is it possible to get the information for a device tree using /sys of a running kernel?
While the information is accurate on those posts, it is not very helpful for me. Since I am building locally my kernel (I added
printk
in the probe function ofjz4780-rng
driver), my question is instead:-
what option should I turn on at compile time so that the kernel prints an accurate information on its failure to call the probe function for the
jz4780-rng
driver ? - In particular how do I print the complete list of the tested bus/driver for
driver_probe_device
?
I am ok to add
printk
anywhere in the code to debug this. The question is rather: which function is traversing the device tree and calling the probe/init function ?For reference:
$ dtc -I fs -O dts /sys/firmware/devicetree/base | grep -A 1 rng rng@d8 { compatible = "ingenic,jz4780-rng"; };
compatible string is declared as:
cgu: jz4780-cgu@10000000 { compatible = "ingenic,jz4780-cgu", "syscon"; reg = <0x10000000 0x100>; clocks = <&ext>, <&rtc>; clock-names = "ext", "rtc"; #clock-cells = <1>; rng: rng@d8 { compatible = "ingenic,jz4780-rng"; }; };
And in the driver as:
static const struct of_device_id jz4780_rng_dt_match[] = { { .compatible = "ingenic,jz4780-rng", }, { }, }; MODULE_DEVICE_TABLE(of, jz4780_rng_dt_match); static struct platform_driver jz4780_rng_driver = { .driver = { .name = "jz4780-rng", .of_match_table = jz4780_rng_dt_match, }, .probe = jz4780_rng_probe, .remove = jz4780_rng_remove, }; module_platform_driver(jz4780_rng_driver);
Update1:
When I build my kernel with
CONFIG_DEBUG_DRIVER=y
, here is what I can see:# grep driver_probe_device syslog Sep 6 10:08:07 ci20 kernel: [ 0.098280] bus: 'platform': driver_probe_device: matched device 10031000.serial with driver ingenic-uart Sep 6 10:08:07 ci20 kernel: [ 0.098742] bus: 'platform': driver_probe_device: matched device 10033000.serial with driver ingenic-uart Sep 6 10:08:07 ci20 kernel: [ 0.099209] bus: 'platform': driver_probe_device: matched device 10034000.serial with driver ingenic-uart Sep 6 10:08:07 ci20 kernel: [ 0.106945] bus: 'platform': driver_probe_device: matched device 1b000000.nand-controller with driver jz4780-nand Sep 6 10:08:07 ci20 kernel: [ 0.107282] bus: 'platform': driver_probe_device: matched device 134d0000.bch with driver jz4780-bch Sep 6 10:08:07 ci20 kernel: [ 0.107470] bus: 'platform': driver_probe_device: matched device 16000000.dm9000 with driver dm9000 Sep 6 10:08:07 ci20 kernel: [ 0.165618] bus: 'platform': driver_probe_device: matched device 10003000.rtc with driver jz4740-rtc Sep 6 10:08:07 ci20 kernel: [ 0.166177] bus: 'platform': driver_probe_device: matched device 10002000.jz4780-watchdog with driver jz4740-wdt Sep 6 10:08:07 ci20 kernel: [ 0.170930] bus: 'platform': driver_probe_device: matched device 1b000000.nand-controller with driver jz4780-nand
But only:
# grep rng syslog Sep 6 10:08:07 ci20 kernel: [ 0.166842] bus: 'platform': add driver jz4780-rng Sep 6 10:08:42 ci20 kernel: [ 54.584451] random: crng init done
As a side note, the
rng
toplevel node:cgu
is not referenced here, but there is ajz4780-cgu
driver.
Update2:
If I move the
rng
node declaration outside the toplevelcgu
node, I can at least see some binding happening at last:# grep rng /var/log/syslog Sep 6 10:30:57 ci20 kernel: [ 0.167017] bus: 'platform': add driver jz4780-rng Sep 6 10:30:57 ci20 kernel: [ 0.167033] bus: 'platform': driver_probe_device: matched device 10000000.rng with driver jz4780-rng Sep 6 10:30:57 ci20 kernel: [ 0.167038] bus: 'platform': really_probe: probing driver jz4780-rng with device 10000000.rng Sep 6 10:30:57 ci20 kernel: [ 0.167050] jz4780-rng 10000000.rng: no pinctrl handle Sep 6 10:30:57 ci20 kernel: [ 0.167066] devices_kset: Moving 10000000.rng to end of list Sep 6 10:30:57 ci20 kernel: [ 0.172774] jz4780-rng: probe of 10000000.rng failed with error -22 Sep 6 10:31:32 ci20 kernel: [ 54.802794] random: crng init done
Using:
rng: rng@100000d8 { compatible = "ingenic,jz4780-rng"; };
I can also verify:
# find /sys/ | grep rng /sys/devices/platform/10000000.rng /sys/devices/platform/10000000.rng/subsystem /sys/devices/platform/10000000.rng/driver_override /sys/devices/platform/10000000.rng/modalias /sys/devices/platform/10000000.rng/uevent /sys/devices/platform/10000000.rng/of_node /sys/firmware/devicetree/base/rng@100000d8 /sys/firmware/devicetree/base/rng@100000d8/compatible /sys/firmware/devicetree/base/rng@100000d8/status /sys/firmware/devicetree/base/rng@100000d8/reg /sys/firmware/devicetree/base/rng@100000d8/name /sys/bus/platform/devices/10000000.rng /sys/bus/platform/drivers/jz4780-rng /sys/bus/platform/drivers/jz4780-rng/bind /sys/bus/platform/drivers/jz4780-rng/unbind /sys/bus/platform/drivers/jz4780-rng/uevent