This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 7efdd31994b43046d09091ed44c177615e43020a Author: Justin Hammond <[email protected]> AuthorDate: Sat Aug 15 19:30:25 2026 +0800 drivers/thermal: Cool a devfreq device instead of a cpufreq policy. The cooling device renamed in the previous commit was written against a cpufreq framework that never landed. It includes nuttx/cpufreq.h, which does not exist, and THERMAL_CDEV_CPUFREQ depends on CPUFREQ, which no Kconfig in the tree defines, so it has never been selectable and has never been compiled. The cpufreq half of the dummy driver is orphaned the same way behind THERMAL_DUMMY_CPUFREQ. Upstream noticed once already and dropped cpufreq from the sim thermal configuration in 898a5d501f. devfreq does the same job and is here. It carries the frequency table, arbitrates windows through QoS, and its DEVFREQ_CONFLICT_PREFER_LOW is documented as the policy for a device protecting a thermal budget, which is exactly a cooling device's claim on it. Point the cooling device at that instead, and the thermal framework can throttle again. Two things change beyond the API. The cooling state now names a ceiling rather than a two entry window, because devfreq resolves a conflicting floor in the ceiling's favour, and that makes the whole table reachable: max_state is one less than the number of usable entries, state zero leaves the top entry available and the highest state holds the device at the bottom one. A DEVFREQ_ENTRY_INVALID entry is a hole the driver has punched and cannot be installed as a ceiling, so it earns no cooling state; counting it would both advertise a state the device cannot deliver and, on reaching it, install a ceiling of ~0u, which caps nothing. And the device is found by name, since devfreq is multi instance where a cpufreq policy was singular, so THERMAL_CDEV_DEVFREQ_NAME says which one to cool and what to call the cooling device in a zone's map. The dummy driver gains a devfreq lower half in place of its cpufreq one, which gives the tree its first devfreq consumer and makes the whole path testable without hardware. On sim, walking the dummy zone from 45 to 90 degrees: temp cooling state frequency 60 0 900 62 1 700 61 2 500 72 3 300 74 4 100 and back down again as it cools. Also fixes two faults the file could not previously reveal: it called therr and thinfo without including nuttx/debug.h, and it reached the driver by casting the policy pointer, which worked only while driver was the first member. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond <[email protected]> --- drivers/thermal/CMakeLists.txt | 4 +- drivers/thermal/Kconfig | 32 +++-- drivers/thermal/Make.defs | 4 +- drivers/thermal/thermal_core.c | 6 +- drivers/thermal/thermal_core.h | 10 +- drivers/thermal/thermal_devfreq_cooling.c | 232 ++++++++++++++++++++---------- drivers/thermal/thermal_dummy.c | 139 ++++++++++-------- 7 files changed, 272 insertions(+), 155 deletions(-) diff --git a/drivers/thermal/CMakeLists.txt b/drivers/thermal/CMakeLists.txt index 47298d87331..a9aa6006882 100644 --- a/drivers/thermal/CMakeLists.txt +++ b/drivers/thermal/CMakeLists.txt @@ -30,8 +30,8 @@ if(CONFIG_THERMAL_GOVERNOR_STEP_WISE) list(APPEND SRCS thermal_step_wise.c) endif() -if(CONFIG_THERMAL_CDEV_CPUFREQ) - list(APPEND SRCS thermal_cpufreq_cooling.c) +if(CONFIG_THERMAL_CDEV_DEVFREQ) + list(APPEND SRCS thermal_devfreq_cooling.c) endif() if(CONFIG_THERMAL_PROCFS) diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 6602f27c2d9..e48b58474c8 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -24,12 +24,26 @@ config THERMAL_GOVERNOR_STEP_WISE ---help--- Enable step wise governor. -config THERMAL_CDEV_CPUFREQ - bool "Thermal cpufreq cooling device" +config THERMAL_CDEV_DEVFREQ + bool "Thermal devfreq cooling device" default n - depends on CPUFREQ + depends on DEVFREQ ---help--- - Enable thermal cpufreq cooling device. + Enable thermal devfreq cooling device, which cools a device by + capping the frequency of its devfreq instance. + +if THERMAL_CDEV_DEVFREQ + +config THERMAL_CDEV_DEVFREQ_NAME + string "Name of the devfreq device to cool" + default "cpu" + ---help--- + The devfreq device this cooling device caps, and the name the + cooling device itself takes, so that a zone's cooling map can + refer to it. The devfreq device must be registered before + thermal_init() runs. + +endif # THERMAL_CDEV_DEVFREQ config THERMAL_PROCFS bool "Thermal PROCFS support" @@ -52,12 +66,14 @@ config THERMAL_DUMMY_POLLING_DELAY ---help--- Polling delay(tick). -config THERMAL_DUMMY_CPUFREQ - bool "Dummy cpufreq driver" +config THERMAL_DUMMY_DEVFREQ + bool "Dummy devfreq driver" default n - depends on CPUFREQ + depends on DEVFREQ + select THERMAL_CDEV_DEVFREQ ---help--- - Enable cpufreq dummy driver. + Enable devfreq dummy driver, giving the dummy zone a frequency + capped cooling device as well as its fan. endif # THERMAL_DUMMY diff --git a/drivers/thermal/Make.defs b/drivers/thermal/Make.defs index facc84a0d2a..85fa19aba19 100644 --- a/drivers/thermal/Make.defs +++ b/drivers/thermal/Make.defs @@ -30,8 +30,8 @@ ifeq ($(CONFIG_THERMAL_GOVERNOR_STEP_WISE),y) CSRCS += thermal_step_wise.c endif -ifeq ($(CONFIG_THERMAL_CDEV_CPUFREQ),y) -CSRCS += thermal_cpufreq_cooling.c +ifeq ($(CONFIG_THERMAL_CDEV_DEVFREQ),y) +CSRCS += thermal_devfreq_cooling.c endif ifeq ($(CONFIG_THERMAL_PROCFS),y) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 0b0c10bd4d0..8eb42690831 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -961,8 +961,10 @@ int thermal_init(void) } #endif -#ifdef CONFIG_THERMAL_CDEV_CPUFREQ - if (NULL == thermal_cpufreq_cooling_register()) +#ifdef CONFIG_THERMAL_CDEV_DEVFREQ + if (NULL == thermal_devfreq_cooling_register( + CONFIG_THERMAL_CDEV_DEVFREQ_NAME, + CONFIG_THERMAL_CDEV_DEVFREQ_NAME)) { return -ENOTSUP; } diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index f264bd91bf5..67667342386 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -59,11 +59,13 @@ struct thermal_instance_s void thermal_cooling_device_update (FAR struct thermal_cooling_device_s *cdev); -#ifdef CONFIG_THERMAL_CDEV_CPUFREQ -FAR struct thermal_cooling_device_s *thermal_cpufreq_cooling_register(void); -void thermal_cpufreq_cooling_unregister( +#ifdef CONFIG_THERMAL_CDEV_DEVFREQ +FAR struct thermal_cooling_device_s * +thermal_devfreq_cooling_register(FAR const char *devfreq_name, + FAR const char *cdev_name); +void thermal_devfreq_cooling_unregister( FAR struct thermal_cooling_device_s *cdev); -#endif /* CONFIG_THERMAL_CDEV_CPUFREQ */ +#endif /* CONFIG_THERMAL_CDEV_DEVFREQ */ /* Zone Device */ diff --git a/drivers/thermal/thermal_devfreq_cooling.c b/drivers/thermal/thermal_devfreq_cooling.c index 7758decd6bd..26208c66cf7 100644 --- a/drivers/thermal/thermal_devfreq_cooling.c +++ b/drivers/thermal/thermal_devfreq_cooling.c @@ -1,5 +1,5 @@ /**************************************************************************** - * drivers/thermal/thermal_cpufreq_cooling.c + * drivers/thermal/thermal_devfreq_cooling.c * * SPDX-License-Identifier: Apache-2.0 * @@ -24,7 +24,10 @@ * Included Files ****************************************************************************/ -#include <nuttx/cpufreq.h> +#include <errno.h> + +#include <nuttx/debug.h> +#include <nuttx/devfreq.h> #include <nuttx/kmalloc.h> #include "thermal_core.h" @@ -33,11 +36,11 @@ * Private Types ****************************************************************************/ -struct cpufreq_cooling_device_s +struct devfreq_cooling_device_s { - FAR const struct cpufreq_frequency_table *table; - FAR struct cpufreq_policy *policy; - FAR struct cpufreq_qos *qos; + FAR const uint32_t *table; + FAR struct devfreq_s *devfreq; + FAR struct qos_request_s *qos; unsigned int cur_state; unsigned int max_state; }; @@ -46,83 +49,144 @@ struct cpufreq_cooling_device_s * Private Function Prototypes ****************************************************************************/ -static int cpufreq_get_max_state(FAR struct thermal_cooling_device_s *cdev, +static int devfreq_get_max_state(FAR struct thermal_cooling_device_s *cdev, FAR unsigned int *state); -static int cpufreq_get_state (FAR struct thermal_cooling_device_s *cdev, +static int devfreq_get_state (FAR struct thermal_cooling_device_s *cdev, FAR unsigned int *state); -static int cpufreq_set_state (FAR struct thermal_cooling_device_s *cdev, +static int devfreq_set_state (FAR struct thermal_cooling_device_s *cdev, unsigned int state); /**************************************************************************** * Private Data ****************************************************************************/ -static const struct thermal_cooling_device_ops_s g_cpufreq_cdev_ops = +static const struct thermal_cooling_device_ops_s g_devfreq_cdev_ops = { - .set_state = cpufreq_set_state, - .get_state = cpufreq_get_state, - .get_max_state = cpufreq_get_max_state, + .set_state = devfreq_set_state, + .get_state = devfreq_get_state, + .get_max_state = devfreq_get_max_state, }; /**************************************************************************** * Private Functions ****************************************************************************/ -static int cpufreq_get_max_state(FAR struct thermal_cooling_device_s *cdev, +/**************************************************************************** + * Name: devfreq_cooling_freq + * + * Description: + * The nth usable frequency of a devfreq table, counting up from the + * lowest. DEVFREQ_ENTRY_INVALID marks a frequency the device cannot be + * held at, so those entries are not counted: n selects among the + * frequencies a cooling state can actually install, not table positions. + * + * Input Parameters: + * table - devfreq frequency table, terminated by DEVFREQ_ENTRY_END + * n - which usable entry to return, zero being the lowest + * + * Returned Value: + * The frequency in kHz, or DEVFREQ_ENTRY_INVALID if the table holds fewer + * than n + 1 usable entries. + * + ****************************************************************************/ + +static uint32_t devfreq_cooling_freq(FAR const uint32_t *table, + unsigned int n) +{ + unsigned int i; + + for (i = 0; table[i] != DEVFREQ_ENTRY_END; i++) + { + if (table[i] == DEVFREQ_ENTRY_INVALID) + { + continue; + } + + if (n == 0) + { + return table[i]; + } + + n--; + } + + return DEVFREQ_ENTRY_INVALID; +} + +static int devfreq_get_max_state(FAR struct thermal_cooling_device_s *cdev, FAR unsigned int *state) { - struct cpufreq_cooling_device_s *cpufreq_cdev = cdev->devdata; + FAR struct devfreq_cooling_device_s *devfreq_cdev = cdev->devdata; - *state = cpufreq_cdev->max_state; + *state = devfreq_cdev->max_state; return OK; } -static int cpufreq_get_state(FAR struct thermal_cooling_device_s *cdev, +static int devfreq_get_state(FAR struct thermal_cooling_device_s *cdev, FAR unsigned int *state) { - struct cpufreq_cooling_device_s *cpufreq_cdev = cdev->devdata; + FAR struct devfreq_cooling_device_s *devfreq_cdev = cdev->devdata; - *state = cpufreq_cdev->cur_state; + *state = devfreq_cdev->cur_state; return OK; } -static int cpufreq_set_state(FAR struct thermal_cooling_device_s *cdev, +static int devfreq_set_state(FAR struct thermal_cooling_device_s *cdev, unsigned int state) { - struct cpufreq_cooling_device_s *cpufreq_cdev = cdev->devdata; - unsigned int index = cpufreq_cdev->max_state - state; + FAR struct devfreq_cooling_device_s *devfreq_cdev = cdev->devdata; + uint32_t ceiling; int ret; - thinfo("CPU Freq cooling %u %u \n", - cpufreq_cdev->table[index].frequency, - cpufreq_cdev->table[index + 1].frequency); + if (state > devfreq_cdev->max_state) + { + return -EINVAL; + } + + /* The cooling state counts upwards as the device is asked to do less, + * and the table climbs the other way, so the two are read from opposite + * ends: state zero leaves the top entry available, and the highest state + * holds the device at the bottom one. + */ + + ceiling = devfreq_cooling_freq(devfreq_cdev->table, + devfreq_cdev->max_state - state); + if (ceiling == DEVFREQ_ENTRY_INVALID) + { + therr("No frequency for cooling state %u!\n", state); + return -EINVAL; + } + + thinfo("devfreq cooling state %u, ceiling %" PRIu32 " kHz\n", + state, ceiling); - if (cpufreq_cdev->qos == NULL) + /* A ceiling and no floor. Where another request wants more than this + * allows, a driver carrying DEVFREQ_CONFLICT_PREFER_LOW resolves it in + * favour of the ceiling, which is what protects the device. + */ + + if (devfreq_cdev->qos == NULL) { - cpufreq_cdev->qos = cpufreq_qos_add_request( - cpufreq_cdev->policy, - cpufreq_cdev->table[index].frequency, - cpufreq_cdev->table[index + 1].frequency); - if (!cpufreq_cdev->qos) + devfreq_cdev->qos = devfreq_qos_add_request(devfreq_cdev->devfreq, + 0, ceiling); + if (devfreq_cdev->qos == NULL) { - therr("Add qos request failed!"); + therr("Add qos request failed!\n"); return -EINVAL; } } else { - ret = cpufreq_qos_update_request( - cpufreq_cdev->qos, - cpufreq_cdev->table[index].frequency, - cpufreq_cdev->table[index + 1].frequency); + ret = devfreq_qos_update_request(devfreq_cdev->devfreq, + devfreq_cdev->qos, 0, ceiling); if (ret < 0) { - therr("Update qos request failed!"); + therr("Update qos request failed!\n"); return ret; } } - cpufreq_cdev->cur_state = state; + devfreq_cdev->cur_state = state; return OK; } @@ -131,106 +195,122 @@ static int cpufreq_set_state(FAR struct thermal_cooling_device_s *cdev, ****************************************************************************/ /**************************************************************************** - * Name: thermal_cpufreq_cooling_register + * Name: thermal_devfreq_cooling_register * * Description: - * Register cpufreq cooling device + * Register a cooling device over a devfreq device, which the thermal + * framework then throttles by capping its frequency. + * + * The devfreq device must already be registered, since it is found by + * name. The cooling device may be registered before or after the zones + * that use it; the core binds them either way. * * Input Parameters: - * policy - cpufreq policy + * devfreq_name - name the devfreq device was registered under + * cdev_name - name for the cooling device, matched against the + * cdev_name of a zone's cooling map * * Returned Value: * Addr of created cooling device entry ****************************************************************************/ -FAR struct thermal_cooling_device_s *thermal_cpufreq_cooling_register(void) +FAR struct thermal_cooling_device_s * +thermal_devfreq_cooling_register(FAR const char *devfreq_name, + FAR const char *cdev_name) { - FAR struct cpufreq_cooling_device_s *cpufreq_cdev; - FAR const struct cpufreq_frequency_table *table; + FAR struct devfreq_cooling_device_s *devfreq_cdev; FAR struct thermal_cooling_device_s *cdev; - FAR struct cpufreq_driver **driver; - FAR struct cpufreq_policy *policy; + FAR struct devfreq_s *devfreq; + FAR const uint32_t *table; unsigned int count; + unsigned int i; - policy = cpufreq_policy_get(); - if (policy == NULL) + devfreq = devfreq_find_by_name(devfreq_name); + if (devfreq == NULL) { - therr("Get cpufreq policy failed!\n"); + therr("No devfreq device named %s!\n", devfreq_name); return NULL; } - driver = (FAR struct cpufreq_driver **)policy; - - table = (*driver)->get_table(policy); + table = devfreq->freq_table; if (table == NULL) { - therr("Get cpufreq table failed!\n"); + therr("Get devfreq table failed!\n"); return NULL; } - for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++) + /* Count what the device can be held at, not what the table holds: an + * entry of DEVFREQ_ENTRY_INVALID is a hole the driver has punched and + * cannot be installed as a ceiling, so it earns no cooling state. + */ + + for (count = 0, i = 0; table[i] != DEVFREQ_ENTRY_END; i++) { + if (table[i] != DEVFREQ_ENTRY_INVALID) + { + count++; + } } if (count < 2) { - therr("Invalid cpufreq table!\n"); + therr("Invalid devfreq table!\n"); return NULL; } - cpufreq_cdev = kmm_zalloc(sizeof(*cpufreq_cdev)); - if (cpufreq_cdev == NULL) + devfreq_cdev = kmm_zalloc(sizeof(*devfreq_cdev)); + if (devfreq_cdev == NULL) { - therr("No memory for cpufreq cooling device registering!\n"); + therr("No memory for devfreq cooling device registering!\n"); return NULL; } - cpufreq_cdev->table = table; - cpufreq_cdev->policy = policy; - cpufreq_cdev->max_state = count - 2; - thinfo("max level of cpufreq is %d \n", cpufreq_cdev->max_state); + devfreq_cdev->table = table; + devfreq_cdev->devfreq = devfreq; + devfreq_cdev->max_state = count - 1; + thinfo("max level of %s is %u\n", devfreq_name, devfreq_cdev->max_state); - cdev = thermal_cooling_device_register("cpufreq", cpufreq_cdev, - &g_cpufreq_cdev_ops); + cdev = thermal_cooling_device_register(cdev_name, devfreq_cdev, + &g_devfreq_cdev_ops); if (cdev == NULL) { - kmm_free(cpufreq_cdev); + kmm_free(devfreq_cdev); } return cdev; } /**************************************************************************** - * Name: thermal_cpufreq_cooling_unregister + * Name: thermal_devfreq_cooling_unregister * * Description: - * Unregister cpufreq cooling device + * Unregister devfreq cooling device * * Input Parameters: - * cdev - Addr of cpufre cooling device entry + * cdev - Addr of devfreq cooling device entry * * Returned Value: * None ****************************************************************************/ void -thermal_cpufreq_cooling_unregister(FAR struct thermal_cooling_device_s *cdev) +thermal_devfreq_cooling_unregister(FAR struct thermal_cooling_device_s *cdev) { - struct cpufreq_cooling_device_s *cpufreq_cdev; + FAR struct devfreq_cooling_device_s *devfreq_cdev; int ret; - cpufreq_cdev = cdev->devdata; + devfreq_cdev = cdev->devdata; - if (cpufreq_cdev->qos) + if (devfreq_cdev->qos) { - ret = cpufreq_qos_remove_request(cpufreq_cdev->qos); + ret = devfreq_qos_remove_request(devfreq_cdev->devfreq, + devfreq_cdev->qos); if (ret < 0) { - thinfo("ret=%d\n", ret); - therr("Remove cpufreq qos failed!\n"); + therr("Remove devfreq qos failed: %d!\n", ret); } } thermal_cooling_device_unregister(cdev); - kmm_free(cpufreq_cdev); + kmm_free(devfreq_cdev); } diff --git a/drivers/thermal/thermal_dummy.c b/drivers/thermal/thermal_dummy.c index fbce40ce1f2..dab185cad04 100644 --- a/drivers/thermal/thermal_dummy.c +++ b/drivers/thermal/thermal_dummy.c @@ -25,8 +25,8 @@ ****************************************************************************/ #include <nuttx/config.h> -#ifdef CONFIG_THERMAL_DUMMY_CPUFREQ -#include <nuttx/cpufreq.h> +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ +#include <nuttx/devfreq.h> #endif #include <nuttx/thermal.h> @@ -57,13 +57,13 @@ struct dummy_cooling_device_s unsigned int max_state; }; -#ifdef CONFIG_THERMAL_DUMMY_CPUFREQ -struct dummy_cpufreq_driver_s +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ +struct dummy_devfreq_driver_s { - struct cpufreq_driver driver; - const struct cpufreq_frequency_table *table; + struct devfreq_driver_s driver; + FAR const uint32_t *table; size_t table_len; - struct cpufreq_frequency_table current; + uint32_t current; }; #endif @@ -90,17 +90,17 @@ static int dummy_cdev_set_state (FAR struct thermal_cooling_device_s *cdev, unsigned int state); -/* CPU Freq */ +/* devfreq */ -#ifdef CONFIG_THERMAL_DUMMY_CPUFREQ -FAR static const struct cpufreq_frequency_table * -dummy_cpufreq_get_table(FAR struct cpufreq_policy *driver); -static int dummy_cpufreq_target_index(FAR struct cpufreq_policy *driver, - unsigned int index); -static int dummy_cpufreq_get_frequency(FAR struct cpufreq_policy *driver); -static int dummy_cpufreq_suspend(FAR struct cpufreq_policy *driver); -static int dummy_cpufreq_resume (FAR struct cpufreq_policy *driver); -#endif /* CONFIG_THERMAL_DUMMY_CPUFREQ */ +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ +static FAR const uint32_t * +dummy_devfreq_get_table(FAR struct devfreq_s *devfreq); +static int dummy_devfreq_target_index(FAR struct devfreq_s *devfreq, + size_t index); +static uint32_t dummy_devfreq_get_frequency(FAR struct devfreq_s *devfreq); +static int dummy_devfreq_suspend(FAR struct devfreq_s *devfreq); +static int dummy_devfreq_resume (FAR struct devfreq_s *devfreq); +#endif /* CONFIG_THERMAL_DUMMY_DEVFREQ */ /**************************************************************************** * Private Data @@ -117,13 +117,15 @@ static const struct thermal_zone_trip_s g_dummy_trips[] = static const struct thermal_zone_map_s g_dummy_maps[] = { +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ { .trip_name = "cpu_alert1", - .cdev_name = "cpufreq", + .cdev_name = CONFIG_THERMAL_CDEV_DEVFREQ_NAME, .low = 3, .high = THERMAL_NO_LIMIT, .weight = 20 }, +#endif { .trip_name = "cpu_alert1", .cdev_name = "fan0", @@ -131,13 +133,15 @@ static const struct thermal_zone_map_s g_dummy_maps[] = .high = THERMAL_NO_LIMIT, .weight = 20 }, +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ { .trip_name = "cpu_alert0", - .cdev_name = "cpufreq", + .cdev_name = CONFIG_THERMAL_CDEV_DEVFREQ_NAME, .low = THERMAL_NO_LIMIT, .high = 2, .weight = 20 }, +#endif { .trip_name = "cpu_alert0", .cdev_name = "passive_dev", @@ -188,30 +192,40 @@ static struct dummy_cooling_device_s g_dummy_fan0_data = .max_state = 16, }; -/* Cooling Device - cpufreq */ +/* Cooling Device - devfreq */ -#ifdef CONFIG_THERMAL_DUMMY_CPUFREQ -static const struct cpufreq_frequency_table g_dummy_cpufreq_table[] = +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ +static const uint32_t g_dummy_devfreq_table[] = { - {100}, - {300}, - {500}, - {700}, - {900}, - {CPUFREQ_TABLE_END}, + 100, + 300, + 500, + 700, + 900, + DEVFREQ_ENTRY_END, }; -static struct dummy_cpufreq_driver_s g_dummy_cpufreq_driver = +static struct dummy_devfreq_driver_s g_dummy_devfreq_driver = { .driver = { - dummy_cpufreq_get_table, - dummy_cpufreq_target_index, - dummy_cpufreq_get_frequency, - dummy_cpufreq_suspend, - dummy_cpufreq_resume, + /* A ceiling from the cooling device must win over any floor, which + * is what a device defending a thermal budget wants. + */ + + .conflict_policy = DEVFREQ_CONFLICT_PREFER_LOW, + .get_table = dummy_devfreq_get_table, + .target_index = dummy_devfreq_target_index, + .get_frequency = dummy_devfreq_get_frequency, + .suspend = dummy_devfreq_suspend, + .resume = dummy_devfreq_resume, }, - .table = g_dummy_cpufreq_table, - .table_len = nitems(g_dummy_cpufreq_table), + .table = g_dummy_devfreq_table, + + /* Frequencies only. target_index is never called with the terminator's + * own index, so it is not counted here. + */ + + .table_len = nitems(g_dummy_devfreq_table) - 1, }; #else static struct dummy_cooling_device_s g_dummy_passive = @@ -219,7 +233,7 @@ static struct dummy_cooling_device_s g_dummy_passive = .cur_state = 0, .max_state = 1, }; -#endif /* CONFIG_THERMAL_DUMMY_CPUFREQ */ +#endif /* CONFIG_THERMAL_DUMMY_DEVFREQ */ /**************************************************************************** * Private Functions @@ -291,46 +305,46 @@ static int dummy_zdev_set_trips(FAR struct thermal_zone_device_s *zdev, return OK; } -#ifdef CONFIG_THERMAL_DUMMY_CPUFREQ -static FAR const struct cpufreq_frequency_table *dummy_cpufreq_get_table( - FAR struct cpufreq_policy *policy) +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ +static FAR const uint32_t *dummy_devfreq_get_table( + FAR struct devfreq_s *devfreq) { - FAR struct dummy_cpufreq_driver_s *driver = - (FAR struct dummy_cpufreq_driver_s *)policy->driver; + FAR struct dummy_devfreq_driver_s *driver = + (FAR struct dummy_devfreq_driver_s *)devfreq->driver; return driver->table; } -static int dummy_cpufreq_target_index(FAR struct cpufreq_policy *policy, - unsigned int index) +static int dummy_devfreq_target_index(FAR struct devfreq_s *devfreq, + size_t index) { - FAR struct dummy_cpufreq_driver_s *driver = - (FAR struct dummy_cpufreq_driver_s *)policy->driver; + FAR struct dummy_devfreq_driver_s *driver = + (FAR struct dummy_devfreq_driver_s *)devfreq->driver; DEBUGASSERT(index < driver->table_len); - driver->current.frequency = driver->table[index].frequency; + driver->current = driver->table[index]; return 0; } -static int dummy_cpufreq_get_frequency(FAR struct cpufreq_policy *policy) +static uint32_t dummy_devfreq_get_frequency(FAR struct devfreq_s *devfreq) { - FAR struct dummy_cpufreq_driver_s *driver = - (FAR struct dummy_cpufreq_driver_s *)policy->driver; + FAR struct dummy_devfreq_driver_s *driver = + (FAR struct dummy_devfreq_driver_s *)devfreq->driver; - return driver->current.frequency; + return driver->current; } -static int dummy_cpufreq_suspend(FAR struct cpufreq_policy *driver) +static int dummy_devfreq_suspend(FAR struct devfreq_s *devfreq) { return 0; } -static int dummy_cpufreq_resume(FAR struct cpufreq_policy *driver) +static int dummy_devfreq_resume(FAR struct devfreq_s *devfreq) { return 0; } -#endif /* CONFIG_THERMAL_DUMMY_CPUFREQ */ +#endif /* CONFIG_THERMAL_DUMMY_DEVFREQ */ int thermal_dummy_init(void) { @@ -338,14 +352,17 @@ int thermal_dummy_init(void) FAR struct thermal_zone_device_s *zdev; int ret = OK; - /* Driver - CPUFreq */ + /* Driver - devfreq. The thermal core registers the cooling device over + * it once this returns, so it has to exist by then. + */ -#ifdef CONFIG_THERMAL_DUMMY_CPUFREQ - ret = cpufreq_init(&g_dummy_cpufreq_driver.driver); - if (ret < 0) +#ifdef CONFIG_THERMAL_DUMMY_DEVFREQ + if (devfreq_register(CONFIG_THERMAL_CDEV_DEVFREQ_NAME, + devfreq_performance(), + &g_dummy_devfreq_driver.driver, NULL) == NULL) { - therr("Dummy cpufreq driver init failed!\n"); - return ret; + therr("Dummy devfreq driver init failed!\n"); + return -ENOTSUP; } #else cdev = thermal_cooling_device_register("passive_dev", &g_dummy_passive, @@ -355,7 +372,7 @@ int thermal_dummy_init(void) therr("Register cooling device passive_dev failed!\n"); return -ENOTSUP; } -#endif /* CONFIG_THERMAL_DUMMY_CPUFREQ */ +#endif /* CONFIG_THERMAL_DUMMY_DEVFREQ */ /* Cooling Device */
