Add thermal framework
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
parent
b78c9a7067
commit
d1b87bd021
31
Kconfig
31
Kconfig
@ -1936,6 +1936,37 @@ config DEBUG_SPI_INFO
|
||||
|
||||
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
|
||||
bool "Timer Debug Features"
|
||||
default n
|
||||
|
@ -42,6 +42,7 @@ source "drivers/rpmsg/Kconfig"
|
||||
source "drivers/rptun/Kconfig"
|
||||
source "drivers/sensors/Kconfig"
|
||||
source "drivers/serial/Kconfig"
|
||||
source "drivers/thermal/Kconfig"
|
||||
source "drivers/usbdev/Kconfig"
|
||||
source "drivers/usbhost/Kconfig"
|
||||
source "drivers/usbmisc/Kconfig"
|
||||
|
@ -63,6 +63,7 @@ include sensors/Make.defs
|
||||
include serial/Make.defs
|
||||
include spi/Make.defs
|
||||
include syslog/Make.defs
|
||||
include thermal/Make.defs
|
||||
include timers/Make.defs
|
||||
include usbdev/Make.defs
|
||||
include usbhost/Make.defs
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <nuttx/serial/uart_ram.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
#include <nuttx/syslog/syslog_console.h>
|
||||
#include <nuttx/thermal.h>
|
||||
#include <nuttx/trace.h>
|
||||
#include <nuttx/usrsock/usrsock_rpmsg.h>
|
||||
#include <nuttx/virtio/virtio.h>
|
||||
@ -271,5 +272,9 @@ void drivers_initialize(void)
|
||||
optee_register();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_THERMAL
|
||||
thermal_init();
|
||||
#endif
|
||||
|
||||
drivers_trace_end();
|
||||
}
|
||||
|
20
drivers/thermal/Kconfig
Normal file
20
drivers/thermal/Kconfig
Normal 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
30
drivers/thermal/Make.defs
Normal 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
|
843
drivers/thermal/thermal_core.c
Normal file
843
drivers/thermal/thermal_core.c
Normal 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, ¤t);
|
||||
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;
|
||||
}
|
76
drivers/thermal/thermal_core.h
Normal file
76
drivers/thermal/thermal_core.h
Normal 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 */
|
@ -758,6 +758,24 @@
|
||||
# define spiinfo _none
|
||||
#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
|
||||
# define tmrerr _err
|
||||
#else
|
||||
|
205
include/nuttx/thermal.h
Normal file
205
include/nuttx/thermal.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user