admin管理员组

文章数量:1536409

rv1126里使用了tsadc温度传感器来探测cpugpu温度,可以在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来进行复位,CRUSOC片上系统的一个组件,它是集成在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-temp5度,其目的是在到达临界资源之前让软件做一些紧急操作,比如备份之类的然后软重启或者开启某些冷却设备,这三个温度阈值都会被设置成阈值,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-passivepolling-delay sustainable-power来配置thermal的管理策略:
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

本文标签: