Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thermal: ti-soc-thermal: use thermal DT infrastructure

This patch improves the ti-soc-thermal driver by adding the
support to build the thermal zones based on DT nodes.

The driver will have two options now to build the thermal
zones. The first option is the zones originally coded
in this driver. So, the driver behavior will be same
if there is no DT node describing the zones. The second
option, when it is found a DT node with thermal data,
will used the common infrastructure to build the thermal
zone and bind its cooling devices.

In case the driver loads thermal data using the legacy
mode, this driver still adds to the system
a cpufreq cooling device. Loading the thermal data from
DT, the driver assumes someone else will add the cpufreq
cooling device, like the cpufreq driver.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>

+62 -15
+62 -15
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
··· 31 31 #include <linux/cpufreq.h> 32 32 #include <linux/cpumask.h> 33 33 #include <linux/cpu_cooling.h> 34 + #include <linux/of.h> 34 35 35 36 #include "ti-thermal.h" 36 37 #include "ti-bandgap.h" ··· 45 44 enum thermal_device_mode mode; 46 45 struct work_struct thermal_wq; 47 46 int sensor_id; 47 + bool our_zone; 48 48 }; 49 49 50 50 static void ti_thermal_work(struct work_struct *work) ··· 77 75 78 76 /* thermal zone ops */ 79 77 /* Get temperature callback function for thermal zone*/ 80 - static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, 81 - unsigned long *temp) 78 + static inline int __ti_thermal_get_temp(void *devdata, long *temp) 82 79 { 83 80 struct thermal_zone_device *pcb_tz = NULL; 84 - struct ti_thermal_data *data = thermal->devdata; 81 + struct ti_thermal_data *data = devdata; 85 82 struct ti_bandgap *bgp; 86 83 const struct ti_temp_sensor *s; 87 84 int ret, tmp, slope, constant; ··· 117 116 *temp = ti_thermal_hotspot_temperature(tmp, slope, constant); 118 117 119 118 return ret; 119 + } 120 + 121 + static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, 122 + unsigned long *temp) 123 + { 124 + struct ti_thermal_data *data = thermal->devdata; 125 + 126 + return __ti_thermal_get_temp(data, temp); 120 127 } 121 128 122 129 /* Bind callback functions for thermal zone */ ··· 239 230 return 0; 240 231 } 241 232 242 - /* Get the temperature trend callback functions for thermal zone */ 243 - static int ti_thermal_get_trend(struct thermal_zone_device *thermal, 244 - int trip, enum thermal_trend *trend) 233 + static int __ti_thermal_get_trend(void *p, long *trend) 245 234 { 246 - struct ti_thermal_data *data = thermal->devdata; 235 + struct ti_thermal_data *data = p; 247 236 struct ti_bandgap *bgp; 248 237 int id, tr, ret = 0; 249 238 ··· 249 242 id = data->sensor_id; 250 243 251 244 ret = ti_bandgap_get_trend(bgp, id, &tr); 245 + if (ret) 246 + return ret; 247 + 248 + *trend = tr; 249 + 250 + return 0; 251 + } 252 + 253 + /* Get the temperature trend callback functions for thermal zone */ 254 + static int ti_thermal_get_trend(struct thermal_zone_device *thermal, 255 + int trip, enum thermal_trend *trend) 256 + { 257 + int ret; 258 + long tr; 259 + 260 + ret = __ti_thermal_get_trend(thermal->devdata, &tr); 252 261 if (ret) 253 262 return ret; 254 263 ··· 331 308 if (!data) 332 309 return -EINVAL; 333 310 334 - /* Create thermal zone */ 335 - data->ti_thermal = thermal_zone_device_register(domain, 311 + /* in case this is specified by DT */ 312 + data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id, 313 + data, __ti_thermal_get_temp, 314 + __ti_thermal_get_trend); 315 + if (IS_ERR(data->ti_thermal)) { 316 + /* Create thermal zone */ 317 + data->ti_thermal = thermal_zone_device_register(domain, 336 318 OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, 337 319 NULL, FAST_TEMP_MONITORING_RATE, 338 320 FAST_TEMP_MONITORING_RATE); 339 - if (IS_ERR(data->ti_thermal)) { 340 - dev_err(bgp->dev, "thermal zone device is NULL\n"); 341 - return PTR_ERR(data->ti_thermal); 321 + if (IS_ERR(data->ti_thermal)) { 322 + dev_err(bgp->dev, "thermal zone device is NULL\n"); 323 + return PTR_ERR(data->ti_thermal); 324 + } 325 + data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; 326 + data->our_zone = true; 342 327 } 343 - data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; 344 328 ti_bandgap_set_sensor_data(bgp, id, data); 345 329 ti_bandgap_write_update_interval(bgp, data->sensor_id, 346 330 data->ti_thermal->polling_delay); ··· 361 331 362 332 data = ti_bandgap_get_sensor_data(bgp, id); 363 333 364 - thermal_zone_device_unregister(data->ti_thermal); 334 + if (data && data->ti_thermal) { 335 + if (data->our_zone) 336 + thermal_zone_device_unregister(data->ti_thermal); 337 + else 338 + thermal_zone_of_sensor_unregister(bgp->dev, 339 + data->ti_thermal); 340 + } 365 341 366 342 return 0; 367 343 } ··· 386 350 int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) 387 351 { 388 352 struct ti_thermal_data *data; 353 + struct device_node *np = bgp->dev->of_node; 354 + 355 + /* 356 + * We are assuming here that if one deploys the zone 357 + * using DT, then it must be aware that the cooling device 358 + * loading has to happen via cpufreq driver. 359 + */ 360 + if (of_find_property(np, "#thermal-sensor-cells", NULL)) 361 + return 0; 389 362 390 363 data = ti_bandgap_get_sensor_data(bgp, id); 391 364 if (!data || IS_ERR(data)) ··· 425 380 struct ti_thermal_data *data; 426 381 427 382 data = ti_bandgap_get_sensor_data(bgp, id); 428 - cpufreq_cooling_unregister(data->cool_dev); 383 + 384 + if (data && data->cool_dev) 385 + cpufreq_cooling_unregister(data->cool_dev); 429 386 430 387 return 0; 431 388 }