rtt更新
This commit is contained in:
28
rt-thread/components/drivers/thermal/Kconfig
Normal file
28
rt-thread/components/drivers/thermal/Kconfig
Normal file
@@ -0,0 +1,28 @@
|
||||
menuconfig RT_USING_THERMAL
|
||||
bool "Using Thermal Management device drivers"
|
||||
depends on RT_USING_DM
|
||||
default n
|
||||
|
||||
if RT_USING_THERMAL
|
||||
comment "Thermal Sensors Drivers"
|
||||
endif
|
||||
|
||||
if RT_USING_THERMAL
|
||||
osource "$(SOC_DM_THERMAL_DIR)/Kconfig"
|
||||
endif
|
||||
|
||||
if RT_USING_THERMAL
|
||||
comment "Thermal Cool Drivers"
|
||||
endif
|
||||
|
||||
config RT_THERMAL_COOL_PWM_FAN
|
||||
bool "PWM Fan"
|
||||
depends on RT_USING_THERMAL
|
||||
depends on RT_USING_PWM
|
||||
depends on RT_USING_REGULATOR
|
||||
depends on RT_USING_OFW
|
||||
default n
|
||||
|
||||
if RT_USING_THERMAL
|
||||
osource "$(SOC_DM_THERMAL_COOL_DIR)/Kconfig"
|
||||
endif
|
18
rt-thread/components/drivers/thermal/SConscript
Normal file
18
rt-thread/components/drivers/thermal/SConscript
Normal file
@@ -0,0 +1,18 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_USING_THERMAL']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../include']
|
||||
|
||||
src = ['thermal.c', 'thermal_dm.c']
|
||||
|
||||
if GetDepend(['RT_THERMAL_COOL_PWM_FAN']):
|
||||
src += ['thermal-cool-pwm-fan.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
288
rt-thread/components/drivers/thermal/thermal-cool-pwm-fan.c
Normal file
288
rt-thread/components/drivers/thermal/thermal-cool-pwm-fan.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* 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 <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "thermal.cool.pwm-fan"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#define MAX_PWM 255
|
||||
|
||||
struct pwm_fan_cool
|
||||
{
|
||||
struct rt_thermal_cooling_device parent;
|
||||
|
||||
rt_uint32_t pwm_fan_level;
|
||||
rt_uint32_t pwm_fan_max_level;
|
||||
rt_uint32_t *pwm_fan_cooling_levels;
|
||||
|
||||
struct rt_device_pwm *pwm_dev;
|
||||
struct rt_pwm_configuration pwm_conf;
|
||||
|
||||
struct rt_regulator *supply;
|
||||
struct rt_spinlock lock;
|
||||
};
|
||||
|
||||
#define raw_to_pwm_fan_cool(raw) rt_container_of(raw, struct pwm_fan_cool, parent)
|
||||
|
||||
static rt_err_t pwm_fan_power_on(struct pwm_fan_cool *pf_cool)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
|
||||
if ((err = rt_pwm_enable(pf_cool->pwm_dev, pf_cool->pwm_conf.channel)))
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
if (pf_cool->supply && (err = rt_regulator_enable(pf_cool->supply)))
|
||||
{
|
||||
rt_pwm_disable(pf_cool->pwm_dev, pf_cool->pwm_conf.channel);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t pwm_fan_power_off(struct pwm_fan_cool *pf_cool)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
|
||||
if (pf_cool->supply && (err = rt_regulator_disable(pf_cool->supply)))
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = rt_pwm_disable(pf_cool->pwm_dev, pf_cool->pwm_conf.channel)))
|
||||
{
|
||||
rt_regulator_enable(pf_cool->supply);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t pwm_fan_cool_get_max_level(struct rt_thermal_cooling_device *cdev,
|
||||
rt_ubase_t *out_level)
|
||||
{
|
||||
struct pwm_fan_cool *pf_cool = raw_to_pwm_fan_cool(cdev);
|
||||
|
||||
*out_level = pf_cool->pwm_fan_max_level;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t pwm_fan_cool_get_cur_level(struct rt_thermal_cooling_device *cdev,
|
||||
rt_ubase_t *out_level)
|
||||
{
|
||||
struct pwm_fan_cool *pf_cool = raw_to_pwm_fan_cool(cdev);
|
||||
|
||||
*out_level = pf_cool->pwm_fan_level;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t pwm_fan_cool_set_cur_level(struct rt_thermal_cooling_device *cdev,
|
||||
rt_ubase_t level)
|
||||
{
|
||||
rt_ubase_t pwm;
|
||||
rt_err_t err = RT_EOK;
|
||||
struct pwm_fan_cool *pf_cool = raw_to_pwm_fan_cool(cdev);
|
||||
|
||||
if (pf_cool->pwm_fan_level == level)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_spin_lock(&pf_cool->lock);
|
||||
|
||||
if ((pwm = pf_cool->pwm_fan_cooling_levels[level]))
|
||||
{
|
||||
rt_ubase_t period;
|
||||
struct rt_pwm_configuration *pwm_conf = &pf_cool->pwm_conf;
|
||||
|
||||
period = pwm_conf->period;
|
||||
pwm_conf->pulse = RT_DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
|
||||
|
||||
err = rt_pwm_set(pf_cool->pwm_dev,
|
||||
pwm_conf->channel, pwm_conf->period, pwm_conf->pulse);
|
||||
|
||||
if (!err && pf_cool->pwm_fan_level == 0)
|
||||
{
|
||||
err = pwm_fan_power_on(pf_cool);
|
||||
}
|
||||
}
|
||||
else if (pf_cool->pwm_fan_level > 0)
|
||||
{
|
||||
err = pwm_fan_power_off(pf_cool);
|
||||
}
|
||||
|
||||
rt_spin_unlock(&pf_cool->lock);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
pf_cool->pwm_fan_level = level;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
const static struct rt_thermal_cooling_device_ops pwm_fan_cool_ops =
|
||||
{
|
||||
.get_max_level = pwm_fan_cool_get_max_level,
|
||||
.get_cur_level = pwm_fan_cool_get_cur_level,
|
||||
.set_cur_level = pwm_fan_cool_set_cur_level,
|
||||
};
|
||||
|
||||
static void pwm_fan_cool_free(struct pwm_fan_cool *pf_cool)
|
||||
{
|
||||
if (!rt_is_err_or_null(pf_cool->supply))
|
||||
{
|
||||
rt_regulator_put(pf_cool->supply);
|
||||
}
|
||||
|
||||
if (pf_cool->pwm_fan_cooling_levels)
|
||||
{
|
||||
rt_free(pf_cool->pwm_fan_cooling_levels);
|
||||
}
|
||||
|
||||
rt_free(pf_cool);
|
||||
}
|
||||
|
||||
static rt_err_t pwm_fan_cool_probe(struct rt_platform_device *pdev)
|
||||
{
|
||||
rt_err_t err;
|
||||
int levels_nr;
|
||||
struct rt_ofw_cell_args pwm_args;
|
||||
struct rt_device *dev = &pdev->parent;
|
||||
struct rt_ofw_node *np = dev->ofw_node, *pwm_np;
|
||||
struct pwm_fan_cool *pf_cool = rt_calloc(1, sizeof(*pf_cool));
|
||||
|
||||
if (!pf_cool)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
if (rt_ofw_parse_phandle_cells(np, "pwms", "#pwm-cells", 0, &pwm_args))
|
||||
{
|
||||
err = -RT_EINVAL;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
pwm_np = pwm_args.data;
|
||||
|
||||
if (!rt_ofw_data(pwm_np))
|
||||
{
|
||||
rt_platform_ofw_request(pwm_np);
|
||||
}
|
||||
|
||||
pf_cool->pwm_dev = rt_ofw_data(pwm_np);
|
||||
rt_ofw_node_put(pwm_np);
|
||||
|
||||
if (!pf_cool->pwm_dev)
|
||||
{
|
||||
err = -RT_EINVAL;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
pf_cool->pwm_conf.channel = pwm_args.args[0];
|
||||
pf_cool->pwm_conf.period = pwm_args.args[1];
|
||||
|
||||
pf_cool->supply = rt_regulator_get(dev, "fan");
|
||||
|
||||
if (rt_is_err(pf_cool->supply))
|
||||
{
|
||||
err = rt_ptr_err(pf_cool->supply);
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if ((levels_nr = rt_dm_dev_prop_count_of_u32(dev, "cooling-levels")) <= 0)
|
||||
{
|
||||
err = -RT_EINVAL;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
pf_cool->pwm_fan_cooling_levels = rt_calloc(levels_nr, sizeof(rt_uint32_t));
|
||||
|
||||
if (!pf_cool->pwm_fan_cooling_levels)
|
||||
{
|
||||
err = -RT_ENOMEM;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if (rt_dm_dev_prop_read_u32_array_index(dev, "cooling-levels",
|
||||
0, levels_nr, pf_cool->pwm_fan_cooling_levels) <= 0)
|
||||
{
|
||||
err = -RT_EINVAL;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
pf_cool->pwm_fan_level = MAX_PWM;
|
||||
pf_cool->pwm_fan_max_level = levels_nr - 1;
|
||||
|
||||
rt_spin_lock_init(&pf_cool->lock);
|
||||
pwm_fan_cool_set_cur_level(&pf_cool->parent, 0);
|
||||
|
||||
rt_dm_dev_set_name(&pf_cool->parent.parent, "%s", rt_dm_dev_get_name(&pdev->parent));
|
||||
pf_cool->parent.parent.ofw_node = dev->ofw_node;
|
||||
pf_cool->parent.ops = &pwm_fan_cool_ops;
|
||||
|
||||
if ((err = rt_thermal_cooling_device_register(&pf_cool->parent)))
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
dev->user_data = pf_cool;
|
||||
|
||||
return RT_EOK;
|
||||
|
||||
_fail:
|
||||
pwm_fan_cool_free(pf_cool);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t pwm_fan_cool_remove(struct rt_platform_device *pdev)
|
||||
{
|
||||
struct pwm_fan_cool *pf_cool = pdev->parent.ofw_node;
|
||||
|
||||
rt_thermal_cooling_device_unregister(&pf_cool->parent);
|
||||
|
||||
pwm_fan_power_off(pf_cool);
|
||||
pwm_fan_cool_free(pf_cool);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t pwm_fan_cool_shutdown(struct rt_platform_device *pdev)
|
||||
{
|
||||
return pwm_fan_cool_remove(pdev);
|
||||
}
|
||||
|
||||
static const struct rt_ofw_node_id pwm_fan_cool_ofw_ids[] =
|
||||
{
|
||||
{ .compatible = "pwm-fan" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct rt_platform_driver pwm_fan_cool_driver =
|
||||
{
|
||||
.name = "pwm-fan-cool",
|
||||
.ids = pwm_fan_cool_ofw_ids,
|
||||
|
||||
.probe = pwm_fan_cool_probe,
|
||||
.remove = pwm_fan_cool_remove,
|
||||
.shutdown = pwm_fan_cool_shutdown,
|
||||
};
|
||||
RT_PLATFORM_DRIVER_EXPORT(pwm_fan_cool_driver);
|
917
rt-thread/components/drivers/thermal/thermal.c
Normal file
917
rt-thread/components/drivers/thermal/thermal.c
Normal file
@@ -0,0 +1,917 @@
|
||||
/*
|
||||
* 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 struct rt_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, 1, 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;
|
||||
|
||||
if (i >= zdev->trips_nr)
|
||||
{
|
||||
goto _call_notifier;
|
||||
}
|
||||
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 */
|
64
rt-thread/components/drivers/thermal/thermal_dm.c
Normal file
64
rt-thread/components/drivers/thermal/thermal_dm.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define DBG_TAG "rtdm.thermal"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include "thermal_dm.h"
|
||||
|
||||
enum rt_thermal_trip_type thermal_type(const char *type)
|
||||
{
|
||||
if (!type)
|
||||
{
|
||||
return RT_THERMAL_TRIP_TYPE_MAX;
|
||||
}
|
||||
|
||||
if (!rt_strcmp(type, "active"))
|
||||
{
|
||||
return RT_THERMAL_TRIP_ACTIVE;
|
||||
}
|
||||
else if (!rt_strcmp(type, "passive"))
|
||||
{
|
||||
return RT_THERMAL_TRIP_PASSIVE;
|
||||
}
|
||||
else if (!rt_strcmp(type, "hot"))
|
||||
{
|
||||
return RT_THERMAL_TRIP_HOT;
|
||||
}
|
||||
else if (!rt_strcmp(type, "critical"))
|
||||
{
|
||||
return RT_THERMAL_TRIP_CRITICAL;
|
||||
}
|
||||
|
||||
return RT_THERMAL_TRIP_TYPE_MAX;
|
||||
}
|
||||
|
||||
rt_err_t thermal_bind(struct rt_thermal_cooling_device *cdev,
|
||||
struct rt_thermal_zone_device *zdev)
|
||||
{
|
||||
if (cdev->ops->bind)
|
||||
{
|
||||
return cdev->ops->bind(cdev, zdev);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t thermal_unbind(struct rt_thermal_cooling_device *cdev,
|
||||
struct rt_thermal_zone_device *zdev)
|
||||
{
|
||||
if (cdev->ops->unbind)
|
||||
{
|
||||
return cdev->ops->unbind(cdev, zdev);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
27
rt-thread/components/drivers/thermal/thermal_dm.h
Normal file
27
rt-thread/components/drivers/thermal/thermal_dm.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __THERMAL_DM_H__
|
||||
#define __THERMAL_DM_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#include <drivers/ofw.h>
|
||||
|
||||
enum rt_thermal_trip_type thermal_type(const char *type);
|
||||
|
||||
rt_err_t thermal_bind(struct rt_thermal_cooling_device *cdev,
|
||||
struct rt_thermal_zone_device *zdev);
|
||||
rt_err_t thermal_unbind(struct rt_thermal_cooling_device *cdev,
|
||||
struct rt_thermal_zone_device *zdev);
|
||||
|
||||
#endif /* __THERMAL_DM_H__ */
|
Reference in New Issue
Block a user