of-thermal.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  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. else
  218. tz->polling_delay = 0;
  219. mutex_unlock(&tz->lock);
  220. data->mode = mode;
  221. thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
  222. return 0;
  223. }
  224. static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
  225. enum thermal_trip_type *type)
  226. {
  227. struct __thermal_zone *data = tz->devdata;
  228. if (trip >= data->ntrips || trip < 0)
  229. return -EDOM;
  230. *type = data->trips[trip].type;
  231. return 0;
  232. }
  233. static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
  234. int *temp)
  235. {
  236. struct __thermal_zone *data = tz->devdata;
  237. if (trip >= data->ntrips || trip < 0)
  238. return -EDOM;
  239. *temp = data->trips[trip].temperature;
  240. return 0;
  241. }
  242. static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
  243. int temp)
  244. {
  245. struct __thermal_zone *data = tz->devdata;
  246. if (trip >= data->ntrips || trip < 0)
  247. return -EDOM;
  248. if (data->ops->set_trip_temp) {
  249. int ret;
  250. ret = data->ops->set_trip_temp(data->sensor_data, trip, temp);
  251. if (ret)
  252. return ret;
  253. }
  254. /* thermal framework should take care of data->mask & (1 << trip) */
  255. data->trips[trip].temperature = temp;
  256. return 0;
  257. }
  258. static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
  259. int *hyst)
  260. {
  261. struct __thermal_zone *data = tz->devdata;
  262. if (trip >= data->ntrips || trip < 0)
  263. return -EDOM;
  264. *hyst = data->trips[trip].hysteresis;
  265. return 0;
  266. }
  267. static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
  268. int hyst)
  269. {
  270. struct __thermal_zone *data = tz->devdata;
  271. if (trip >= data->ntrips || trip < 0)
  272. return -EDOM;
  273. /* thermal framework should take care of data->mask & (1 << trip) */
  274. data->trips[trip].hysteresis = hyst;
  275. return 0;
  276. }
  277. static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
  278. int *temp)
  279. {
  280. struct __thermal_zone *data = tz->devdata;
  281. int i;
  282. for (i = 0; i < data->ntrips; i++)
  283. if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
  284. *temp = data->trips[i].temperature;
  285. return 0;
  286. }
  287. return -EINVAL;
  288. }
  289. static struct thermal_zone_device_ops of_thermal_ops = {
  290. .get_mode = of_thermal_get_mode,
  291. .set_mode = of_thermal_set_mode,
  292. .get_trip_type = of_thermal_get_trip_type,
  293. .get_trip_temp = of_thermal_get_trip_temp,
  294. .set_trip_temp = of_thermal_set_trip_temp,
  295. .get_trip_hyst = of_thermal_get_trip_hyst,
  296. .set_trip_hyst = of_thermal_set_trip_hyst,
  297. .get_crit_temp = of_thermal_get_crit_temp,
  298. .bind = of_thermal_bind,
  299. .unbind = of_thermal_unbind,
  300. };
  301. /*** sensor API ***/
  302. static struct thermal_zone_device *
  303. thermal_zone_of_add_sensor(struct device_node *zone,
  304. struct device_node *sensor, void *data,
  305. const struct thermal_zone_of_device_ops *ops)
  306. {
  307. struct thermal_zone_device *tzd;
  308. struct __thermal_zone *tz;
  309. tzd = thermal_zone_get_zone_by_name(zone->name);
  310. if (IS_ERR(tzd))
  311. return ERR_PTR(-EPROBE_DEFER);
  312. tz = tzd->devdata;
  313. if (!ops)
  314. return ERR_PTR(-EINVAL);
  315. mutex_lock(&tzd->lock);
  316. tz->ops = ops;
  317. tz->sensor_data = data;
  318. tzd->ops->get_temp = of_thermal_get_temp;
  319. tzd->ops->get_trend = of_thermal_get_trend;
  320. /*
  321. * The thermal zone core will calculate the window if they have set the
  322. * optional set_trips pointer.
  323. */
  324. if (ops->set_trips)
  325. tzd->ops->set_trips = of_thermal_set_trips;
  326. if (ops->set_emul_temp)
  327. tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
  328. mutex_unlock(&tzd->lock);
  329. return tzd;
  330. }
  331. /**
  332. * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
  333. * @dev: a valid struct device pointer of a sensor device. Must contain
  334. * a valid .of_node, for the sensor node.
  335. * @sensor_id: a sensor identifier, in case the sensor IP has more
  336. * than one sensors
  337. * @data: a private pointer (owned by the caller) that will be passed
  338. * back, when a temperature reading is needed.
  339. * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
  340. *
  341. * This function will search the list of thermal zones described in device
  342. * tree and look for the zone that refer to the sensor device pointed by
  343. * @dev->of_node as temperature providers. For the zone pointing to the
  344. * sensor node, the sensor will be added to the DT thermal zone device.
  345. *
  346. * The thermal zone temperature is provided by the @get_temp function
  347. * pointer. When called, it will have the private pointer @data back.
  348. *
  349. * The thermal zone temperature trend is provided by the @get_trend function
  350. * pointer. When called, it will have the private pointer @data back.
  351. *
  352. * TODO:
  353. * 01 - This function must enqueue the new sensor instead of using
  354. * it as the only source of temperature values.
  355. *
  356. * 02 - There must be a way to match the sensor with all thermal zones
  357. * that refer to it.
  358. *
  359. * Return: On success returns a valid struct thermal_zone_device,
  360. * otherwise, it returns a corresponding ERR_PTR(). Caller must
  361. * check the return value with help of IS_ERR() helper.
  362. */
  363. struct thermal_zone_device *
  364. thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
  365. const struct thermal_zone_of_device_ops *ops)
  366. {
  367. struct device_node *np, *child, *sensor_np;
  368. struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
  369. np = of_find_node_by_name(NULL, "thermal-zones");
  370. if (!np)
  371. return ERR_PTR(-ENODEV);
  372. if (!dev || !dev->of_node) {
  373. of_node_put(np);
  374. return ERR_PTR(-EINVAL);
  375. }
  376. sensor_np = of_node_get(dev->of_node);
  377. for_each_available_child_of_node(np, child) {
  378. struct of_phandle_args sensor_specs;
  379. int ret, id;
  380. /* For now, thermal framework supports only 1 sensor per zone */
  381. ret = of_parse_phandle_with_args(child, "thermal-sensors",
  382. "#thermal-sensor-cells",
  383. 0, &sensor_specs);
  384. if (ret)
  385. continue;
  386. if (sensor_specs.args_count >= 1) {
  387. id = sensor_specs.args[0];
  388. WARN(sensor_specs.args_count > 1,
  389. "%s: too many cells in sensor specifier %d\n",
  390. sensor_specs.np->name, sensor_specs.args_count);
  391. } else {
  392. id = 0;
  393. }
  394. if (sensor_specs.np == sensor_np && id == sensor_id) {
  395. tzd = thermal_zone_of_add_sensor(child, sensor_np,
  396. data, ops);
  397. if (!IS_ERR(tzd))
  398. tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);
  399. of_node_put(sensor_specs.np);
  400. of_node_put(child);
  401. goto exit;
  402. }
  403. of_node_put(sensor_specs.np);
  404. }
  405. exit:
  406. of_node_put(sensor_np);
  407. of_node_put(np);
  408. return tzd;
  409. }
  410. EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register);
  411. /**
  412. * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone
  413. * @dev: a valid struct device pointer of a sensor device. Must contain
  414. * a valid .of_node, for the sensor node.
  415. * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
  416. *
  417. * This function removes the sensor callbacks and private data from the
  418. * thermal zone device registered with thermal_zone_of_sensor_register()
  419. * API. It will also silent the zone by remove the .get_temp() and .get_trend()
  420. * thermal zone device callbacks.
  421. *
  422. * TODO: When the support to several sensors per zone is added, this
  423. * function must search the sensor list based on @dev parameter.
  424. *
  425. */
  426. void thermal_zone_of_sensor_unregister(struct device *dev,
  427. struct thermal_zone_device *tzd)
  428. {
  429. struct __thermal_zone *tz;
  430. if (!dev || !tzd || !tzd->devdata)
  431. return;
  432. tz = tzd->devdata;
  433. /* no __thermal_zone, nothing to be done */
  434. if (!tz)
  435. return;
  436. mutex_lock(&tzd->lock);
  437. tzd->ops->get_temp = NULL;
  438. tzd->ops->get_trend = NULL;
  439. tzd->ops->set_emul_temp = NULL;
  440. tz->ops = NULL;
  441. tz->sensor_data = NULL;
  442. mutex_unlock(&tzd->lock);
  443. }
  444. EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
  445. static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res)
  446. {
  447. thermal_zone_of_sensor_unregister(dev,
  448. *(struct thermal_zone_device **)res);
  449. }
  450. static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res,
  451. void *data)
  452. {
  453. struct thermal_zone_device **r = res;
  454. if (WARN_ON(!r || !*r))
  455. return 0;
  456. return *r == data;
  457. }
  458. /**
  459. * devm_thermal_zone_of_sensor_register - Resource managed version of
  460. * thermal_zone_of_sensor_register()
  461. * @dev: a valid struct device pointer of a sensor device. Must contain
  462. * a valid .of_node, for the sensor node.
  463. * @sensor_id: a sensor identifier, in case the sensor IP has more
  464. * than one sensors
  465. * @data: a private pointer (owned by the caller) that will be passed
  466. * back, when a temperature reading is needed.
  467. * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
  468. *
  469. * Refer thermal_zone_of_sensor_register() for more details.
  470. *
  471. * Return: On success returns a valid struct thermal_zone_device,
  472. * otherwise, it returns a corresponding ERR_PTR(). Caller must
  473. * check the return value with help of IS_ERR() helper.
  474. * Registered thermal_zone_device device will automatically be
  475. * released when device is unbounded.
  476. */
  477. struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
  478. struct device *dev, int sensor_id,
  479. void *data, const struct thermal_zone_of_device_ops *ops)
  480. {
  481. struct thermal_zone_device **ptr, *tzd;
  482. ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr),
  483. GFP_KERNEL);
  484. if (!ptr)
  485. return ERR_PTR(-ENOMEM);
  486. tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops);
  487. if (IS_ERR(tzd)) {
  488. devres_free(ptr);
  489. return tzd;
  490. }
  491. *ptr = tzd;
  492. devres_add(dev, ptr);
  493. return tzd;
  494. }
  495. EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register);
  496. /**
  497. * devm_thermal_zone_of_sensor_unregister - Resource managed version of
  498. * thermal_zone_of_sensor_unregister().
  499. * @dev: Device for which which resource was allocated.
  500. * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
  501. *
  502. * This function removes the sensor callbacks and private data from the
  503. * thermal zone device registered with devm_thermal_zone_of_sensor_register()
  504. * API. It will also silent the zone by remove the .get_temp() and .get_trend()
  505. * thermal zone device callbacks.
  506. * Normally this function will not need to be called and the resource
  507. * management code will ensure that the resource is freed.
  508. */
  509. void devm_thermal_zone_of_sensor_unregister(struct device *dev,
  510. struct thermal_zone_device *tzd)
  511. {
  512. WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release,
  513. devm_thermal_zone_of_sensor_match, tzd));
  514. }
  515. EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
  516. /*** functions parsing device tree nodes ***/
  517. /**
  518. * thermal_of_populate_bind_params - parse and fill cooling map data
  519. * @np: DT node containing a cooling-map node
  520. * @__tbp: data structure to be filled with cooling map info
  521. * @trips: array of thermal zone trip points
  522. * @ntrips: number of trip points inside trips.
  523. *
  524. * This function parses a cooling-map type of node represented by
  525. * @np parameter and fills the read data into @__tbp data structure.
  526. * It needs the already parsed array of trip points of the thermal zone
  527. * in consideration.
  528. *
  529. * Return: 0 on success, proper error code otherwise
  530. */
  531. static int thermal_of_populate_bind_params(struct device_node *np,
  532. struct __thermal_bind_params *__tbp,
  533. struct thermal_trip *trips,
  534. int ntrips)
  535. {
  536. struct of_phandle_args cooling_spec;
  537. struct device_node *trip;
  538. int ret, i;
  539. u32 prop;
  540. /* Default weight. Usage is optional */
  541. __tbp->usage = THERMAL_WEIGHT_DEFAULT;
  542. ret = of_property_read_u32(np, "contribution", &prop);
  543. if (ret == 0)
  544. __tbp->usage = prop;
  545. trip = of_parse_phandle(np, "trip", 0);
  546. if (!trip) {
  547. pr_err("missing trip property\n");
  548. return -ENODEV;
  549. }
  550. /* match using device_node */
  551. for (i = 0; i < ntrips; i++)
  552. if (trip == trips[i].np) {
  553. __tbp->trip_id = i;
  554. break;
  555. }
  556. if (i == ntrips) {
  557. ret = -ENODEV;
  558. goto end;
  559. }
  560. ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells",
  561. 0, &cooling_spec);
  562. if (ret < 0) {
  563. pr_err("missing cooling_device property\n");
  564. goto end;
  565. }
  566. __tbp->cooling_device = cooling_spec.np;
  567. if (cooling_spec.args_count >= 2) { /* at least min and max */
  568. __tbp->min = cooling_spec.args[0];
  569. __tbp->max = cooling_spec.args[1];
  570. } else {
  571. pr_err("wrong reference to cooling device, missing limits\n");
  572. }
  573. end:
  574. of_node_put(trip);
  575. return ret;
  576. }
  577. /**
  578. * It maps 'enum thermal_trip_type' found in include/linux/thermal.h
  579. * into the device tree binding of 'trip', property type.
  580. */
  581. static const char * const trip_types[] = {
  582. [THERMAL_TRIP_ACTIVE] = "active",
  583. [THERMAL_TRIP_PASSIVE] = "passive",
  584. [THERMAL_TRIP_HOT] = "hot",
  585. [THERMAL_TRIP_CRITICAL] = "critical",
  586. };
  587. /**
  588. * thermal_of_get_trip_type - Get phy mode for given device_node
  589. * @np: Pointer to the given device_node
  590. * @type: Pointer to resulting trip type
  591. *
  592. * The function gets trip type string from property 'type',
  593. * and store its index in trip_types table in @type,
  594. *
  595. * Return: 0 on success, or errno in error case.
  596. */
  597. static int thermal_of_get_trip_type(struct device_node *np,
  598. enum thermal_trip_type *type)
  599. {
  600. const char *t;
  601. int err, i;
  602. err = of_property_read_string(np, "type", &t);
  603. if (err < 0)
  604. return err;
  605. for (i = 0; i < ARRAY_SIZE(trip_types); i++)
  606. if (!strcasecmp(t, trip_types[i])) {
  607. *type = i;
  608. return 0;
  609. }
  610. return -ENODEV;
  611. }
  612. /**
  613. * thermal_of_populate_trip - parse and fill one trip point data
  614. * @np: DT node containing a trip point node
  615. * @trip: trip point data structure to be filled up
  616. *
  617. * This function parses a trip point type of node represented by
  618. * @np parameter and fills the read data into @trip data structure.
  619. *
  620. * Return: 0 on success, proper error code otherwise
  621. */
  622. static int thermal_of_populate_trip(struct device_node *np,
  623. struct thermal_trip *trip)
  624. {
  625. int prop;
  626. int ret;
  627. ret = of_property_read_u32(np, "temperature", &prop);
  628. if (ret < 0) {
  629. pr_err("missing temperature property\n");
  630. return ret;
  631. }
  632. trip->temperature = prop;
  633. ret = of_property_read_u32(np, "hysteresis", &prop);
  634. if (ret < 0) {
  635. pr_err("missing hysteresis property\n");
  636. return ret;
  637. }
  638. trip->hysteresis = prop;
  639. ret = thermal_of_get_trip_type(np, &trip->type);
  640. if (ret < 0) {
  641. pr_err("wrong trip type property\n");
  642. return ret;
  643. }
  644. /* Required for cooling map matching */
  645. trip->np = np;
  646. of_node_get(np);
  647. return 0;
  648. }
  649. /**
  650. * thermal_of_build_thermal_zone - parse and fill one thermal zone data
  651. * @np: DT node containing a thermal zone node
  652. *
  653. * This function parses a thermal zone type of node represented by
  654. * @np parameter and fills the read data into a __thermal_zone data structure
  655. * and return this pointer.
  656. *
  657. * TODO: Missing properties to parse: thermal-sensor-names
  658. *
  659. * Return: On success returns a valid struct __thermal_zone,
  660. * otherwise, it returns a corresponding ERR_PTR(). Caller must
  661. * check the return value with help of IS_ERR() helper.
  662. */
  663. static struct __thermal_zone
  664. __init *thermal_of_build_thermal_zone(struct device_node *np)
  665. {
  666. struct device_node *child = NULL, *gchild;
  667. struct __thermal_zone *tz;
  668. int ret, i;
  669. u32 prop, coef[2];
  670. if (!np) {
  671. pr_err("no thermal zone np\n");
  672. return ERR_PTR(-EINVAL);
  673. }
  674. tz = kzalloc(sizeof(*tz), GFP_KERNEL);
  675. if (!tz)
  676. return ERR_PTR(-ENOMEM);
  677. ret = of_property_read_u32(np, "polling-delay-passive", &prop);
  678. if (ret < 0) {
  679. pr_err("missing polling-delay-passive property\n");
  680. goto free_tz;
  681. }
  682. tz->passive_delay = prop;
  683. ret = of_property_read_u32(np, "polling-delay", &prop);
  684. if (ret < 0) {
  685. pr_err("missing polling-delay property\n");
  686. goto free_tz;
  687. }
  688. tz->polling_delay = prop;
  689. /*
  690. * REVIST: for now, the thermal framework supports only
  691. * one sensor per thermal zone. Thus, we are considering
  692. * only the first two values as slope and offset.
  693. */
  694. ret = of_property_read_u32_array(np, "coefficients", coef, 2);
  695. if (ret == 0) {
  696. tz->slope = coef[0];
  697. tz->offset = coef[1];
  698. } else {
  699. tz->slope = 1;
  700. tz->offset = 0;
  701. }
  702. /* trips */
  703. child = of_get_child_by_name(np, "trips");
  704. /* No trips provided */
  705. if (!child)
  706. goto finish;
  707. tz->ntrips = of_get_child_count(child);
  708. if (tz->ntrips == 0) /* must have at least one child */
  709. goto finish;
  710. tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL);
  711. if (!tz->trips) {
  712. ret = -ENOMEM;
  713. goto free_tz;
  714. }
  715. i = 0;
  716. for_each_child_of_node(child, gchild) {
  717. ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
  718. if (ret)
  719. goto free_trips;
  720. }
  721. of_node_put(child);
  722. /* cooling-maps */
  723. child = of_get_child_by_name(np, "cooling-maps");
  724. /* cooling-maps not provided */
  725. if (!child)
  726. goto finish;
  727. tz->num_tbps = of_get_child_count(child);
  728. if (tz->num_tbps == 0)
  729. goto finish;
  730. tz->tbps = kcalloc(tz->num_tbps, sizeof(*tz->tbps), GFP_KERNEL);
  731. if (!tz->tbps) {
  732. ret = -ENOMEM;
  733. goto free_trips;
  734. }
  735. i = 0;
  736. for_each_child_of_node(child, gchild) {
  737. ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++],
  738. tz->trips, tz->ntrips);
  739. if (ret)
  740. goto free_tbps;
  741. }
  742. finish:
  743. of_node_put(child);
  744. tz->mode = THERMAL_DEVICE_DISABLED;
  745. return tz;
  746. free_tbps:
  747. for (i = i - 1; i >= 0; i--)
  748. of_node_put(tz->tbps[i].cooling_device);
  749. kfree(tz->tbps);
  750. free_trips:
  751. for (i = 0; i < tz->ntrips; i++)
  752. of_node_put(tz->trips[i].np);
  753. kfree(tz->trips);
  754. of_node_put(gchild);
  755. free_tz:
  756. kfree(tz);
  757. of_node_put(child);
  758. return ERR_PTR(ret);
  759. }
  760. static inline void of_thermal_free_zone(struct __thermal_zone *tz)
  761. {
  762. int i;
  763. for (i = 0; i < tz->num_tbps; i++)
  764. of_node_put(tz->tbps[i].cooling_device);
  765. kfree(tz->tbps);
  766. for (i = 0; i < tz->ntrips; i++)
  767. of_node_put(tz->trips[i].np);
  768. kfree(tz->trips);
  769. kfree(tz);
  770. }
  771. /**
  772. * of_parse_thermal_zones - parse device tree thermal data
  773. *
  774. * Initialization function that can be called by machine initialization
  775. * code to parse thermal data and populate the thermal framework
  776. * with hardware thermal zones info. This function only parses thermal zones.
  777. * Cooling devices and sensor devices nodes are supposed to be parsed
  778. * by their respective drivers.
  779. *
  780. * Return: 0 on success, proper error code otherwise
  781. *
  782. */
  783. int __init of_parse_thermal_zones(void)
  784. {
  785. struct device_node *np, *child;
  786. struct __thermal_zone *tz;
  787. struct thermal_zone_device_ops *ops;
  788. np = of_find_node_by_name(NULL, "thermal-zones");
  789. if (!np) {
  790. pr_debug("unable to find thermal zones\n");
  791. return 0; /* Run successfully on systems without thermal DT */
  792. }
  793. for_each_available_child_of_node(np, child) {
  794. struct thermal_zone_device *zone;
  795. struct thermal_zone_params *tzp;
  796. int i, mask = 0;
  797. u32 prop;
  798. tz = thermal_of_build_thermal_zone(child);
  799. if (IS_ERR(tz)) {
  800. pr_err("failed to build thermal zone %s: %ld\n",
  801. child->name,
  802. PTR_ERR(tz));
  803. continue;
  804. }
  805. ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
  806. if (!ops)
  807. goto exit_free;
  808. tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
  809. if (!tzp) {
  810. kfree(ops);
  811. goto exit_free;
  812. }
  813. /* No hwmon because there might be hwmon drivers registering */
  814. tzp->no_hwmon = true;
  815. if (!of_property_read_u32(child, "sustainable-power", &prop))
  816. tzp->sustainable_power = prop;
  817. for (i = 0; i < tz->ntrips; i++)
  818. mask |= 1 << i;
  819. /* these two are left for temperature drivers to use */
  820. tzp->slope = tz->slope;
  821. tzp->offset = tz->offset;
  822. zone = thermal_zone_device_register(child->name, tz->ntrips,
  823. mask, tz,
  824. ops, tzp,
  825. tz->passive_delay,
  826. tz->polling_delay);
  827. if (IS_ERR(zone)) {
  828. pr_err("Failed to build %s zone %ld\n", child->name,
  829. PTR_ERR(zone));
  830. kfree(tzp);
  831. kfree(ops);
  832. of_thermal_free_zone(tz);
  833. /* attempting to build remaining zones still */
  834. }
  835. }
  836. of_node_put(np);
  837. return 0;
  838. exit_free:
  839. of_node_put(child);
  840. of_node_put(np);
  841. of_thermal_free_zone(tz);
  842. /* no memory available, so free what we have built */
  843. of_thermal_destroy_zones();
  844. return -ENOMEM;
  845. }
  846. /**
  847. * of_thermal_destroy_zones - remove all zones parsed and allocated resources
  848. *
  849. * Finds all zones parsed and added to the thermal framework and remove them
  850. * from the system, together with their resources.
  851. *
  852. */
  853. void of_thermal_destroy_zones(void)
  854. {
  855. struct device_node *np, *child;
  856. np = of_find_node_by_name(NULL, "thermal-zones");
  857. if (!np) {
  858. pr_debug("unable to find thermal zones\n");
  859. return;
  860. }
  861. for_each_available_child_of_node(np, child) {
  862. struct thermal_zone_device *zone;
  863. zone = thermal_zone_get_zone_by_name(child->name);
  864. if (IS_ERR(zone))
  865. continue;
  866. thermal_zone_device_unregister(zone);
  867. kfree(zone->tzp);
  868. kfree(zone->ops);
  869. of_thermal_free_zone(zone->devdata);
  870. }
  871. of_node_put(np);
  872. }