1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Generic OPP Interface |
4 | * |
5 | * Copyright (C) 2009-2010 Texas Instruments Incorporated. |
6 | * Nishanth Menon |
7 | * Romit Dasgupta |
8 | * Kevin Hilman |
9 | */ |
10 | |
11 | #ifndef __DRIVER_OPP_H__ |
12 | #define __DRIVER_OPP_H__ |
13 | |
14 | #include <linux/device.h> |
15 | #include <linux/interconnect.h> |
16 | #include <linux/kernel.h> |
17 | #include <linux/kref.h> |
18 | #include <linux/list.h> |
19 | #include <linux/limits.h> |
20 | #include <linux/pm_opp.h> |
21 | #include <linux/notifier.h> |
22 | |
23 | struct clk; |
24 | struct regulator; |
25 | |
26 | /* Lock to allow exclusive modification to the device and opp lists */ |
27 | extern struct mutex opp_table_lock; |
28 | |
29 | extern struct list_head opp_tables; |
30 | |
31 | /* OPP Config flags */ |
32 | #define OPP_CONFIG_CLK BIT(0) |
33 | #define OPP_CONFIG_REGULATOR BIT(1) |
34 | #define OPP_CONFIG_REGULATOR_HELPER BIT(2) |
35 | #define OPP_CONFIG_PROP_NAME BIT(3) |
36 | #define OPP_CONFIG_SUPPORTED_HW BIT(4) |
37 | #define OPP_CONFIG_GENPD BIT(5) |
38 | #define OPP_CONFIG_REQUIRED_DEVS BIT(6) |
39 | |
40 | /** |
41 | * struct opp_config_data - data for set config operations |
42 | * @opp_table: OPP table |
43 | * @flags: OPP config flags |
44 | * |
45 | * This structure stores the OPP config information for each OPP table |
46 | * configuration by the callers. |
47 | */ |
48 | struct opp_config_data { |
49 | struct opp_table *opp_table; |
50 | unsigned int flags; |
51 | }; |
52 | |
53 | /** |
54 | * struct dev_pm_opp_icc_bw - Interconnect bandwidth values |
55 | * @avg: Average bandwidth corresponding to this OPP (in icc units) |
56 | * @peak: Peak bandwidth corresponding to this OPP (in icc units) |
57 | * |
58 | * This structure stores the bandwidth values for a single interconnect path. |
59 | */ |
60 | struct dev_pm_opp_icc_bw { |
61 | u32 avg; |
62 | u32 peak; |
63 | }; |
64 | |
65 | /* |
66 | * Internal data structure organization with the OPP layer library is as |
67 | * follows: |
68 | * opp_tables (root) |
69 | * |- device 1 (represents voltage domain 1) |
70 | * | |- opp 1 (availability, freq, voltage) |
71 | * | |- opp 2 .. |
72 | * ... ... |
73 | * | `- opp n .. |
74 | * |- device 2 (represents the next voltage domain) |
75 | * ... |
76 | * `- device m (represents mth voltage domain) |
77 | * device 1, 2.. are represented by opp_table structure while each opp |
78 | * is represented by the opp structure. |
79 | */ |
80 | |
81 | /** |
82 | * struct dev_pm_opp - Generic OPP description structure |
83 | * @node: opp table node. The nodes are maintained throughout the lifetime |
84 | * of boot. It is expected only an optimal set of OPPs are |
85 | * added to the library by the SoC framework. |
86 | * IMPORTANT: the opp nodes should be maintained in increasing |
87 | * order. |
88 | * @kref: for reference count of the OPP. |
89 | * @available: true/false - marks if this OPP as available or not |
90 | * @dynamic: not-created from static DT entries. |
91 | * @turbo: true if turbo (boost) OPP |
92 | * @suspend: true if suspend OPP |
93 | * @removed: flag indicating that OPP's reference is dropped by OPP core. |
94 | * @rates: Frequencies in hertz |
95 | * @level: Performance level |
96 | * @supplies: Power supplies voltage/current values |
97 | * @bandwidth: Interconnect bandwidth values |
98 | * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's |
99 | * frequency from any other OPP's frequency. |
100 | * @required_opps: List of OPPs that are required by this OPP. |
101 | * @opp_table: points back to the opp_table struct this opp belongs to |
102 | * @np: OPP's device node. |
103 | * @dentry: debugfs dentry pointer (per opp) |
104 | * |
105 | * This structure stores the OPP information for a given device. |
106 | */ |
107 | struct dev_pm_opp { |
108 | struct list_head node; |
109 | struct kref kref; |
110 | |
111 | bool available; |
112 | bool dynamic; |
113 | bool turbo; |
114 | bool suspend; |
115 | bool removed; |
116 | unsigned long *rates; |
117 | unsigned int level; |
118 | |
119 | struct dev_pm_opp_supply *supplies; |
120 | struct dev_pm_opp_icc_bw *bandwidth; |
121 | |
122 | unsigned long clock_latency_ns; |
123 | |
124 | struct dev_pm_opp **required_opps; |
125 | struct opp_table *opp_table; |
126 | |
127 | struct device_node *np; |
128 | |
129 | #ifdef CONFIG_DEBUG_FS |
130 | struct dentry *dentry; |
131 | const char *of_name; |
132 | #endif |
133 | }; |
134 | |
135 | /** |
136 | * struct opp_device - devices managed by 'struct opp_table' |
137 | * @node: list node |
138 | * @dev: device to which the struct object belongs |
139 | * @dentry: debugfs dentry pointer (per device) |
140 | * |
141 | * This is an internal data structure maintaining the devices that are managed |
142 | * by 'struct opp_table'. |
143 | */ |
144 | struct opp_device { |
145 | struct list_head node; |
146 | const struct device *dev; |
147 | |
148 | #ifdef CONFIG_DEBUG_FS |
149 | struct dentry *dentry; |
150 | #endif |
151 | }; |
152 | |
153 | enum opp_table_access { |
154 | OPP_TABLE_ACCESS_UNKNOWN = 0, |
155 | OPP_TABLE_ACCESS_EXCLUSIVE = 1, |
156 | OPP_TABLE_ACCESS_SHARED = 2, |
157 | }; |
158 | |
159 | /** |
160 | * struct opp_table - Device opp structure |
161 | * @node: table node - contains the devices with OPPs that |
162 | * have been registered. Nodes once added are not modified in this |
163 | * table. |
164 | * @head: notifier head to notify the OPP availability changes. |
165 | * @dev_list: list of devices that share these OPPs |
166 | * @opp_list: table of opps |
167 | * @kref: for reference count of the table. |
168 | * @lock: mutex protecting the opp_list and dev_list. |
169 | * @np: struct device_node pointer for opp's DT node. |
170 | * @clock_latency_ns_max: Max clock latency in nanoseconds. |
171 | * @parsed_static_opps: Count of devices for which OPPs are initialized from DT. |
172 | * @shared_opp: OPP is shared between multiple devices. |
173 | * @current_rate_single_clk: Currently configured frequency for single clk. |
174 | * @current_opp: Currently configured OPP for the table. |
175 | * @suspend_opp: Pointer to OPP to be used during device suspend. |
176 | * @required_opp_tables: List of device OPP tables that are required by OPPs in |
177 | * this table. |
178 | * @required_devs: List of devices for required OPP tables. |
179 | * @required_opp_count: Number of required devices. |
180 | * @supported_hw: Array of version number to support. |
181 | * @supported_hw_count: Number of elements in supported_hw array. |
182 | * @prop_name: A name to postfix to many DT properties, while parsing them. |
183 | * @config_clks: Platform specific config_clks() callback. |
184 | * @clks: Device's clock handles, for multiple clocks. |
185 | * @clk: Device's clock handle, for single clock. |
186 | * @clk_count: Number of clocks. |
187 | * @config_regulators: Platform specific config_regulators() callback. |
188 | * @regulators: Supply regulators |
189 | * @regulator_count: Number of power supply regulators. Its value can be -1 |
190 | * (uninitialized), 0 (no opp-microvolt property) or > 0 (has opp-microvolt |
191 | * property). |
192 | * @paths: Interconnect path handles |
193 | * @path_count: Number of interconnect paths |
194 | * @enabled: Set to true if the device's resources are enabled/configured. |
195 | * @is_genpd: Marks if the OPP table belongs to a genpd. |
196 | * @dentry: debugfs dentry pointer of the real device directory (not links). |
197 | * @dentry_name: Name of the real dentry. |
198 | * |
199 | * @voltage_tolerance_v1: In percentage, for v1 bindings only. |
200 | * |
201 | * This is an internal data structure maintaining the link to opps attached to |
202 | * a device. This structure is not meant to be shared to users as it is |
203 | * meant for book keeping and private to OPP library. |
204 | */ |
205 | struct opp_table { |
206 | struct list_head node, lazy; |
207 | |
208 | struct blocking_notifier_head head; |
209 | struct list_head dev_list; |
210 | struct list_head opp_list; |
211 | struct kref kref; |
212 | struct mutex lock; |
213 | |
214 | struct device_node *np; |
215 | unsigned long clock_latency_ns_max; |
216 | |
217 | /* For backward compatibility with v1 bindings */ |
218 | unsigned int voltage_tolerance_v1; |
219 | |
220 | unsigned int parsed_static_opps; |
221 | enum opp_table_access shared_opp; |
222 | unsigned long current_rate_single_clk; |
223 | struct dev_pm_opp *current_opp; |
224 | struct dev_pm_opp *suspend_opp; |
225 | |
226 | struct opp_table **required_opp_tables; |
227 | struct device **required_devs; |
228 | unsigned int required_opp_count; |
229 | |
230 | unsigned int *supported_hw; |
231 | unsigned int supported_hw_count; |
232 | const char *prop_name; |
233 | config_clks_t config_clks; |
234 | struct clk **clks; |
235 | struct clk *clk; |
236 | int clk_count; |
237 | config_regulators_t config_regulators; |
238 | struct regulator **regulators; |
239 | int regulator_count; |
240 | struct icc_path **paths; |
241 | unsigned int path_count; |
242 | bool enabled; |
243 | bool is_genpd; |
244 | |
245 | #ifdef CONFIG_DEBUG_FS |
246 | struct dentry *dentry; |
247 | char dentry_name[NAME_MAX]; |
248 | #endif |
249 | }; |
250 | |
251 | /* Routines internal to opp core */ |
252 | void dev_pm_opp_get(struct dev_pm_opp *opp); |
253 | bool _opp_remove_all_static(struct opp_table *opp_table); |
254 | void _get_opp_table_kref(struct opp_table *opp_table); |
255 | int _get_opp_count(struct opp_table *opp_table); |
256 | struct opp_table *_find_opp_table(struct device *dev); |
257 | struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table); |
258 | struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table); |
259 | void _opp_free(struct dev_pm_opp *opp); |
260 | int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2); |
261 | int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table); |
262 | int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic); |
263 | void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu); |
264 | struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk); |
265 | void _put_opp_list_kref(struct opp_table *opp_table); |
266 | void _required_opps_available(struct dev_pm_opp *opp, int count); |
267 | void _update_set_required_opps(struct opp_table *opp_table); |
268 | |
269 | static inline bool lazy_linking_pending(struct opp_table *opp_table) |
270 | { |
271 | return unlikely(!list_empty(&opp_table->lazy)); |
272 | } |
273 | |
274 | #ifdef CONFIG_OF |
275 | void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index); |
276 | void _of_clear_opp_table(struct opp_table *opp_table); |
277 | struct opp_table *_managed_opp(struct device *dev, int index); |
278 | void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp); |
279 | #else |
280 | static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {} |
281 | static inline void _of_clear_opp_table(struct opp_table *opp_table) {} |
282 | static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; } |
283 | static inline void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) {} |
284 | #endif |
285 | |
286 | #ifdef CONFIG_DEBUG_FS |
287 | void opp_debug_remove_one(struct dev_pm_opp *opp); |
288 | void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table); |
289 | void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table); |
290 | void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table); |
291 | #else |
292 | static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {} |
293 | |
294 | static inline void opp_debug_create_one(struct dev_pm_opp *opp, |
295 | struct opp_table *opp_table) { } |
296 | |
297 | static inline void opp_debug_register(struct opp_device *opp_dev, |
298 | struct opp_table *opp_table) { } |
299 | |
300 | static inline void opp_debug_unregister(struct opp_device *opp_dev, |
301 | struct opp_table *opp_table) |
302 | { } |
303 | #endif /* DEBUG_FS */ |
304 | |
305 | #endif /* __DRIVER_OPP_H__ */ |
306 | |