Add thermal framework

Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
wangjianyu3 2023-10-13 23:10:56 +08:00 committed by Xiang Xiao
parent b78c9a7067
commit d1b87bd021
10 changed files with 1230 additions and 0 deletions

31
Kconfig
View File

@ -1936,6 +1936,37 @@ config DEBUG_SPI_INFO
endif # DEBUG_SPI endif # DEBUG_SPI
config DEBUG_THERMAL
bool "Thermal Debug Features"
default n
---help---
Enable thermal debug features.
if DEBUG_THERMAL
config DEBUG_THERMAL_ERROR
bool "Thermal Error Output"
default n
depends on DEBUG_ERROR
---help---
Enable thermal error output to SYSLOG.
config DEBUG_THERMAL_WARN
bool "Thermal Warnings Output"
default n
depends on DEBUG_WARN
---help---
Enable thermal warning output to SYSLOG.
config DEBUG_THERMAL_INFO
bool "Thermal Informational Output"
default n
depends on DEBUG_INFO
---help---
Enable thermal informational output to SYSLOG.
endif # DEBUG_THERMAL
config DEBUG_TIMER config DEBUG_TIMER
bool "Timer Debug Features" bool "Timer Debug Features"
default n default n

View File

@ -42,6 +42,7 @@ source "drivers/rpmsg/Kconfig"
source "drivers/rptun/Kconfig" source "drivers/rptun/Kconfig"
source "drivers/sensors/Kconfig" source "drivers/sensors/Kconfig"
source "drivers/serial/Kconfig" source "drivers/serial/Kconfig"
source "drivers/thermal/Kconfig"
source "drivers/usbdev/Kconfig" source "drivers/usbdev/Kconfig"
source "drivers/usbhost/Kconfig" source "drivers/usbhost/Kconfig"
source "drivers/usbmisc/Kconfig" source "drivers/usbmisc/Kconfig"

View File

@ -63,6 +63,7 @@ include sensors/Make.defs
include serial/Make.defs include serial/Make.defs
include spi/Make.defs include spi/Make.defs
include syslog/Make.defs include syslog/Make.defs
include thermal/Make.defs
include timers/Make.defs include timers/Make.defs
include usbdev/Make.defs include usbdev/Make.defs
include usbhost/Make.defs include usbhost/Make.defs

View File

@ -46,6 +46,7 @@
#include <nuttx/serial/uart_ram.h> #include <nuttx/serial/uart_ram.h>
#include <nuttx/syslog/syslog.h> #include <nuttx/syslog/syslog.h>
#include <nuttx/syslog/syslog_console.h> #include <nuttx/syslog/syslog_console.h>
#include <nuttx/thermal.h>
#include <nuttx/trace.h> #include <nuttx/trace.h>
#include <nuttx/usrsock/usrsock_rpmsg.h> #include <nuttx/usrsock/usrsock_rpmsg.h>
#include <nuttx/virtio/virtio.h> #include <nuttx/virtio/virtio.h>
@ -271,5 +272,9 @@ void drivers_initialize(void)
optee_register(); optee_register();
#endif #endif
#ifdef CONFIG_THERMAL
thermal_init();
#endif
drivers_trace_end(); drivers_trace_end();
} }

20
drivers/thermal/Kconfig Normal file
View File

@ -0,0 +1,20 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
menuconfig THERMAL
bool "Thermal framework"
default n
---help---
Enable thermal framework.
if THERMAL
config THERMAL_DEFAULT_GOVERNOR
string "Thermal default governor name"
default "step_wise"
---help---
Default governor name.
endif # THERMAL

30
drivers/thermal/Make.defs Normal file
View File

@ -0,0 +1,30 @@
############################################################################
# drivers/thermal/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
# Include thermal sources
ifeq ($(CONFIG_THERMAL),y)
CSRCS += thermal_core.c
DEPPATH += --dep-path thermal
VPATH += thermal
endif

View File

@ -0,0 +1,843 @@
/****************************************************************************
* drivers/thermal/thermal_core.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/kmalloc.h>
#include <debug.h>
#include <stdio.h>
#include <sys/boardctl.h>
#include "thermal_core.h"
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int zone_bind_cooling (FAR struct thermal_zone_device_s *zdev,
int trip,
FAR struct thermal_cooling_device_s *cdev,
unsigned int upper, unsigned int lower,
unsigned int weight);
static void zone_unbind_cooling(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR struct thermal_cooling_device_s *cdev);
static FAR struct thermal_governor_s *
find_governor_by_name (FAR const char *name);
static int zone_set_governor (FAR struct thermal_zone_device_s *zdev,
FAR struct thermal_governor_s *gov);
static void device_bind (FAR struct thermal_zone_device_s *zdev,
FAR struct thermal_cooling_device_s *cdev);
static void device_unbind (FAR struct thermal_zone_device_s *zdev,
FAR struct thermal_cooling_device_s *cdev);
/****************************************************************************
* Private Data
****************************************************************************/
static struct list_node
g_cooling_dev_list = LIST_INITIAL_VALUE(g_cooling_dev_list);
static struct list_node
g_governor_list = LIST_INITIAL_VALUE(g_governor_list);
static struct list_node
g_zone_dev_list = LIST_INITIAL_VALUE(g_zone_dev_list);
static mutex_t g_thermal_lock = NXMUTEX_INITIALIZER;
static FAR struct thermal_governor_s *g_def_governor = NULL;
/****************************************************************************
* Private Functions
****************************************************************************/
static int zone_set_governor(FAR struct thermal_zone_device_s *zdev,
FAR struct thermal_governor_s *gov)
{
int ret = OK;
/* The caller must use `g_thermal_lock` to protect zones and governors */
if (zdev->governor && zdev->governor->unbind_from_tz)
{
zdev->governor->unbind_from_tz(zdev);
}
if (gov && gov->bind_to_tz)
{
ret = gov->bind_to_tz(zdev);
if (ret < 0)
{
if (zdev->governor->bind_to_tz(zdev) < 0)
{
zdev->governor = NULL;
}
return ret;
}
}
zdev->governor = gov;
return ret;
}
static int zone_bind_cooling(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR struct thermal_cooling_device_s *cdev,
unsigned int upper, unsigned int lower,
unsigned int weight)
{
FAR struct thermal_instance_s *ins;
FAR struct thermal_instance_s *pos;
unsigned int max_state;
int ret;
ret = cdev->ops->get_max_state(cdev, &max_state);
if (ret < 0)
{
therr("Get max state failed!\n");
return ret;
}
list_for_every_entry(&zdev->instance_list, pos,
struct thermal_instance_s, zdev_node)
{
if (zdev == pos->zdev && cdev == pos->cdev && trip == pos->trip)
{
thwarn("Instance %s %s %d already exist!",
zdev->name, cdev->name, trip);
return -EEXIST;
}
}
ins = kmm_malloc(sizeof(struct thermal_instance_s));
if (!ins)
{
return -ENOMEM;
}
ins->zdev = zdev;
ins->cdev = cdev;
ins->trip = trip;
ins->target = THERMAL_NO_TARGET;
if (lower == THERMAL_NO_LIMIT)
{
ins->lower = 0;
}
else
{
ins->lower = lower;
}
if (upper == THERMAL_NO_LIMIT)
{
ins->upper = max_state;
}
else
{
ins->upper = upper;
}
ins->weight = weight;
thinfo("Adding instance zdev:%-4s cdev:%-4s h:%2u l:%2u t:%d\n",
zdev->name, cdev->name, ins->upper, ins->lower, ins->trip);
list_add_tail(&zdev->instance_list, &ins->zdev_node);
list_add_tail(&cdev->instance_list, &ins->cdev_node);
return OK;
}
static void zone_unbind_cooling(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR struct thermal_cooling_device_s *cdev)
{
FAR struct thermal_instance_s *ins;
list_for_every_entry(&zdev->instance_list, ins,
struct thermal_instance_s, zdev_node)
{
if (zdev == ins->zdev && cdev == ins->cdev && trip == ins->trip)
{
list_delete(&ins->zdev_node);
list_delete(&ins->cdev_node);
kmm_free(ins);
break;
}
}
}
static void device_bind(FAR struct thermal_zone_device_s *zdev,
FAR struct thermal_cooling_device_s *cdev)
{
FAR const struct thermal_zone_map_s *map;
FAR const struct thermal_zone_trip_s *trip;
int ret;
int i;
int j;
for (i = 0; i < zdev->params->num_maps; i++)
{
map = &zdev->params->maps[i];
if (strcmp(map->cdev_name, cdev->name))
{
continue;
}
for (j = 0; j < zdev->params->num_trips; j++)
{
trip = &zdev->params->trips[j];
if (strcmp(map->trip_name, trip->name))
{
continue;
}
ret = zone_bind_cooling(zdev, j, cdev, map->high, map->low,
map->weight);
if (ret < 0)
{
therr("Failed to bind %s and %s, trip %d\n",
zdev->name, cdev->name, j);
}
}
}
}
static void device_unbind(FAR struct thermal_zone_device_s *zdev,
FAR struct thermal_cooling_device_s *cdev)
{
int i;
for (i = 0; i < zdev->params->num_trips; i++)
{
zone_unbind_cooling(zdev, i, cdev);
}
}
static FAR struct thermal_governor_s *
find_governor_by_name(FAR const char *name)
{
FAR struct thermal_governor_s *gov;
if (!name)
{
return NULL;
}
/* The caller must use `g_thermal_lock` to protect governors */
list_for_every_entry(&g_governor_list, gov, struct thermal_governor_s,
node)
{
if (!strcmp(gov->name, name))
{
return gov;
}
}
return NULL;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int thermal_zone_enable(FAR struct thermal_zone_device_s *zdev,
bool enabled)
{
nxmutex_lock(&g_thermal_lock);
if (enabled == zdev->enabled)
{
nxmutex_unlock(&g_thermal_lock);
return OK;
}
zdev->enabled = enabled;
work_cancel_sync(LPWORK, &zdev->monitor);
nxmutex_unlock(&g_thermal_lock);
thermal_zone_device_update(zdev);
return OK;
}
int thermal_zone_get_trend(FAR struct thermal_zone_device_s *zdev)
{
enum thermal_trend_e trend;
if (zdev->ops->get_trend)
{
if (!zdev->ops->get_trend(zdev, &trend))
{
return trend;
}
}
if (zdev->last_temperature == THERMAL_INVALID_TEMP ||
zdev->temperature == THERMAL_INVALID_TEMP)
{
trend = THERMAL_TREND_STABLE;
}
else if (zdev->last_temperature > zdev->temperature)
{
trend = THERMAL_TREND_DROPPING;
}
else if (zdev->last_temperature < zdev->temperature)
{
trend = THERMAL_TREND_RAISING;
}
else
{
trend = THERMAL_TREND_STABLE;
}
return trend;
}
int thermal_zone_get_trip_temp(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR int *temp)
{
if (!temp || trip >= zdev->params->num_trips)
{
return -EINVAL;
}
*temp = zdev->params->trips[trip].temp;
return OK;
}
int thermal_zone_get_trip_type(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR enum thermal_trip_type_e *type)
{
if (!type || trip >= zdev->params->num_trips)
{
return -EINVAL;
}
*type = zdev->params->trips[trip].type;
return OK;
}
int thermal_zone_get_trip_hyst(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR int *hyst)
{
if (!hyst || trip >= zdev->params->num_trips)
{
return -EINVAL;
}
*hyst = zdev->params->trips[trip].hyst;
return OK;
}
/****************************************************************************
* Name: thermal_register_governor
*
* Description:
* Register governor
*
* Input Parameters:
* gov - the struct thermal_governor_s addr
*
* Returned Value:
* Zero (OK) is returned on success. Otherwise a negated errno value is
* returned to indicate the nature of the failure.
****************************************************************************/
int thermal_register_governor(FAR struct thermal_governor_s *gov)
{
FAR struct thermal_governor_s *pos;
if (!gov || !gov->throttle)
{
therr("Invalid governor!\n");
return -EINVAL;
}
nxmutex_lock(&g_thermal_lock);
list_for_every_entry(&g_governor_list, pos,
struct thermal_governor_s, node)
{
if (!strcmp(gov->name, pos->name))
{
thwarn("Governor (%s) already exists!", gov->name);
nxmutex_unlock(&g_thermal_lock);
return -EEXIST;
}
}
list_add_tail(&g_governor_list, &gov->node);
thinfo("Register governor %s\n", gov->name);
/* Default governor */
if (!strcmp(gov->name, CONFIG_THERMAL_DEFAULT_GOVERNOR))
{
g_def_governor = gov;
thinfo("Default governor %s registered!\n", g_def_governor->name);
}
nxmutex_unlock(&g_thermal_lock);
return OK;
}
/****************************************************************************
* Name: thermal_unregister_governor
*
* Description:
* Unregister governor
*
* Input Parameters:
* gov - the struct thermal_governor_s addr
*
* Returned Value:
* None
****************************************************************************/
void thermal_unregister_governor(FAR struct thermal_governor_s *gov)
{
FAR struct thermal_zone_device_s *zdev;
if (!gov)
{
return;
}
nxmutex_lock(&g_thermal_lock);
list_for_every_entry(&g_zone_dev_list, zdev,
struct thermal_zone_device_s, node)
{
if (zdev->governor == gov)
{
zone_set_governor(zdev, NULL);
}
}
list_delete(&gov->node);
nxmutex_unlock(&g_thermal_lock);
}
/****************************************************************************
* Name: thermal_cooling_device_register
*
* Description:
* Register thermal cooling device.
*
* Input Parameters:
* name - Name of cooling device
* devdata - Device driver data
* ops - Operations
*
* Returned Value:
* Addr of created cooling device entry.
****************************************************************************/
FAR struct thermal_cooling_device_s *
thermal_cooling_device_register(FAR const char *name, void *devdata,
FAR const struct thermal_cooling_device_ops_s *ops)
{
FAR struct thermal_zone_device_s *zdev;
FAR struct thermal_cooling_device_s *cdev;
nxmutex_lock(&g_thermal_lock);
list_for_every_entry(&g_cooling_dev_list, cdev,
struct thermal_cooling_device_s, node)
{
if (!strcmp(cdev->name, name))
{
thwarn("Cooling device (%s) already exists!", name);
nxmutex_unlock(&g_thermal_lock);
return NULL;
}
}
cdev = kmm_zalloc(sizeof(*cdev));
if (!cdev)
{
therr("Cannot allocate memory for cooling device registering!\n");
nxmutex_unlock(&g_thermal_lock);
return NULL;
}
strlcpy(cdev->name, name, THERMAL_NAME_LEN);
cdev->ops = ops;
cdev->devdata = devdata;
list_initialize(&cdev->instance_list);
list_add_tail(&g_cooling_dev_list, &cdev->node);
list_for_every_entry(&g_zone_dev_list, zdev,
struct thermal_zone_device_s, node)
{
device_bind(zdev, cdev);
}
thinfo("Registered cooling device %s\n", cdev->name);
nxmutex_unlock(&g_thermal_lock);
return cdev;
}
/****************************************************************************
* Name: thermal_cooling_device_unregister
*
* Description:
* Unregister thermal cooling device.
*
* Input Parameters:
* cdev - Cooling Device
*
* Returned Value:
* None
****************************************************************************/
void
thermal_cooling_device_unregister(FAR struct thermal_cooling_device_s *cdev)
{
FAR struct thermal_zone_device_s *zdev;
/* Unbind */
nxmutex_lock(&g_thermal_lock);
list_delete(&cdev->node);
list_for_every_entry(&g_zone_dev_list, zdev,
struct thermal_zone_device_s, node)
{
device_unbind(zdev, cdev);
}
kmm_free(cdev);
nxmutex_unlock(&g_thermal_lock);
}
/****************************************************************************
* Name: thermal_cooling_device_update
*
* Description:
* Update thermal cooling device.
*
* Input Parameters:
* cdev - Cooling Device.
*
* Returned Value:
* None
****************************************************************************/
void thermal_cooling_device_update(FAR struct thermal_cooling_device_s *cdev)
{
FAR struct thermal_instance_s *instance;
unsigned int target = THERMAL_NO_TARGET;
unsigned int current = THERMAL_NO_TARGET;
int ret;
ret = cdev->ops->get_state(cdev, &current);
if (ret < 0)
{
thwarn("Thermal get cooling state failed!\n");
return;
}
list_for_every_entry(&cdev->instance_list, instance,
struct thermal_instance_s, cdev_node)
{
if ((instance->target != THERMAL_NO_TARGET) &&
(instance->target > target ||
target == THERMAL_NO_TARGET))
{
target = instance->target;
}
}
if (target != THERMAL_NO_TARGET && target != current)
{
ret = cdev->ops->set_state(cdev, target);
if (ret < 0)
{
thwarn("Thermal set cooling state of %s failed!\n", cdev->name);
}
}
}
/****************************************************************************
* Name: thermal_zone_device_register
*
* Description:
* Register thermal zone device.
*
* Input Parameters:
* name - Name of zone.
* devdata - Device driver data.
* ops - Operations of zone deivce.
* params - Parameter of zone device.
*
* Returned Value:
* Addr of created zone device entry.
****************************************************************************/
struct thermal_zone_device_s *
thermal_zone_device_register(FAR const char *name,
FAR void *devdata,
FAR const struct thermal_zone_device_ops_s *ops,
FAR const struct thermal_zone_params_s *params)
{
FAR struct thermal_cooling_device_s *cdev;
FAR struct thermal_governor_s *gov;
FAR struct thermal_zone_device_s *pos;
FAR struct thermal_zone_device_s *zdev;
if (!ops || !ops->get_temp)
{
therr("Invalid zone operations!\n");
return NULL;
}
nxmutex_lock(&g_thermal_lock);
list_for_every_entry(&g_zone_dev_list, pos,
struct thermal_zone_device_s, node)
{
if (!strcmp(name, pos->name))
{
thwarn("Zone device (%s) already exists!", name);
nxmutex_unlock(&g_thermal_lock);
return NULL;
}
}
zdev = kmm_zalloc(sizeof(struct thermal_zone_device_s));
if (!zdev)
{
nxmutex_unlock(&g_thermal_lock);
return NULL;
}
zdev->ops = ops;
zdev->devdata = devdata;
zdev->enabled = true;
strlcpy(zdev->name, name, THERMAL_NAME_LEN);
zdev->params = params;
zdev->temperature = THERMAL_INVALID_TEMP;
list_initialize(&zdev->instance_list);
/* Set governor */
gov = find_governor_by_name(zdev->params->gov_name);
zone_set_governor(zdev, gov ? gov : g_def_governor);
thinfo("Set governor of zone %s to %s.\n", zdev->name,
zdev->governor ? zdev->governor->name : "");
list_add_tail(&g_zone_dev_list, &zdev->node);
list_for_every_entry(&g_cooling_dev_list, cdev,
struct thermal_cooling_device_s, node)
{
device_bind(zdev, cdev);
}
nxmutex_unlock(&g_thermal_lock);
thinfo("Registered zone device %s\n", zdev->name);
thermal_zone_device_update(zdev);
return zdev;
}
/****************************************************************************
* Name: thermal_zone_device_unregister
*
* Description:
* Unregister thermal zone device.
*
* Input Parameters:
* zdev - Zone Device
*
* Returned Value:
* None
****************************************************************************/
void thermal_zone_device_unregister(FAR struct thermal_zone_device_s *zdev)
{
FAR struct thermal_cooling_device_s *cdev;
/* Disable Zone */
thermal_zone_enable(zdev, false);
/* Unbind */
nxmutex_lock(&g_thermal_lock);
list_for_every_entry(&g_cooling_dev_list, cdev,
struct thermal_cooling_device_s, node)
{
device_unbind(zdev, cdev);
}
list_delete(&zdev->node);
zone_set_governor(zdev, NULL);
kmm_free(zdev);
nxmutex_unlock(&g_thermal_lock);
}
/****************************************************************************
* Name: thermal_zone_device_update
*
* Description:
* Update thermal zone device.
* Get temperature from sensor and throttle if necessary.
*
* Input Parameters:
* zdev - Zone Device
*
* Returned Value:
* None
****************************************************************************/
void thermal_zone_device_update(FAR struct thermal_zone_device_s *zdev)
{
int trip_high = INT_MAX;
int trip_low = INT_MIN;
int trip;
int temp;
int ret;
nxmutex_lock(&g_thermal_lock);
/* Update termerature */
if (!zdev->enabled)
{
goto unlock;
}
ret = zdev->ops->get_temp(zdev, &temp);
if (ret < 0)
{
therr("Failed to get temperature from zone %s \n", zdev->name);
goto unlock;
}
zdev->last_temperature = zdev->temperature;
zdev->temperature = temp;
for (trip = 0; trip < zdev->params->num_trips; trip++)
{
enum thermal_trip_type_e type;
int temp_low;
int hyst;
thermal_zone_get_trip_temp(zdev, trip, &temp);
thermal_zone_get_trip_hyst(zdev, trip, &hyst);
thermal_zone_get_trip_type(zdev, trip, &type);
if (zdev->temperature < temp && trip_high > temp)
{
trip_high = temp;
}
temp_low = temp - hyst;
if (zdev->temperature > temp_low && trip_low < temp_low)
{
trip_low = temp_low;
}
/* Critical */
if (type == THERMAL_CRITICAL && zdev->temperature >= temp)
{
therr("Thermal critical (%d), resetting...\n", zdev->temperature);
#ifdef CONFIG_BOARDCTL_RESET
boardctl(BOARDIOC_RESET, BOARDIOC_SOFTRESETCAUSE_THERMAL);
#endif
}
else if (zdev->governor)
{
zdev->governor->throttle(zdev, trip);
}
else if(g_def_governor)
{
g_def_governor->throttle(zdev, trip);
}
else
{
therr("No valid governor!\n");
}
}
if (zdev->ops->set_trips)
{
ret = zdev->ops->set_trips(zdev, trip_low, trip_high);
if (ret < 0)
{
thwarn("Set trip points (l:%d, h:%d) for %s failed\n",
trip_low, trip_high, zdev->name);
}
}
work_queue(LPWORK, &zdev->monitor, (worker_t)thermal_zone_device_update,
zdev, zdev->params->polling_delay);
unlock:
nxmutex_unlock(&g_thermal_lock);
}
/****************************************************************************
* Name: thermal_init
*
* Description:
* Init thermal framework
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. Otherwise a negated errno value is
* returned to indicate the nature of the failure.
****************************************************************************/
int thermal_init(void)
{
int ret = OK;
return ret;
}

View File

@ -0,0 +1,76 @@
/****************************************************************************
* drivers/thermal/thermal_core.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __DRIVERS_THERMAL_THERMAL_CORE_H
#define __DRIVERS_THERMAL_THERMAL_CORE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/thermal.h>
/****************************************************************************
* Public Types
****************************************************************************/
struct thermal_instance_s
{
FAR struct thermal_cooling_device_s *cdev;
FAR struct thermal_zone_device_s *zdev;
int trip;
/* Cooling State */
unsigned int target; /* Expected Cooling State */
unsigned int upper; /* The Maximum cooling state for this trip point */
unsigned int lower; /* Minimum cooling state */
unsigned int weight;
struct list_node cdev_node;
struct list_node zdev_node;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Cooling Device */
void
thermal_cooling_device_update (FAR struct thermal_cooling_device_s *cdev);
/* Zone Device */
int thermal_zone_enable (FAR struct thermal_zone_device_s *zdev,
bool enabled);
int thermal_zone_get_trend (FAR struct thermal_zone_device_s *zdev);
int thermal_zone_get_trip_temp(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR int *temp);
int thermal_zone_get_trip_type(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR enum thermal_trip_type_e *type);
int thermal_zone_get_trip_hyst(FAR struct thermal_zone_device_s *zdev,
int trip,
FAR int *hyst);
#endif /* __DRIVERS_THERMAL_THERMAL_CORE_H */

View File

@ -758,6 +758,24 @@
# define spiinfo _none # define spiinfo _none
#endif #endif
#ifdef CONFIG_DEBUG_THERMAL_ERROR
# define therr _err
#else
# define therr _none
#endif
#ifdef CONFIG_DEBUG_THERMAL_WARN
# define thwarn _warn
#else
# define thwarn _none
#endif
#ifdef CONFIG_DEBUG_THERMAL_INFO
# define thinfo _info
#else
# define thinfo _none
#endif
#ifdef CONFIG_DEBUG_TIMER_ERROR #ifdef CONFIG_DEBUG_TIMER_ERROR
# define tmrerr _err # define tmrerr _err
#else #else

205
include/nuttx/thermal.h Normal file
View File

@ -0,0 +1,205 @@
/****************************************************************************
* include/nuttx/thermal.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_THERMAL_H
#define __INCLUDE_NUTTX_THERMAL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/list.h>
#include <nuttx/mutex.h>
#include <nuttx/wqueue.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Generic */
#define THERMAL_NAME_LEN 32
/* Trips */
#define THERMAL_NO_LIMIT 0
/* Temperature */
#define THERMAL_INVALID_TEMP INT_MIN
/* Cooling State */
#define THERMAL_TARGET_MIN 0
#define THERMAL_TARGET_MAX (UINT_MAX - 1)
#define THERMAL_NO_TARGET UINT_MAX
/****************************************************************************
* Public Types
****************************************************************************/
struct thermal_cooling_device_ops_s;
struct thermal_zone_device_ops_s;
struct thermal_zone_device_s;
struct thermal_zone_params_s;
enum thermal_trend_e
{
THERMAL_TREND_RAISING,
THERMAL_TREND_DROPPING,
THERMAL_TREND_STABLE,
};
enum thermal_trip_type_e
{
THERMAL_COLD,
THERMAL_NORMAL,
THERMAL_HOT,
THERMAL_CRITICAL,
};
struct thermal_governor_s
{
struct list_node node;
FAR const char *name;
CODE int (*bind_to_tz) (FAR struct thermal_zone_device_s *zdev);
CODE int (*throttle) (FAR struct thermal_zone_device_s *zdev,
int trip);
CODE void (*unbind_from_tz)(FAR struct thermal_zone_device_s *zdev);
};
struct thermal_cooling_device_s
{
struct list_node node;
char name[THERMAL_NAME_LEN];
FAR void *devdata;
FAR const struct thermal_cooling_device_ops_s *ops;
struct list_node instance_list;
};
struct thermal_zone_device_s
{
struct list_node node;
char name[THERMAL_NAME_LEN];
bool enabled;
FAR void *devdata;
int last_temperature;
int temperature;
FAR const struct thermal_zone_device_ops_s *ops;
FAR struct thermal_governor_s *governor;
FAR const struct thermal_zone_params_s *params;
struct work_s monitor;
struct list_node instance_list;
};
struct thermal_cooling_device_ops_s
{
CODE int (*set_state) (FAR struct thermal_cooling_device_s *cdev,
unsigned int state);
CODE int (*get_state) (FAR struct thermal_cooling_device_s *cdev,
FAR unsigned int *state);
CODE int (*get_max_state)(FAR struct thermal_cooling_device_s *cdev,
FAR unsigned int *state);
};
struct thermal_zone_device_ops_s
{
CODE int (*get_temp) (FAR struct thermal_zone_device_s *zdev,
FAR int *temp);
CODE int (*get_trend) (FAR struct thermal_zone_device_s *zdev,
FAR enum thermal_trend_e *trend);
CODE int (*set_trips) (FAR struct thermal_zone_device_s *zdev,
int low, int high);
};
struct thermal_zone_map_s
{
FAR const char *trip_name;
FAR const char *cdev_name;
unsigned int low;
unsigned int high;
unsigned int weight;
};
struct thermal_zone_trip_s
{
FAR const char *name;
unsigned int temp;
unsigned int hyst;
enum thermal_trip_type_e type;
};
struct thermal_zone_params_s
{
FAR const char *gov_name;
int polling_delay;
FAR const struct thermal_zone_trip_s *trips;
int num_trips;
FAR const struct thermal_zone_map_s *maps;
int num_maps;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Governor */
int thermal_register_governor (FAR struct thermal_governor_s *gov);
void thermal_unregister_governor(FAR struct thermal_governor_s *gov);
/* Cooling Device */
FAR struct thermal_cooling_device_s *
thermal_cooling_device_register(FAR const char *name, void *devdata,
FAR const struct thermal_cooling_device_ops_s *ops);
void
thermal_cooling_device_unregister(
FAR struct thermal_cooling_device_s *cdev);
/* Zone Device */
FAR struct thermal_zone_device_s *
thermal_zone_device_register(FAR const char *name, FAR void *devdata,
FAR const struct thermal_zone_device_ops_s *ops,
FAR const struct thermal_zone_params_s *params);
void
thermal_zone_device_unregister(
FAR struct thermal_zone_device_s *zdev);
void
thermal_zone_device_update (FAR struct thermal_zone_device_s *zdev);
/* Thermal Framework initialization */
int thermal_init(void);
#endif /* __INCLUDE_NUTTX_THERMAL_H */