summaryrefslogtreecommitdiff
path: root/components/drivers/include
diff options
context:
space:
mode:
Diffstat (limited to 'components/drivers/include')
-rw-r--r--components/drivers/include/drivers/dvfs.h353
-rw-r--r--components/drivers/include/drivers/thermal.h4
-rw-r--r--components/drivers/include/rtdevice.h4
3 files changed, 361 insertions, 0 deletions
diff --git a/components/drivers/include/drivers/dvfs.h b/components/drivers/include/drivers/dvfs.h
new file mode 100644
index 0000000000..0b22446219
--- /dev/null
+++ b/components/drivers/include/drivers/dvfs.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-21 GuEe-GUI first version
+ */
+
+#ifndef __DVFS_H__
+#define __DVFS_H__
+
+#include <rtthread.h>
+#include <drivers/ofw.h>
+#include <drivers/misc.h>
+#include <drivers/core/dm.h>
+
+#include <ref.h>
+#include <bitmap.h>
+
+enum
+{
+ /* Run the device at the maximum frequency */
+ RT_DVFS_GOVERNOR_TYPE_PERFORMANCE = 0,
+ /* Run the device at the minimum frequency */
+ RT_DVFS_GOVERNOR_TYPE_POWERSAVE,
+ /* Run the device at user specified frequencies */
+ RT_DVFS_GOVERNOR_TYPE_FREEDOM,
+ /*
+ * Scales the frequency dynamically according to current load.
+ * Jumps to the highest frequency and then possibly back off as
+ * the idle time increases.
+ */
+ RT_DVFS_GOVERNOR_TYPE_ONDEMAND,
+ /*
+ * Scales the frequency dynamically according to current load.
+ * Scales the frequency more gradually than ondemand.
+ */
+ RT_DVFS_GOVERNOR_TYPE_CONSERVATIVE,
+ /* Scheduler-driven CPU frequency selection */
+ RT_DVFS_GOVERNOR_TYPE_SCHEDUTIL,
+
+ /* Custom for user start */
+ RT_DVFS_GOVERNOR_TYPE_CUSTOM,
+};
+
+struct rt_dvfs_opp;
+struct rt_dvfs_opp_table;
+struct rt_dvfs_governor;
+struct rt_dvfs_scaling_ops;
+struct rt_dvfs_event_ops;
+struct rt_dvfs_idle_ops;
+struct rt_dvfs_idle_status;
+struct rt_dvfs_idle_status_table;
+
+/* CPU load statistics */
+struct rt_dvfs_cpu_load
+{
+ rt_uint64_t total_tick; /* Total ticks in sampling period */
+ rt_uint64_t idle_tick; /* Idle ticks in sampling period */
+ rt_uint32_t load_percentage; /* Load percentage (0-100) */
+ rt_tick_t last_update; /* Last update tick */
+};
+
+/* Governor parameters (Linux-like defaults) */
+struct rt_dvfs_governor_params
+{
+ rt_uint32_t sampling_rate_ms; /* Sampling interval in ms, default 1000 */
+ rt_uint32_t up_threshold; /* Up threshold percentage, default 80 */
+ rt_uint32_t down_differential; /* Down differential percentage, default 20 */
+ rt_uint32_t sampling_down_factor; /* Sampling down factor for conservative, default 1 */
+ rt_uint32_t freq_step; /* Frequency step percentage for conservative, default 5 */
+ rt_bool_t ignore_nice_load; /* Ignore nice tasks, default RT_FALSE */
+ rt_uint32_t powersave_bias; /* Powersave bias percentage, default 0 */
+};
+
+struct rt_dvfs_scaling
+{
+ struct rt_device *dev;
+
+ struct rt_clk *clk;
+ struct rt_regulator *supply;
+
+ const struct rt_dvfs_scaling_ops *ops;
+
+ /* Hz */
+ rt_ubase_t min_freq;
+ rt_ubase_t max_freq;
+ rt_ubase_t cur_freq;
+ rt_ubase_t suspend_freq;
+
+ /* NS */
+ rt_uint32_t retry_delay;
+ rt_uint32_t transition_latency;
+
+ struct rt_dvfs_opp_table *opp_table;
+
+ struct rt_dvfs_governor *gov;
+ struct rt_dvfs_governor_params gov_params;
+ void *gov_data;
+
+ /* CPU load statistics */
+ struct rt_dvfs_cpu_load cpu_load;
+ void (*load_update)(struct rt_dvfs_scaling *dvfs);
+
+ void *priv;
+};
+
+struct rt_dvfs_scaling_ops
+{
+ rt_err_t (*suspend)(struct rt_dvfs_scaling *dvfs);
+ rt_err_t (*resume)(struct rt_dvfs_scaling *dvfs);
+ rt_err_t (*set_opp)(struct rt_dvfs_scaling *dvfs, struct rt_dvfs_opp *opp);
+
+ rt_err_t (*parse_opp)(struct rt_dvfs_scaling *dvfs, struct rt_dvfs_opp *opp, void *fw_np);
+};
+
+/*
+ * DVFS device hierarchy:
+ * rt_dvfs_scaling - internal core (OPP / governor / frequency)
+ * rt_dvfs_devfreq - DVFS device (clk/regulator + optional event)
+ * rt_dvfs_cpufreq - CPU DVFS, extends devfreq (idle-hook load)
+ */
+struct rt_dvfs_devfreq
+{
+ struct rt_dvfs_scaling parent;
+
+ struct rt_dvfs_event *ev;
+};
+
+struct rt_dvfs_cpufreq
+{
+ struct rt_dvfs_devfreq parent;
+
+ int master_cpu;
+ RT_BITMAP_DECLARE(cpus_map, RT_CPUS_NR);
+};
+
+rt_inline struct rt_dvfs_scaling *rt_dvfs_devfreq_to_scaling(struct rt_dvfs_devfreq *devfreq)
+{
+ return &devfreq->parent;
+}
+
+rt_inline struct rt_dvfs_devfreq *rt_dvfs_cpufreq_to_devfreq(struct rt_dvfs_cpufreq *cpufreq)
+{
+ return &cpufreq->parent;
+}
+
+rt_inline struct rt_dvfs_scaling *rt_dvfs_cpufreq_to_scaling(struct rt_dvfs_cpufreq *cpufreq)
+{
+ return &cpufreq->parent.parent;
+}
+
+extern struct rt_dvfs_scaling_ops rt_dvfs_devfreq_ops;
+
+struct rt_dvfs_idle
+{
+ struct rt_device *dev;
+
+ rt_uint32_t ref_count;
+ rt_uint32_t entry_count;
+
+ const struct rt_dvfs_idle_ops *ops;
+
+ struct rt_dvfs_idle_status_table *status_table;
+
+ void *priv;
+};
+
+struct rt_dvfs_idle_ops
+{
+ rt_err_t (*entry)(struct rt_dvfs_idle *idle, struct rt_dvfs_idle_status *status);
+ rt_err_t (*exit)(struct rt_dvfs_idle *idle, struct rt_dvfs_idle_status *status);
+
+ rt_bool_t (*timer_can_stop)(struct rt_dvfs_idle *idle);
+};
+
+struct rt_dvfs_idle_status
+{
+ rt_list_t list;
+
+ rt_uint32_t entry_latency_us;
+ rt_uint32_t exit_latency_us;
+ rt_uint32_t min_residency_us;
+
+ rt_bool_t timer_stop;
+
+ void *priv;
+};
+
+struct rt_dvfs_idle_status_table
+{
+ rt_list_t status_nodes;
+ struct rt_dvfs_idle_status *current_status;
+
+ void *priv;
+};
+
+struct rt_dvfs_opp
+{
+ rt_list_t list;
+
+ rt_ubase_t freq; /* Hz */
+ rt_ubase_t uvolt; /* uV */
+ rt_ubase_t power; /* mW */
+ rt_bool_t available;
+
+ void *priv;
+};
+
+struct rt_dvfs_opp_table
+{
+ rt_bool_t share;
+
+ rt_list_t opp_nodes;
+ struct rt_dvfs_opp *current_opp;
+
+ void *priv;
+};
+
+struct rt_dvfs_event_data
+{
+ /* Load count of dvfs-event device for the given period */
+ rt_ubase_t load_count;
+ /* Total count of dvfs-event device for the given period */
+ rt_ubase_t total_count;
+};
+
+struct rt_dvfs_event
+{
+ struct rt_device *dev;
+
+ const struct rt_dvfs_event_ops *ops;
+
+ rt_uint32_t enable_count;
+ struct rt_spinlock lock;
+
+ void *priv;
+};
+
+struct rt_dvfs_event_ops
+{
+ rt_err_t (*ready)(struct rt_dvfs_event *ev);
+ rt_err_t (*read)(struct rt_dvfs_event *ev, struct rt_dvfs_event_data *evd);
+
+ rt_err_t (*enable)(struct rt_dvfs_event *ev);
+ rt_err_t (*disable)(struct rt_dvfs_event *ev);
+ rt_err_t (*reset)(struct rt_dvfs_event *ev);
+};
+
+struct rt_dvfs_governor
+{
+ rt_list_t list;
+ char name[16];
+
+ rt_uint32_t type;
+ struct rt_ref ref;
+
+ rt_err_t (*start)(struct rt_dvfs_scaling *dvfs);
+ rt_err_t (*stop)(struct rt_dvfs_scaling *dvfs);
+ rt_err_t (*suspend)(struct rt_dvfs_scaling *dvfs);
+ rt_err_t (*resume)(struct rt_dvfs_scaling *dvfs);
+ rt_err_t (*set_interval)(struct rt_dvfs_scaling *dvfs, rt_uint32_t interval_ms);
+ rt_err_t (*set_frequency)(struct rt_dvfs_scaling *dvfs, rt_ubase_t *out_freq);
+};
+
+/* DVFS */
+rt_err_t rt_dvfs_scaling_register(struct rt_dvfs_scaling *dvfs);
+rt_err_t rt_dvfs_scaling_unregister(struct rt_dvfs_scaling *dvfs);
+
+void rt_dvfs_scaling_enter(struct rt_dvfs_scaling *dvfs);
+void rt_dvfs_scaling_leave(struct rt_dvfs_scaling *dvfs);
+
+void rt_dvfs_ns_sleep(rt_uint32_t ns);
+
+rt_err_t rt_dvfs_scaling_suspend(struct rt_dvfs_scaling *dvfs);
+rt_err_t rt_dvfs_scaling_resume(struct rt_dvfs_scaling *dvfs);
+rt_err_t rt_dvfs_scaling_set_governor(struct rt_dvfs_scaling *dvfs, rt_uint32_t governor);
+rt_err_t rt_dvfs_scaling_set_frequency(struct rt_dvfs_scaling *dvfs, rt_ubase_t frequency);
+rt_err_t rt_dvfs_scaling_apply_opp(struct rt_dvfs_scaling *dvfs, struct rt_dvfs_opp *opp);
+
+/* OPP */
+struct rt_dvfs_opp *rt_dvfs_scaling_add_opp(struct rt_dvfs_scaling *dvfs, rt_ubase_t freq, rt_ubase_t uvolt);
+rt_err_t rt_dvfs_scaling_remove_opp(struct rt_dvfs_scaling *dvfs, rt_ubase_t freq);
+rt_err_t rt_dvfs_scaling_remove_opp_all(struct rt_dvfs_scaling *dvfs);
+
+rt_err_t rt_dvfs_scaling_enable_opp(struct rt_dvfs_scaling *dvfs, rt_ubase_t freq);
+rt_err_t rt_dvfs_scaling_disable_opp(struct rt_dvfs_scaling *dvfs, rt_ubase_t freq);
+
+struct rt_dvfs_opp *rt_dvfs_scaling_find_opp(struct rt_dvfs_scaling *dvfs, rt_ubase_t freq);
+struct rt_dvfs_opp *rt_dvfs_scaling_find_ceil_opp(struct rt_dvfs_scaling *dvfs, rt_ubase_t freq);
+struct rt_dvfs_opp *rt_dvfs_scaling_find_floor_opp(struct rt_dvfs_scaling *dvfs, rt_ubase_t freq);
+
+/* CPU */
+rt_err_t rt_dvfs_cpufreq_register(struct rt_dvfs_cpufreq *cpufreq);
+rt_err_t rt_dvfs_cpufreq_unregister(struct rt_dvfs_cpufreq *cpufreq);
+
+rt_err_t rt_dvfs_devfreq_register(struct rt_dvfs_devfreq *devfreq);
+rt_err_t rt_dvfs_devfreq_unregister(struct rt_dvfs_devfreq *devfreq);
+
+/* CPU-Idle */
+rt_err_t rt_dvfs_idle_register(struct rt_dvfs_idle *idle);
+rt_err_t rt_dvfs_idle_unregister(struct rt_dvfs_idle *idle);
+
+rt_err_t rt_dvfs_idle_add_status(struct rt_dvfs_idle *idle, struct rt_dvfs_idle_status *status);
+void rt_dvfs_idle_remove_status(struct rt_dvfs_idle *idle, struct rt_dvfs_idle_status *status);
+void rt_dvfs_idle_remove_status_all(struct rt_dvfs_idle *idle,
+ void (*release)(struct rt_dvfs_idle *, struct rt_dvfs_idle_status *));
+
+rt_err_t rt_dvfs_idle_entry(struct rt_dvfs_idle *idle);
+rt_err_t rt_dvfs_idle_exit(struct rt_dvfs_idle *idle);
+
+struct rt_dvfs_idle *rt_dvfs_idle_get(struct rt_device *dev);
+void rt_dvfs_idle_put(struct rt_dvfs_idle *idle);
+
+/* Event */
+rt_err_t rt_dvfs_event_register(struct rt_dvfs_event *ev);
+rt_err_t rt_dvfs_event_unregister(struct rt_dvfs_event *ev);
+
+rt_err_t rt_dvfs_event_ready(struct rt_dvfs_event *ev);
+rt_err_t rt_dvfs_event_read(struct rt_dvfs_event *ev, struct rt_dvfs_event_data *evd);
+rt_err_t rt_dvfs_event_enable(struct rt_dvfs_event *ev);
+rt_err_t rt_dvfs_event_disable(struct rt_dvfs_event *ev);
+rt_bool_t rt_dvfs_event_is_enabled(struct rt_dvfs_event *ev);
+rt_err_t rt_dvfs_event_reset(struct rt_dvfs_event *ev);
+
+struct rt_dvfs_event *rt_dvfs_event_get(struct rt_device *dev, const char *name, int index);
+void rt_dvfs_event_put(struct rt_dvfs_event *ev);
+
+/* Governor */
+rt_err_t rt_dvfs_governor_register(struct rt_dvfs_governor *gov);
+rt_err_t rt_dvfs_governor_unregister(struct rt_dvfs_governor *gov);
+struct rt_dvfs_governor *rt_dvfs_governor_get(rt_uint32_t governor);
+struct rt_dvfs_governor *rt_dvfs_governor_get_by_name(const char *name);
+void rt_dvfs_governor_put(struct rt_dvfs_governor *gov);
+
+rt_err_t rt_dvfs_governor_set_params(struct rt_dvfs_scaling *dvfs, struct rt_dvfs_governor_params *params);
+rt_err_t rt_dvfs_governor_get_params(struct rt_dvfs_scaling *dvfs, struct rt_dvfs_governor_params *params);
+
+/* Load */
+void rt_dvfs_load_update(struct rt_dvfs_scaling *dvfs);
+void rt_dvfs_cpu_load_update(struct rt_dvfs_cpu_load *load);
+rt_uint32_t rt_dvfs_cpu_load_get(struct rt_dvfs_cpu_load *load);
+
+/* PM */
+struct rt_device_pm;
+
+rt_err_t rt_dvfs_scaling_pm_suspend(struct rt_device_pm *device_pm, rt_uint8_t mode);
+rt_err_t rt_dvfs_scaling_pm_resume(struct rt_device_pm *device_pm, rt_uint8_t mode);
+rt_err_t rt_dvfs_scaling_pm_frequency_change(struct rt_device_pm *device_pm, rt_uint8_t mode);
+
+#endif /* __DVFS_H__ */
diff --git a/components/drivers/include/drivers/thermal.h b/components/drivers/include/drivers/thermal.h
index 0770c5c453..c7c2244582 100644
--- a/components/drivers/include/drivers/thermal.h
+++ b/components/drivers/include/drivers/thermal.h
@@ -59,6 +59,10 @@ struct rt_thermal_cooling_cell
struct rt_thermal_cooling_device *cooling_devices;
rt_uint32_t level_range[2];
+
+#ifdef RT_USING_OFW
+ struct rt_ofw_node *cooling_np;
+#endif
};
struct rt_thermal_cooling_map
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index 0c83137087..b416b5e928 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -153,6 +153,10 @@ extern "C" {
#include "drivers/hwcache.h"
#endif /* RT_USING_HWCACHE */
+#ifdef RT_USING_DVFS
+#include "drivers/dvfs.h"
+#endif /* RT_USING_DVFS */
+
#ifdef RT_USING_NVMEM
#include "drivers/nvmem.h"
#endif /* RT_USING_NVMEM */