跳转至

Thermal Management 使用参考


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 10/08/2026

    1. 概述

    SGS thermal management 子系统是维持 SoC 工作在安全温度范围内的软件层。它构建在标准 Linux thermal 框架之上,复用片上 Tsensor 作为温度源。

    默认策略是带滞回的双状态循环(详见第 3 章):温度低于 115°C 时 CPU 可使用全 DVFS 范围;温度一旦达到 115°C 即被强制降到最低 OPP,只有当温度回落到 100°C 以下时才恢复全 DVFS 范围。

    本子系统将 Linux thermal 的三个概念串联起来:

    • 一个绑定到 SGS Tsensor 的 thermal zonesoc-thermal)。
    • 一组 trip point(被动降频点 + 临界关机点)。
    • 由自定义 governor sgs_highest 驱动的 cooling device(CPU DVFS 和 IPU 加速器),在跨越 trip 时被调用。

    2. 关键字说明

    • Thermal zone(热区)

      一个逻辑对象,聚合了一个温度传感器、一组 trip point 和绑定到这些 trip 的 cooling device。具体定义见 <Kernel>/Documentation/devicetree/bindings/thermal/thermal-zones.yaml

    • Trip point(触发点)

      thermal zone 内部的温度阈值。每个 trip 包含温度、滞回值和类型(passivecriticalhot 等)。

    • Cooling device(降温设备)

      被触发后可以散热的设备。mhera 上绑定到 SoC thermal zone 的 cooling device 有两个:CPU DVFS(通过降低 CPU 频率/电压降频)和 IPU 加速器(通过降低 IPU 时钟降频)。IPU 节点在 DTS 中标签为 dla,因此 cooling-device 引用写作 <&dla ...>

    • Governor(策略模块)

      决定当 trip 被跨越时 cooling device 应处于哪个 cooling state 的策略模块。内核原生提供 step_wisepower_allocatoruser_space 等多个 governor;SGS 在此基础上新增了 sgs_highest,并在 mhera 上选为默认 governor。

    • sgs_highest governor

      SGS 贡献的双点 governor:一旦到达 trip 温度就立即把 cooling device 推到上界(instance->upper),只有当温度回落到 trip_temp - hysteresis 以下时才释放回 state 0。详细行为见 3.1 节。

    3. 功能描述

    3.1. 双状态降频策略

    下图说明了 mhera 默认的 thermal 策略。阈值取自 arch/arm64/boot/dts/sgs/mhera.dtsitarget trip = 115000 m°C,hysteresis = 15000 m°C):

    Full DVFS Range                    Lowest Frequency
    (No Throttling)                      (Throttled)
    +--------------+                   +--------------+
    |              |  Temp >= 115 C    |              |
    |   CPU runs   | ----------------> |   CPU runs   |
    |  at any freq |                   |  at min freq |
    |              |  Temp <= 100 C    |              |
    |              | <---------------- |              |
    +--------------+                   +--------------+
         (State 0)                         (State MAX)
    

    故意选取了 15°C 这个较大的滞回值,避免温度在 trip 附近反复震荡 —— 之前 10°C 的滞回会让 CPU 在 115°C 附近反复进出降频状态。整个循环包含三个阶段:

    • 温度低于 115°C 时 cooling device 停在 state 0 —— cpufreq 表中所有 OPP 均可使用。
    • 到达 115°C 时,sgs_highest governor 把 cooling device 一次性推到上界(instance->upper)。对 CPU DVFS 而言,upper 对应 OPP 表中的最低频率,因此 CPU 被钉在最低 OPP。
    • CPU 会停在最低 OPP,直到温度回落到 115 - 15 = 100°C,governor 才把 cooling device 释放回 state 0。

    3.2. 临界 trip

    另设一个 125°C 的 critical trip,会触发内核的 thermal 关机路径(thermal_zone_device_check() → orderly poweroff)。该 trip 的 hysteresis = <0>,因为它是一刀切的硬关机点,不是恢复点。

    3.3. 内核态温度 API

    Tsensor 驱动导出了一个辅助函数,任何树内内核模块都可以调用它读取当前 SoC 温度:

    int sgs_get_temp(void);
    

    其内部查找 soc-thermal zone,读取温度,并以摄氏度(整数)返回。详见 7.1 节。

    4. 硬件连接介绍

    无。Thermal management 复用片上 Tsensor,不涉及任何外部管脚或元件。

    5. Uboot 用法介绍

    不支持。Thermal management 完全运行在 kernel 中。

    6. Kernel 用法介绍

    6.1. Kernel Config 配置

    menuconfig 中相关选项分布在两个菜单下:

    Device Drivers  --->
        [*] Thermal drivers  --->
            [*] Enable writable trip points         (THERMAL_WRITABLE_TRIPS)
            [*] Generic cpu cooling support         (CPU_THERMAL)
            ()  Default Thermal governor            ---> sgs_highest
                                                        (THERMAL_DEFAULT_GOV_SGS_HIGHEST)
            [*]   sgs_highest                       (THERMAL_GOV_SGS_HIGHEST)
            [*]   step_wise                         (THERMAL_GOV_STEP_WISE)
            [*]   User_space thermal governor       (THERMAL_GOV_USER_SPACE)
        [*] Sgs SoC platform drivers  --->
            <*>   SGS T-sensor driver               (SGS_TSENSOR)
    

    每个发布的 mhera defconfig 中均显式打开了以下配置(见 arch/arm64/configs/mhera_ssm004a_*_defconfig):

    CONFIG_THERMAL_DEFAULT_GOV_SGS_HIGHEST=y
    CONFIG_THERMAL_GOV_STEP_WISE=y
    CONFIG_THERMAL_GOV_SGS_HIGHEST=y
    CONFIG_CPU_THERMAL=y
    CONFIG_THERMAL_WRITABLE_TRIPS=y
    CONFIG_SGS_TSENSOR=y
    

    CONFIG_THERMAL_DEFAULT_GOV_SGS_HIGHEST 会让 drivers/thermal/thermal_core.h 中的 DEFAULT_THERMAL_GOVERNOR 宏展开为 "sgs_highest"。如果未设置,内核会回退到原生默认 governor(step_wise),后者并不实现 3.1 节描述的策略。

    6.2. DTS 配置

    Thermal management 需要两部分设备树:sgs_thermal 传感器节点(已在 Tsensor 文档中说明)和 thermal-zones 块。

    6.2.1. CPU 和 IPU 节点 —— 声明为 cooling device

    在 CPU 节点中加入 #cooling-cells = <2>,cpufreq 驱动才能将其注册为 cooling device:

    cpu0: cpu@0 {
        compatible = "arm,cortex-a53";
        clocks = <&CLK_cpu_pll>, <&CLK_cpu_pll>;
        operating-points-v2 = <&cpu0_opp_table>;
        #cooling-cells = <2>;          /* CPU_THERMAL 必需 */
        reg = <0x000>;
    };
    

    sgs cpufreq 驱动在其 cpufreq_driver 结构体上设置了 .flags = CPUFREQ_IS_COOLING_DEV,因此只要存在该 cell,内核就会自动把 CPU 注册为 cooling device。

    IPU 加速器(DTS 节点标签为 dlacompatible = "sgs,dla")以同样方式注册为第二个 cooling device —— 给节点加上 label 并添加 #cooling-cells = <2>

    dla: dla {
        compatible = "sgs,dla";
        interrupts = <GIC_SPI INT_IRQ_IPU2TOP0 IRQ_TYPE_LEVEL_HIGH>,
                     <GIC_SPI INT_IRQ_IPU2TOP1 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&CLK_ipupll_clk>;
        status = "ok";
        #cooling-cells = <2>;          /* CPU_THERMAL 必需 */
    };
    

    当 trip 被跨越时,sgs_highest governor 会把所有绑定的 cooling device 都推到各自上界,因此 CPU 被钉在最低 OPP 的同时 IPU 也会被降频。

    6.2.2. thermal-zones 块

    thermal_zones: thermal-zones {
        soc_thermal: soc-thermal {
            polling-delay-passive = <100>;
            polling-delay = <1000>;
            thermal-sensors = <&sgs_thermal 0>;
    
            trips {
                target: trip-point-0 {
                    temperature = <115000>;   /* mC */
                    hysteresis = <15000>;     /* mC,100 C 时恢复 */
                    type = "passive";
                };
                soc_crit: soc-crit {
                    temperature = <125000>;   /* mC */
                    hysteresis = <0>;
                    type = "critical";
                };
            };
    
            cooling-maps {
                map0 {
                    trip = <&target>;
                    cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
                                     <&dla 0 1>;
                };
            };
        };
    };
    

    thermal 驱动支持的属性:

    属性 说明
    thermal-sensors 温度传感器的 phandle,此处为 sgs_thermal 节点。
    polling-delay 没有被动 trip 触发时的轮询周期(ms)。
    polling-delay-passive 被动 trip 触发后的轮询周期(ms)。
    trips/temperature trip 阈值,单位 millicelsius。
    trips/hysteresis governor 释放 cooling device 前需要回落的温度差。
    trips/type passive 表示降频点,critical 表示关机点。
    cooling-maps trip 与 cooling device 的绑定。每条写作 <&dev min_state max_state>THERMAL_NO_LIMIT 让 governor 任意选取设备支持的 state。CPU 用 THERMAL_NO_LIMIT THERMAL_NO_LIMIT(全 DVFS 范围),IPU 用 0 1(两个 state:0 = 满速,1 = 降频)。

    实际的 mhera.dtsi 用 #ifdef CONFIG_CPU_THERMALtrip-point-0cooling-maps 块包了起来,因此若 CONFIG_CPU_THERMAL 被关闭,编译出的 DTB 里只剩 critical trip —— 没有 DVFS 降频。critical trip 始终存在,是最后一道防线。

    完整的 thermal-zone 绑定语法请参考:<Kernel>/Documentation/devicetree/bindings/thermal/thermal-zones.yaml

    6.3. Padmux 配置

    无。

    6.4. 模块使用介绍

    6.4.1. SYSFS —— 读取温度

    Linux thermal 框架为每个 thermal zone 暴露一组 sysfs 节点。SoC zone 的名称为 soc-thermal

    # 读取当前温度(millicelsius)
    cat /sys/class/thermal/thermal_zone0/temp
    
    # 读取 type 字符串
    cat /sys/class/thermal/thermal_zone0/type
    # -> soc-thermal
    
    # 列出 cooling device 及其当前 state
    cat /sys/class/thermal/cooling_device0/cur_state
    cat /sys/class/thermal/cooling_device0/max_state
    

    每个 trip 也有独立的 sysfs 属性,例如 /sys/class/thermal/thermal_zone0/trip_point_0_temp/sys/class/thermal/thermal_zone0/trip_point_0_type。由于打开了 CONFIG_THERMAL_WRITABLE_TRIPS=y,这些节点运行时可写。

    6.4.2. SYSFS —— 强制注入温度(调试用)

    Tsensor 驱动在 thermal-zone 设备上注册了一个只写的 test_temp 属性。写入非零值(单位 millicelsius)后,驱动会把这个值当作温度上报,而不是真实的 Tsensor 读数。这样在一块实际上达不到 115°C 的板子上也能完整验证 thermal 策略:

    # 强制 SoC 上报 120 C —— governor 应该把 CPU 钉在最低频
    echo 120000 > /sys/class/thermal/thermal_zone0/test_temp
    
    # 恢复真实 Tsensor 读数
    echo 0 > /sys/class/thermal/thermal_zone0/test_temp
    

    test_temp 仅用于 EVB 调试和自动化测试,对量产部署没有影响。

    6.4.3. 运行时切换 governor

    governor 可以按 zone 在运行时通过 sysfs 切换,便于在同一块板子上对比 sgs_higheststep_wise

    # 可选 governor 列表
    cat /sys/class/thermal/thermal_zone0/available_policies
    
    # 当前 governor
    cat /sys/class/thermal/thermal_zone0/policy
    
    # 切换到 step_wise
    echo step_wise > /sys/class/thermal/thermal_zone0/policy
    
    # 切回 sgs_highest
    echo sgs_highest > /sys/class/thermal/thermal_zone0/policy
    

    6.5. Sample code

    6.5.1. 用户空间读取温度

    awk '{printf "SoC temp: %.1f C\n", $1/1000}' \
        /sys/class/thermal/thermal_zone0/temp
    

    6.5.2. 内核模块读取温度

    #include <linux/thermal.h>
    
    int soc_temp_degC(void)
    {
        struct thermal_zone_device *tzd;
        int temp, ret;
    
        tzd = thermal_zone_get_zone_by_name("soc-thermal");
        if (IS_ERR(tzd))
            return -ENODEV;
    
        ret = thermal_zone_get_temp(tzd, &temp);
        if (ret)
            return ret;
    
        return temp / 1000;   /* millicelsius -> 摄氏度 */
    }
    

    或者直接调用 Tsensor 驱动导出的辅助函数:

    extern int sgs_get_temp(void);   /* 返回摄氏度 */
    
    int now = sgs_get_temp();
    

    7. API 参考

    内核态 API 声明于 drivers/sgs_common/tsensor/drv/src/drv_tsensor_lnx.c,对任何依赖 SGS Tsensor 驱动的模块可用。

    7.1. sgs_get_temp

    • 功能

      soc-thermal zone 读取当前 SoC 温度。

    • 语法

      int sgs_get_temp(void)
      
    • 参数

      参数 说明
    • 返回值

      返回值 说明
      N >= 0 当前 SoC 温度,单位摄氏度。
      0 当找不到 soc-thermal zone 或 thermal_zone_get_temp 失败时返回。

    8. FAQ

    Q1:为什么需要 sgs_highest?内核不是已经有 step_wise 了吗?

    step_wise 每个轮询周期只走一步,无法立即把 CPU 降到最低 OPP。要强制降到最低 OPP,cooling-device 绑定里需要硬编码 min_state/max_state,但 mhera 使用一张统一的 OPP 表,其有效长度由 cpufreq_cfg 根据芯片型号在运行时裁剪,DTS 中的硬编码范围无法跟随这种变化,因此需要一个总是直接跳到 instance->upper 的 governor。

    Q2:滞回值为什么从 10°C 调到 15°C?

    10°C(即 105°C 恢复)的滞回让 CPU 在阈值附近反复切换最低 OPP 和全 OPP 表,产生大量 thermal 事件,肉眼可见的频率抖动也很明显。15°C(100°C 恢复)在 EVB 上验证更稳定。

    Q3:如果 CONFIG_CPU_THERMAL 关掉会怎样?

    target 被动 trip 和 cooling-maps 块会从 DTB 中编译排除。只剩 125°C 的 critical trip,SoC 仍能在过温时关机,但不会有 DVFS 降频。mhera 默认 defconfig 全部打开了 CONFIG_CPU_THERMAL

    Q4:板子永远达不到 115°C,如何在 EVB 上验证策略?

    test_temp 调试节点(6.4.2 节)注入伪造温度,然后观察 /sys/class/thermal/cooling_device0/cur_state/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq,确认 cooling state 和 CPU 频率按预期变化。