Несоответствие дерева устройств: .probe никогда не вызывается
У меня проблемы с пониманием того, как работает дерево устройств, или, в частности, почему этот драйвер не запускается. Это в ядре производителя Rockchip для Android, версия 3.10
drivers / watchdog / rk29_wdt.c (уменьшено для удобства чтения)
static const struct of_device_id of_rk29_wdt_match[] = {
{ .compatible = "rockchip,watch dog" }
};
static struct platform_driver rk29_wdt_driver = {
.probe = rk29_wdt_probe,
[..]
.of_match_table = of_rk29_wdt_match,
.name = "rk29-wdt",
},
};
static int __init watchdog_init(void)
{
printk("watchdog_init\n");
return platform_driver_register(&rk29_wdt_driver);
}
а это соц дци
арка / руки / загрузки / DTS /rk3288.dtsi
watchdog: wdt@2004c000 {
compatible = "rockchip,watch dog";
reg = <0xff800000 0x100>;
clocks = <&pclk_pd_alive>;
clock-names = "pclk_wdt";
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
rockchip,irq = <0>;
rockchip,timeout = <2>;
rockchip,atboot = <1>;
rockchip,debug = <0>;
status = "okay";
};
однако функция драйвера.probe никогда не вызывается. Он компилируется и вызывается функция __init. Я подозреваю, что это связано с тем, что запись в дереве устройств не совпадает? Может быть, пространство это проблема?
Или есть еще что-то, что запускается до.probe, определяющее, должен ли драйвер продолжаться?
Также я не уверен, как работает сплющенное дерево, так что, возможно, это уместно:
арка / рука / маш-Rockchip/rk3288
DT_MACHINE_START(RK3288_DT, "Rockchip RK3288 (Flattened Device Tree)")
.smp = smp_ops(rockchip_smp_ops),
.map_io = rk3288_dt_map_io,
.init_time = rk3288_dt_init_timer,
.dt_compat = rk3288_dt_compat,
.init_late = rk3288_init_late,
.reserve = rk3288_reserve,
.restart = rk3288_restart,
MACHINE_END
1 ответ
Это может произойти несколькими способами, и большинство из них находятся далеко от самого кода драйвера. Во-первых, один фрагмент.dtsi не рассказывает всей истории - синтаксис дерева устройств является иерархическим, поэтому свойства (в частности, status
) все еще может быть переопределено.dts уровня платы, который включает в себя основной файл.dtsi SoC . Во-вторых, скомпилированный DTB также не является последним словом, поскольку загрузчик может динамически изменять его перед передачей его ядру - это обычно делается для узлов памяти и методов включения SMP, но потенциально может повлиять на что угодно.
Этот вид отладки часто лучше всего решать в обратном порядке, изучая состояние загруженной системы, а затем работая в обратном направлении, чтобы выяснить, как все получилось - специфика этого конкретного вопроса уже кое-что проясняет, но ради полнота:
- Если ядро знает о драйвере, и оно загружено и правильно инициализировано, оно должно появиться где-то в /sys/bus/*/drivers / - в противном случае оно может быть в модуле, который нуждается в загрузке, или он не смог инициализироваться из-за некоторой неудовлетворенной зависимости от какого-либо другого драйвера или ресурса.
- Если ядро знает об устройстве, оно должно появиться где-то в /sys/bus/*/devices /, и если оно правильно связано с драйвером и проверено, то они оба должны иметь символическую ссылку друг на друга.
- Если устройство нигде не найдено, то в системе на базе DT следующим местом для проверки будет / proc / device-tree/ (зависит от CONFIG_PROC_DEVICETREE на старых ядрах и канонически находится в / sys / firmware / devicetree / base / на более новых) - это покажет вид DT в том виде, в котором его нашло ядро, и немного осмотритесь там, надо надеяться, прояснить любые отсутствующие узлы или свойства не на своем месте, такие как отключенный узел, вызывающий ядро пропустить создание устройства вообще. Помните, что сами файлы свойств - это просто необработанные данные - так что вы, вероятно, захотите подглядывать с помощью hexdump, а не cat - и что все числовые ячейки имеют порядок байтов с прямым порядком байтов.
Я заметил, что в вашем определении вы упускаете так называемый SENTINEL в своем массиве, пустую пустую структуру. Вот пример:
static const struct of_device_id clk_ids[] = {
{ .compatible = "sirf,atlas7-clkc" },
{},
};