| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Generic OPP Interface |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * Nishanth Menon |
|---|
| 6 | 7 | * Romit Dasgupta |
|---|
| 7 | 8 | * Kevin Hilman |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 10 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 11 | | - * published by the Free Software Foundation. |
|---|
| 12 | 9 | */ |
|---|
| 13 | 10 | |
|---|
| 14 | 11 | #ifndef __DRIVER_OPP_H__ |
|---|
| 15 | 12 | #define __DRIVER_OPP_H__ |
|---|
| 16 | 13 | |
|---|
| 17 | 14 | #include <linux/device.h> |
|---|
| 15 | +#include <linux/interconnect.h> |
|---|
| 18 | 16 | #include <linux/kernel.h> |
|---|
| 19 | 17 | #include <linux/kref.h> |
|---|
| 20 | 18 | #include <linux/list.h> |
|---|
| .. | .. |
|---|
| 60 | 58 | * @suspend: true if suspend OPP |
|---|
| 61 | 59 | * @pstate: Device's power domain's performance state. |
|---|
| 62 | 60 | * @rate: Frequency in hertz |
|---|
| 61 | + * @level: Performance level |
|---|
| 63 | 62 | * @supplies: Power supplies voltage/current values |
|---|
| 63 | + * @bandwidth: Interconnect bandwidth values |
|---|
| 64 | 64 | * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's |
|---|
| 65 | 65 | * frequency from any other OPP's frequency. |
|---|
| 66 | + * @required_opps: List of OPPs that are required by this OPP. |
|---|
| 66 | 67 | * @opp_table: points back to the opp_table struct this opp belongs to |
|---|
| 67 | 68 | * @np: OPP's device node. |
|---|
| 68 | 69 | * @dentry: debugfs dentry pointer (per opp) |
|---|
| .. | .. |
|---|
| 79 | 80 | bool suspend; |
|---|
| 80 | 81 | unsigned int pstate; |
|---|
| 81 | 82 | unsigned long rate; |
|---|
| 83 | + unsigned int level; |
|---|
| 82 | 84 | |
|---|
| 83 | 85 | struct dev_pm_opp_supply *supplies; |
|---|
| 86 | + struct dev_pm_opp_icc_bw *bandwidth; |
|---|
| 84 | 87 | |
|---|
| 85 | 88 | unsigned long clock_latency_ns; |
|---|
| 86 | 89 | |
|---|
| 90 | + struct dev_pm_opp **required_opps; |
|---|
| 87 | 91 | struct opp_table *opp_table; |
|---|
| 88 | 92 | |
|---|
| 89 | 93 | struct device_node *np; |
|---|
| .. | .. |
|---|
| 126 | 130 | * @dev_list: list of devices that share these OPPs |
|---|
| 127 | 131 | * @opp_list: table of opps |
|---|
| 128 | 132 | * @kref: for reference count of the table. |
|---|
| 129 | | - * @lock: mutex protecting the opp_list. |
|---|
| 133 | + * @lock: mutex protecting the opp_list and dev_list. |
|---|
| 130 | 134 | * @np: struct device_node pointer for opp's DT node. |
|---|
| 131 | 135 | * @clock_latency_ns_max: Max clock latency in nanoseconds. |
|---|
| 136 | + * @parsed_static_opps: Count of devices for which OPPs are initialized from DT. |
|---|
| 132 | 137 | * @shared_opp: OPP is shared between multiple devices. |
|---|
| 133 | 138 | * @suspend_opp: Pointer to OPP to be used during device suspend. |
|---|
| 139 | + * @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers. |
|---|
| 140 | + * @genpd_virt_devs: List of virtual devices for multiple genpd support. |
|---|
| 141 | + * @required_opp_tables: List of device OPP tables that are required by OPPs in |
|---|
| 142 | + * this table. |
|---|
| 143 | + * @required_opp_count: Number of required devices. |
|---|
| 134 | 144 | * @supported_hw: Array of version number to support. |
|---|
| 135 | 145 | * @supported_hw_count: Number of elements in supported_hw array. |
|---|
| 136 | 146 | * @prop_name: A name to postfix to many DT properties, while parsing them. |
|---|
| .. | .. |
|---|
| 139 | 149 | * @regulator_count: Number of power supply regulators. Its value can be -1 |
|---|
| 140 | 150 | * (uninitialized), 0 (no opp-microvolt property) or > 0 (has opp-microvolt |
|---|
| 141 | 151 | * property). |
|---|
| 152 | + * @paths: Interconnect path handles |
|---|
| 153 | + * @path_count: Number of interconnect paths |
|---|
| 154 | + * @enabled: Set to true if the device's resources are enabled/configured. |
|---|
| 142 | 155 | * @genpd_performance_state: Device's power domain support performance state. |
|---|
| 156 | + * @is_genpd: Marks if the OPP table belongs to a genpd. |
|---|
| 143 | 157 | * @set_opp: Platform specific set_opp callback |
|---|
| 144 | 158 | * @set_opp_data: Data to be passed to set_opp callback |
|---|
| 145 | 159 | * @dentry: debugfs dentry pointer of the real device directory (not links). |
|---|
| .. | .. |
|---|
| 166 | 180 | /* For backward compatibility with v1 bindings */ |
|---|
| 167 | 181 | unsigned int voltage_tolerance_v1; |
|---|
| 168 | 182 | |
|---|
| 183 | + unsigned int parsed_static_opps; |
|---|
| 169 | 184 | enum opp_table_access shared_opp; |
|---|
| 170 | 185 | struct dev_pm_opp *suspend_opp; |
|---|
| 186 | + |
|---|
| 187 | + struct mutex genpd_virt_dev_lock; |
|---|
| 188 | + struct device **genpd_virt_devs; |
|---|
| 189 | + struct opp_table **required_opp_tables; |
|---|
| 190 | + unsigned int required_opp_count; |
|---|
| 171 | 191 | |
|---|
| 172 | 192 | unsigned int *supported_hw; |
|---|
| 173 | 193 | unsigned int supported_hw_count; |
|---|
| .. | .. |
|---|
| 175 | 195 | struct clk *clk; |
|---|
| 176 | 196 | struct regulator **regulators; |
|---|
| 177 | 197 | int regulator_count; |
|---|
| 198 | + struct icc_path **paths; |
|---|
| 199 | + unsigned int path_count; |
|---|
| 200 | + bool enabled; |
|---|
| 178 | 201 | bool genpd_performance_state; |
|---|
| 202 | + bool is_genpd; |
|---|
| 179 | 203 | |
|---|
| 180 | 204 | int (*set_opp)(struct dev_pm_set_opp_data *data); |
|---|
| 181 | 205 | struct dev_pm_set_opp_data *set_opp_data; |
|---|
| .. | .. |
|---|
| 188 | 212 | |
|---|
| 189 | 213 | /* Routines internal to opp core */ |
|---|
| 190 | 214 | void dev_pm_opp_get(struct dev_pm_opp *opp); |
|---|
| 215 | +bool _opp_remove_all_static(struct opp_table *opp_table); |
|---|
| 191 | 216 | void _get_opp_table_kref(struct opp_table *opp_table); |
|---|
| 192 | 217 | int _get_opp_count(struct opp_table *opp_table); |
|---|
| 193 | 218 | struct opp_table *_find_opp_table(struct device *dev); |
|---|
| 194 | 219 | struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table); |
|---|
| 195 | | -void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev, bool remove_all); |
|---|
| 196 | | -void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all); |
|---|
| 197 | 220 | struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table); |
|---|
| 198 | 221 | void _opp_free(struct dev_pm_opp *opp); |
|---|
| 222 | +int _opp_compare_key(struct dev_pm_opp *opp1, struct dev_pm_opp *opp2); |
|---|
| 199 | 223 | int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table, bool rate_not_available); |
|---|
| 200 | 224 | int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic); |
|---|
| 201 | | -void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of); |
|---|
| 225 | +void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu); |
|---|
| 202 | 226 | struct opp_table *_add_opp_table(struct device *dev); |
|---|
| 227 | +void _put_opp_list_kref(struct opp_table *opp_table); |
|---|
| 203 | 228 | |
|---|
| 204 | 229 | #ifdef CONFIG_OF |
|---|
| 205 | | -void _of_init_opp_table(struct opp_table *opp_table, struct device *dev); |
|---|
| 230 | +void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index); |
|---|
| 231 | +void _of_clear_opp_table(struct opp_table *opp_table); |
|---|
| 232 | +struct opp_table *_managed_opp(struct device *dev, int index); |
|---|
| 233 | +void _of_opp_free_required_opps(struct opp_table *opp_table, |
|---|
| 234 | + struct dev_pm_opp *opp); |
|---|
| 206 | 235 | #else |
|---|
| 207 | | -static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev) {} |
|---|
| 236 | +static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {} |
|---|
| 237 | +static inline void _of_clear_opp_table(struct opp_table *opp_table) {} |
|---|
| 238 | +static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; } |
|---|
| 239 | +static inline void _of_opp_free_required_opps(struct opp_table *opp_table, |
|---|
| 240 | + struct dev_pm_opp *opp) {} |
|---|
| 208 | 241 | #endif |
|---|
| 209 | 242 | |
|---|
| 210 | 243 | #ifdef CONFIG_DEBUG_FS |
|---|
| 211 | 244 | void opp_debug_remove_one(struct dev_pm_opp *opp); |
|---|
| 212 | | -int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table); |
|---|
| 213 | | -int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table); |
|---|
| 245 | +void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table); |
|---|
| 246 | +void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table); |
|---|
| 214 | 247 | void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table); |
|---|
| 215 | 248 | #else |
|---|
| 216 | 249 | static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {} |
|---|
| 217 | 250 | |
|---|
| 218 | | -static inline int opp_debug_create_one(struct dev_pm_opp *opp, |
|---|
| 219 | | - struct opp_table *opp_table) |
|---|
| 220 | | -{ return 0; } |
|---|
| 221 | | -static inline int opp_debug_register(struct opp_device *opp_dev, |
|---|
| 222 | | - struct opp_table *opp_table) |
|---|
| 223 | | -{ return 0; } |
|---|
| 251 | +static inline void opp_debug_create_one(struct dev_pm_opp *opp, |
|---|
| 252 | + struct opp_table *opp_table) { } |
|---|
| 253 | + |
|---|
| 254 | +static inline void opp_debug_register(struct opp_device *opp_dev, |
|---|
| 255 | + struct opp_table *opp_table) { } |
|---|
| 224 | 256 | |
|---|
| 225 | 257 | static inline void opp_debug_unregister(struct opp_device *opp_dev, |
|---|
| 226 | 258 | struct opp_table *opp_table) |
|---|