4.3.14. Thermal 系统

4.3.14.1. Thermal 系统概述

Thermal 系统一个用于监控管理设备温度机制,旨在防止系统过热发生硬件损坏性能下降。它通过读取温度传感器数据,并根据预定阈值采取不同响应措施,如调整设备性能触发降频操作。该系统设备提供温度控制保护功能,确保硬件安全温度范围运行。

4.3.14.2. Thermal 系统功能描述

Thermal 系统典型应用

端系统三个温度传感器,分别用于显示 DDR、BPU 以及 CPU 的温度。thermal 系统相关典型应用示例如下:

  • 降频:通过减少 CPU 或 GPU 频率降低功耗,从而减少热量产生。

  • 风扇加速:如果设备风扇,系统可以通过调整风扇转速加强散热。

  • 系统关闭重启:当温度过高且无法通过降频措施控制时,系统可能进行自动关闭重启。

Thermal 系统功能原理

Thermal 系统核心原理通过读取硬件系统温度传感器值,并预设温度阈值进行对比。当温度达到某个临界值时,系统启动响应机制,采取措施防止硬件过热。

Thermal 系统功能原理如下所示:

thermal_function_principle

Thermal 系统工作方式

Thermal 系统工作方式通常分为以下几个步骤:

  1. 温度采集:通过硬件温度传感器获取实时温度数据。这些传感器可以建于处理器温度传感器,或者外部热电偶热敏电阻。

  2. 阈值设置:内核用户空间应用定义温度安全范围响应措施。通常包括高温阈值(Critical)、中等温度阈值(Warning)等。

  3. 响应策略:当温度超出预设阈值时,系统启动相应策略。响应可以是:

    • 降低频率

    • 增加风扇转速

    • 关闭不必要硬件服务

    • 触发保护(如系统关机)

  4. 温度调整:根据策略调整后,系统继续监测温度变化,并重复上述过程。

4.3.14.3. Thermal 驱动代码

Thermal 相关代码路径

kernel/drivers/thermal/thermal_of.c
kernel/drivers/thermal/thermal_core.c
kernel/include/linux/thermal.h

Thermal 设备树配置

Thermal 系统设备树定义位于 BSP 包的 kernel 文件夹下 的 arch/arm64/boot/dts/hobot/x5.dtsi 文件内:

thermal-zones {
thermal_cpu: thermal-cpu {
polling-delay-passive = <1000>;
polling-delay = <1000>;

		thermal-sensors = <&pvt 2>;

		trips {
			cpu_alert0: cpu-alert0 {
				temperature = <110000>;
				hysteresis = <500>;
				type = "passive";
			};
			cpu_alert1: cpu-alert1 {
				temperature = <95000>;
				hysteresis = <1000>;
				type = "passive";
			};
			cpu_crit: cpu-crit {
				temperature = <110000>;
				hysteresis = <0>;
				type = "critical";
			};
		};

		cooling-maps {
			cpu_map0: cpu-map0 {
				trip = <&cpu_alert1>;
				cooling-device =
						<&cpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
						<&cpu_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
						<&cpu_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
						<&cpu_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
						<&cpu_4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
						<&cpu_5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
						<&cpu_6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
						<&cpu_7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
			};
			cpu_map1: cpu-map1 {
				trip = <&cpu_alert1>;
				cooling-device = <&bpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
			};
			cpu_map2: cpu-map2 {
				trip = <&cpu_alert1>;
				cooling-device = <&gc8000 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
			};
		};
	};

	thermal_ddr: thermal-ddr {
		polling-delay-passive = <1000>;
		polling-delay = <1000>;

		thermal-sensors = <&pvt 0>;

		trips {
			ddr_alert0: ddr-alert0 {
				temperature = <95000>;
				hysteresis = <1000>;
				type = "passive";
			};
		};

		cooling-maps {
			ddr_map0: ddr-map0 {
				trip = <&ddr_alert0>;
				cooling-device = <&ddrc_freq THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
			};
		};
	};
};

设备树描述了 CPU 和 DDR 热区温度管理配置,主要包含以下部分:

  • 温度传感器:为每个热区指定相关温度传感器实例。

  • 温度阈值(trips):定义不同温度阈值(cpu_alert0cpu_alert1cpu_crit 等),每个阈值达到触发不同行为(如被动冷却临界保护)。

  • 冷却映射:定义温度阈值触发时,如何启用不同冷却设备(如 CPU 核心、BPU、GC8000、DDR 等)。

下面详细分析:

  • thermal-zones thermal-zones 节点列出所有热区配置。在这个文件中,有两个热区:thermal_cpu(对应 CPU 的温度管理)和 thermal_ddr(对应 DDR 内存温度管理)。

  • thermal_cpu: thermal-cpu 这个部分定义与 CPU 相关热区,包含以下关键配置:

    • polling-delay-passivepolling-delay:这两个属性设定热区轮询延时,单位毫秒。polling-delay-passive处于被动模式轮询延时,而 polling-delay正常模式轮询延时。这里它们设置为 1000 毫秒(即 1 秒)。

    • thermal-sensors:这个属性定义热区相关温度传感器。在此处,< &pvt 2 > 表示与 CPU 温度监控相关传感器,它指向一个名为 pvt传感器,并且选择第二个实例。

  • trips (CPU) trips 描述不同温度阈值行为(触发条件),即温度达到某个水平系统如何反应。在这个文件中,有三个阈值:

    • cpu_alert0:触发温度为 110,000 毫度(110°C),属于被动类型(passive)。这表示当 CPU 温度超过 110°C 时,采取被动散热措施,减少功耗等。

    • cpu_alert1:触发温度为 95,000 毫度(95°C),也被动类型。低于 cpu_alert0,但仍会采取类似被动散热措施。

    • cpu_crit:临界温度为 110,000 毫度(110°C),触发类型临界(critical)。通常,临界温度触发更强保护措施,如关闭 CPU 或其他硬件。

  • cooling-maps cooling-maps 描述特定温度触发条件下,如何调节冷却设备。具体三个冷却映射:

    • cpu_map0:当 cpu_alert1 温度阈值触发时,会激活以下冷却设备:

      • 8 个 CPU 核心冷却设备(CPU 0 到 CPU 7)。这里THERMAL_NO_LIMIT 表示没有具体温度限制。

    • cpu_map1:当 cpu_alert1 温度阈值触发时,会激活名为 bpu冷却设备。THERMAL_NO_LIMIT 同样表示没有温度限 制。

    • cpu_map2:当 cpu_alert1 温度阈值触发时,会激活名为 gc8000冷却设备。

  • thermal_ddr: thermal-ddr 这个部分定义与 DDR 内存相关热区。与 thermal_cpu 类似,包含温度轮询传感器设置,但定义一个温度阈值。

    • thermal-sensors:与 DDR 相关温度传感器< &pvt 0 >,它指向名为 pvt第一个传感器实例。

  • trips (DDR) DDR 热区定义一个温度阈值:

    • ddr_alert0:触发温度为 95,000 毫度(95°C),类型被动(passive)。当 DDR 温度超过阈值时,采取被动散热措施。

  • cooling-maps

    • ddr_map0:当 ddr_alert0触发时,激活名为 ddrc_freq冷却设备。同样,THERMAL_NO_LIMIT 表示没有具体温度限制。

设备树代码可以内核解析,指导系统不同温度条件有效管理硬件温度,避免过热问题,并确保硬件安全温度范围工作。

Thermal 内核配置

Thermal 系统内核相关配置可以在 menuconfig 中看到,当前系统配置如下:

--- Thermal drivers
[ ]   Thermal netlink management
[ ]   Thermal state transition statistics
(0)   Emergency poweroff delay in milli-seconds
[*]   Expose thermal sensors as hwmon device
[*]   APIs to parse thermal data out of device tree
[*]   Enable writable trip points
      Default Thermal governor (step_wise)  --->
[ ]   Fair-share thermal governor
-*-   Step_wise thermal governor
[ ]   Bang Bang thermal governor
[*]   User_space thermal governor
[*]   Generic cpu cooling support
[*]     CPU frequency cooling device
[*]   Generic device cooling support
[ ]   Thermal emulation mode support
< >   Generic Thermal MMIO driver
< >   Generic ADC based thermal sensor

以下当前系统已经开启选项及其解析:

  • Expose thermal sensors as hwmon device

    • 启用选项后,系统传感器作为硬件监控(hwmon)设备暴露用户空间。通过这个功能,用户可以通过 /sys/class/hwmon/ 目录访问温度传感器数据。例如,lm_sensors工具可以使用这些数据监控系统温度情况,便于调试优化系统管理。

  • APIs to parse thermal data out of device tree

    • 启用选项后,内核具备解析设备树中热管理相关数据能力。设备树描述硬件配置文件,通常在 ARM 架构系统使用。通过启用这个选项,内核可以设备树读取有关温度传感器、热阈值、冷却设备信息,并据此做出相应管理操作。

  • Enable writable trip points

    • 启用选项后,系统允许用户运行修改管理trip points(温度阈值)。Trip points预设温度阈值,超过这些阈值时,系统采取措施(如降低频率启动风扇)。启用选项后,用户可以通过 sysfs 接口动态修改这些阈值,以更好适应不同工作负载环境条件。

  • Step_wise thermal governor

    • 这是系统默认管理调度器(thermal governor)。step_wise 调度器会根据温度变化逐步调整冷却策略。例如,当温度逐渐上升时,系统采取逐步增加冷却措施方式。相简单bang-bang其他策略,step_wise 更加细致,能够提供平稳温度控制。

  • User_space thermal governor

    • 启用选项后,系统允许用户空间应用程序控制管理策略。这意味着用户可以通过编写自己应用程序动态调整温度控制措施,例如启动/停止冷却设备修改冷却策略等。这个功能适用需要自定义管理行为系统,尤其一些嵌入式高性能应用中,可以根据特定需求调节冷却方式。

  • Generic cpu cooling support

    • 启用选项后,系统支持通用的 CPU 冷却机制,通常通过调整 CPU 的频率、调整功耗启动/停止冷却设备降低温度。这项功能对于需要高效管理 CPU 温度系统非常重要,尤其负载高时,能够通过减少功耗避免过热。

  • CPU frequency cooling device

    • 启用选项后,系统支持基于 CPU 频率 调整冷却设备。这意味着温度升高时,系统可以动态降低 CPU 的频率,以减少功耗热量,从而帮助系统降低温度。此功能通常与 CPU 动态频率调节(DVFS)相关,能够高温情况自动降低 CPU 性能保护硬件。

  • Generic device cooling support

    • 启用选项后,系统支持通用设备冷却机制。这包括 CPU 以外设备(例如 GPU、内存控制器、硬盘等)的冷却措施。系统根据温度变化调整相关设备功耗启动冷却装置,以提高系统整体管理能力。

4.3.14.4. Thermal 系统功能使用

Linux Thermal 是 Linux 系统温度控制相关模块,主要用来控制系统运行过程芯片产生热量,使芯片温度设备外壳温度维持一个安全、舒适范围。

整个 Thermal 框架可以分为部分:

  • Thermal Driver: 负责获取温度设备,注册struct thermal_zone_device,Thermal Zone Device 本质获取温度设备抽象,本板端系统两个 thermal zone,分别thermal_zone0thermal_zone1

  • Thermal Governor: 则负责如何控制温度,注册struct thermal_governor,比如 Step Wise、User space 等等。Thermal Governor 本质控制温度策略。

  • Thermal Cooling: 负责控制温度设备,注册struct thermal_cooling_device,实际就是需要降温设备,在端系统一共四个 cooling device:

    • cooling_device0: cpu

    • cooling_device1: bpu

    • cooling_device2: gpu

    • cooling_device3: ddr 其中,cooling 设备 DDR 与 thermal_zone0 关联,cooling 设备 CPU/BPU/GPU 与 thermal_zone1 关联。

  • Thermal Core: 负责把 governor、cooling device、zone device 等部分关联一起,同时提供用户空间 sysfs 节点通用功能,Thermal Core 是 thermal的核心。

以上模块信息控制状态可以/sys/class/thermal 目录获取。

Thermal 的工作流程通过 Thermal Driver 获取温度,然后经过 Thermal Governor 决策,最后通过 Thermal Cooling 执行温度控制。这几个模块之间关系可以描述下图:

thermal_kernel_framwork

加入设备组件后,Thermal 框架设备组件之间关系,以及温度变化数据处理流程如下所示:

thermal_kernel_framwork

Thermal 驱动关键结构说明

thermal_zone_device

struct thermal_zone_device {
	int id;
	char type[THERMAL_NAME_LENGTH];
	struct device device;
	struct attribute_group trips_attribute_group;
	struct thermal_attr *trip_temp_attrs;
	struct thermal_attr *trip_type_attrs;
	struct thermal_attr *trip_hyst_attrs;
	enum thermal_device_mode mode;
	void *devdata;
	struct thermal_trip *trips;
	int num_trips;
	unsigned long trips_disabled;	/* bitmap for disabled trips */
	unsigned long passive_delay_jiffies;
	unsigned long polling_delay_jiffies;
	int temperature;
	int last_temperature;
	int emul_temperature;
	int passive;
	int prev_low_trip;
	int prev_high_trip;
	atomic_t need_update;
	struct thermal_zone_device_ops *ops;
	struct thermal_zone_params *tzp;
	struct thermal_governor *governor;
	void *governor_data;
	struct list_head thermal_instances;
	struct ida ida;
	struct mutex lock;
	struct list_head node;
	struct delayed_work poll_queue;
	enum thermal_notify_event notify_event;
};

struct thermal_zone_device一个用于描述热区设备结构体,包含管理监控管理相关信息各个段。热区设备(thermal zone)是操作系统一种抽象,用于表示具有管理功能硬件区域。该结构涉及温度传感器、热管理策略、温控阈值各种系统参数等。

下面各个成员变量详细解析:

  1. id:

    • 类型:int

    • 该字段用于每个热区分配一个唯一标识符,用于区分不同热区。

  2. type:

    • 类型:char[THERMAL_NAME_LENGTH]

    • 该字段表示热区设备类型名称,通常一个字符串,指示热区设备类型(例如 CPU 热区,GPU 热区等)。

  3. device:

    • 类型:struct device

    • 该字段表示热区设备本身,它一个 device 结构体,允许设备模型进行交互,便于管理热区相关硬件。

  4. trips_attribute_group:

    • 类型:struct attribute_group

    • 用于管理热区属性组(例如通过 sysfs 访问)。trips_attribute_group 包含温度阈值(trip points)相关属性。

  5. trip_temp_attrs, trip_type_attrs, trip_hyst_attrs:

    • 类型:struct thermal_attr *

    • 这些分别指向热区温度阈值相关属性:

      • trip_temp_attrs:阈值温度属性;

      • trip_type_attrs:阈值类型属性(如高温、低温等);

      • trip_hyst_attrs:阈值滞后属性,用于控制温度下限间隔。

  6. mode:

    • 类型:enum thermal_device_mode

    • 表示当前热区工作模式。热区设备模式决定如何响应温度变化(如工作、休眠、关机模式)。

  7. devdata:

    • 类型:void *

    • 指向热区设备相关私有数据,驱动程序可以使用该字存储特定设备私有数据。

  8. trips:

    • 类型:struct thermal_trip *

    • 该字一个指向 struct thermal_trip 结构指针数组,用于存储热区各个温度阈值(trip points)。每个阈值定义一个温度点,当系统温度达到这些时会触发特定操作(如启用风扇、降低频率等)。

  9. num_trips:

    • 类型:int

    • 表示当前热区设备支持温度阈值数量。每个阈值可能触发不同冷却措施。

  10. trips_disabled:

    • 类型:unsigned long

    • 图,用于表示哪些温度阈值禁用。如果某个阈值禁用,则不会触发阈值相关任何事件。

  11. passive_delay_jiffies:

    • 类型:unsigned long

    • 系统执行被动冷却时,需要等待延迟时间,以 jiffies 为单位。被动冷却通常通过降低 CPU 或其他设备频率降低温度。

  12. polling_delay_jiffies:

    • 类型:unsigned long

    • 用于检查温度是否超出某些阈值延迟时间,以 jiffies 为单位。如果系统中断驱动的,这个可能为 0。

  13. temperature:

    • 类型:int

    • 当前温度。这个主要核心代码使用,驱动程序应该使用 thermal_zone_get_temp() 函数获取当前温度。

  14. last_temperature:

    • 类型:int

    • 一次读取温度值。

  15. emul_temperature:

    • 类型:int

    • 如果启用CONFIG_THERMAL_EMULATION(热管理仿真),则这个表示模拟温度值。它开发测试非常有用,尤其没有真实硬件情况下。

  16. passive:

    • 类型:int

    • 如果设备已经通过某个被动阈值,则为 1;否则为 0。被动冷却通常通过调整设备频率降低温度。

  17. prev_low_trip, prev_high_trip:

    • 类型:int

    • 这些分别存储被动冷却阈值触发温度范围。prev_low_trip一个低温阈值,prev_high_trip一个高温阈值。

  18. need_update:

    • 类型:atomic_t

    • 用于标记热区设备是否需要更新。该字段通常核心代码设置为 1,如果设备温度状态需要更新,则触发更新。

  19. ops:

    • 类型:struct thermal_zone_device_ops *

    • 指向热区设备操作函数集合指针。这些操作函数定义热区设备行为,包括如何获取温度、设置模式、触发阈值等。

  20. tzp:

    • 类型:struct thermal_zone_params *

    • 指向热区参数结构指针。这个结构包含热区相关其他配置参数。

  21. governor:

    • 类型:struct thermal_governor *

    • 指向热区管理器指针。热区管理器负责根据当前温度热区策略决定如何调整温度(例如通过改变 CPU 或其他硬件频率实现冷却)。

  22. governor_data:

    • 类型:void *

    • 用于存储热区管理器相关私有数据。

  23. thermal_instances:

    • 类型:struct list_head

    • 热区所有实例链表。每个实例表示热区设备一个具体硬件功能。

  24. ida:

    • 类型:struct ida

    • IDA(ID allocator)结构体,用于生成唯一的 ID,通常用于每个热区冷却设备分配唯一 ID。

  25. lock:

    • 类型:struct mutex

    • 用于保护 thermal_instances 链表锁,防止多线程中断竞争。

  26. node:

    • 类型:struct list_head

    • 用于thermal_zone_device 添加全局热区列表节点。thermal_tz_list一个包含所有热区设备链表。

  27. poll_queue:

    • 类型:struct delayed_work

    • 用于延迟工作任务队列,在周期性检查温度触发阈值使用。

  28. notify_event:

    • 类型:enum thermal_notify_event

    • 一个通知事件类型,用于指示温度触发什么样通知事件(例如温度高等)。

上述成员ops该 Thermal Zone 操作抽象,governor该 Thermal Zone 所使用调温策略,thermal_instances该 Thermal Zone 下的 Cooling Device 列表。

thermal_governor

struct thermal_governor {
	char name[THERMAL_NAME_LENGTH];
	int (*bind_to_tz)(struct thermal_zone_device *tz);
	void (*unbind_from_tz)(struct thermal_zone_device *tz);
	int (*throttle)(struct thermal_zone_device *tz, int trip);
	struct list_head	governor_list;
};

结构thermal_governor 用于表示一个“热管制器”(thermal governor)及其热区(thermal zone)设备之间关系。热管制器是一种用于控制温度对系统进行温控调节机制。它通过热区设备(thermal_zone_device)和相应温度阈值(trip points)进行交互,帮助避免系统过热确保温度维持一定范围内。该结构包含以下成员:

1) name (char name[THERMAL_NAME_LENGTH])

char name[THERMAL_NAME_LENGTH];
  • 功能:存储管制名称。THERMAL_NAME_LENGTH名称最大长度。这个名称用于标识不同管制器(例如“用户模式”或“硬件控制”)。

2) bind_to_tz (int (*bind_to_tz)(struct thermal_zone_device *tz))

int (*bind_to_tz)(struct thermal_zone_device *tz);
  • 功能:一个回调函数,用于管制热区设备(thermal_zone_device)绑定调用。

  • 参数

    • tz:指向绑定热区设备指针。

  • 返回值:如果返回 0,表示绑定成功;如果返回非零值,表示绑定失败。

  • 说明:这个回调函数管制热区设备关联过程。成功绑定后,热管制能够控制热区设备温度。

3) unbind_from_tz (void (*unbind_from_tz)(struct thermal_zone_device *tz))

void (*unbind_from_tz)(struct thermal_zone_device *tz);
  • 功能:一个回调函数,用于管制热区设备解除绑定调用。

  • 参数

    • tz:指向解除绑定热区设备指针。

  • 返回值:该函数没有返回值。

  • 说明:当热管制不再需要控制某个热区设备时,调用函数解除绑定。

4) throttle (int (*throttle)(struct thermal_zone_device *tz, int trip))

int (*throttle)(struct thermal_zone_device *tz, int trip);
  • 功能:一个回调函数,用于温度触发某个阈值时(无论温度是否达到阈值),进行管制调节操作。通常,这用于温度接近超过某个阈值时,调节系统功率性能。

  • 参数

    • tz:指向热区设备指针。

    • trip:热区设备温度阈值索引,表示当前温度是否接近超过某个阈值。

  • 返回值:返回一个整数,通常成功错误码,0 表示成功,其他表示失败。

  • 说明:该回调函数通过给定阈值(trip)调整系统行为。例如,降低 CPU 频率、调整风扇速度等。

5) governor_list (struct list_head governor_list)

struct list_head governor_list;
  • 功能:一个链表节点,用于不同管制添加全局管制列表中。

  • 说明:该结构成员list_head 类型,它是 Linux 内核实现链表数据结构,允许管制系统作为链表元素进行管理调度。

总的来说,struct thermal_governor一个用来管理控制温度结构体,通常温度管理系统热区设备温度阈值密切合作。它通过以下方式实现管制: 1) 绑定/解绑:通过 bind_to_tzunbind_from_tz 回调函数,热管制可以热区设备绑定或解绑。 2) 温度调节:通过 throttle 回调函数,热管制根据温度阈值(trip)对设备进行调节,确保温度安全范围内。

thermal_bind_params(Cooling Device)

结构thermal_bind_params ,用于描述 热区(thermal zone)与冷却设备(cooling device)之间绑定参数。在系统管理框架中,热区冷却设备可能需要根据不同温度阈值(trip points)进行绑定,以有效控制设备温度。该结构就是降温设备抽象,对风扇设备就是不同转速,对 CPU、DDR、GPU 就是不同电压或者频率。

struct thermal_bind_params {
    struct thermal_cooling_device *cdev;
    int weight;
    int trip_mask;
    unsigned long *binding_limits;
    int (*match)(struct thermal_zone_device *tz, struct thermal_cooling_device *cdev);
};

1) cdev (struct thermal_cooling_device *cdev)

struct thermal_cooling_device *cdev;
  • 类型:指向 thermal_cooling_device 类型指针。

  • 功能:指向一个冷却设备(cooling device)。冷却设备用来调节热区温度硬件组件软件控制机制。通过这个指针,系统可以操作冷却设备,启动、停止或者调整冷却能力。

2) weight (int weight)

int weight;
  • 类型:整数类型。

  • 功能:表示冷却设备热区冷却效果权重。权重系统特性决定的,表示冷却设备冷却能力。权重越高,冷却效果好。例如,权重冷却设备两倍设备权重设备有效降低温度。

  • 说明:冷却设备weight相对的。如果多个冷却设备,它们权重帮助系统决定某些温度阈值哪个设备应该优先激活。

3) trip_mask (int trip_mask)

int trip_mask;
  • 类型:整数类型。

  • 功能:这是一个掩码(bitmask),用于指定冷却设备热区之间绑定关系,特别对于特定温度阈值(trip point)。它表明某些温度阈值下,哪些冷却设备应该启用或者激活。

  • 说明:每个 trip_mask一位代表一个温度阈值对应冷却设备状态。可以通过设置掩码确定冷却设备不同温度范围应该如何工作。

4) binding_limits (unsigned long *binding_limits)

unsigned long *binding_limits;
  • 类型:指向 unsigned long 类型指针。

  • 功能:这是一个数组,表示冷却设备热区绑定冷却状态限制。该数组大小2 * thermal_zone.number_of_trip_points,即每个温度阈值一个对应限制范围。每个温度阈值关联一对状态限制(下限上限)。例如,在某个温度阈值下,冷却设备工作状态可能限制一定范围内。

  • 说明:如果 binding_limitsNULL,则表示没有冷却设备状态进行限制,所有温度阈值冷却设备没有任何限制。

5) match (int (*match)(struct thermal_zone_device *tz, struct thermal_cooling_device *cdev))

int (*match)(struct thermal_zone_device *tz, struct thermal_cooling_device *cdev);
  • 类型:一个函数指针,指向一个匹配函数。

  • 功能:这是一个回调函数,用于匹配冷却设备热区设备是否适配。具体来说,match 函数根据当前热区(tz)和冷却设备(cdev)的特性,返回一个整数值,通常0 表示匹配成功,非 0 表示匹配失败。

  • 说明:这个函数使得系统能够根据冷却设备热区设备具体特性,决定是否绑定它们。

thermal_instance

struct thermal_instance {
	int id;
	char name[THERMAL_NAME_LENGTH];
	struct thermal_zone_device *tz;
	struct thermal_cooling_device *cdev;
	int trip;
	bool initialized;
	unsigned long upper;	/* Highest cooling state for this trip point */
	unsigned long lower;	/* Lowest cooling state for this trip point */
	unsigned long target;	/* expected cooling state */
	char attr_name[THERMAL_NAME_LENGTH];
	struct device_attribute attr;
	char weight_attr_name[THERMAL_NAME_LENGTH];
	struct device_attribute weight_attr;
	struct list_head tz_node; /* node in tz->thermal_instances */
	struct list_head cdev_node; /* node in cdev->thermal_instances */
	unsigned int weight; /* The weight of the cooling device */
};

结构thermal_instance,用于描述 冷却设备特定温度阈值(trip point)下行为。它主要用于系统管理机制中,表示一个冷却设备某个特定热区(thermal zone)和温度阈值状态配置。

1) id (int id)

int id;
  • 类型:整数类型。

  • 功能:唯一标识一个 thermal_instance。它可以用来区分不同冷却设备实例,即使它们处在同一个热区相同温度阈值下。

2) name (char name[THERMAL_NAME_LENGTH])

char name[THERMAL_NAME_LENGTH];
  • 类型:字符数组,用来存储实例名称。

  • 功能:该名称用于标识当前冷却设备实例。THERMAL_NAME_LENGTH一个宏,定义名称最大长度。名称一般用于调试日志中,帮助开发者理解当前冷却设备实例。

3) tz (struct thermal_zone_device *tz)

struct thermal_zone_device *tz;
  • 类型:指向 thermal_zone_device 结构指针。

  • 功能:指向冷却设备绑定热区(thermal zone)。热区代表一个监控控制温度区域,可能一个物理区域系统某个硬件组件。这个成员表示冷却设备某个热区行为。

4) cdev (struct thermal_cooling_device *cdev)

struct thermal_cooling_device *cdev;
  • 类型:指向 thermal_cooling_device 结构指针。

  • 功能:指向冷却设备(cooling device)。冷却设备通常硬件组件(如风扇、散热片等)或软件控制机制,用于降低热区温度。

5) trip (int trip)

int trip;
  • 类型:整数类型。

  • 功能:表示冷却设备实例关联温度阈值(trip point)的索引。热区通常多个温度阈值,每个阈值对应不同冷却策略。trip 用来指定当前实例针对哪个阈值冷却行为。

6) initialized (bool initialized)

bool initialized;
  • 类型:布尔类型。

  • 功能:表示冷却设备实例是否初始化。如果true,表示实例已经初始化准备使用。如果false,则说明实例没有初始化。

7) upper (unsigned long upper)

unsigned long upper;
  • 类型:无符号长整型。

  • 功能:表示冷却设备指定温度阈值最高冷却状态。冷却状态通常表示设备工作强度(例如,风扇转速)。upper 表示冷却设备达到最高状态。

8) lower (unsigned long lower)

unsigned long lower;
  • 类型:无符号长整型。

  • 功能:表示冷却设备指定温度阈值最低冷却状态。与 upper 相对,lower 表示冷却设备温度阈值最小工作强度。

9) target (unsigned long target)

unsigned long target;
  • 类型:无符号长整型。

  • 功能:表示当前预期冷却状态。这个状态根据温度阈值热区需求动态计算的,系统尝试使冷却设备达到目标状态。

10) attr_name (char attr_name[THERMAL_NAME_LENGTH])

char attr_name[THERMAL_NAME_LENGTH];
  • 类型:字符数组。

  • 功能:存储冷却设备实例相关属性名称。属性名称用于系统设备树文件系统创建文件,使用户可以访问控制冷却设备状态。

11) attr (struct device_attribute attr)

struct device_attribute attr;
  • 类型device_attribute 结构体。

  • 功能:表示冷却设备实例相关设备属性。这通常用于设备的 sysfs 接口,允许用户空间内核空间之间交换信息。例如,通过 attr 用户可以控制冷却设备工作状态。

12) weight_attr_name (char weight_attr_name[THERMAL_NAME_LENGTH])

char weight_attr_name[THERMAL_NAME_LENGTH];
  • 类型:字符数组。

  • 功能:存储冷却设备权重属性名称。冷却设备权重通常用于决定设备管理优先级冷却效果。

13) weight_attr (struct device_attribute weight_attr)

struct device_attribute weight_attr;
  • 类型device_attribute 结构体。

  • 功能:表示冷却设备权重相关设备属性。这通常在 sysfs 中作为一个接口提供用户空间,让用户可以调整冷却设备权重,从而影响系统管理策略。

14) tz_node (struct list_head tz_node)

struct list_head tz_node;
  • 类型list_head 结构。

  • 功能:该节点用于当前 thermal_instance 添加热区设备(tz)的实例链表中。每个热区可以包含多个冷却设备实例,这个节点帮助组织热区所有冷却设备实例链表结构。

15) cdev_node (struct list_head cdev_node)

struct list_head cdev_node;
  • 类型list_head 结构。

  • 功能:该节点用于当前 thermal_instance 添加冷却设备(cdev)的实例链表中。每个冷却设备可以多个热区使用,这个节点帮助组织冷却设备所有实例链表结构。

16) weight (unsigned int weight)

unsigned int weight;
  • 类型:无符号整数。

  • 功能:表示冷却设备权重。权重通常用于决策管理冷却策略,较权重表示冷却效果较强。它影响冷却设备热区调度优先级。

Thermal 关键函数接口说明

Thermal core 是 Thermal Zone、Thermal Cooling 和 Thermal Governor 之间协调者,通过提供统一的 API 将它们相互关联,实现温度控制功能。

具体来说,Thermal core 通过以下方式工作:

  1. 从 Thermal Zone 获取温度:首先,通过 Thermal Zone 设备获取当前温度值。

  2. 选择对应的 Thermal Governor:根据温度值,选择适当的 Thermal Governor 来管理温控策略。

  3. 控制 Thermal Cooling 设备:根据 Thermal Governor 的设置,调整 Thermal Cooling 设备状态,从而达到温度调节目的。

设备注册注销

  • 注册 Thermal Zone 设备:通过调用 thermal_zone_device_register(),注册 thermal zone 设备,并创建一系列 sysfs 节点,同时相应的 governor 和 cooling 设备进行绑定。

  • 注销 Thermal Zone 设备thermal_zone_device_unregister() 函数执行相反操作,移除 thermal zone 设备,解除与 cooling 设备绑定,并删除相应的 sysfs 节点。

Cooling 设备管理

  • 注册 Cooling 设备:通过 thermal_cooling_device_register() 创建 cooling 设备,将加入thermal_cdev_list 中,并为 cooling 设备创建相关的 sysfs 节点。此时,cooling 设备与 thermal zone 设备进行绑定。

  • 注销 Cooling 设备thermal_cooling_device_unregister() 执行相反操作,解除 cooling 设备与 thermal zone 的绑定,并移除相关的 sysfs 节点。

Governor 的管理

  • 注册 Thermal Governorthermal_register_governor() 首先检查 thermal_governor_list是否已有同名 governor,如果没有,则添加列表中,并更新 thermal_tz_list未指定 governor 的 thermal zone。

  • 注销 Thermal Governor:通过 thermal_unregister_governor(),将指定的 governor 与其绑定的 thermal zone 解除绑定,并调用 unbind_from_tz() 清空相关数据,最后thermal_go移除该 governor。

设备绑定解绑

  • 绑定 Cooling 设备到 Thermal Zonethermal_zone_bind_cooling_device() 通过创建 thermal_instances 设备,将 Thermal Zone 与 Thermal Cooling 设备进行绑定,从而实现基于温度的 Cooling 设备控制。

  • 解绑 Cooling 设备thermal_zone_unbind_cooling_device()绑定thermal_instances两者链表移除,解除绑定关系。

温度更新处理

  • 更新 Thermal Zone 的温度thermal_zone_device_update() 一般由 Thermal 驱动触发,可能通过 polling 或中断方式更新当前温度值,并根据温度变化通过 handle_thermal_trip() 进行相应处理。

监控延时处理

  • 监控 Thermal Zonemonitor_thermal_zone() 根据 passive 或 polling 设置决定是否启动 thermal_zone_device->pool_queue 这个延时工作项(delayed_work)。

  • Polling 流程:整个 polling 流程thermal_zone_device_update() 触发,具体流程如下:

    1. handle_thermal_trip()启动 monitor_thermal_zone()

    2. monitor_thermal_zone() 中,调用 mod_delayed_work() 更新 poll_queue 的延时值。如果 thermal zone 有多个 trip,poll_queue 的延时可能多次更新。

    3. poll_queue 被放入 system_freezable_wq 后,达到设定时间后,调用 thermal_zone_device_check(),进而调用 thermal_zone_device_update() 完成周期性更新处理。

上述流程可以描述如下图:

thermal_api

下面一些关键函数详细分析。

thermal_set_governor 函数

功能: 切换热区(thermal zone)的政策(governor)。

函数原型:

static int thermal_set_governor(struct thermal_zone_device *tz,
				struct thermal_governor *new_gov)

参数:

  • tz: 指向热区设备指针。

  • new_gov: 新政策。

逻辑:

  • 如果当前热区已有绑定政策,先调用unbind_from_tz 方法解除绑定。

  • 如果新热政策存在bind_to_tz 方法,尝试绑定热区。

  • 如果绑定失败,尝试恢复之前政策。

  • 最后,更新热区政策指针。

返回值:

  • 成功返回0,绑定新热政策失败返回错误码。

thermal_register_governor 函数

功能: 注册一个政策。

函数原型:

int thermal_register_governor(struct thermal_governor *governor)

参数:

  • governor: 要注册政策。

逻辑:

  • 检查政策是否存在。

  • 如果存在,将添加政策列表,并设置默认政策(如果匹配)。

  • 遍历所有热区,尝试政策应用每个热区。

返回值:

  • 成功返回0,失败返回错误码。

thermal_unregister_governor 函数

功能: 注销一个政策。

函数原型:

void thermal_unregister_governor(struct thermal_governor *governor)

参数:

  • governor: 要注销政策。

逻辑:

  • 政策列表移除指定政策。

  • 遍历所有热区,将使用政策热区恢复默认政策。

update_temperature 函数

功能: 更新热区设备温度。

函数原型:

static void update_temperature(struct thermal_zone_device *tz)

参数:

  • tz: 指向热区设备指针。

逻辑:

  • 调用 thermal_zone_get_temp 函数读取温度。

  • 更新热区设备温度值。

  • 如果温度有效,触发相应通知。

thermal_zone_device_update 函数

功能: 更新热区设备状态。

函数原型:

void thermal_zone_device_update(struct thermal_zone_device *tz,
				enum thermal_notify_event event)

参数:

  • tz: 指向热区设备指针。

  • event: 触发更新事件类型。

逻辑:

  • 检查系统是否起,如果直接返回。

  • 更新温度。

  • 处理所有温度阈值(trip points)。

  • 根据需要调整轮询频率。

thermal_zone_device_check 函数

功能: 作为工作队列回调函数,用于检查和更新热区设备状态。

函数原型:

static void thermal_zone_device_check(struct work_struct *work)

参数:

  • work: 工作队列结构指针。

逻辑:

  • 调用 thermal_zone_device_update 函数更新热区设备状态。

thermal_zone_bind_cooling_device 函数

功能:冷却设备绑定热区设备特定温度阈值。

函数原型:

int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
				     int trip,
				     struct thermal_cooling_device *cdev,
				     unsigned long upper, unsigned long lower,
				     unsigned int weight)

参数:

  • tz: 热区设备。

  • trip: 温度阈值索引。

  • cdev: 冷却设备。

  • upper: 最高冷却状态。

  • lower: 最低冷却状态。

  • weight: 冷却设备权重。

逻辑:

  • 检查参数有效性。

  • 创建一个thermal_instance 结构体,表示冷却设备热区绑定。

  • 更新 sysfs 接口反映绑定关系。

返回值:

  • 成功返回0,失败返回错误码。

thermal_zone_unbind_cooling_device 函数

功能:一个热区设备中解一个冷却设备。

函数原型:

int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
				       int trip,
				       struct thermal_cooling_device *cdev)

参数:

  • tz: 热区设备。

  • trip: 温度阈值索引。

  • cdev: 冷却设备。

逻辑:

  • 找到对应thermal_instance 结构体,并列表移除。

  • 更新 sysfs 接口反映解绑关系。

返回值:

  • 成功返回0,失败返回错误码。

thermal_cooling_device_unregister 函数

功能: 注销一个冷却设备。

函数原型:

void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)

参数:

  • cdev: 要注销冷却设备。

逻辑:

  • 冷却设备列表移除指定冷却设备。

  • 解绑所有冷却设备关联热区。

bind_tz 函数

功能:冷却设备绑定热区。

函数原型:

static void bind_tz(struct thermal_zone_device *tz)

参数:

  • tz: 热区设备。

逻辑:

  • 遍历所有冷却设备,尝试每个冷却设备绑定热区。

thermal_zone_device_register_with_trips 函数

功能: 创建注册一个热区设备,并指定热区(trip)信息。

函数原型:

struct thermal_zone_device *
thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *trips, int num_trips, int mask,
					void *devdata, struct thermal_zone_device_ops *ops,
					struct thermal_zone_params *tzp, int passive_delay,
					int polling_delay)

参数:

  • type: 热区名称。

  • trips: 温度阈值数组。

  • num_trips: 温度阈值数量。

  • mask: 温度阈值掩码。

  • devdata: 私有数据。

  • ops: 热区操作接口。

  • tzp: 热区参数。

  • passive_delay: 被动冷却延迟。

  • polling_delay: 轮询延迟。

逻辑:

  • 初始化热区设备。

  • 注册设备到 sysfs。

  • 绑定冷却设备。

  • 设置轮询延迟。

返回值:

  • 成功返回热区设备指针,失败返回错误指针。

thermal_zone_device_unregister 函数

功能: 注销一个热区设备。

函数原型:

void thermal_zone_device_unregister(struct thermal_zone_device *tz)

参数:

  • tz: 热区设备。

逻辑:

  • 热区列表移除热区。

  • 解绑所有冷却设备。

  • 注销设备。

thermal_init 函数

功能: 初始化管理框架。

函数原型:

static int __init thermal_init(void)

逻辑:

  • 注册政策。

  • 注册热类(thermal class)。

  • 注册 PM 通知器。

返回值:

  • 成功返回0,失败返回错误码。

4.3.14.5. 驱动平台 thermal 系统调试说明

端系统 /sys/class/hwmon/hwmon0 目录包含温度传感器相关参数 temp1_input 是 DDR 的温度,temp2_input 是 BPU 的温度,temp3_input 是 CPU 的温度,具体如下:

root@buildroot:~# ls /sys/class/hwmon/hwmon0/ | grep temp
temp1_input
temp2_input
temp3_input

温度精度为0.001摄氏度,查看一个 DDR 温度命令如下:

cat /sys/class/hwmon/hwmon0/temp1_input
46643

上述日志表示当前 DDR 的温度是46.643℃。

注意:BPU 的温度传感器位于 bpu subsytem,bpu subsystem 只有在 bpu 运行时才会上电,所以只有 bpu 运行时,bpu 的温度可以查看。

目前默认策略通过以下命令可知使用的 step_wise:

cat /sys/class/thermal/thermal_zone0/policy
step_wise

通过以下命令看到支持策略:user_space、step_wise 一共两种:

cat /sys/class/thermal/thermal_zone0/available_policies
user_space step_wise
  • user_space 是通过 uevent 将温区当前温度,温控触发信息上报用户空间,由用户空间软件制定温控策略。

  • step_wise 是每个轮询周期逐级提高冷却状态,是一种相对温和温控策略

具体选择策略根据产品需要自己选择。可编译时候指定或者通过 sysfs 动态切换。 例如:动态切换 thermal_zone0 的策略为 user_space 模式

echo user_space > /sys/class/thermal/thermal_zone0/policy

thermal_zone0 中有1个 trip_point,用于控制 cooling 设备 DDR 的调频温度

通过 sysfs 查看 DDR 的调频温度,当前配置为95度

cat /sys/devices/virtual/thermal/thermal_zone0/trip_point_0_temp

若想调整 DDR 的调频温度,如85度,可通过如下命令:

echo 85000 > /sys/devices/virtual/thermal/thermal_zone0/trip_point_0_temp

在 thermal_zone1中有3个 trip_point,其中:

  • trip_point_0_temp 为预留作用。

  • trip_point_1_temp 是该 thermal zone 的调频温度,可控制 CPU/BPU/GPU 的频率,当前设置为95度。

  • trip_point_2_temp 为关机温度,当前设置为105度。

例如想要结温到85摄氏度,CPU/BPU/GPU 开始调频:

echo 85000 > /sys/devices/virtual/thermal/thermal_zone1/trip_point_1_temp

如果想要调整关机温度为105摄氏度:

echo 105000 > /sys/devices/virtual/thermal/thermal_zone1/trip_point_2_temp

ps:以上设置断电重启需要重新设置

4.3.14.6. thermal参考文档

以下路径以kernel代码目录根目录:

./Documentation/devicetree/bindings/thermal
./Documentation/driver-api/thermal