VS-RK3399 Android7.1 TSADC驱动流程小结 前言:和RK3288一样,RK3399上有两路TSADC通道分别用于监测CPU和GPU的温度。 不同的是RK3399结合kernel thermal core框架来管控,而RK3288直接是写了一个独立驱动控制硬件。 TSADC两种模式: 1.用户自定义模式。 所以信号都通过是user写到寄存器中控制。 2.自动模式。 控制器自动查询TSADC输出,如果温度过高就会产生中断,如果再高就会发信号给CRU模块复位整个芯片或者通过gpio通知PMU做处理。 TSADC控制器特性: 1. 支持用户自定义和自动模式 2. 支持两路通道 3. 系统复位的温度点可被配置 4. 可设置范围:~40-125°, 精度是5° 5. ADC精度10bit,采样率50kb/s 6. 温度探测和周期值可配置 控制器配置: rk3399.dtsi: tsadc: tsadc@ff260000 { compatible = "rockchip,rk3399-tsadc"; //设备名,和驱动匹配 reg = <0x0 0xff260000 0x0 0x100>; interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH 0>; rockchip,grf = <&grf>; clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; clock-names = "tsadc", "apb_pclk"; assigned-clocks = <&cru SCLK_TSADC>; assigned-clock-rates = <750000>; resets = <&cru SRST_TSADC>;//reset对应的cru reset-names = "tsadc-apb"; pinctrl-names = "init", "default", "sleep"; pinctrl-0 = <&otp_gpio>; pinctrl-1 = <&otp_out>; pinctrl-2 = <&otp_gpio>; #thermal-sensor-cells = <1>; rockchip,hw-tshut-temp = <95000>; //设置的关机温度 status = "disabled";}; 另一部分配置是在rk3399-core.c中: &tsadc { /* tshut mode 0:CRU 1:GPIO */ rockchip,hw-tshut-mode = <1>; //关机模式,设置为通过gpio方式 /* tshut polarity 0 OW 1:HIGH */ rockchip,hw-tshut-polarity = <1>; //对应关机极性 status = "okay";}; 除了tsadc之外,我们也需要了解thermal zone的配置: thermal_zones: thermal-zones { soc_thermal: soc-thermal { //对应cpu thermal polling-delay-passive = <20>; /* milliseconds */ //当超过阀值时,每隔20ms查询一次。 polling-delay = <1000>; /* milliseconds */ //未超过阀值时,每隔1000ms查询一次。 sustainable-power = <1000>; /* milliwatts */ //当前温度到达预设的最高值时,系统能分配给 cooling 设备的能量。 //用于power allocator策略。 thermal-sensors = <&tsadc 0>; //使用tsadc的channel 0. trips { //控制温度触发范围值配置 threshold: trip-point@0 { temperature = <70000>; /* millicelsius */ //温度超过70°温控策略开始工作,但不一定马上限制频率。 hysteresis = <2000>; /* millicelsius */ //迟滞值,允许一定时间缓冲后才开始执行控制策略。 type = "passive"; //要设置成"passive" }; target: trip-point@1 { // temperature = <85000>; /* millicelsius */ hysteresis = <2000>; /* millicelsius */ type = "passive"; }; soc_crit: soc-crit { //系统温度的临界值,超过就要关机了。 temperature = <95000>; /* millicelsius */ hysteresis = <2000>; /* millicelsius */ type = "critical"; //要设置成critical才会起作用。 }; }; cooling-maps { //降温策略配置,有三个要被降温的设备,分别是小核A53(cpu_l0), 大核A72(cpu_b0)以及GPU map0 { trip = <&target>; //power_allocater策略子节点的trip属性都设置target。 cooling-device = <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; //允许被限制最低和最高频率。 contribution = <4096>; //注释是 the percentage (from 0 to 100) of cooling contribution,还未研究其意义。 }; map1 { trip = <&target>; cooling-device = <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; contribution = <1024>; }; map2 { trip = <&target>; cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; contribution = <4096>; }; }; }; gpu_thermal: gpu-thermal { polling-delay-passive = <100>; /* milliseconds */ polling-delay = <1000>; /* milliseconds */ thermal-sensors = <&tsadc 1>; };}; 驱动文件: rockchip_thermal.c: rk3399 thermal controller驱动。 of-thermal.c: thermal core device tree接口。 thermal_core.c: linux thermal core核心框架。 重要数据结构: 代码调用流程: TSADC驱动初始化: rockchip_thermal_probe -> rockchip-thermal.c 用struct rockchip_thermal_data结构体表示thermal信息。 thermal->chip = (const struct rockchip_tsadc_chip *)match->data; //data就是rk3399_tsadc_data变量 rockchip_thermal_reset_controller //先复位控制器 rockchip_configure_from_dt //解析dts中的"rockchip,hw-tshut-temp","rockchip,hw-tshut-mode"以及"rockchip,hw-tshut-polarity" thermal->chip->initialize -> rk_tsadcv3_initialize //初始化TSADC控制器 rockchip_thermal_register_sensor -> //注册控制器 tsadc->set_tshut_mode -> //设置关机模式 rk_tsadcv2_tshut_mode tsadc->set_tshut_temp -> //设置关机温度 devm_thermal_zone_of_sensor_register -> of-thermal.c //注册thermal zone到系统中,留意其中的ops: rockchip_of_thermal_ops thermal_zone_of_sensor_register -> //返回的struct thermal_zone_device是thermal框架中标准结构 of_find_node_by_name(NULL, "thermal-zones"); //rk3399.dtsi中有此节点 thermal_zone_of_add_sensor -> //有soc_thermal和gpu_thermal两个zone,rockchip定义的ops会和 //struct rockchip_thermal_sensor被放到struct __thermal_zone中 //可以看到,thermal_zone_device包含__thermal_zone和ops, __thermal_zone包含 //rk自己定义的rockchip_thermal_sensor和ops,注意两者ops的区别,不要混淆了,下面的 //set_mode调用过程可以看到ops的一级级调用,最终控制到rk的tsadc控制器。 thermal_zone_get_zone_by_name //thermal zone在thermal_core.c中注册过了。 tzd->ops->set_mode -> of_thermal_set_mode -> of-thermal.c thermal_zone_device_update -> update_temperature -> //更新温度 thermal_zone_get_temp -> tz->ops->get_temp -> of_thermal_get_temp -> data->ops->get_temp -> //对应ops是rockchip_of_thermal_ops rockchip_thermal_get_temp -> tsadc->get_temp -> rk_tsadcv2_get_temp -> //调用控制器的get temp接口 rk_tsadcv2_code_to_temp //code转换成temperature thermal_zone_set_trips -> tz->ops->get_trip_temp -> //获取各个trip对应的温度,trip有三个,配置在thermal_zones节点中定义。 of_thermal_get_trip_temp -> *temp = data->trips[trip].temperature //根据trip number获取对应的温度 tz->ops->get_trip_hyst -> //获取迟滞值,此值会和上面的temperature结合,比如原本是75°触发,迟滞值是5°,那么80°才会真的触发thermal core做策略调整 of_thermal_get_trip_hyst tz->ops->set_trips -> of_thermal_set_trips -> data->ops->set_trips -> rockchip_thermal_set_trips -> tsadc->set_alarm_temp -> rk_tsadcv2_alarm_temp -> //设置触发alarm的温度,对应中断处理在下面注册 handle_thermal_trip -> tz->ops->get_trip_type -> //获取trip type of_thermal_get_trip_type handle_critical_trips -> //如果type是critical就走此流程 tz->ops->get_trip_temp //获取此trip对应设置的温度(dts中配置),如果没达到此温度就不做处理 orderly_poweroff //执行关机动作 handle_non_critical_trips -> //非critical的情况 tz->governor->throttle //执行thermal core cooling策略 monitor_thermal_zone //继续定时监测温度 devm_request_threaded_irq //创建一个thermal thread,处理函数是rockchip_thermal_alarm_irq_thread() thermal->chip->control -> //使能tsadc控制器 rk_tsadcv3_control rockchip_thermal_toggle_sensor -> tzd->ops->set_mode //又重新调用了一次 atomic_notifier_chain_register //系统panic的时候会发送回调,对应的处理函数是rockchip_thermal_panic(),打 |