如何在主线Linux的sun8i平台上获取SOC温度?
环境
- 主线Linux内核5.15.35
- OrangePi Plus 2E开发板
- Yocto构建的Linux发行版
需求
需要通过/sys/class/thermal/thermal_zoneX路径获取SOC温度,但初始状态下/sys/class/thermal目录为空。
已尝试操作
内核配置
添加了以下内核配置(部分可能非必需):
CONFIG_THERMAL=y CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 CONFIG_THERMAL_HWMON=y CONFIG_THERMAL_OF=y CONFIG_THERMAL_WRITABLE_TRIPS=y CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE=y CONFIG_THERMAL_GOV_FAIR_SHARE=y CONFIG_THERMAL_GOV_STEP_WISE=y CONFIG_THERMAL_GOV_BANG_BANG=y CONFIG_CPU_THERMAL=y CONFIG_CPU_FREQ_THERMAL=y CONFIG_THERMAL_MMIO=m CONFIG_SUN8I_THERMAL=m CONFIG_GENERIC_ADC_THERMAL=m
执行sudo modprobe sun8i_thermal后模块加载成功,但/sys/class/thermal目录仍为空。
注:此前使用5.4内核时完全不支持sun8i_thermal模块,升级到5.15后模块已被支持。
11/21更新:修改设备树后的问题
对sun8i-h3.dtsi设备树文件做了如下补丁修改:
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index ae4f933ab..4e642df08 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -230,8 +230,8 @@ mali: gpu@1c40000 { ths: thermal-sensor@1c25000 { compatible = "allwinner,sun8i-h3-ths"; - reg = <0x01c25000 0x400>; - interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x01c25000 0x400>,<0x01c14234 0x4>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; resets = <&ccu RST_BUS_THS>; clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; clock-names = "bus", "mod";
修改后/sys/class/thermal/thermal_zone0/temp路径出现,但读取时报错:
# cat temp cat: temp: Invalid argument
过滤thermal相关的dmesg输出:
[ 0.044283] thermal_sys: Registered thermal governor 'fair_share' [ 0.044293] thermal_sys: Registered thermal governor 'bang_bang' [ 0.044315] thermal_sys: Registered thermal governor 'step_wise' [ 152.544779] WARNING: CPU: 3 PID: 2396 at drivers/thermal/thermal_core.c:496 thermal_zone_device_update.part.0+0x284/0x2a4 [ 152.555818] 'thermal_zone_device_update' must not be called without 'get_temp' ops set [ 152.563825] Modules linked in: tun cfg80211 ipt_REJECT nf_reject_ipv4 xt_multiport xt_conntrack xt_comment iptable_filter iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c ip_tables x_tables sun8i_thermal fuse autofs4 [ 152.625873] [<c079c04c>] (warn_slowpath_fmt) from [<c05b65c0>] (thermal_zone_device_update.part.0+0x284/0x2a4) [ 152.635910] [<c05b65c0>] (thermal_zone_device_update.part.0) from [<c05b67e0>] (thermal_zone_device_set_mode+0x88/0xb0) [ 152.646726] [<c05b67e0>] (thermal_zone_device_set_mode) from [<c05b7a8c>] (mode_store+0x6c/0x70)
从日志看,sun8i_thermal驱动未正确设置get_temp操作函数,导致无法读取温度。
解决建议
恢复设备树原始配置:你修改的
reg和interrupts参数是错误的。5.15内核中sun8i-h3.dtsi的原始配置是正确的——H3的THS模块寄存器基地址就是0x01c25000,不需要额外添加第二个reg;中断号31是H3 THS模块的正确硬件中断号,63并非对应THS。错误的设备树配置会导致驱动无法正确初始化硬件,进而缺失get_temp操作函数。精简内核配置:移除
CONFIG_GENERIC_ADC_THERMAL=m,H3的温度传感器是专用THS模块,不需要ADC模拟温度的驱动。保留CONFIG_SUN8I_THERMAL=m或改为y,确保CONFIG_THERMAL_OF=y已开启(你当前已配置)。验证驱动与设备树绑定:
- 加载sun8i_thermal模块后,执行
dmesg | grep sun8i_thermal,查看是否有设备探测成功的日志,例如类似sun8i_thermal 1c25000.thermal-sensor: registered thermal zone的输出。 - 用
fdtget /sys/firmware/devicetree/base/soc/thermal-sensor@1c25000 compatible确认设备树中的compatible字符串为allwinner,sun8i-h3-ths,确保与5.15内核sun8i_thermal驱动支持的匹配。
- 加载sun8i_thermal模块后,执行
检查驱动初始化状态:如果驱动未探测到设备,可能是设备树节点被禁用,或者内核配置中遗漏了相关依赖。可以尝试将
CONFIG_SUN8I_THERMAL设为y(编译进内核),而非模块加载,排除模块加载时的潜在问题。
内容的提问来源于stack exchange,提问作者smthingshwere

