123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-3-08 GuEe-GUI the first version
- */
- #include <drivers/platform.h>
- #define DBG_TAG "rtdm.thermal"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include "thermal_dm.h"
- #ifndef INT_MAX
- #define INT_MAX (RT_UINT32_MAX >> 1)
- #endif
- #define device_list(dev) (dev)->parent.parent.list
- #define device_foreach(dev, nodes) rt_list_for_each_entry(dev, nodes, parent.parent.list)
- static RT_DEFINE_SPINLOCK(nodes_lock);
- static rt_list_t thermal_zone_device_nodes = RT_LIST_OBJECT_INIT(thermal_zone_device_nodes);
- static rt_list_t thermal_cooling_device_nodes = RT_LIST_OBJECT_INIT(thermal_cooling_device_nodes);
- static rt_list_t thermal_cooling_governor_nodes = RT_LIST_OBJECT_INIT(thermal_cooling_governor_nodes);
- #ifdef RT_USING_OFW
- static void thermal_ofw_params_parse(struct rt_ofw_node *np,
- struct rt_thermal_zone_params *tz_params)
- {
- rt_uint32_t coef[2], prop;
- if (!np)
- {
- return;
- }
- if (!rt_ofw_prop_read_u32(np, "sustainable-power", &prop))
- {
- tz_params->sustainable_power = prop;
- }
- /*
- * For now, the thermal framework supports only one sensor per thermal zone.
- * Thus, we are considering only the first two values as slope and offset.
- */
- if (rt_ofw_prop_read_u32_array_index(np, "coefficients", 0, 2, coef) < 0)
- {
- coef[0] = 1;
- coef[1] = 0;
- }
- tz_params->slope = coef[0];
- tz_params->offset = coef[1];
- }
- static void thermal_ofw_setup(struct rt_ofw_node *np, struct rt_thermal_zone_device *zdev)
- {
- int i = 0;
- rt_uint32_t delay, pdelay;
- struct rt_ofw_cell_args args;
- struct rt_ofw_node *tmp_np, *tz_np, *trip_np, *cm_np, *cdev_np;
- if (!np || !zdev)
- {
- return;
- }
- tmp_np = rt_ofw_find_node_by_path("/thermal-zones");
- if (!tmp_np)
- {
- return;
- }
- rt_ofw_foreach_child_node(tmp_np, tz_np)
- {
- if (!rt_ofw_parse_phandle_cells(tz_np, "thermal-sensors", "#thermal-sensor-cells", 0, &args))
- {
- if (args.data == np && (!args.args_count || args.args[0] == zdev->zone_id))
- {
- rt_ofw_node_put(args.data);
- goto _found;
- }
- rt_ofw_node_put(args.data);
- }
- }
- return;
- _found:
- rt_ofw_prop_read_u32(tz_np, "polling-delay-passive", &pdelay);
- rt_ofw_prop_read_u32(tz_np, "polling-delay", &delay);
- zdev->passive_delay = rt_tick_from_millisecond(pdelay);
- zdev->polling_delay = rt_tick_from_millisecond(delay);
- thermal_ofw_params_parse(tz_np, &zdev->params);
- if (zdev->trips_nr)
- {
- goto _scan_cooling;
- }
- tmp_np = rt_ofw_get_child_by_tag(tz_np, "trips");
- if (!tmp_np)
- {
- goto _scan_cooling;
- }
- zdev->trips_nr = rt_ofw_get_child_count(tmp_np);
- if (!zdev->trips_nr)
- {
- goto _scan_cooling;
- }
- zdev->trips = rt_calloc(zdev->trips_nr, sizeof(*zdev->trips));
- zdev->trips_free = RT_TRUE;
- if (!zdev->trips)
- {
- LOG_E("%s: No memory to create %s", rt_ofw_node_full_name(np), "trips");
- RT_ASSERT(0);
- }
- rt_ofw_foreach_child_node(tmp_np, trip_np)
- {
- const char *type;
- rt_ofw_prop_read_u32(trip_np, "temperature", (rt_uint32_t *)&zdev->trips[i].temperature);
- rt_ofw_prop_read_u32(trip_np, "hysteresis", (rt_uint32_t *)&zdev->trips[i].hysteresis);
- rt_ofw_prop_read_string(trip_np, "type", &type);
- zdev->trips[i].type = thermal_type(type);
- rt_ofw_data(trip_np) = &zdev->trips[i];
- ++i;
- }
- _scan_cooling:
- i = 0;
- tmp_np = rt_ofw_get_child_by_tag(tz_np, "cooling-maps");
- if (!tmp_np)
- {
- goto _end;
- }
- zdev->cooling_maps_nr = rt_ofw_get_child_count(tmp_np);
- if (!zdev->cooling_maps_nr)
- {
- goto _end;
- }
- zdev->cooling_maps = rt_calloc(zdev->cooling_maps_nr, sizeof(*zdev->cooling_maps));
- if (!zdev->cooling_maps)
- {
- LOG_E("%s: No memory to create %s", rt_ofw_node_full_name(np), "cooling_maps");
- RT_ASSERT(0);
- }
- rt_ofw_foreach_child_node(tmp_np, cm_np)
- {
- struct rt_thermal_cooling_device *cdev;
- struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i++];
- map->cells_nr = rt_ofw_count_phandle_cells(cm_np, "cooling-device", "#cooling-cells");
- map->cells = rt_calloc(sizeof(*map->cells), map->cells_nr);
- if (!map->cells)
- {
- LOG_E("%s: No memory to create %s", rt_ofw_node_full_name(np), "cells");
- RT_ASSERT(0);
- }
- trip_np = rt_ofw_parse_phandle(cm_np, "trip", 0);
- map->trips = rt_ofw_data(trip_np);
- rt_ofw_node_put(trip_np);
- if (!map->trips)
- {
- LOG_E("%s: trips(%s) not found", rt_ofw_node_full_name(np),
- rt_ofw_node_full_name(trip_np));
- RT_ASSERT(0);
- }
- rt_ofw_prop_read_u32(cm_np, "contribution", &map->contribution);
- for (int c = 0; c < map->cells_nr; ++c)
- {
- struct rt_thermal_cooling_cell *cell = &map->cells[c];
- if (rt_ofw_parse_phandle_cells(cm_np, "cooling-device", "#cooling-cells", c, &args))
- {
- continue;
- }
- cdev_np = args.data;
- rt_spin_lock(&nodes_lock);
- device_foreach(cdev, &thermal_cooling_device_nodes)
- {
- if (cdev->parent.ofw_node == cdev_np)
- {
- cell->cooling_devices = cdev;
- break;
- }
- }
- rt_spin_unlock(&nodes_lock);
- cell->level_range[0] = args.args[0];
- cell->level_range[1] = args.args[1];
- if (cell->cooling_devices)
- {
- thermal_bind(cell->cooling_devices, zdev);
- }
- rt_ofw_node_put(cdev_np);
- }
- }
- _end:
- }
- #else
- rt_inline void thermal_ofw_setup(struct rt_ofw_node *np, struct rt_thermal_zone_device *zdev)
- {
- }
- #endif /* RT_USING_OFW */
- static void thermal_zone_poll(struct rt_work *work, void *work_data)
- {
- struct rt_thermal_zone_device *zdev = work_data;
- rt_thermal_zone_device_update(zdev, RT_THERMAL_MSG_EVENT_UNSPECIFIED);
- }
- rt_err_t rt_thermal_zone_device_register(struct rt_thermal_zone_device *zdev)
- {
- if (!zdev || !zdev->ops || !zdev->ops->get_temp)
- {
- return -RT_EINVAL;
- }
- zdev->ops->get_temp(zdev, &zdev->temperature);
- zdev->last_temperature = zdev->temperature;
- if (!zdev->trips)
- {
- zdev->trips_nr = 0;
- }
- rt_spin_lock_init(&zdev->nodes_lock);
- rt_list_init(&zdev->notifier_nodes);
- rt_list_init(&device_list(zdev));
- rt_mutex_init(&zdev->mutex, rt_dm_dev_get_name(&zdev->parent), RT_IPC_FLAG_PRIO);
- zdev->temperature = RT_THERMAL_TEMP_INVALID;
- zdev->prev_low_trip = -INT_MAX;
- zdev->prev_high_trip = INT_MAX;
- rt_spin_lock(&nodes_lock);
- rt_list_insert_before(&thermal_zone_device_nodes, &device_list(zdev));
- rt_spin_unlock(&nodes_lock);
- thermal_ofw_setup(zdev->parent.ofw_node, zdev);
- rt_work_init(&zdev->poller, thermal_zone_poll, zdev);
- zdev->enabled = RT_TRUE;
- /* Start to poll */
- rt_work_submit(&zdev->poller, zdev->polling_delay);
- return RT_EOK;
- }
- rt_err_t rt_thermal_zone_device_unregister(struct rt_thermal_zone_device *zdev)
- {
- if (!zdev)
- {
- return -RT_EINVAL;
- }
- rt_spin_lock(&zdev->nodes_lock);
- if (rt_list_isempty(&zdev->notifier_nodes))
- {
- LOG_E("%s: there is %u user", rt_dm_dev_get_name(&zdev->parent),
- rt_list_len(&zdev->notifier_nodes));
- rt_spin_unlock(&zdev->nodes_lock);
- return -RT_EBUSY;
- }
- rt_spin_unlock(&zdev->nodes_lock);
- rt_work_cancel(&zdev->poller);
- rt_spin_lock(&nodes_lock);
- rt_list_remove(&device_list(zdev));
- rt_spin_unlock(&nodes_lock);
- if (zdev->trips_free && zdev->trips)
- {
- rt_free(zdev->trips);
- }
- if (zdev->cooling_maps_nr && zdev->cooling_maps_nr)
- {
- for (int i = 0; i < zdev->cooling_maps_nr; ++i)
- {
- struct rt_thermal_cooling_device *cdev;
- struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i];
- for (int c = 0; c < map->cells_nr; ++c)
- {
- cdev = map->cells[i].cooling_devices;
- if (cdev)
- {
- thermal_unbind(cdev, zdev);
- }
- }
- rt_free(map->cells);
- }
- rt_free(zdev->cooling_maps);
- }
- rt_mutex_detach(&zdev->mutex);
- return RT_EOK;
- }
- rt_err_t rt_thermal_cooling_device_register(struct rt_thermal_cooling_device *cdev)
- {
- rt_err_t err;
- if (!cdev || !cdev->ops ||
- !cdev->ops->get_max_level || !cdev->ops->get_cur_level || !cdev->ops->set_cur_level)
- {
- return -RT_EINVAL;
- }
- if ((err = cdev->ops->get_max_level(cdev, &cdev->max_level)))
- {
- return err;
- }
- rt_list_init(&device_list(cdev));
- rt_list_init(&cdev->governor_node);
- rt_spin_lock(&nodes_lock);
- rt_list_insert_before(&thermal_cooling_device_nodes, &device_list(cdev));
- rt_spin_unlock(&nodes_lock);
- err = rt_thermal_cooling_device_change_governor(cdev, RT_NULL);
- return err;
- }
- rt_err_t rt_thermal_cooling_device_unregister(struct rt_thermal_cooling_device *cdev)
- {
- if (!cdev)
- {
- return -RT_EINVAL;
- }
- if (cdev->parent.ref_count)
- {
- LOG_E("%s: there is %u user",
- rt_dm_dev_get_name(&cdev->parent), cdev->parent.ref_count);
- return -RT_EINVAL;
- }
- rt_spin_lock(&nodes_lock);
- rt_list_remove(&device_list(cdev));
- rt_spin_unlock(&nodes_lock);
- return RT_EOK;
- }
- static void dumb_governor_tuning(struct rt_thermal_zone_device *zdev,
- int map_idx, int cell_idx, rt_ubase_t *level)
- {
- struct rt_thermal_cooling_map *map = &zdev->cooling_maps[map_idx];
- if (zdev->cooling && zdev->temperature > map->trips->temperature)
- {
- if (zdev->temperature - zdev->last_temperature > map->trips->hysteresis)
- {
- ++*level;
- }
- else if (zdev->last_temperature - zdev->temperature > map->trips->hysteresis)
- {
- --*level;
- }
- }
- else
- {
- *level = 0;
- }
- }
- static struct rt_thermal_cooling_governor dumb_governor =
- {
- .name = "dumb",
- .tuning = dumb_governor_tuning,
- };
- static int system_thermal_cooling_governor_init(void)
- {
- rt_thermal_cooling_governor_register(&dumb_governor);
- return 0;
- }
- INIT_CORE_EXPORT(system_thermal_cooling_governor_init);
- rt_err_t rt_thermal_cooling_governor_register(struct rt_thermal_cooling_governor *gov)
- {
- rt_err_t err = RT_EOK;
- struct rt_thermal_cooling_governor *gov_tmp;
- if (!gov || !gov->name || !gov->tuning)
- {
- return -RT_EINVAL;
- }
- rt_list_init(&gov->list);
- rt_list_init(&gov->cdev_nodes);
- rt_spin_lock(&nodes_lock);
- rt_list_for_each_entry(gov_tmp, &thermal_cooling_governor_nodes, list)
- {
- if (!rt_strcmp(gov_tmp->name, gov->name))
- {
- err = -RT_ERROR;
- goto _out_unlock;
- }
- }
- rt_list_insert_before(&thermal_cooling_governor_nodes, &gov->list);
- _out_unlock:
- rt_spin_unlock(&nodes_lock);
- return err;
- }
- rt_err_t rt_thermal_cooling_governor_unregister(struct rt_thermal_cooling_governor *gov)
- {
- if (!gov)
- {
- return -RT_EINVAL;
- }
- if (gov == &dumb_governor)
- {
- return -RT_EINVAL;
- }
- rt_spin_lock(&nodes_lock);
- if (!rt_list_isempty(&gov->cdev_nodes))
- {
- goto _out_unlock;
- }
- rt_list_remove(&gov->list);
- _out_unlock:
- rt_spin_unlock(&nodes_lock);
- return RT_EOK;
- }
- rt_err_t rt_thermal_cooling_device_change_governor(struct rt_thermal_cooling_device *cdev,
- const char *name)
- {
- rt_err_t err;
- struct rt_thermal_cooling_governor *gov;
- if (!cdev)
- {
- return -RT_EINVAL;
- }
- name = name ? : dumb_governor.name;
- err = -RT_ENOSYS;
- rt_spin_lock(&nodes_lock);
- rt_list_for_each_entry(gov, &thermal_cooling_governor_nodes, list)
- {
- if (!rt_strcmp(gov->name, name))
- {
- if (cdev->gov)
- {
- rt_list_remove(&cdev->governor_node);
- }
- cdev->gov = gov;
- rt_list_insert_before(&cdev->governor_node, &gov->cdev_nodes);
- err = RT_EOK;
- break;
- }
- }
- rt_spin_unlock(&nodes_lock);
- return err;
- }
- rt_err_t rt_thermal_zone_notifier_register(struct rt_thermal_zone_device *zdev,
- struct rt_thermal_notifier *notifier)
- {
- if (!zdev || !notifier)
- {
- return -RT_EINVAL;
- }
- notifier->zdev = zdev;
- rt_list_init(¬ifier->list);
- rt_spin_lock(&zdev->nodes_lock);
- rt_list_insert_after(&zdev->notifier_nodes, ¬ifier->list);
- rt_spin_unlock(&zdev->nodes_lock);
- return RT_EOK;
- }
- rt_err_t rt_thermal_zone_notifier_unregister(struct rt_thermal_zone_device *zdev,
- struct rt_thermal_notifier *notifier)
- {
- if (!zdev || !notifier)
- {
- return -RT_EINVAL;
- }
- rt_spin_lock(&zdev->nodes_lock);
- rt_list_remove(¬ifier->list);
- rt_spin_unlock(&zdev->nodes_lock);
- return RT_EOK;
- }
- void rt_thermal_zone_device_update(struct rt_thermal_zone_device *zdev, rt_ubase_t msg)
- {
- rt_err_t err;
- rt_bool_t passive = RT_FALSE, need_cool = RT_FALSE;
- struct rt_thermal_notifier *notifier, *next_notifier;
- RT_ASSERT(zdev != RT_NULL);
- if (!rt_interrupt_get_nest())
- {
- rt_mutex_take(&zdev->mutex, RT_WAITING_FOREVER);
- }
- /* Check thermal zone status */
- if (msg == RT_THERMAL_MSG_DEVICE_DOWN)
- {
- zdev->enabled = RT_FALSE;
- }
- else if (msg == RT_THERMAL_MSG_DEVICE_UP)
- {
- zdev->enabled = RT_TRUE;
- }
- /* Read temperature */
- zdev->last_temperature = zdev->temperature;
- zdev->ops->get_temp(zdev, &zdev->temperature);
- for (int i = 0; i < zdev->trips_nr; ++i)
- {
- struct rt_thermal_trip *tmp_trip = &zdev->trips[i];
- if (zdev->temperature <= tmp_trip->temperature)
- {
- continue;
- }
- switch (tmp_trip->type)
- {
- case RT_THERMAL_TRIP_PASSIVE:
- passive = RT_TRUE;
- goto cooling;
- case RT_THERMAL_TRIP_CRITICAL:
- if (zdev->ops->critical)
- {
- zdev->ops->critical(zdev);
- }
- else if (zdev->last_temperature > tmp_trip->temperature)
- {
- /* Tried to cool already, but failed */
- rt_hw_cpu_reset();
- }
- else
- {
- goto cooling;
- }
- break;
- case RT_THERMAL_TRIP_HOT:
- if (zdev->ops->hot)
- {
- zdev->ops->hot(zdev);
- break;
- }
- default:
- cooling:
- zdev->cooling = need_cool = RT_TRUE;
- rt_thermal_cooling_device_kick(zdev);
- break;
- }
- }
- if (!need_cool && zdev->cooling)
- {
- rt_thermal_cooling_device_kick(zdev);
- }
- /* Set the new trips */
- if (zdev->ops->set_trips)
- {
- rt_bool_t same_trip = RT_FALSE;
- int low = -INT_MAX, high = INT_MAX;
- struct rt_thermal_trip trip;
- for (int i = 0; i < zdev->trips_nr; ++i)
- {
- int trip_low;
- rt_bool_t low_set = RT_FALSE;
- rt_memcpy(&trip, &zdev->trips[i], sizeof(trip));
- trip_low = trip.temperature - trip.hysteresis;
- if (trip_low < zdev->temperature && trip_low > low)
- {
- low = trip_low;
- low_set = RT_TRUE;
- same_trip = RT_FALSE;
- }
- if (trip.temperature > zdev->temperature && trip.temperature < high)
- {
- high = trip.temperature;
- same_trip = low_set;
- }
- }
- /* No need to change trip points */
- if (zdev->prev_low_trip == low && zdev->prev_high_trip == high)
- {
- goto _call_notifier;
- }
- if (same_trip &&
- (zdev->prev_low_trip != -INT_MAX || zdev->prev_high_trip != INT_MAX))
- {
- goto _call_notifier;
- }
- zdev->prev_low_trip = low;
- zdev->prev_high_trip = high;
- if ((err = zdev->ops->set_trips(zdev, low, high)))
- {
- LOG_E("%s: Set trips error = %s", rt_dm_dev_get_name(&zdev->parent),
- rt_strerror(err));
- }
- }
- /* Call all notifier, maybe have governor */
- _call_notifier:
- rt_spin_lock(&zdev->nodes_lock);
- rt_list_for_each_entry_safe(notifier, next_notifier, &zdev->notifier_nodes, list)
- {
- rt_spin_unlock(&zdev->nodes_lock);
- notifier->callback(notifier, msg);
- rt_spin_lock(&zdev->nodes_lock);
- }
- rt_spin_unlock(&zdev->nodes_lock);
- /* Prepare for the next report */
- if (!zdev->enabled)
- {
- rt_work_cancel(&zdev->poller);
- }
- else if (passive && zdev->passive_delay)
- {
- rt_work_submit(&zdev->poller, zdev->passive_delay);
- }
- else if (zdev->polling_delay)
- {
- rt_work_submit(&zdev->poller, zdev->polling_delay);
- }
- if (!rt_interrupt_get_nest())
- {
- rt_mutex_release(&zdev->mutex);
- }
- }
- void rt_thermal_cooling_device_kick(struct rt_thermal_zone_device *zdev)
- {
- RT_ASSERT(zdev != RT_NULL);
- for (int i = 0; i < zdev->cooling_maps_nr; ++i)
- {
- rt_ubase_t level;
- struct rt_thermal_cooling_device *cdev;
- struct rt_thermal_cooling_cell *cell;
- struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i];
- for (int c = 0; c < map->cells_nr; ++c)
- {
- cell = &map->cells[c];
- cdev = cell->cooling_devices;
- if (!cdev)
- {
- continue;
- }
- /* Update status */
- if (cdev->ops->get_max_level(cdev, &cdev->max_level))
- {
- continue;
- }
- if (cdev->ops->get_cur_level(cdev, &level) || level > cdev->max_level)
- {
- continue;
- }
- /* Check if cooling is required */
- if (level >= cell->level_range[0] && level <= cell->level_range[1])
- {
- /* Is cooling, not call */
- continue;
- }
- cdev->gov->tuning(zdev, i, c, &level);
- level = rt_min_t(rt_ubase_t, level, cdev->max_level);
- cdev->ops->set_cur_level(cdev, level);
- }
- }
- }
- rt_err_t rt_thermal_zone_set_trip(struct rt_thermal_zone_device *zdev, int trip_id,
- const struct rt_thermal_trip *trip)
- {
- rt_err_t err;
- struct rt_thermal_trip tmp_trip;
- if (!zdev || !trip)
- {
- return -RT_EINVAL;
- }
- rt_mutex_take(&zdev->mutex, RT_WAITING_FOREVER);
- if (!zdev->ops->set_trip_temp && !zdev->ops->set_trip_hyst && !zdev->trips)
- {
- err = -RT_EINVAL;
- goto _out_unlock;
- }
- if (trip_id >= zdev->trips_nr)
- {
- err = -RT_EINVAL;
- goto _out_unlock;
- }
- rt_memcpy(&tmp_trip, &zdev->trips[trip_id], sizeof(tmp_trip));
- if (tmp_trip.type != trip->type)
- {
- err = -RT_EINVAL;
- goto _out_unlock;
- }
- if (tmp_trip.temperature != trip->temperature && zdev->ops->set_trip_temp)
- {
- if ((err = zdev->ops->set_trip_temp(zdev, trip_id, trip->temperature)))
- {
- goto _out_unlock;
- }
- }
- if (tmp_trip.hysteresis != trip->hysteresis && zdev->ops->set_trip_hyst)
- {
- if ((err = zdev->ops->set_trip_hyst(zdev, trip_id, trip->hysteresis)))
- {
- goto _out_unlock;
- }
- }
- if (zdev->trips &&
- (tmp_trip.temperature != trip->temperature || tmp_trip.hysteresis != trip->hysteresis))
- {
- zdev->trips[trip_id] = *trip;
- }
- _out_unlock:
- rt_mutex_release(&zdev->mutex);
- if (!err)
- {
- rt_thermal_zone_device_update(zdev, RT_THERMAL_MSG_TRIP_CHANGED);
- }
- return err;
- }
- rt_err_t rt_thermal_zone_get_trip(struct rt_thermal_zone_device *zdev, int trip_id,
- struct rt_thermal_trip *out_trip)
- {
- rt_err_t err = RT_EOK;
- if (!zdev || !out_trip)
- {
- return -RT_EINVAL;
- }
- rt_mutex_take(&zdev->mutex, RT_WAITING_FOREVER);
- if (!zdev->trips_nr)
- {
- err = -RT_ENOSYS;
- goto _out_unlock;
- }
- if (trip_id >= zdev->trips_nr)
- {
- err = -RT_EINVAL;
- goto _out_unlock;
- }
- *out_trip = zdev->trips[trip_id];
- _out_unlock:
- rt_mutex_release(&zdev->mutex);
- return err;
- }
- #if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH)
- static int list_thermal(int argc, char**argv)
- {
- struct rt_thermal_zone_device *zdev;
- /* Thermal is an important subsystem, please do not output too much. */
- rt_spin_lock(&nodes_lock);
- device_foreach(zdev, &thermal_zone_device_nodes)
- {
- int temperature = zdev->temperature;
- rt_kprintf("%s-%d\n", rt_dm_dev_get_name(&zdev->parent), zdev->zone_id);
- rt_kprintf("temperature:\t%+d.%u C\n", temperature / 1000, rt_abs(temperature) % 1000);
- for (int i = 0, id = 0; i < zdev->cooling_maps_nr; ++i)
- {
- rt_ubase_t level;
- struct rt_thermal_trip *trips;
- struct rt_thermal_cooling_device *cdev;
- struct rt_thermal_cooling_cell *cell;
- struct rt_thermal_cooling_map *map = &zdev->cooling_maps[i];
- for (int c = 0; c < map->cells_nr; ++c, ++id)
- {
- trips = map->trips;
- cell = &map->cells[c];
- cdev = cell->cooling_devices;
- if (cdev)
- {
- cdev->ops->get_cur_level(cdev, &level);
- rt_kprintf("cooling%u:\t%s[%+d.%u C] %d\n", id,
- rt_dm_dev_get_name(&cdev->parent),
- trips->temperature / 1000, rt_abs(trips->temperature) % 1000,
- level);
- }
- else
- {
- rt_kprintf("cooling%u:\t%s[%+d.%u C] %d\n", id,
- "(not supported)",
- trips->temperature / 1000, rt_abs(trips->temperature) % 1000,
- 0);
- }
- }
- }
- }
- rt_spin_unlock(&nodes_lock);
- return 0;
- }
- MSH_CMD_EXPORT(list_thermal, dump all of thermal information);
- #endif /* RT_USING_CONSOLE && RT_USING_MSH */
|