IMX8MM平台SNVS子模块内核驱动probe函数未调用排查求助
IMX8MM SNVS MC驱动probe函数未触发问题排查
问题描述
为IMX8MM处理器编写调用SNVS模块的简易内核驱动,参考内核rtc-snvs.c实现,但新增的snvs_mc驱动的probe函数始终未触发。已在imx8mm.dtsi中添加snvs_mc节点,相关代码如下:
原设备树片段
snvs: snvs@30370000 { compatible = "fsl,sec-v4.0-mon","syscon", "simple-mfd"; reg = <0x30370000 0x10000>; snvs_rtc: snvs-rtc-lp { compatible = "fsl,sec-v4.0-mon-rtc-lp"; regmap = <&snvs>; offset = <0x34>; interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MM_CLK_SNVS_ROOT>; clock-names = "snvs-rtc"; }; snvs_pwrkey: snvs-powerkey { compatible = "fsl,sec-v4.0-pwrkey"; regmap = <&snvs>; interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MM_CLK_SNVS_ROOT>; clock-names = "snvs-pwrkey"; linux,keycode = <KEY_POWER>; wakeup-source; status = "disabled"; }; };
修改后的设备树片段
snvs: snvs@30370000 { compatible = "fsl,sec-v4.0-mon","syscon", "simple-mfd"; reg = <0x30370000 0x10000>; snvs_mc: snvs-mc-lp { compatible = "fsl,sec-v4.0-mc-lp"; regmap = <&snvs>; }; snvs_rtc: snvs-rtc-lp { compatible = "fsl,sec-v4.0-mon-rtc-lp"; regmap = <&snvs>; offset = <0x34>; interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MM_CLK_SNVS_ROOT>; clock-names = "snvs-rtc"; }; snvs_pwrkey: snvs-powerkey { compatible = "fsl,sec-v4.0-pwrkey"; regmap = <&snvs>; interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MM_CLK_SNVS_ROOT>; clock-names = "snvs-pwrkey"; linux,keycode = <KEY_POWER>; wakeup-source; status = "disabled"; }; };
自定义驱动框架代码
static const struct of_device_id snvs_mc_ids[] = { { .compatible = "fsl,sec-v4.0-mc-lp", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, snvs_mc_ids); static struct platform_driver snvs_mc_driver = { .driver = { .name = "snvs_mc", .pm = &snvs_mc_pm_ops, .of_match_table = snvs_mc_ids, }, .probe = snvs_mc_probe, }; module_platform_driver(snvs_mc_driver); MODULE_LICENSE("GPL");
参考的内核rtc-snvs.c代码片段
static const struct of_device_id snvs_dt_ids[] = { { .compatible = "fsl,sec-v4.0-mon-rtc-lp", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, snvs_dt_ids); static struct platform_driver snvs_rtc_driver = { .driver = { .name = "snvs_rtc", .pm = &snvs_rtc_pm_ops, .of_match_table = snvs_dt_ids, }, .probe = snvs_rtc_probe, }; module_platform_driver(snvs_rtc_driver); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_DESCRIPTION("Freescale SNVS RTC Driver"); MODULE_LICENSE("GPL");
排查要点
验证MFD子节点的兼容性匹配
父节点snvs属于*MFD(Multi-Function Device)*框架,会遍历子节点创建设备。先通过命令确认设备树节点是否正确加载:cat /proc/device-tree/snvs@30370000/snvs-mc-lp/compatible确保输出的字符串和驱动中
of_match_table里的"fsl,sec-v4.0-mc-lp"完全一致,无拼写、大小写或空格差异。确认驱动的编译与加载状态
- 若驱动编译进内核,检查内核配置是否开启对应选项(如
CONFIG_SNVS_MC=y); - 若作为模块,执行
lsmod | grep snvs_mc确认模块是否加载,未加载则手动加载并查看日志:
查看是否有驱动注册失败、兼容性不匹配的报错信息。insmod snvs_mc.ko dmesg | tail -20
- 若驱动编译进内核,检查内核配置是否开启对应选项(如
检查MFD子节点的必要属性
参考snvs_rtc节点,它包含时钟、偏移量等属性,而你的snvs_mc节点仅配置了regmap。部分MFD子驱动需要额外属性才能被框架识别,尝试添加时钟属性并更新驱动:
修改设备树节点:snvs_mc: snvs-mc-lp { compatible = "fsl,sec-v4.0-mc-lp"; regmap = <&snvs>; clocks = <&clk IMX8MM_CLK_SNVS_ROOT>; clock-names = "snvs-mc"; };驱动中添加时钟获取逻辑(参考
rtc-snvs.c的时钟处理)。查看内核MFD框架日志
过滤内核日志中的MFD相关信息,查看是否有节点处理错误:dmesg | grep -i mfd dmesg | grep snvs重点关注是否有
snvs-mc-lp节点被跳过、属性缺失或兼容性不匹配的提示。排查驱动注册的潜在问题
若snvs_mc_pm_ops未正确定义,可能导致驱动注册失败。暂时注释掉.pm字段测试:static struct platform_driver snvs_mc_driver = { .driver = { .name = "snvs_mc", // .pm = &snvs_mc_pm_ops, .of_match_table = snvs_mc_ids, }, .probe = snvs_mc_probe, };
内容的提问来源于stack exchange,提问作者OfficeMan
相关产品推荐
相关产品推荐

