thermal.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-3-08 GuEe-GUI the first version
  9. */
  10. #include <drivers/platform.h>
  11. #define DBG_TAG "rtdm.thermal"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #include "thermal_dm.h"
  15. #ifndef INT_MAX
  16. #define INT_MAX (RT_UINT32_MAX >> 1)
  17. #endif
  18. #define device_list(dev) (dev)->parent.parent.list
  19. #define device_foreach(dev, nodes) rt_list_for_each_entry(dev, nodes, parent.parent.list)
  20. static RT_DEFINE_SPINLOCK(nodes_lock);
  21. static rt_list_t thermal_zone_device_nodes = RT_LIST_OBJECT_INIT(thermal_zone_device_nodes);
  22. static rt_list_t thermal_cooling_device_nodes = RT_LIST_OBJECT_INIT(thermal_cooling_device_nodes);
  23. static rt_list_t thermal_cooling_governor_nodes = RT_LIST_OBJECT_INIT(thermal_cooling_governor_nodes);
  24. #ifdef RT_USING_OFW
  25. static void thermal_ofw_params_parse(struct rt_ofw_node *np,
  26. struct rt_thermal_zone_params *tz_params)
  27. {
  28. rt_uint32_t coef[2], prop;
  29. if (!np)
  30. {
  31. return;
  32. }
  33. if (!rt_ofw_prop_read_u32(np, "sustainable-power", &prop))
  34. {
  35. tz_params->sustainable_power = prop;
  36. }
  37. /*
  38. * For now, the thermal framework supports only one sensor per thermal zone.
  39. * Thus, we are considering only the first two values as slope and offset.
  40. */
  41. if (rt_ofw_prop_read_u32_array_index(np, "coefficients", 0, 2, coef) < 0)
  42. {
  43. coef[0] = 1;
  44. coef[1] = 0;
  45. }
  46. tz_params->slope = coef[0];
  47. tz_params->offset = coef[1];
  48. }
  49. static void thermal_ofw_setup(struct rt_ofw_node *np, struct rt_thermal_zone_device *zdev)
  50. {
  51. int i = 0;
  52. rt_uint32_t delay, pdelay;
  53. struct rt_ofw_cell_args args;
  54. struct rt_ofw_node *tmp_np, *tz_np, *trip_np, *cm_np, *cdev_np;
  55. if (!np || !zdev)
  56. {
  57. return;
  58. }
  59. tmp_np = rt_ofw_find_node_by_path("/thermal-zones");
  60. if (!tmp_np)
  61. {
  62. return;
  63. }
  64. rt_ofw_foreach_child_node(tmp_np, tz_np)
  65. {
  66. if (!rt_ofw_parse_phandle_cells(tz_np, "thermal-sensors", "#thermal-sensor-cells", 0, &args))
  67. {
  68. if (args.data == np && (!args.args_count || args.args[0] == zdev->zone_id))
  69. {
  70. rt_ofw_node_put(args.data);
  71. goto _found;
  72. }
  73. rt_ofw_node_put(args.data);
  74. }
  75. }
  76. return;
  77. _found:
  78. rt_ofw_prop_read_u32(tz_np, "polling-delay-passive", &pdelay);
  79. rt_ofw_prop_read_u32(tz_np, "polling-delay", &delay);
  80. zdev->passive_delay = rt_tick_from_millisecond(pdelay);
  81. zdev->polling_delay = rt_tick_from_millisecond(delay);
  82. thermal_ofw_params_parse(tz_np, &zdev->params);
  83. if (zdev->trips_nr)
  84. {
  85. goto _scan_cooling;
  86. }
  87. tmp_np = rt_ofw_get_child_by_tag(tz_np, "trips");
  88. if (!tmp_np)
  89. {
  90. goto _scan_cooling;
  91. }
  92. zdev->trips_nr = rt_ofw_get_child_count(tmp_np);
  93. if (!zdev->trips_nr)
  94. {
  95. goto _scan_cooling;
  96. }
  97. zdev->trips = rt_calloc(zdev->trips_nr, sizeof(*zdev->trips));
  98. zdev->trips_free = RT_TRUE;
  99. if (!zdev->trips)
  100. {
  101. LOG_E("%s: No memory to create %s", rt_ofw_node_full_name(np), "trips");
  102. RT_ASSERT(0);
  103. }
  104. rt_ofw_foreach_child_node(tmp_np, trip_np)
  105. {
  106. const char *type;
  107. rt_ofw_prop_read_u32(trip_np, "temperature", (rt_uint32_t *)&zdev->trips[i].temperature);
  108. rt_ofw_prop_read_u32(trip_np, "hysteresis", (rt_uint32_t *)&zdev->trips[i].hysteresis);
  109. rt_ofw_prop_read_string(trip_np, "type", &type);
  110. zdev->trips[i].type = thermal_type(type);
  111. rt_ofw_data(trip_np) = &zdev->trips[i];
  112. ++i;
  113. }
  114. _scan_cooling:
  115. i = 0;
  116. tmp_np = rt_ofw_get_child_by_tag(tz_np, "cooling-maps");
  117. if (!tmp_np)
  118. {
  119. goto _end;
  120. }
  121. zdev->cooling_maps_nr = rt_ofw_get_child_count(tmp_np);
  122. if (!zdev->cooling_maps_nr)
  123. {
  124. goto _end;
  125. }
  126. zdev->cooling_maps = rt_calloc(zdev->cooling_maps_nr, sizeof(*zdev->cooling_maps));
  127. if (!zdev->cooling_maps)
  128. {
  129. LOG_E("%s: No memory to create %s", rt_ofw_node_full_name(np), "cooling_maps");
  130. RT_ASSERT(0);
  131. }
  132. rt_ofw_foreach_child_node(tmp_np, cm_np)
  133. {
  134. struct rt_thermal_cooling_device *cdev;
  135. struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i++];
  136. map->cells_nr = rt_ofw_count_phandle_cells(cm_np, "cooling-device", "#cooling-cells");
  137. map->cells = rt_calloc(sizeof(*map->cells), map->cells_nr);
  138. if (!map->cells)
  139. {
  140. LOG_E("%s: No memory to create %s", rt_ofw_node_full_name(np), "cells");
  141. RT_ASSERT(0);
  142. }
  143. trip_np = rt_ofw_parse_phandle(cm_np, "trip", 0);
  144. map->trips = rt_ofw_data(trip_np);
  145. rt_ofw_node_put(trip_np);
  146. if (!map->trips)
  147. {
  148. LOG_E("%s: trips(%s) not found", rt_ofw_node_full_name(np),
  149. rt_ofw_node_full_name(trip_np));
  150. RT_ASSERT(0);
  151. }
  152. rt_ofw_prop_read_u32(cm_np, "contribution", &map->contribution);
  153. for (int c = 0; c < map->cells_nr; ++c)
  154. {
  155. struct rt_thermal_cooling_cell *cell = &map->cells[c];
  156. if (rt_ofw_parse_phandle_cells(cm_np, "cooling-device", "#cooling-cells", c, &args))
  157. {
  158. continue;
  159. }
  160. cdev_np = args.data;
  161. rt_spin_lock(&nodes_lock);
  162. device_foreach(cdev, &thermal_cooling_device_nodes)
  163. {
  164. if (cdev->parent.ofw_node == cdev_np)
  165. {
  166. cell->cooling_devices = cdev;
  167. break;
  168. }
  169. }
  170. rt_spin_unlock(&nodes_lock);
  171. cell->level_range[0] = args.args[0];
  172. cell->level_range[1] = args.args[1];
  173. if (cell->cooling_devices)
  174. {
  175. thermal_bind(cell->cooling_devices, zdev);
  176. }
  177. rt_ofw_node_put(cdev_np);
  178. }
  179. }
  180. _end:
  181. }
  182. #else
  183. rt_inline void thermal_ofw_setup(struct rt_ofw_node *np, struct rt_thermal_zone_device *zdev)
  184. {
  185. }
  186. #endif /* RT_USING_OFW */
  187. static void thermal_zone_poll(struct rt_work *work, void *work_data)
  188. {
  189. struct rt_thermal_zone_device *zdev = work_data;
  190. rt_thermal_zone_device_update(zdev, RT_THERMAL_MSG_EVENT_UNSPECIFIED);
  191. }
  192. rt_err_t rt_thermal_zone_device_register(struct rt_thermal_zone_device *zdev)
  193. {
  194. if (!zdev || !zdev->ops || !zdev->ops->get_temp)
  195. {
  196. return -RT_EINVAL;
  197. }
  198. zdev->ops->get_temp(zdev, &zdev->temperature);
  199. zdev->last_temperature = zdev->temperature;
  200. if (!zdev->trips)
  201. {
  202. zdev->trips_nr = 0;
  203. }
  204. rt_spin_lock_init(&zdev->nodes_lock);
  205. rt_list_init(&zdev->notifier_nodes);
  206. rt_list_init(&device_list(zdev));
  207. rt_mutex_init(&zdev->mutex, rt_dm_dev_get_name(&zdev->parent), RT_IPC_FLAG_PRIO);
  208. zdev->temperature = RT_THERMAL_TEMP_INVALID;
  209. zdev->prev_low_trip = -INT_MAX;
  210. zdev->prev_high_trip = INT_MAX;
  211. rt_spin_lock(&nodes_lock);
  212. rt_list_insert_before(&thermal_zone_device_nodes, &device_list(zdev));
  213. rt_spin_unlock(&nodes_lock);
  214. thermal_ofw_setup(zdev->parent.ofw_node, zdev);
  215. rt_work_init(&zdev->poller, thermal_zone_poll, zdev);
  216. zdev->enabled = RT_TRUE;
  217. /* Start to poll */
  218. rt_work_submit(&zdev->poller, zdev->polling_delay);
  219. return RT_EOK;
  220. }
  221. rt_err_t rt_thermal_zone_device_unregister(struct rt_thermal_zone_device *zdev)
  222. {
  223. if (!zdev)
  224. {
  225. return -RT_EINVAL;
  226. }
  227. rt_spin_lock(&zdev->nodes_lock);
  228. if (rt_list_isempty(&zdev->notifier_nodes))
  229. {
  230. LOG_E("%s: there is %u user", rt_dm_dev_get_name(&zdev->parent),
  231. rt_list_len(&zdev->notifier_nodes));
  232. rt_spin_unlock(&zdev->nodes_lock);
  233. return -RT_EBUSY;
  234. }
  235. rt_spin_unlock(&zdev->nodes_lock);
  236. rt_work_cancel(&zdev->poller);
  237. rt_spin_lock(&nodes_lock);
  238. rt_list_remove(&device_list(zdev));
  239. rt_spin_unlock(&nodes_lock);
  240. if (zdev->trips_free && zdev->trips)
  241. {
  242. rt_free(zdev->trips);
  243. }
  244. if (zdev->cooling_maps_nr && zdev->cooling_maps_nr)
  245. {
  246. for (int i = 0; i < zdev->cooling_maps_nr; ++i)
  247. {
  248. struct rt_thermal_cooling_device *cdev;
  249. struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i];
  250. for (int c = 0; c < map->cells_nr; ++c)
  251. {
  252. cdev = map->cells[i].cooling_devices;
  253. if (cdev)
  254. {
  255. thermal_unbind(cdev, zdev);
  256. }
  257. }
  258. rt_free(map->cells);
  259. }
  260. rt_free(zdev->cooling_maps);
  261. }
  262. rt_mutex_detach(&zdev->mutex);
  263. return RT_EOK;
  264. }
  265. rt_err_t rt_thermal_cooling_device_register(struct rt_thermal_cooling_device *cdev)
  266. {
  267. rt_err_t err;
  268. if (!cdev || !cdev->ops ||
  269. !cdev->ops->get_max_level || !cdev->ops->get_cur_level || !cdev->ops->set_cur_level)
  270. {
  271. return -RT_EINVAL;
  272. }
  273. if ((err = cdev->ops->get_max_level(cdev, &cdev->max_level)))
  274. {
  275. return err;
  276. }
  277. rt_list_init(&device_list(cdev));
  278. rt_list_init(&cdev->governor_node);
  279. rt_spin_lock(&nodes_lock);
  280. rt_list_insert_before(&thermal_cooling_device_nodes, &device_list(cdev));
  281. rt_spin_unlock(&nodes_lock);
  282. err = rt_thermal_cooling_device_change_governor(cdev, RT_NULL);
  283. return err;
  284. }
  285. rt_err_t rt_thermal_cooling_device_unregister(struct rt_thermal_cooling_device *cdev)
  286. {
  287. if (!cdev)
  288. {
  289. return -RT_EINVAL;
  290. }
  291. if (cdev->parent.ref_count)
  292. {
  293. LOG_E("%s: there is %u user",
  294. rt_dm_dev_get_name(&cdev->parent), cdev->parent.ref_count);
  295. return -RT_EINVAL;
  296. }
  297. rt_spin_lock(&nodes_lock);
  298. rt_list_remove(&device_list(cdev));
  299. rt_spin_unlock(&nodes_lock);
  300. return RT_EOK;
  301. }
  302. static void dumb_governor_tuning(struct rt_thermal_zone_device *zdev,
  303. int map_idx, int cell_idx, rt_ubase_t *level)
  304. {
  305. struct rt_thermal_cooling_map *map = &zdev->cooling_maps[map_idx];
  306. if (zdev->cooling && zdev->temperature > map->trips->temperature)
  307. {
  308. if (zdev->temperature - zdev->last_temperature > map->trips->hysteresis)
  309. {
  310. ++*level;
  311. }
  312. else if (zdev->last_temperature - zdev->temperature > map->trips->hysteresis)
  313. {
  314. --*level;
  315. }
  316. }
  317. else
  318. {
  319. *level = 0;
  320. }
  321. }
  322. static struct rt_thermal_cooling_governor dumb_governor =
  323. {
  324. .name = "dumb",
  325. .tuning = dumb_governor_tuning,
  326. };
  327. static int system_thermal_cooling_governor_init(void)
  328. {
  329. rt_thermal_cooling_governor_register(&dumb_governor);
  330. return 0;
  331. }
  332. INIT_CORE_EXPORT(system_thermal_cooling_governor_init);
  333. rt_err_t rt_thermal_cooling_governor_register(struct rt_thermal_cooling_governor *gov)
  334. {
  335. rt_err_t err = RT_EOK;
  336. struct rt_thermal_cooling_governor *gov_tmp;
  337. if (!gov || !gov->name || !gov->tuning)
  338. {
  339. return -RT_EINVAL;
  340. }
  341. rt_list_init(&gov->list);
  342. rt_list_init(&gov->cdev_nodes);
  343. rt_spin_lock(&nodes_lock);
  344. rt_list_for_each_entry(gov_tmp, &thermal_cooling_governor_nodes, list)
  345. {
  346. if (!rt_strcmp(gov_tmp->name, gov->name))
  347. {
  348. err = -RT_ERROR;
  349. goto _out_unlock;
  350. }
  351. }
  352. rt_list_insert_before(&thermal_cooling_governor_nodes, &gov->list);
  353. _out_unlock:
  354. rt_spin_unlock(&nodes_lock);
  355. return err;
  356. }
  357. rt_err_t rt_thermal_cooling_governor_unregister(struct rt_thermal_cooling_governor *gov)
  358. {
  359. if (!gov)
  360. {
  361. return -RT_EINVAL;
  362. }
  363. if (gov == &dumb_governor)
  364. {
  365. return -RT_EINVAL;
  366. }
  367. rt_spin_lock(&nodes_lock);
  368. if (!rt_list_isempty(&gov->cdev_nodes))
  369. {
  370. goto _out_unlock;
  371. }
  372. rt_list_remove(&gov->list);
  373. _out_unlock:
  374. rt_spin_unlock(&nodes_lock);
  375. return RT_EOK;
  376. }
  377. rt_err_t rt_thermal_cooling_device_change_governor(struct rt_thermal_cooling_device *cdev,
  378. const char *name)
  379. {
  380. rt_err_t err;
  381. struct rt_thermal_cooling_governor *gov;
  382. if (!cdev)
  383. {
  384. return -RT_EINVAL;
  385. }
  386. name = name ? : dumb_governor.name;
  387. err = -RT_ENOSYS;
  388. rt_spin_lock(&nodes_lock);
  389. rt_list_for_each_entry(gov, &thermal_cooling_governor_nodes, list)
  390. {
  391. if (!rt_strcmp(gov->name, name))
  392. {
  393. if (cdev->gov)
  394. {
  395. rt_list_remove(&cdev->governor_node);
  396. }
  397. cdev->gov = gov;
  398. rt_list_insert_before(&cdev->governor_node, &gov->cdev_nodes);
  399. err = RT_EOK;
  400. break;
  401. }
  402. }
  403. rt_spin_unlock(&nodes_lock);
  404. return err;
  405. }
  406. rt_err_t rt_thermal_zone_notifier_register(struct rt_thermal_zone_device *zdev,
  407. struct rt_thermal_notifier *notifier)
  408. {
  409. if (!zdev || !notifier)
  410. {
  411. return -RT_EINVAL;
  412. }
  413. notifier->zdev = zdev;
  414. rt_list_init(&notifier->list);
  415. rt_spin_lock(&zdev->nodes_lock);
  416. rt_list_insert_after(&zdev->notifier_nodes, &notifier->list);
  417. rt_spin_unlock(&zdev->nodes_lock);
  418. return RT_EOK;
  419. }
  420. rt_err_t rt_thermal_zone_notifier_unregister(struct rt_thermal_zone_device *zdev,
  421. struct rt_thermal_notifier *notifier)
  422. {
  423. if (!zdev || !notifier)
  424. {
  425. return -RT_EINVAL;
  426. }
  427. rt_spin_lock(&zdev->nodes_lock);
  428. rt_list_remove(&notifier->list);
  429. rt_spin_unlock(&zdev->nodes_lock);
  430. return RT_EOK;
  431. }
  432. void rt_thermal_zone_device_update(struct rt_thermal_zone_device *zdev, rt_ubase_t msg)
  433. {
  434. rt_err_t err;
  435. rt_bool_t passive = RT_FALSE, need_cool = RT_FALSE;
  436. struct rt_thermal_notifier *notifier, *next_notifier;
  437. RT_ASSERT(zdev != RT_NULL);
  438. if (!rt_interrupt_get_nest())
  439. {
  440. rt_mutex_take(&zdev->mutex, RT_WAITING_FOREVER);
  441. }
  442. /* Check thermal zone status */
  443. if (msg == RT_THERMAL_MSG_DEVICE_DOWN)
  444. {
  445. zdev->enabled = RT_FALSE;
  446. }
  447. else if (msg == RT_THERMAL_MSG_DEVICE_UP)
  448. {
  449. zdev->enabled = RT_TRUE;
  450. }
  451. /* Read temperature */
  452. zdev->last_temperature = zdev->temperature;
  453. zdev->ops->get_temp(zdev, &zdev->temperature);
  454. for (int i = 0; i < zdev->trips_nr; ++i)
  455. {
  456. struct rt_thermal_trip *tmp_trip = &zdev->trips[i];
  457. if (zdev->temperature <= tmp_trip->temperature)
  458. {
  459. continue;
  460. }
  461. switch (tmp_trip->type)
  462. {
  463. case RT_THERMAL_TRIP_PASSIVE:
  464. passive = RT_TRUE;
  465. goto cooling;
  466. case RT_THERMAL_TRIP_CRITICAL:
  467. if (zdev->ops->critical)
  468. {
  469. zdev->ops->critical(zdev);
  470. }
  471. else if (zdev->last_temperature > tmp_trip->temperature)
  472. {
  473. /* Tried to cool already, but failed */
  474. rt_hw_cpu_reset();
  475. }
  476. else
  477. {
  478. goto cooling;
  479. }
  480. break;
  481. case RT_THERMAL_TRIP_HOT:
  482. if (zdev->ops->hot)
  483. {
  484. zdev->ops->hot(zdev);
  485. break;
  486. }
  487. default:
  488. cooling:
  489. zdev->cooling = need_cool = RT_TRUE;
  490. rt_thermal_cooling_device_kick(zdev);
  491. break;
  492. }
  493. }
  494. if (!need_cool && zdev->cooling)
  495. {
  496. rt_thermal_cooling_device_kick(zdev);
  497. }
  498. /* Set the new trips */
  499. if (zdev->ops->set_trips)
  500. {
  501. rt_bool_t same_trip = RT_FALSE;
  502. int low = -INT_MAX, high = INT_MAX;
  503. struct rt_thermal_trip trip;
  504. for (int i = 0; i < zdev->trips_nr; ++i)
  505. {
  506. int trip_low;
  507. rt_bool_t low_set = RT_FALSE;
  508. rt_memcpy(&trip, &zdev->trips[i], sizeof(trip));
  509. trip_low = trip.temperature - trip.hysteresis;
  510. if (trip_low < zdev->temperature && trip_low > low)
  511. {
  512. low = trip_low;
  513. low_set = RT_TRUE;
  514. same_trip = RT_FALSE;
  515. }
  516. if (trip.temperature > zdev->temperature && trip.temperature < high)
  517. {
  518. high = trip.temperature;
  519. same_trip = low_set;
  520. }
  521. }
  522. /* No need to change trip points */
  523. if (zdev->prev_low_trip == low && zdev->prev_high_trip == high)
  524. {
  525. goto _call_notifier;
  526. }
  527. if (same_trip &&
  528. (zdev->prev_low_trip != -INT_MAX || zdev->prev_high_trip != INT_MAX))
  529. {
  530. goto _call_notifier;
  531. }
  532. zdev->prev_low_trip = low;
  533. zdev->prev_high_trip = high;
  534. if ((err = zdev->ops->set_trips(zdev, low, high)))
  535. {
  536. LOG_E("%s: Set trips error = %s", rt_dm_dev_get_name(&zdev->parent),
  537. rt_strerror(err));
  538. }
  539. }
  540. /* Call all notifier, maybe have governor */
  541. _call_notifier:
  542. rt_spin_lock(&zdev->nodes_lock);
  543. rt_list_for_each_entry_safe(notifier, next_notifier, &zdev->notifier_nodes, list)
  544. {
  545. rt_spin_unlock(&zdev->nodes_lock);
  546. notifier->callback(notifier, msg);
  547. rt_spin_lock(&zdev->nodes_lock);
  548. }
  549. rt_spin_unlock(&zdev->nodes_lock);
  550. /* Prepare for the next report */
  551. if (!zdev->enabled)
  552. {
  553. rt_work_cancel(&zdev->poller);
  554. }
  555. else if (passive && zdev->passive_delay)
  556. {
  557. rt_work_submit(&zdev->poller, zdev->passive_delay);
  558. }
  559. else if (zdev->polling_delay)
  560. {
  561. rt_work_submit(&zdev->poller, zdev->polling_delay);
  562. }
  563. if (!rt_interrupt_get_nest())
  564. {
  565. rt_mutex_release(&zdev->mutex);
  566. }
  567. }
  568. void rt_thermal_cooling_device_kick(struct rt_thermal_zone_device *zdev)
  569. {
  570. RT_ASSERT(zdev != RT_NULL);
  571. for (int i = 0; i < zdev->cooling_maps_nr; ++i)
  572. {
  573. rt_ubase_t level;
  574. struct rt_thermal_cooling_device *cdev;
  575. struct rt_thermal_cooling_cell *cell;
  576. struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i];
  577. for (int c = 0; c < map->cells_nr; ++c)
  578. {
  579. cell = &map->cells[c];
  580. cdev = cell->cooling_devices;
  581. if (!cdev)
  582. {
  583. continue;
  584. }
  585. /* Update status */
  586. if (cdev->ops->get_max_level(cdev, &cdev->max_level))
  587. {
  588. continue;
  589. }
  590. if (cdev->ops->get_cur_level(cdev, &level) || level > cdev->max_level)
  591. {
  592. continue;
  593. }
  594. /* Check if cooling is required */
  595. if (level >= cell->level_range[0] && level <= cell->level_range[1])
  596. {
  597. /* Is cooling, not call */
  598. continue;
  599. }
  600. cdev->gov->tuning(zdev, i, c, &level);
  601. level = rt_min_t(rt_ubase_t, level, cdev->max_level);
  602. cdev->ops->set_cur_level(cdev, level);
  603. }
  604. }
  605. }
  606. rt_err_t rt_thermal_zone_set_trip(struct rt_thermal_zone_device *zdev, int trip_id,
  607. const struct rt_thermal_trip *trip)
  608. {
  609. rt_err_t err;
  610. struct rt_thermal_trip tmp_trip;
  611. if (!zdev || !trip)
  612. {
  613. return -RT_EINVAL;
  614. }
  615. rt_mutex_take(&zdev->mutex, RT_WAITING_FOREVER);
  616. if (!zdev->ops->set_trip_temp && !zdev->ops->set_trip_hyst && !zdev->trips)
  617. {
  618. err = -RT_EINVAL;
  619. goto _out_unlock;
  620. }
  621. if (trip_id >= zdev->trips_nr)
  622. {
  623. err = -RT_EINVAL;
  624. goto _out_unlock;
  625. }
  626. rt_memcpy(&tmp_trip, &zdev->trips[trip_id], sizeof(tmp_trip));
  627. if (tmp_trip.type != trip->type)
  628. {
  629. err = -RT_EINVAL;
  630. goto _out_unlock;
  631. }
  632. if (tmp_trip.temperature != trip->temperature && zdev->ops->set_trip_temp)
  633. {
  634. if ((err = zdev->ops->set_trip_temp(zdev, trip_id, trip->temperature)))
  635. {
  636. goto _out_unlock;
  637. }
  638. }
  639. if (tmp_trip.hysteresis != trip->hysteresis && zdev->ops->set_trip_hyst)
  640. {
  641. if ((err = zdev->ops->set_trip_hyst(zdev, trip_id, trip->hysteresis)))
  642. {
  643. goto _out_unlock;
  644. }
  645. }
  646. if (zdev->trips &&
  647. (tmp_trip.temperature != trip->temperature || tmp_trip.hysteresis != trip->hysteresis))
  648. {
  649. zdev->trips[trip_id] = *trip;
  650. }
  651. _out_unlock:
  652. rt_mutex_release(&zdev->mutex);
  653. if (!err)
  654. {
  655. rt_thermal_zone_device_update(zdev, RT_THERMAL_MSG_TRIP_CHANGED);
  656. }
  657. return err;
  658. }
  659. rt_err_t rt_thermal_zone_get_trip(struct rt_thermal_zone_device *zdev, int trip_id,
  660. struct rt_thermal_trip *out_trip)
  661. {
  662. rt_err_t err = RT_EOK;
  663. if (!zdev || !out_trip)
  664. {
  665. return -RT_EINVAL;
  666. }
  667. rt_mutex_take(&zdev->mutex, RT_WAITING_FOREVER);
  668. if (!zdev->trips_nr)
  669. {
  670. err = -RT_ENOSYS;
  671. goto _out_unlock;
  672. }
  673. if (trip_id >= zdev->trips_nr)
  674. {
  675. err = -RT_EINVAL;
  676. goto _out_unlock;
  677. }
  678. *out_trip = zdev->trips[trip_id];
  679. _out_unlock:
  680. rt_mutex_release(&zdev->mutex);
  681. return err;
  682. }
  683. #if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH)
  684. static int list_thermal(int argc, char**argv)
  685. {
  686. struct rt_thermal_zone_device *zdev;
  687. /* Thermal is an important subsystem, please do not output too much. */
  688. rt_spin_lock(&nodes_lock);
  689. device_foreach(zdev, &thermal_zone_device_nodes)
  690. {
  691. int temperature = zdev->temperature;
  692. rt_kprintf("%s-%d\n", rt_dm_dev_get_name(&zdev->parent), zdev->zone_id);
  693. rt_kprintf("temperature:\t%+d.%u C\n", temperature / 1000, rt_abs(temperature) % 1000);
  694. for (int i = 0, id = 0; i < zdev->cooling_maps_nr; ++i)
  695. {
  696. rt_ubase_t level;
  697. struct rt_thermal_trip *trips;
  698. struct rt_thermal_cooling_device *cdev;
  699. struct rt_thermal_cooling_cell *cell;
  700. struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i];
  701. for (int c = 0; c < map->cells_nr; ++c, ++id)
  702. {
  703. trips = map->trips;
  704. cell = &map->cells[c];
  705. cdev = cell->cooling_devices;
  706. if (cdev)
  707. {
  708. cdev->ops->get_cur_level(cdev, &level);
  709. rt_kprintf("cooling%u:\t%s[%+d.%u C] %d\n", id,
  710. rt_dm_dev_get_name(&cdev->parent),
  711. trips->temperature / 1000, rt_abs(trips->temperature) % 1000,
  712. level);
  713. }
  714. else
  715. {
  716. rt_kprintf("cooling%u:\t%s[%+d.%u C] %d\n", id,
  717. "(not supported)",
  718. trips->temperature / 1000, rt_abs(trips->temperature) % 1000,
  719. 0);
  720. }
  721. }
  722. }
  723. }
  724. rt_spin_unlock(&nodes_lock);
  725. return 0;
  726. }
  727. MSH_CMD_EXPORT(list_thermal, dump all of thermal information);
  728. #endif /* RT_USING_CONSOLE && RT_USING_MSH */