【平台信息】
平台:RK3288
Android:5.1
Linux:4.4
【代码梳理】
1、Dts配置
1)tsadc配置,文件:kernelarcharmbootdtsrk3288.dtsi
tsadc: tsadc@ff280000 {
compatible = "rockchip,rk3288-tsadc"; //设备名,和驱动匹配
reg = <0x0 0xff280000 0x0 0x100>;
interrupts = ;
clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
clock-names = "tsadc", "apb_pclk";
assigned-clocks = <&cru SCLK_TSADC>; //工作时钟,5KHz
assigned-clock-rates = <5000>;
resets = <&cru SRST_TSADC>; //reset对应的cru
reset-names = "tsadc-apb";
pinctrl-names = "init", "default", "sleep"; // tsadc输出引脚配置,支持gpio和otpout模式
pinctrl-0 = <&otp_gpio>;
pinctrl-1 = <&otp_gpio>;
pinctrl-2 = <&otp_gpio>;
#thermal-sensor-cells = <1>; //表示tsadc可以作为一个thermal sensor,并制定引用tsadc节点的时候需要带几个参数,如果SOC只有一个tsadc,可以设置为0,超过一个必须设置为1
rockchip,hw-tshut-temp = <120000>; //设置的关机温度
rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
status = "disabled";
};
2)pinctrl配置,文件:kernelarcharmbootdtsrk3288.dtsi
pinctrl: pinctrl {
...
tsadc {
otp_gpio: otp-gpio {
rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_none>;
};
otp_out: otp-out {
rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>; //配置为Over Temp Protect模式
};
};
...
3)文件kernelarcharmbootdtsrk3288-remoter.dts
&tsadc {
status = "okay";
rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */ //关机模式,设置为通过gpio方式
rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */ //对应关机极性
pinctrl-1 = <&otp_out>;
};
4)thermal配置, 文件:kernelarcharmbootdtsrk3288.dtsi
参考文档:
thermal_zones: thermal-zones {
soc_thermal: soc-thermal {
polling-delay-passive = <200>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
sustainable-power = <1200>; /* milliwatts */
thermal-sensors = <&tsadc 1>; //当前thermal-sensor通过tsadc1获取温度
trips {
threshold: trip-point@0 {
temperature = <75000>; /* millicelsius */
hysteresis = <2000>; /* millicelsius */
type = "passive";
};
target: trip-point@1 {
temperature = <85000>; /* millicelsius */
hysteresis = <2000>; /* millicelsius */
type = "passive";
};
soc_crit: soc-crit {
temperature = <115000>; /* millicelsius */
hysteresis = <2000>; /* millicelsius */
type = "critical";
};
};
cooling-maps {
map0 {
trip = <&target>;
cooling-device =
<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
map1 {
trip = <&target>;
cooling-device =
<&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
};
};
gpu_thermal: gpu-thermal {
polling-delay-passive = <200>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
thermal-sensors = <&tsadc 2>;
};
};
参考文档:Documentation/devicetree/bindings/thermal/thermal.txt
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
Documentation/devicetree/bindings/thermal/power_allocator.txt
2、驱动代码
kerneldrivershwmonrockchip-hwmon.c
kerneldrivershwmonrockchip_tsadc.c
rockchip_temp_probe -> rockchip-hwmon.c
rockchip_hwmon_init -> rockchip_tsadc.c
request_threaded_irq //申请一个中断线程,对应函数是rockchip_tsadc_auto_ht_interrupt()
create_singlethread_workqueue //创建workqueue thread,对应函数是rockchip_tsadc_auto_ht_work
of_property_read_u32 //读取dts中的tsadc-ht-temp, tsadc-ht-reset-cru,tsadc-ht-pull-gpio
rockchip_tsadc_set_auto_temp //设置为自动温度探测模式,参数channel表示只针对此channel设置,rk3288 cpu对应是channel 1.
rockchip_tsadc_auto_mode_set -> //设置中断和关机的温度, 分别对应的是80和120度
data->ops.read_sensor = rockchip_rk3288_tsadc_get_temp; //读取温度函数接口定义.
INIT_DEFERRABLE_WORK(&data->work, tsadc_monitor); //温度变化时更新sysfs中的alarm node信息.
sysfs_create_group //在tsadc device下创建sysfs,attr为rockchip_temp_group, 按照SENSOR_DEVICE_ATTR格式来定义,不过最终用的都是sysfs文件创建那一套.
hwmon_device_register //hwmon device注册, 会在/sys/class/hwmon下看到.
当达到80°的时候,中断被触发:
rockchip_tsadc_auto_ht_interrupt ->
queue_work(dev->workqueue, &dev->auto_ht_irq_work) -> //给workqueue执行
rockchip_tsadc_auto_ht_work ->
tsadc_readl //读取中断状态
pm_power_off //过温就执行关机
【用户态接口】
用户态接口在/sys/class/thermal/⽬录,具体内容和DTSI中thermal zone节点的配置对应。有的平台thermal
zone节点下只有⼀个⼦节点,对应/sys/class/thermal/⽬录下也只有thermal_zone0⼦⽬录;有的平台有两个⼦节
点,对应/sys/class/thermal/⽬录下就会有thermal_zone0和thermal_zone1⼦⽬录。通过⽤⼾态接口可以切换温
控策略,查看当前温度等。
以RK3288为例⼦,/sys/class/thermal/thermal_zone0/⽬录下包含如下常⽤的信息:
temp /* 当前温度 */
available_policies /* ⽀持的温控策略 */
policy /* 当前使⽤的温控策略 */
sustainable_power /* 期望的最⾼温度下对应的power值 */
integral_cutoff /* PID算法中I的触发条件:当前温度-期望的最⾼温度
k_d /* PID算法中计算D的时候⽤的参数 */
k_i /* PID算法中计算I的时候⽤的参数 */
k_po /* PID算法中计算P的时候⽤的参数 */
k_pu /* PID算法中计算P的时候⽤的参数 */
mode /* enabled:⾃带定时获取温度,判断是否需要降频。disabled关闭该功能 */
type /* 当前thermal zone的类型 */
/* 不同的温度阀值,对应trips节点的配置 */
trip_point_0_hyst
trip_point_0_temp
trip_point_0_type
trip_point_1_hyst
trip_point_1_temp
trip_point_1_type
trip_point_2_hyst
trip_point_2_temp
trip_point_2_type
/* 不同cooling devic的状态,对应cooling-maps节点的配置 */
cdev0 /* 代表⼀个cooling devic,有的平台还有cdev1、cdev2等 */
cur_state /* 该cooling device当前频率的档位 */
max_state /* 该cooling device最多有⼏个档位 */
type /* 该cooling device的类型 */
cdev0_weight /* 该cooling devic在计算power时扩⼤的倍数 */
参考文档:Documentation/thermal/sysfs-api.txt
【调试总结】
1、查看thermal类型
rk3288:/ # cat /sys/class/thermal/thermal_zone0/type
soc-thermal
rk3288:/ # cat /sys/class/thermal/thermal_zone1/type
gpu-thermal
rk3288:/ # cat /sys/class/thermal/thermal_zone2/type
rk-bat
2、获取温度值
rk3288:/ # cat /sys/class/thermal/thermal_zone0/temp
36999
rk3288:/ # cat /sys/class/thermal/thermal_zone1/temp
37198
rk3288:/ # cat /sys/class/thermal/thermal_zone2/temp
18800
【平台信息】
平台:RK3288
Android:5.1
Linux:4.4
【代码梳理】
1、Dts配置
1)tsadc配置,文件:kernelarcharmbootdtsrk3288.dtsi
tsadc: tsadc@ff280000 {
compatible = "rockchip,rk3288-tsadc"; //设备名,和驱动匹配
reg = <0x0 0xff280000 0x0 0x100>;
interrupts = ;
clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
clock-names = "tsadc", "apb_pclk";
assigned-clocks = <&cru SCLK_TSADC>; //工作时钟,5KHz
assigned-clock-rates = <5000>;
resets = <&cru SRST_TSADC>; //reset对应的cru
reset-names = "tsadc-apb";
pinctrl-names = "init", "default", "sleep"; // tsadc输出引脚配置,支持gpio和otpout模式
pinctrl-0 = <&otp_gpio>;
pinctrl-1 = <&otp_gpio>;
pinctrl-2 = <&otp_gpio>;
#thermal-sensor-cells = <1>; //表示tsadc可以作为一个thermal sensor,并制定引用tsadc节点的时候需要带几个参数,如果SOC只有一个tsadc,可以设置为0,超过一个必须设置为1
rockchip,hw-tshut-temp = <120000>; //设置的关机温度
rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
status = "disabled";
};
2)pinctrl配置,文件:kernelarcharmbootdtsrk3288.dtsi
pinctrl: pinctrl {
...
tsadc {
otp_gpio: otp-gpio {
rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_none>;
};
otp_out: otp-out {
rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>; //配置为Over Temp Protect模式
};
};
...
3)文件kernelarcharmbootdtsrk3288-remoter.dts
&tsadc {
status = "okay";
rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */ //关机模式,设置为通过gpio方式
rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */ //对应关机极性
pinctrl-1 = <&otp_out>;
};
4)thermal配置, 文件:kernelarcharmbootdtsrk3288.dtsi
参考文档:
thermal_zones: thermal-zones {
soc_thermal: soc-thermal {
polling-delay-passive = <200>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
sustainable-power = <1200>; /* milliwatts */
thermal-sensors = <&tsadc 1>; //当前thermal-sensor通过tsadc1获取温度
trips {
threshold: trip-point@0 {
temperature = <75000>; /* millicelsius */
hysteresis = <2000>; /* millicelsius */
type = "passive";
};
target: trip-point@1 {
temperature = <85000>; /* millicelsius */
hysteresis = <2000>; /* millicelsius */
type = "passive";
};
soc_crit: soc-crit {
temperature = <115000>; /* millicelsius */
hysteresis = <2000>; /* millicelsius */
type = "critical";
};
};
cooling-maps {
map0 {
trip = <&target>;
cooling-device =
<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
map1 {
trip = <&target>;
cooling-device =
<&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <1024>;
};
};
};
gpu_thermal: gpu-thermal {
polling-delay-passive = <200>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
thermal-sensors = <&tsadc 2>;
};
};
参考文档:Documentation/devicetree/bindings/thermal/thermal.txt
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
Documentation/devicetree/bindings/thermal/power_allocator.txt
2、驱动代码
kerneldrivershwmonrockchip-hwmon.c
kerneldrivershwmonrockchip_tsadc.c
rockchip_temp_probe -> rockchip-hwmon.c
rockchip_hwmon_init -> rockchip_tsadc.c
request_threaded_irq //申请一个中断线程,对应函数是rockchip_tsadc_auto_ht_interrupt()
create_singlethread_workqueue //创建workqueue thread,对应函数是rockchip_tsadc_auto_ht_work
of_property_read_u32 //读取dts中的tsadc-ht-temp, tsadc-ht-reset-cru,tsadc-ht-pull-gpio
rockchip_tsadc_set_auto_temp //设置为自动温度探测模式,参数channel表示只针对此channel设置,rk3288 cpu对应是channel 1.
rockchip_tsadc_auto_mode_set -> //设置中断和关机的温度, 分别对应的是80和120度
data->ops.read_sensor = rockchip_rk3288_tsadc_get_temp; //读取温度函数接口定义.
INIT_DEFERRABLE_WORK(&data->work, tsadc_monitor); //温度变化时更新sysfs中的alarm node信息.
sysfs_create_group //在tsadc device下创建sysfs,attr为rockchip_temp_group, 按照SENSOR_DEVICE_ATTR格式来定义,不过最终用的都是sysfs文件创建那一套.
hwmon_device_register //hwmon device注册, 会在/sys/class/hwmon下看到.
当达到80°的时候,中断被触发:
rockchip_tsadc_auto_ht_interrupt ->
queue_work(dev->workqueue, &dev->auto_ht_irq_work) -> //给workqueue执行
rockchip_tsadc_auto_ht_work ->
tsadc_readl //读取中断状态
pm_power_off //过温就执行关机
【用户态接口】
用户态接口在/sys/class/thermal/⽬录,具体内容和DTSI中thermal zone节点的配置对应。有的平台thermal
zone节点下只有⼀个⼦节点,对应/sys/class/thermal/⽬录下也只有thermal_zone0⼦⽬录;有的平台有两个⼦节
点,对应/sys/class/thermal/⽬录下就会有thermal_zone0和thermal_zone1⼦⽬录。通过⽤⼾态接口可以切换温
控策略,查看当前温度等。
以RK3288为例⼦,/sys/class/thermal/thermal_zone0/⽬录下包含如下常⽤的信息:
temp /* 当前温度 */
available_policies /* ⽀持的温控策略 */
policy /* 当前使⽤的温控策略 */
sustainable_power /* 期望的最⾼温度下对应的power值 */
integral_cutoff /* PID算法中I的触发条件:当前温度-期望的最⾼温度
k_d /* PID算法中计算D的时候⽤的参数 */
k_i /* PID算法中计算I的时候⽤的参数 */
k_po /* PID算法中计算P的时候⽤的参数 */
k_pu /* PID算法中计算P的时候⽤的参数 */
mode /* enabled:⾃带定时获取温度,判断是否需要降频。disabled关闭该功能 */
type /* 当前thermal zone的类型 */
/* 不同的温度阀值,对应trips节点的配置 */
trip_point_0_hyst
trip_point_0_temp
trip_point_0_type
trip_point_1_hyst
trip_point_1_temp
trip_point_1_type
trip_point_2_hyst
trip_point_2_temp
trip_point_2_type
/* 不同cooling devic的状态,对应cooling-maps节点的配置 */
cdev0 /* 代表⼀个cooling devic,有的平台还有cdev1、cdev2等 */
cur_state /* 该cooling device当前频率的档位 */
max_state /* 该cooling device最多有⼏个档位 */
type /* 该cooling device的类型 */
cdev0_weight /* 该cooling devic在计算power时扩⼤的倍数 */
参考文档:Documentation/thermal/sysfs-api.txt
【调试总结】
1、查看thermal类型
rk3288:/ # cat /sys/class/thermal/thermal_zone0/type
soc-thermal
rk3288:/ # cat /sys/class/thermal/thermal_zone1/type
gpu-thermal
rk3288:/ # cat /sys/class/thermal/thermal_zone2/type
rk-bat
2、获取温度值
rk3288:/ # cat /sys/class/thermal/thermal_zone0/temp
36999
rk3288:/ # cat /sys/class/thermal/thermal_zone1/temp
37198
rk3288:/ # cat /sys/class/thermal/thermal_zone2/temp
18800
举报