在rv1126
里使用了tsadc
温度传感器来探测cpu
和gpu
温度,可以在rv1126.dtsi
里找到配置:
cpu_tsadc: tsadc@ff5f0000 {
compatible = "rockchip,rv1126-tsadc";
reg = <0xff5f0000 0x100>;
rockchip,grf = <&grf>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
assigned-clocks = <&cru CLK_CPU_TSADC>;
assigned-clock-rates = <4000000>;
clocks = <&cru CLK_CPU_TSADC>, <&cru PCLK_CPU_TSADC>,
<&cru CLK_CPU_TSADCPHY>;
clock-names = "tsadc", "apb_pclk", "phy_clk";
resets = <&cru SRST_CPU_TSADC_P>, <&cru SRST_CPU_TSADC>,
<&cru SRST_CPU_TSADCPHY>;
reset-names = "tsadc-apb", "tsadc", "tsadc-phy";
rockchip,hw-tshut-temp = <120000>;
#thermal-sensor-cells = <1>;
nvmem-cells = <&cpu_tsadc_trim_l>, <&cpu_tsadc_trim_h>, <&tsadc_trim_base>;
nvmem-cell-names = "trim_l", "trim_h", "trim_base";
rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
pinctrl-names = "gpio", "otpout";
pinctrl-0 = <&tsadcm0_shut>;
pinctrl-1 = <&tsadc_shutorg>;
status = "disabled";
};
npu_tsadc: tsadc@ff5f8000 {
compatible = "rockchip,rv1126-tsadc";
reg = <0xff5f8000 0x100>;
rockchip,grf = <&grf>;
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
assigned-clocks = <&cru CLK_NPU_TSADC>;
assigned-clock-rates = <4000000>;
clocks = <&cru CLK_NPU_TSADC>, <&cru PCLK_NPU_TSADC>,
<&cru CLK_NPU_TSADCPHY>;
clock-names = "tsadc", "apb_pclk", "phy_clk";
resets = <&cru SRST_NPU_TSADC_P>, <&cru SRST_NPU_TSADC>,
<&cru SRST_NPU_TSADCPHY>;
reset-names = "tsadc-apb", "tsadc", "tsadc-phy";
rockchip,hw-tshut-temp = <120000>;
#thermal-sensor-cells = <1>;
nvmem-cells = <&npu_tsadc_trim_l>, <&npu_tsadc_trim_h>, <&tsadc_trim_base>;
nvmem-cell-names = "trim_l", "trim_h", "trim_base";
rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
pinctrl-names = "gpio", "otpout";
pinctrl-0 = <&tsadcm0_shut>;
pinctrl-1 = <&tsadc_shutorg>;
status = "disabled";
};
在dts里通过rockchip,hw-tshut-temp = <120000>;
来配置温度阈值,当超过这个温度时它会产生IRQ并给CPU发送复位信号,强制重启,rockchip,hw-tshut-mode = <0>;
用来配置重启方法,默认是使用CRU
来进行复位,CRU
是SOC
片上系统的一个组件,它是集成在SOC内部
的,它为SOC内部各个模块提供时钟频率
,它具有更快的响应速度
,能够更快速的重启芯片
,因为集成在内部它的总线路径更短
,受到外部电磁信号影响较小
。
GPIO
复位是通过向PMIC(Power Management IC)
发送复位信号来复位,PMIC是电源管理系统
,它为SOC以及其它模块提供电源,它的重启方式是通过对每个连接在PMIC里的设备对复位引脚发送电平让其复位,它不集成在SOC内部,相较于CRU来说,CRU还支持频率控制,当温度达到一定要求时还可以动态调整时钟频率来降低温度
,并且CRU只能复位SOC,而PMIC则会将整个系统全部复位
。
rv1126芯片工作温度范围为-40~120°
,当超过这个温度时芯片则无法正常工作,它是基于linux thermal
框架工作,其代码在kernel/drivers/thermal/rockchip_thermal.c
如果我们想控制温度只需要修改rockchip,hw-tshut-temp = <120000>;
的值就可以了,它的单位是毫摄氏度
,可以在代码约1515
行看到它读取rockchip,hw-tshut-temp
的值, 并将存储到阈值变量里:
if (of_property_read_u32(np, "rockchip,hw-tshut-temp", &shut_temp)) {
dev_warn(dev,
"Missing tshut temp property, using default %d\n",
thermal->chip->tshut_temp);
thermal->tshut_temp = thermal->chip->tshut_temp;
} else {
if (shut_temp > INT_MAX) {
dev_err(dev, "Invalid tshut temperature specified: %d\n",
shut_temp);
return -ERANGE;
}
thermal->tshut_temp = shut_temp;
}
如果没有设置它也会有默认值,在框架代码里设置了默认为95度:
static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
.chn_num = 1, /* one channel for tsadc */
.tshut_mode = TSHUT_MODE_OTP, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv2_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
.get_temp = rk_tsadcv2_get_temp,
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rv1108_table,
.length = ARRAY_SIZE(rv1108_table),
.data_mask = TSADCV2_DATA_MASK,
.mode = ADC_INCREMENT,
},
};
然后在约1607
行将其注册到thermal
框架里
tsadc->set_tshut_mode(thermal->grf, id, thermal->regs,
thermal->tshut_mode);
error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs,
thermal->tshut_temp);
if (error)
dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
__func__, thermal->tshut_temp, error);
sensor->thermal = thermal;
sensor->id = id;
sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id,
sensor, &rockchip_of_thermal_ops);
注册完毕之后会由linux thermal
子系统来进行调度。
在1463
行定义了rockchip_of_thermal_ops
:
static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
.get_temp = rockchip_thermal_get_temp,
.set_trips = rockchip_thermal_set_trips,
};
在通过devm_thermal_zone_of_sensor_register
注册到thermal子系统之后子系统会调用get_temp
函数,这个函数内部会去调用rk_tsadcv2_get_temp
来判断温度去做其它控制,例如动态调整频率、开启风扇,但它不会做重启。
static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
{
struct rockchip_thermal_sensor *sensor = _sensor;
struct rockchip_thermal_data *thermal = sensor->thermal;
const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
int retval;
retval = tsadc->get_temp(&tsadc->table,
sensor->id, thermal->regs, out_temp);
if (tsadc->trim_temp)
*out_temp -= tsadc->trim_temp(thermal->pdev);
dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
sensor->id, *out_temp, retval);
return retval;
}
get_temp
指针指向rk_tsadcv2_get_temp
重启是在约1607
行会调用set_tshut_temp
来注册温度给TSADC
error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs,
thermal->tshut_temp);
当温度超过这个阈值之后则会触发TSHUT信号,同时在1604
行会去调用set_tshut_mode
来设置触发模式,当触发TSHUT
信号会产生中断转而到TSADC
内部去根据设置的模式来决定对CRU
还是PMIC
发送TSHUT
信号
static void rk_tsadcv3_tshut_mode(struct regmap *grf, int chn,
void __iomem *regs,
enum tshut_mode mode)
{
u32 val;
val = readl_relaxed(regs + TSADCV2_INT_EN);
if (mode == TSHUT_MODE_OTP) {
val &= ~TSADCV2_SHUT_2CRU_SRC_EN(chn);
val |= TSADCV2_SHUT_2GPIO_SRC_EN(chn);
if (!IS_ERR(grf))
regmap_write(grf, RV1126_GRF0_TSADC_CON,
RV1126_GRF0_TSADC_SHUT_2GPIO);
} else {
val &= ~TSADCV2_SHUT_2GPIO_SRC_EN(chn);
val |= TSADCV2_SHUT_2CRU_SRC_EN(chn);
if (!IS_ERR(grf))
regmap_write(grf, RV1126_GRF0_TSADC_CON,
RV1126_GRF0_TSADC_SHUT_2CRU);
}
writel_relaxed(val, regs + TSADCV2_INT_EN);
}
除此之外TSADC还有一个阈值,是接近预设的温度值时的值,也就是报警温度,在约1465可以看到它的定义:
static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
.get_temp = rockchip_thermal_get_temp,
.set_trips = rockchip_thermal_set_trips,
};
rockchip_of_thermal_ops
里的set_trips
是给thermal
子系统使用的,子系统会注册到sysfs里,通过sysfs文件来调用这个接口达到动态修改温度的方法,在rk里cpu的路径为:/sys/class/thermal/thermal_zone0/trip_point_0_temp
, 其默认值在tsadc_table
里
static const struct tsadc_table rv1108_table[] = {
{0, -40000},
{374, -40000},
{382, -35000},
{389, -30000},
{397, -25000},
{405, -20000},
{413, -15000},
{421, -10000},
{429, -5000},
{436, 0},
{444, 5000},
{452, 10000},
{460, 15000},
{468, 20000},
{476, 25000},
{483, 30000},
{491, 35000},
{499, 40000},
{507, 45000},
{515, 50000},
{523, 55000},
{531, 60000},
{539, 65000},
{547, 70000},
{555, 75000},
{562, 80000},
{570, 85000},
{578, 90000},
{586, 95000},
{594, 100000},
{602, 105000},
{610, 110000},
{618, 115000},
{626, 120000},
{634, 125000},
{TSADCV2_DATA_MASK, 125000},
};
tsadc_table参数:
struct tsadc_table {
unsigned long code;
int temp;
};
code: 原始raw数据,是tsadc读取出来的原始电压信号转换成数字信号的值
temp: 温度
tsadc
转换后的值不是实际温度,但它有对应关系,code是原始raw数据
,temp是原始raw数据的对应温度值
,其中你会发现raw每次递增8,而温度每次递增5,由此可以看得出这个驱动的温度报警阈值策略的精度是以5为单位的。
而tsadc_table
会被关联到rockchip_tsadc_chip
里
static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
.chn_num = 1, /* one channel for tsadc */
.tshut_mode = TSHUT_MODE_OTP, /* default TSHUT via GPIO give PMIC */
.tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
.tshut_temp = 95000,
.initialize = rk_tsadcv2_initialize,
.irq_ack = rk_tsadcv3_irq_ack,
.control = rk_tsadcv3_control,
.get_temp = rk_tsadcv2_get_temp,
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv2_tshut_mode,
.table = {
.id = rv1108_table,
.length = ARRAY_SIZE(rv1108_table),
.data_mask = TSADCV2_DATA_MASK,
.mode = ADC_INCREMENT,
},
};
而rockchip_tsadc_chip
会关联到of_device_id
里用于匹配compatible
static const struct of_device_id of_rockchip_thermal_match[] = {
{
.compatible = "rockchip,rv1108-tsadc",
.data = (void *)&rv1108_tsadc_data,
},
{
.compatible = "rockchip,rv1126-tsadc",
.data = (void *)&rv1126_tsadc_data,
},
{ .compatible = "rockchip,px30-tsadc",
.data = (void *)&px30_tsadc_data,
},
{
.compatible = "rockchip,rk1808-tsadc",
.data = (void *)&rk1808_tsadc_data,
},
{
.compatible = "rockchip,rk3228-tsadc",
.data = (void *)&rk3228_tsadc_data,
},
{
.compatible = "rockchip,rk3288-tsadc",
.data = (void *)&rk3288_tsadc_data,
},
{
.compatible = "rockchip,rk3308-tsadc",
.data = (void *)&rk3308_tsadc_data,
},
{
.compatible = "rockchip,rk3328-tsadc",
.data = (void *)&rk3328_tsadc_data,
},
{
.compatible = "rockchip,rk3366-tsadc",
.data = (void *)&rk3366_tsadc_data,
},
{
.compatible = "rockchip,rk3368-tsadc",
.data = (void *)&rk3368_tsadc_data,
},
{
.compatible = "rockchip,rk3399-tsadc",
.data = (void *)&rk3399_tsadc_data,
},
{ /* end */ },
};
最后会关联到platform_driver
被探测之后传递给probe
做初始化
static struct platform_driver rockchip_thermal_driver = {
.driver = {
.name = "rockchip-thermal",
.pm = &rockchip_thermal_pm_ops,
.of_match_table = of_rockchip_thermal_match,
},
.probe = rockchip_thermal_probe,
.remove = rockchip_thermal_remove,
.shutdown = rockchip_thermal_shutdown,
};
module_platform_driver(rockchip_thermal_driver);
在probe函数约1762行调用rockchip_thermal_register_sensor
函数来注册,其内部会去调用devm_thermal_zone_of_sensor_register
来设置注册,会在约1615
行调用devm_thermal_zone_of_sensor_register
来注册,其内部会调用devm_thermal_zone_of_sensor_register
函数,这个函数在注册时会调用并设置报警值,其默认值在dts里定义:
thermal_zones: thermal-zones {
cpu_thermal: cpu-thermal {
polling-delay-passive = <20>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
sustainable-power = <875>; /* milliwatts */
k_pu = <75>;
k_po = <175>;
k_i = <0>;
thermal-sensors = <&cpu_tsadc 0>;
trips {
threshold: trip-point-0 {
/* millicelsius */
temperature = <75000>;
/* millicelsius */
hysteresis = <2000>;
type = "passive";
};
target: trip-point-1 {
/* millicelsius */
temperature = <85000>;
/* millicelsius */
hysteresis = <2000>;
type = "passive";
};
soc_crit: soc-crit {
/* millicelsius */
temperature = <115000>;
/* millicelsius */
hysteresis = <2000>;
type = "critical";
};
};
cooling-maps {
map0 {
trip = <&target>;
cooling-device =
<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
map1 {
trip = <&target>;
cooling-device =
<&npu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
map2 {
trip = <&target>;
cooling-device =
<&rkvenc THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1060>;
};
};
};
npu_thermal: npu-thermal {
polling-delay-passive = <20>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
sustainable-power = <977>; /* milliwatts */
thermal-sensors = <&npu_tsadc 0>;
};
};
temperature = <75000>;
就是设置的报警温度,为75
度,读取之后便调用rockchip_thermal_set_trips
来设置TSADC
报警温度:
static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
{
struct rockchip_thermal_sensor *sensor = _sensor;
struct rockchip_thermal_data *thermal = sensor->thermal;
const struct rockchip_tsadc_chip *tsadc = thermal->chip;
dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
__func__, sensor->id, low, high);
if (tsadc->trim_temp)
high += tsadc->trim_temp(thermal->pdev);
return tsadc->set_alarm_temp(&tsadc->table,
sensor->id, thermal->regs, high);
}
内部会调用rk_tsadcv2_alarm_temp
来设置TSADC硬件报警中断
static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
int chn, void __iomem *regs, int temp)
{
u32 alarm_value;
u32 int_en, int_clr;
/*
* In some cases, some sensors didn't need the trip points, the
* set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
* in the end, ignore this case and disable the high temperature
* interrupt.
*/
if (temp == INT_MAX) {
int_clr = readl_relaxed(regs + TSADCV2_INT_EN);
int_clr &= ~TSADCV2_INT_SRC_EN(chn);
writel_relaxed(int_clr, regs + TSADCV2_INT_EN);
return 0;
}
/* Make sure the value is valid */
alarm_value = rk_tsadcv2_temp_to_code(table, temp);
if (alarm_value == table->data_mask)
return -ERANGE;
writel_relaxed(alarm_value & table->data_mask,
regs + TSADCV2_COMP_INT(chn));
int_en = readl_relaxed(regs + TSADCV2_INT_EN);
int_en |= TSADCV2_INT_SRC_EN(chn);
writel_relaxed(int_en, regs + TSADCV2_INT_EN);
return 0;
}
当设置了之后还需要注册中断函数, 在约1773行会调用devm_request_threaded_irq
来注册硬件中断
error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
&rockchip_thermal_alarm_irq_thread,
IRQF_ONESHOT,
"rockchip_thermal", thermal);
这个中断是报警中断和TSHUT不一样,一旦产生TSHUT信号就会触发保护重启,报警中断则是进入中断处理函数里,目的是为了让系统采取措施,例如降频或开启风扇等等,在rk的函数里它是通过调用thermal_zone_device_update
来通知其它thermal_zone_device
采取措施
static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
{
struct rockchip_thermal_data *thermal = dev;
int i;
dev_dbg(&thermal->pdev->dev, "thermal alarm\n");
thermal->chip->irq_ack(thermal->regs);
for (i = 0; i < thermal->chip->chn_num; i++)
thermal_zone_device_update(thermal->sensors[i].tzd,
THERMAL_EVENT_UNSPECIFIED);
return IRQ_HANDLED;
}
这个措施是通过thermal_zones
里的cooling-maps
配置而来的,在thermal里分为热区(thermal zone
)和冷却设备(cooling device
),通过配置dts,thermal子系统会将其关联在一起,根据热区温度设置来调用对应的冷却设备,也就是策略在dts里cpu_thermal
定义热区与冷却设备的关联信息:
热区配置:
trips {
threshold: trip-point-0 {
/* millicelsius */
temperature = <75000>;
/* millicelsius */
hysteresis = <2000>;
type = "passive";
};
target: trip-point-1 {
/* millicelsius */
temperature = <85000>;
/* millicelsius */
hysteresis = <2000>;
type = "passive";
};
soc_crit: soc-crit {
/* millicelsius */
temperature = <115000>;
/* millicelsius */
hysteresis = <2000>;
type = "critical";
};
};
cooling-maps {
map0 {
trip = <&target>;
cooling-device =
<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
map1 {
trip = <&target>;
cooling-device =
<&npu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
map2 {
trip = <&target>;
cooling-device =
<&rkvenc THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1060>;
};
};
cooling-maps通过trip = <&target>;
来绑定热区,target
对应了三个策略,也就是说当温度达到热区报警时会依次调用这三个策略。
最后在trips里定义的节点会根据type的类型来注册到sysfs里面
trips {
threshold: trip-point-0 {
/* millicelsius */
temperature = <75000>;
/* millicelsius */
hysteresis = <2000>;
type = "passive";
};
target: trip-point-1 {
/* millicelsius */
temperature = <85000>;
/* millicelsius */
hysteresis = <2000>;
type = "passive";
};
soc_crit: soc-crit {
/* millicelsius */
temperature = <115000>;
/* millicelsius */
hysteresis = <2000>;
type = "critical";
};
};
passive
代表被动的,一般被用于做触发冷却措施用的,它们会被暴漏在sysfs
里可以动态的去修改,而critical
不会,这个是关键的类型,这个值一般是给驱动用的,当到达这个值的时候应该进入紧急关机的状态,它与rockchip,hw-tshut-temp
不同,rockchip,hw-tshut-temp
是硬件层的,当到达这个温度会硬件立刻进入重启,而critical
则是一种软方式,你会发现它的温度定义会比rockchip,hw-tshut-temp
少5度
,其目的是在到达临界资源之前让软件做一些紧急操作,比如备份之类的然后软重启或者开启某些冷却设备,这三个温度阈值都会被设置成阈值,TSADC 是支持多个温度报警阈值
的,产生多个温度时它会产生中断并将温度传递给irq
,在irq
里来根据温度阈值来确定属于哪一类报警等级。
到这一步你是不是发现tsadc_table为什么没有使用?它仅仅是绑定到了of_rockchip_thermal_match里面,它其实会作为子系统调用时传递给ops函数的,会在调用get_temp被使用,因为tsadc读取出来的是原始raw,它并不能和温度直接对应,所以调用get_temp读取出原始raw时会通过tsadc_table的表来查找原始raw然后返回实际温度给thermal子系统。
在约1453行可以看到代码:
static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
{
struct rockchip_thermal_sensor *sensor = _sensor;
struct rockchip_thermal_data *thermal = sensor->thermal;
const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
int retval;
retval = tsadc->get_temp(&tsadc->table,
sensor->id, thermal->regs, out_temp);
if (tsadc->trim_temp)
*out_temp -= tsadc->trim_temp(thermal->pdev);
dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
sensor->id, *out_temp, retval);
return retval;
}
这里将table传递进去了: retval = tsadc->get_temp(&tsadc->table, sensor->id, thermal->regs, out_temp);
,从开始的注册流程我们可以得知tsadc_table就绑定到了rockchip_tsadc_chip->table->id上,在约1104行可以看到代码:
.table = {
.id = rv1108_table,
.length = ARRAY_SIZE(rv1108_table),
.data_mask = TSADCV2_DATA_MASK,
.mode = ADC_INCREMENT,
},
其中get_temp对应的函数是rk_tsadcv2_get_temp,其内部会调用rk_tsadcv2_code_to_temp来做映射转换然后得到我们想要的值:
return rk_tsadcv2_code_to_temp(table, val, temp);
最后你还可以通过设置polling-delay-passive
、polling-delay
和 sustainable-power
来配置therma
l的管理策略:
polling-delay-passive
含义:不显著变化时候的轮询延迟
单位:毫秒。
作用:在温度变化不显著时,系统会以此间隔轮询温度传感器的值。较短的轮询间隔可以使系统更快地响应温度变化,但会增加系统的负担。
polling-delay
含义:显著变化时候的轮询延迟
单位:毫秒。
作用:在温度变化较显著时(例如,接近或超过某个 trip-point),系统会以此间隔更频繁地轮询温度传感器的值,以更快地响应和处理温度变化。
sustainable-power
含义:可持续功率,表示系统在正常运行时可以持续承受的功率。
单位:毫瓦(milliwatts)。
作用:这个值用于热管理策略中,以帮助系统维持在一个稳定的功率和温度范围内。它可以用于控制冷却策略,使得系统在运行时不会超出这个功率范围,从而避免过热。
sustainable-power
一般是给DVFS
使用的,它会作为输入给到DVFS
里面,然后DVFS
会通过硬件功率传感器获取到当前功率来判断是否大于sustainable-power
从而进行功耗调节, 一般调节方法就是降频。
当注册到thermal
子系统时在sysfs
时,子系统也会注册一个temp
来表示当前的温度、type
表示类型,以rv1126
为例,查看当前温度类型可以用如下命令:
cat /sys/class/thermal/thermal_zone0/type
查看当前实时温度可以用如下命令
cat /sys/class/thermal/thermal_zone0/temp