of-thermal.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * of-thermal.c - Generic Thermal Management device tree support.
  4. *
  5. * Copyright (C) 2013 Texas Instruments
  6. * Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
  7. */
  8. #include <linux/thermal.h>
  9. #include <linux/slab.h>
  10. #include <linux/types.h>
  11. #include <linux/of_device.h>
  12. #include <linux/of_platform.h>
  13. #include <linux/err.h>
  14. #include <linux/export.h>
  15. #include <linux/string.h>
  16. #include "thermal_core.h"
  17. /*** Private data structures to represent thermal device tree data ***/
  18. /**
  19. * struct __thermal_bind_param - a match between trip and cooling device
  20. * @cooling_device: a pointer to identify the referred cooling device
  21. * @trip_id: the trip point index
  22. * @usage: the percentage (from 0 to 100) of cooling contribution
  23. * @min: minimum cooling state used at this trip point
  24. * @max: maximum cooling state used at this trip point
  25. */
  26. struct __thermal_bind_params {
  27. struct device_node *cooling_device;
  28. unsigned int trip_id;
  29. unsigned int usage;
  30. unsigned long min;
  31. unsigned long max;
  32. };
  33. /**
  34. * struct __thermal_zone - internal representation of a thermal zone
  35. * @mode: current thermal zone device mode (enabled/disabled)
  36. * @passive_delay: polling interval while passive cooling is activated
  37. * @polling_delay: zone polling interval
  38. * @slope: slope of the temperature adjustment curve
  39. * @offset: offset of the temperature adjustment curve
  40. * @ntrips: number of trip points
  41. * @trips: an array of trip points (0..ntrips - 1)
  42. * @num_tbps: number of thermal bind params
  43. * @tbps: an array of thermal bind params (0..num_tbps - 1)
  44. * @sensor_data: sensor private data used while reading temperature and trend
  45. * @ops: set of callbacks to handle the thermal zone based on DT
  46. */
  47. struct __thermal_zone {
  48. enum thermal_device_mode mode;
  49. int passive_delay;
  50. int polling_delay;
  51. int slope;
  52. int offset;
  53. /* trip data */
  54. int ntrips;
  55. struct thermal_trip *trips;
  56. /* cooling binding data */
  57. int num_tbps;
  58. struct __thermal_bind_params *tbps;
  59. /* sensor interface */
  60. void *sensor_data;
  61. const struct thermal_zone_of_device_ops *ops;
  62. };
  63. /*** DT thermal zone device callbacks ***/
  64. static int of_thermal_get_temp(struct thermal_zone_device *tz,
  65. int *temp)
  66. {
  67. struct __thermal_zone *data = tz->devdata;
  68. if (!data->ops->get_temp)
  69. return -EINVAL;
  70. return data->ops->get_temp(data->sensor_data, temp);
  71. }
  72. static int of_thermal_set_trips(struct thermal_zone_device *tz,
  73. int low, int high)
  74. {
  75. struct __thermal_zone *data = tz->devdata;
  76. if (!data->ops || !data->ops->set_trips)
  77. return -EINVAL;
  78. return data->ops->set_trips(data->sensor_data, low, high);
  79. }
  80. /**
  81. * of_thermal_get_ntrips - function to export number of available trip
  82. * points.
  83. * @tz: pointer to a thermal zone
  84. *
  85. * This function is a globally visible wrapper to get number of trip points
  86. * stored in the local struct __thermal_zone
  87. *
  88. * Return: number of available trip points, -ENODEV when data not available
  89. */
  90. int of_thermal_get_ntrips(struct thermal_zone_device *tz)
  91. {
  92. struct __thermal_zone *data = tz->devdata;
  93. if (!data || IS_ERR(data))
  94. return -ENODEV;
  95. return data->ntrips;
  96. }
  97. EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
  98. /**
  99. * of_thermal_is_trip_valid - function to check if trip point is valid
  100. *
  101. * @tz: pointer to a thermal zone
  102. * @trip: trip point to evaluate
  103. *
  104. * This function is responsible for checking if passed trip point is valid
  105. *
  106. * Return: true if trip point is valid, false otherwise
  107. */
  108. bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip)
  109. {
  110. struct __thermal_zone *data = tz->devdata;
  111. if (!data || trip >= data->ntrips || trip < 0)
  112. return false;
  113. return true;
  114. }
  115. EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
  116. /**
  117. * of_thermal_get_trip_points - function to get access to a globally exported
  118. * trip points
  119. *
  120. * @tz: pointer to a thermal zone
  121. *
  122. * This function provides a pointer to trip points table
  123. *
  124. * Return: pointer to trip points table, NULL otherwise
  125. */
  126. const struct thermal_trip *
  127. of_thermal_get_trip_points(struct thermal_zone_device *tz)
  128. {
  129. struct __thermal_zone *data = tz->devdata;
  130. if (!data)
  131. return NULL;
  132. return data->trips;
  133. }
  134. EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
  135. /**
  136. * of_thermal_set_emul_temp - function to set emulated temperature
  137. *
  138. * @tz: pointer to a thermal zone
  139. * @temp: temperature to set
  140. *
  141. * This function gives the ability to set emulated value of temperature,
  142. * which is handy for debugging
  143. *
  144. * Return: zero on success, error code otherwise
  145. */
  146. static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
  147. int temp)
  148. {
  149. struct __thermal_zone *data = tz->devdata;
  150. return data->ops->set_emul_temp(data->sensor_data, temp);
  151. }
  152. static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
  153. enum thermal_trend *trend)
  154. {
  155. struct __thermal_zone *data = tz->devdata;
  156. if (!data->ops->get_trend)
  157. return -EINVAL;
  158. return data->ops->get_trend(data->sensor_data, trip, trend);
  159. }
  160. static int of_thermal_bind(struct thermal_zone_device *thermal,
  161. struct thermal_cooling_device *cdev)
  162. {
  163. struct __thermal_zone *data = thermal->devdata;
  164. int i;
  165. if (!data || IS_ERR(data))
  166. return -ENODEV;
  167. /* find where to bind */
  168. for (i = 0; i < data->num_tbps; i++) {
  169. struct __thermal_bind_params *tbp = data->tbps + i;
  170. if (tbp->cooling_device == cdev->np) {
  171. int ret;
  172. ret = thermal_zone_bind_cooling_device(thermal,
  173. tbp->trip_id, cdev,
  174. tbp->max,
  175. tbp->min,
  176. tbp->usage);
  177. if (ret)
  178. return ret;
  179. }
  180. }
  181. return 0;
  182. }
  183. static int of_thermal_unbind(struct thermal_zone_device *thermal,
  184. struct thermal_cooling_device *cdev)
  185. {
  186. struct __thermal_zone *data = thermal->devdata;
  187. int i;
  188. if (!data || IS_ERR(data))
  189. return -ENODEV;
  190. /* find where to unbind */
  191. for (i = 0; i < data->num_tbps; i++) {
  192. struct __thermal_bind_params *tbp = data->tbps + i;
  193. if (tbp->cooling_device == cdev->np) {
  194. int ret;
  195. ret = thermal_zone_unbind_cooling_device(thermal,
  196. tbp->trip_id, cdev);
  197. if (ret)
  198. return ret;
  199. }
  200. }
  201. return 0;
  202. }
  203. static int of_thermal_get_mode(struct thermal_zone_device *tz,
  204. enum thermal_device_mode *mode)
  205. {
  206. struct __thermal_zone *data = tz->devdata;
  207. *mode = data->mode;
  208. return 0;
  209. }
  210. static int of_thermal_set_mode(struct thermal_zone_device *tz,
  211. enum thermal_device_mode mode)
  212. {
  213. struct __thermal_zone *data = tz->devdata;
  214. mutex_lock(&tz->lock);
  215. if (mode == THERMAL_DEVICE_ENABLED) {
  216. tz->polling_delay = data->polling_delay;
  217. tz->passive_delay = data->passive_delay;
  218. } else {
  219. tz->polling_delay = 0;
  220. tz->passive_delay = 0;
  221. }
  222. mutex_unlock(&tz->lock);
  223. data->mode = mode;
  224. thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
  225. return 0;
  226. }
  227. static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
  228. enum thermal_trip_type *type)
  229. {
  230. struct __thermal_zone *data = tz->devdata;
  231. if (trip >= data->ntrips || trip < 0)
  232. return -EDOM;
  233. *type = data->trips[trip].type;
  234. return 0;
  235. }
  236. static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
  237. int *temp)
  238. {
  239. struct __thermal_zone *data = tz->devdata;
  240. if (trip >= data->ntrips || trip < 0)
  241. return -EDOM;
  242. *temp = data->trips[trip].temperature;
  243. return 0;
  244. }
  245. static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
  246. int temp)
  247. {
  248. struct __thermal_zone *data = tz->devdata;
  249. if (trip >= data->ntrips || trip < 0)
  250. return -EDOM;
  251. if (data->ops->set_trip_temp) {
  252. int ret;
  253. ret = data->ops->set_trip_temp(data->sensor_data, trip, temp);
  254. if (ret)
  255. return ret;
  256. }
  257. /* thermal framework should take care of data->mask & (1 << trip) */
  258. data->trips[trip].temperature = temp;
  259. return 0;
  260. }
  261. static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
  262. int *hyst)
  263. {
  264. struct __thermal_zone *data = tz->devdata;
  265. if (trip >= data->ntrips || trip < 0)
  266. return -EDOM;
  267. *hyst = data->trips[trip].hysteresis;
  268. return 0;
  269. }
  270. static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
  271. int hyst)
  272. {
  273. struct __thermal_zone *data = tz->devdata;
  274. if (trip >= data->ntrips || trip < 0)
  275. return -EDOM;
  276. /* thermal framework should take care of data->mask & (1 << trip) */
  277. data->trips[trip].hysteresis = hyst;
  278. return 0;
  279. }
  280. static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
  281. int *temp)
  282. {
  283. struct __thermal_zone *data = tz->devdata;
  284. int i;
  285. for (i = 0; i < data->ntrips; i++)
  286. if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
  287. *temp = data->trips[i].temperature;
  288. return 0;
  289. }
  290. return -EINVAL;
  291. }
  292. static struct thermal_zone_device_ops of_thermal_ops = {
  293. .get_mode = of_thermal_get_mode,
  294. .set_mode = of_thermal_set_mode,
  295. .get_trip_type = of_thermal_get_trip_type,
  296. .get_trip_temp = of_thermal_get_trip_temp,
  297. .set_trip_temp = of_thermal_set_trip_temp,
  298. .get_trip_hyst = of_thermal_get_trip_hyst,
  299. .set_trip_hyst = of_thermal_set_trip_hyst,
  300. .get_crit_temp = of_thermal_get_crit_temp,
  301. .bind = of_thermal_bind,
  302. .unbind = of_thermal_unbind,
  303. };
  304. /*** sensor API ***/
  305. static struct thermal_zone_device *
  306. thermal_zone_of_add_sensor(struct device_node *zone,
  307. struct device_node *sensor, void *data,
  308. const struct thermal_zone_of_device_ops *ops)
  309. {
  310. struct thermal_zone_device *tzd;
  311. struct __thermal_zone *tz;
  312. tzd = thermal_zone_get_zone_by_name(zone->name);
  313. if (IS_ERR(tzd))
  314. return ERR_PTR(-EPROBE_DEFER);
  315. tz = tzd->devdata;
  316. if (!ops)
  317. return ERR_PTR(-EINVAL);
  318. mutex_lock(&tzd->lock);
  319. tz->ops = ops;
  320. tz->sensor_data = data;
  321. tzd->ops->get_temp = of_thermal_get_temp;
  322. tzd->ops->get_trend = of_thermal_get_trend;
  323. /*
  324. * The thermal zone core will calculate the window if they have set the
  325. * optional set_trips pointer.
  326. */
  327. if (ops->set_trips)
  328. tzd->ops->set_trips = of_thermal_set_trips;
  329. if (ops->set_emul_temp)
  330. tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
  331. mutex_unlock(&tzd->lock);
  332. return tzd;
  333. }
  334. /**
  335. * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
  336. * @dev: a valid struct device pointer of a sensor device. Must contain
  337. * a valid .of_node, for the sensor node.
  338. * @sensor_id: a sensor identifier, in case the sensor IP has more
  339. * than one sensors
  340. * @data: a private pointer (owned by the caller) that will be passed
  341. * back, when a temperature reading is needed.
  342. * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
  343. *
  344. * This function will search the list of thermal zones described in device
  345. * tree and look for the zone that refer to the sensor device pointed by
  346. * @dev->of_node as temperature providers. For the zone pointing to the
  347. * sensor node, the sensor will be added to the DT thermal zone device.
  348. *
  349. * The thermal zone temperature is provided by the @get_temp function
  350. * pointer. When called, it will have the private pointer @data back.
  351. *
  352. * The thermal zone temperature trend is provided by the @get_trend function
  353. * pointer. When called, it will have the private pointer @data back.
  354. *
  355. * TODO:
  356. * 01 - This function must enqueue the new sensor instead of using
  357. * it as the only source of temperature values.
  358. *
  359. * 02 - There must be a way to match the sensor with all thermal zones
  360. * that refer to it.
  361. *
  362. * Return: On success returns a valid struct thermal_zone_device,
  363. * otherwise, it returns a corresponding ERR_PTR(). Caller must
  364. * check the return value with help of IS_ERR() helper.
  365. */
  366. struct thermal_zone_device *
  367. thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
  368. const struct thermal_zone_of_device_ops *ops)
  369. {
  370. struct device_node *np, *child, *sensor_np;
  371. struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
  372. np = of_find_node_by_name(NULL, "thermal-zones");
  373. if (!np)
  374. return ERR_PTR(-ENODEV);
  375. if (!dev || !dev->of_node) {
  376. of_node_put(np);
  377. return ERR_PTR(-EINVAL);
  378. }
  379. sensor_np = of_node_get(dev->of_node);
  380. for_each_available_child_of_node(np, child) {
  381. struct of_phandle_args sensor_specs;
  382. int ret, id;
  383. /* For now, thermal framework supports only 1 sensor per zone */
  384. ret = of_parse_phandle_with_args(child, "thermal-sensors",
  385. "#thermal-sensor-cells",
  386. 0, &sensor_specs);
  387. if (ret)
  388. continue;
  389. if (sensor_specs.args_count >= 1) {
  390. id = sensor_specs.args[0];
  391. WARN(sensor_specs.args_count > 1,
  392. "%s: too many cells in sensor specifier %d\n",
  393. sensor_specs.np->name, sensor_specs.args_count);
  394. } else {
  395. id = 0;
  396. }
  397. if (sensor_specs.np == sensor_np && id == sensor_id) {
  398. tzd = thermal_zone_of_add_sensor(child, sensor_np,
  399. data, ops);
  400. if (!IS_ERR(tzd))
  401. tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);
  402. of_node_put(sensor_specs.np);
  403. of_node_put(child);
  404. goto exit;
  405. }
  406. of_node_put(sensor_specs.np);
  407. }
  408. exit:
  409. of_node_put(sensor_np);
  410. of_node_put(np);
  411. return tzd;
  412. }
  413. EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register);
  414. /**
  415. * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone
  416. * @dev: a valid struct device pointer of a sensor device. Must contain
  417. * a valid .of_node, for the sensor node.
  418. * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
  419. *
  420. * This function removes the sensor callbacks and private data from the
  421. * thermal zone device registered with thermal_zone_of_sensor_register()
  422. * API. It will also silent the zone by remove the .get_temp() and .get_trend()
  423. * thermal zone device callbacks.
  424. *
  425. * TODO: When the support to several sensors per zone is added, this
  426. * function must search the sensor list based on @dev parameter.
  427. *
  428. */
  429. void thermal_zone_of_sensor_unregister(struct device *dev,
  430. struct thermal_zone_device *tzd)
  431. {
  432. struct __thermal_zone *tz;
  433. if (!dev || !tzd || !tzd->devdata)
  434. return;
  435. tz = tzd->devdata;
  436. /* no __thermal_zone, nothing to be done */
  437. if (!tz)
  438. return;
  439. mutex_lock(&tzd->lock);
  440. tzd->ops->get_temp = NULL;
  441. tzd->ops->get_trend = NULL;
  442. tzd->ops->set_emul_temp = NULL;
  443. tz->ops = NULL;
  444. tz->sensor_data = NULL;
  445. mutex_unlock(&tzd->lock);
  446. }
  447. EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
  448. static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res)
  449. {
  450. thermal_zone_of_sensor_unregister(dev,
  451. *(struct thermal_zone_device **)res);
  452. }
  453. static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res,
  454. void *data)
  455. {
  456. struct thermal_zone_device **r = res;
  457. if (WARN_ON(!r || !*r))
  458. return 0;
  459. return *r == data;
  460. }
  461. /**
  462. * devm_thermal_zone_of_sensor_register - Resource managed version of
  463. * thermal_zone_of_sensor_register()
  464. * @dev: a valid struct device pointer of a sensor device. Must contain
  465. * a valid .of_node, for the sensor node.
  466. * @sensor_id: a sensor identifier, in case the sensor IP has more
  467. * than one sensors
  468. * @data: a private pointer (owned by the caller) that will be passed
  469. * back, when a temperature reading is needed.
  470. * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
  471. *
  472. * Refer thermal_zone_of_sensor_register() for more details.
  473. *
  474. * Return: On success returns a valid struct thermal_zone_device,
  475. * otherwise, it returns a corresponding ERR_PTR(). Caller must
  476. * check the return value with help of IS_ERR() helper.
  477. * Registered thermal_zone_device device will automatically be
  478. * released when device is unbounded.
  479. */
  480. struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
  481. struct device *dev, int sensor_id,
  482. void *data, const struct thermal_zone_of_device_ops *ops)
  483. {
  484. struct thermal_zone_device **ptr, *tzd;
  485. ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr),
  486. GFP_KERNEL);
  487. if (!ptr)
  488. return ERR_PTR(-ENOMEM);
  489. tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops);
  490. if (IS_ERR(tzd)) {
  491. devres_free(ptr);
  492. return tzd;
  493. }
  494. *ptr = tzd;
  495. devres_add(dev, ptr);
  496. return tzd;
  497. }
  498. EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register);
  499. /**
  500. * devm_thermal_zone_of_sensor_unregister - Resource managed version of
  501. * thermal_zone_of_sensor_unregister().
  502. * @dev: Device for which which resource was allocated.
  503. * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
  504. *
  505. * This function removes the sensor callbacks and private data from the
  506. * thermal zone device registered with devm_thermal_zone_of_sensor_register()
  507. * API. It will also silent the zone by remove the .get_temp() and .get_trend()
  508. * thermal zone device callbacks.
  509. * Normally this function will not need to be called and the resource
  510. * management code will ensure that the resource is freed.
  511. */
  512. void devm_thermal_zone_of_sensor_unregister(struct device *dev,
  513. struct thermal_zone_device *tzd)
  514. {
  515. WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release,
  516. devm_thermal_zone_of_sensor_match, tzd));
  517. }
  518. EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
  519. /*** functions parsing device tree nodes ***/
  520. /**
  521. * thermal_of_populate_bind_params - parse and fill cooling map data
  522. * @np: DT node containing a cooling-map node
  523. * @__tbp: data structure to be filled with cooling map info
  524. * @trips: array of thermal zone trip points
  525. * @ntrips: number of trip points inside trips.
  526. *
  527. * This function parses a cooling-map type of node represented by
  528. * @np parameter and fills the read data into @__tbp data structure.
  529. * It needs the already parsed array of trip points of the thermal zone
  530. * in consideration.
  531. *
  532. * Return: 0 on success, proper error code otherwise
  533. */
  534. static int thermal_of_populate_bind_params(struct device_node *np,
  535. struct __thermal_bind_params *__tbp,
  536. struct thermal_trip *trips,
  537. int ntrips)
  538. {
  539. struct of_phandle_args cooling_spec;
  540. struct device_node *trip;
  541. int ret, i;
  542. u32 prop;
  543. /* Default weight. Usage is optional */
  544. __tbp->usage = THERMAL_WEIGHT_DEFAULT;
  545. ret = of_property_read_u32(np, "contribution", &prop);
  546. if (ret == 0)
  547. __tbp->usage = prop;
  548. trip = of_parse_phandle(np, "trip", 0);
  549. if (!trip) {
  550. pr_err("missing trip property\n");
  551. return -ENODEV;
  552. }
  553. /* match using device_node */
  554. for (i = 0; i < ntrips; i++)
  555. if (trip == trips[i].np) {
  556. __tbp->trip_id = i;
  557. break;
  558. }
  559. if (i == ntrips) {
  560. ret = -ENODEV;
  561. goto end;
  562. }
  563. ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells",
  564. 0, &cooling_spec);
  565. if (ret < 0) {
  566. pr_err("missing cooling_device property\n");
  567. goto end;
  568. }
  569. __tbp->cooling_device = cooling_spec.np;
  570. if (cooling_spec.args_count >= 2) { /* at least min and max */
  571. __tbp->min = cooling_spec.args[0];
  572. __tbp->max = cooling_spec.args[1];
  573. } else {
  574. pr_err("wrong reference to cooling device, missing limits\n");
  575. }
  576. end:
  577. of_node_put(trip);
  578. return ret;
  579. }
  580. /**
  581. * It maps 'enum thermal_trip_type' found in include/linux/thermal.h
  582. * into the device tree binding of 'trip', property type.
  583. */
  584. static const char * const trip_types[] = {
  585. [THERMAL_TRIP_ACTIVE] = "active",
  586. [THERMAL_TRIP_PASSIVE] = "passive",
  587. [THERMAL_TRIP_HOT] = "hot",
  588. [THERMAL_TRIP_CRITICAL] = "critical",
  589. };
  590. /**
  591. * thermal_of_get_trip_type - Get phy mode for given device_node
  592. * @np: Pointer to the given device_node
  593. * @type: Pointer to resulting trip type
  594. *
  595. * The function gets trip type string from property 'type',
  596. * and store its index in trip_types table in @type,
  597. *
  598. * Return: 0 on success, or errno in error case.
  599. */
  600. static int thermal_of_get_trip_type(struct device_node *np,
  601. enum thermal_trip_type *type)
  602. {
  603. const char *t;
  604. int err, i;
  605. err = of_property_read_string(np, "type", &t);
  606. if (err < 0)
  607. return err;
  608. for (i = 0; i < ARRAY_SIZE(trip_types); i++)
  609. if (!strcasecmp(t, trip_types[i])) {
  610. *type = i;
  611. return 0;
  612. }
  613. return -ENODEV;
  614. }
  615. /**
  616. * thermal_of_populate_trip - parse and fill one trip point data
  617. * @np: DT node containing a trip point node
  618. * @trip: trip point data structure to be filled up
  619. *
  620. * This function parses a trip point type of node represented by
  621. * @np parameter and fills the read data into @trip data structure.
  622. *
  623. * Return: 0 on success, proper error code otherwise
  624. */
  625. static int thermal_of_populate_trip(struct device_node *np,
  626. struct thermal_trip *trip)
  627. {
  628. int prop;
  629. int ret;
  630. ret = of_property_read_u32(np, "temperature", &prop);
  631. if (ret < 0) {
  632. pr_err("missing temperature property\n");
  633. return ret;
  634. }
  635. trip->temperature = prop;
  636. ret = of_property_read_u32(np, "hysteresis", &prop);
  637. if (ret < 0) {
  638. pr_err("missing hysteresis property\n");
  639. return ret;
  640. }
  641. trip->hysteresis = prop;
  642. ret = thermal_of_get_trip_type(np, &trip->type);
  643. if (ret < 0) {
  644. pr_err("wrong trip type property\n");
  645. return ret;
  646. }
  647. /* Required for cooling map matching */
  648. trip->np = np;
  649. of_node_get(np);
  650. return 0;
  651. }
  652. /**
  653. * thermal_of_build_thermal_zone - parse and fill one thermal zone data
  654. * @np: DT node containing a thermal zone node
  655. *
  656. * This function parses a thermal zone type of node represented by
  657. * @np parameter and fills the read data into a __thermal_zone data structure
  658. * and return this pointer.
  659. *
  660. * TODO: Missing properties to parse: thermal-sensor-names
  661. *
  662. * Return: On success returns a valid struct __thermal_zone,
  663. * otherwise, it returns a corresponding ERR_PTR(). Caller must
  664. * check the return value with help of IS_ERR() helper.
  665. */
  666. static struct __thermal_zone
  667. __init *thermal_of_build_thermal_zone(struct device_node *np)
  668. {
  669. struct device_node *child = NULL, *gchild;
  670. struct __thermal_zone *tz;
  671. int ret, i;
  672. u32 prop, coef[2];
  673. if (!np) {
  674. pr_err("no thermal zone np\n");
  675. return ERR_PTR(-EINVAL);
  676. }
  677. tz = kzalloc(sizeof(*tz), GFP_KERNEL);
  678. if (!tz)
  679. return ERR_PTR(-ENOMEM);
  680. ret = of_property_read_u32(np, "polling-delay-passive", &prop);
  681. if (ret < 0) {
  682. pr_err("missing polling-delay-passive property\n");
  683. goto free_tz;
  684. }
  685. tz->passive_delay = prop;
  686. ret = of_property_read_u32(np, "polling-delay", &prop);
  687. if (ret < 0) {
  688. pr_err("missing polling-delay property\n");
  689. goto free_tz;
  690. }
  691. tz->polling_delay = prop;
  692. /*
  693. * REVIST: for now, the thermal framework supports only
  694. * one sensor per thermal zone. Thus, we are considering
  695. * only the first two values as slope and offset.
  696. */
  697. ret = of_property_read_u32_array(np, "coefficients", coef, 2);
  698. if (ret == 0) {
  699. tz->slope = coef[0];
  700. tz->offset = coef[1];
  701. } else {
  702. tz->slope = 1;
  703. tz->offset = 0;
  704. }
  705. /* trips */
  706. child = of_get_child_by_name(np, "trips");
  707. /* No trips provided */
  708. if (!child)
  709. goto finish;
  710. tz->ntrips = of_get_child_count(child);
  711. if (tz->ntrips == 0) /* must have at least one child */
  712. goto finish;
  713. tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL);
  714. if (!tz->trips) {
  715. ret = -ENOMEM;
  716. goto free_tz;
  717. }
  718. i = 0;
  719. for_each_child_of_node(child, gchild) {
  720. ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
  721. if (ret)
  722. goto free_trips;
  723. }
  724. of_node_put(child);
  725. /* cooling-maps */
  726. child = of_get_child_by_name(np, "cooling-maps");
  727. /* cooling-maps not provided */
  728. if (!child)
  729. goto finish;
  730. tz->num_tbps = of_get_child_count(child);
  731. if (tz->num_tbps == 0)
  732. goto finish;
  733. tz->tbps = kcalloc(tz->num_tbps, sizeof(*tz->tbps), GFP_KERNEL);
  734. if (!tz->tbps) {
  735. ret = -ENOMEM;
  736. goto free_trips;
  737. }
  738. i = 0;
  739. for_each_child_of_node(child, gchild) {
  740. ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++],
  741. tz->trips, tz->ntrips);
  742. if (ret)
  743. goto free_tbps;
  744. }
  745. finish:
  746. of_node_put(child);
  747. tz->mode = THERMAL_DEVICE_DISABLED;
  748. return tz;
  749. free_tbps:
  750. for (i = i - 1; i >= 0; i--)
  751. of_node_put(tz->tbps[i].cooling_device);
  752. kfree(tz->tbps);
  753. free_trips:
  754. for (i = 0; i < tz->ntrips; i++)
  755. of_node_put(tz->trips[i].np);
  756. kfree(tz->trips);
  757. of_node_put(gchild);
  758. free_tz:
  759. kfree(tz);
  760. of_node_put(child);
  761. return ERR_PTR(ret);
  762. }
  763. static inline void of_thermal_free_zone(struct __thermal_zone *tz)
  764. {
  765. int i;
  766. for (i = 0; i < tz->num_tbps; i++)
  767. of_node_put(tz->tbps[i].cooling_device);
  768. kfree(tz->tbps);
  769. for (i = 0; i < tz->ntrips; i++)
  770. of_node_put(tz->trips[i].np);
  771. kfree(tz->trips);
  772. kfree(tz);
  773. }
  774. /**
  775. * of_parse_thermal_zones - parse device tree thermal data
  776. *
  777. * Initialization function that can be called by machine initialization
  778. * code to parse thermal data and populate the thermal framework
  779. * with hardware thermal zones info. This function only parses thermal zones.
  780. * Cooling devices and sensor devices nodes are supposed to be parsed
  781. * by their respective drivers.
  782. *
  783. * Return: 0 on success, proper error code otherwise
  784. *
  785. */
  786. int __init of_parse_thermal_zones(void)
  787. {
  788. struct device_node *np, *child;
  789. struct __thermal_zone *tz;
  790. struct thermal_zone_device_ops *ops;
  791. np = of_find_node_by_name(NULL, "thermal-zones");
  792. if (!np) {
  793. pr_debug("unable to find thermal zones\n");
  794. return 0; /* Run successfully on systems without thermal DT */
  795. }
  796. for_each_available_child_of_node(np, child) {
  797. struct thermal_zone_device *zone;
  798. struct thermal_zone_params *tzp;
  799. int i, mask = 0;
  800. u32 prop;
  801. tz = thermal_of_build_thermal_zone(child);
  802. if (IS_ERR(tz)) {
  803. pr_err("failed to build thermal zone %s: %ld\n",
  804. child->name,
  805. PTR_ERR(tz));
  806. continue;
  807. }
  808. ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
  809. if (!ops)
  810. goto exit_free;
  811. tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
  812. if (!tzp) {
  813. kfree(ops);
  814. goto exit_free;
  815. }
  816. /* No hwmon because there might be hwmon drivers registering */
  817. tzp->no_hwmon = true;
  818. if (!of_property_read_u32(child, "sustainable-power", &prop))
  819. tzp->sustainable_power = prop;
  820. for (i = 0; i < tz->ntrips; i++)
  821. mask |= 1 << i;
  822. /* these two are left for temperature drivers to use */
  823. tzp->slope = tz->slope;
  824. tzp->offset = tz->offset;
  825. zone = thermal_zone_device_register(child->name, tz->ntrips,
  826. mask, tz,
  827. ops, tzp,
  828. tz->passive_delay,
  829. tz->polling_delay);
  830. if (IS_ERR(zone)) {
  831. pr_err("Failed to build %s zone %ld\n", child->name,
  832. PTR_ERR(zone));
  833. kfree(tzp);
  834. kfree(ops);
  835. of_thermal_free_zone(tz);
  836. /* attempting to build remaining zones still */
  837. }
  838. }
  839. of_node_put(np);
  840. return 0;
  841. exit_free:
  842. of_node_put(child);
  843. of_node_put(np);
  844. of_thermal_free_zone(tz);
  845. /* no memory available, so free what we have built */
  846. of_thermal_destroy_zones();
  847. return -ENOMEM;
  848. }
  849. /**
  850. * of_thermal_destroy_zones - remove all zones parsed and allocated resources
  851. *
  852. * Finds all zones parsed and added to the thermal framework and remove them
  853. * from the system, together with their resources.
  854. *
  855. */
  856. void of_thermal_destroy_zones(void)
  857. {
  858. struct device_node *np, *child;
  859. np = of_find_node_by_name(NULL, "thermal-zones");
  860. if (!np) {
  861. pr_debug("unable to find thermal zones\n");
  862. return;
  863. }
  864. for_each_available_child_of_node(np, child) {
  865. struct thermal_zone_device *zone;
  866. zone = thermal_zone_get_zone_by_name(child->name);
  867. if (IS_ERR(zone))
  868. continue;
  869. thermal_zone_device_unregister(zone);
  870. kfree(zone->tzp);
  871. kfree(zone->ops);
  872. of_thermal_free_zone(zone->devdata);
  873. }
  874. of_node_put(np);
  875. }