Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */
2 : : /*
3 : : * pm_domain.h - Definitions and headers related to device power domains.
4 : : *
5 : : * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
6 : : */
7 : :
8 : : #ifndef _LINUX_PM_DOMAIN_H
9 : : #define _LINUX_PM_DOMAIN_H
10 : :
11 : : #include <linux/device.h>
12 : : #include <linux/mutex.h>
13 : : #include <linux/pm.h>
14 : : #include <linux/err.h>
15 : : #include <linux/of.h>
16 : : #include <linux/notifier.h>
17 : : #include <linux/spinlock.h>
18 : : #include <linux/cpumask.h>
19 : :
20 : : /*
21 : : * Flags to control the behaviour of a genpd.
22 : : *
23 : : * These flags may be set in the struct generic_pm_domain's flags field by a
24 : : * genpd backend driver. The flags must be set before it calls pm_genpd_init(),
25 : : * which initializes a genpd.
26 : : *
27 : : * GENPD_FLAG_PM_CLK: Instructs genpd to use the PM clk framework,
28 : : * while powering on/off attached devices.
29 : : *
30 : : * GENPD_FLAG_IRQ_SAFE: This informs genpd that its backend callbacks,
31 : : * ->power_on|off(), doesn't sleep. Hence, these
32 : : * can be invoked from within atomic context, which
33 : : * enables genpd to power on/off the PM domain,
34 : : * even when pm_runtime_is_irq_safe() returns true,
35 : : * for any of its attached devices. Note that, a
36 : : * genpd having this flag set, requires its
37 : : * masterdomains to also have it set.
38 : : *
39 : : * GENPD_FLAG_ALWAYS_ON: Instructs genpd to always keep the PM domain
40 : : * powered on.
41 : : *
42 : : * GENPD_FLAG_ACTIVE_WAKEUP: Instructs genpd to keep the PM domain powered
43 : : * on, in case any of its attached devices is used
44 : : * in the wakeup path to serve system wakeups.
45 : : *
46 : : * GENPD_FLAG_CPU_DOMAIN: Instructs genpd that it should expect to get
47 : : * devices attached, which may belong to CPUs or
48 : : * possibly have subdomains with CPUs attached.
49 : : * This flag enables the genpd backend driver to
50 : : * deploy idle power management support for CPUs
51 : : * and groups of CPUs. Note that, the backend
52 : : * driver must then comply with the so called,
53 : : * last-man-standing algorithm, for the CPUs in the
54 : : * PM domain.
55 : : *
56 : : * GENPD_FLAG_RPM_ALWAYS_ON: Instructs genpd to always keep the PM domain
57 : : * powered on except for system suspend.
58 : : */
59 : : #define GENPD_FLAG_PM_CLK (1U << 0)
60 : : #define GENPD_FLAG_IRQ_SAFE (1U << 1)
61 : : #define GENPD_FLAG_ALWAYS_ON (1U << 2)
62 : : #define GENPD_FLAG_ACTIVE_WAKEUP (1U << 3)
63 : : #define GENPD_FLAG_CPU_DOMAIN (1U << 4)
64 : : #define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
65 : :
66 : : enum gpd_status {
67 : : GPD_STATE_ACTIVE = 0, /* PM domain is active */
68 : : GPD_STATE_POWER_OFF, /* PM domain is off */
69 : : };
70 : :
71 : : struct dev_power_governor {
72 : : bool (*power_down_ok)(struct dev_pm_domain *domain);
73 : : bool (*suspend_ok)(struct device *dev);
74 : : };
75 : :
76 : : struct gpd_dev_ops {
77 : : int (*start)(struct device *dev);
78 : : int (*stop)(struct device *dev);
79 : : };
80 : :
81 : : struct genpd_power_state {
82 : : s64 power_off_latency_ns;
83 : : s64 power_on_latency_ns;
84 : : s64 residency_ns;
85 : : struct fwnode_handle *fwnode;
86 : : ktime_t idle_time;
87 : : void *data;
88 : : };
89 : :
90 : : struct genpd_lock_ops;
91 : : struct dev_pm_opp;
92 : : struct opp_table;
93 : :
94 : : struct generic_pm_domain {
95 : : struct device dev;
96 : : struct dev_pm_domain domain; /* PM domain operations */
97 : : struct list_head gpd_list_node; /* Node in the global PM domains list */
98 : : struct list_head master_links; /* Links with PM domain as a master */
99 : : struct list_head slave_links; /* Links with PM domain as a slave */
100 : : struct list_head dev_list; /* List of devices */
101 : : struct dev_power_governor *gov;
102 : : struct work_struct power_off_work;
103 : : struct fwnode_handle *provider; /* Identity of the domain provider */
104 : : bool has_provider;
105 : : const char *name;
106 : : atomic_t sd_count; /* Number of subdomains with power "on" */
107 : : enum gpd_status status; /* Current state of the domain */
108 : : unsigned int device_count; /* Number of devices */
109 : : unsigned int suspended_count; /* System suspend device counter */
110 : : unsigned int prepared_count; /* Suspend counter of prepared devices */
111 : : unsigned int performance_state; /* Aggregated max performance state */
112 : : cpumask_var_t cpus; /* A cpumask of the attached CPUs */
113 : : int (*power_off)(struct generic_pm_domain *domain);
114 : : int (*power_on)(struct generic_pm_domain *domain);
115 : : struct opp_table *opp_table; /* OPP table of the genpd */
116 : : unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd,
117 : : struct dev_pm_opp *opp);
118 : : int (*set_performance_state)(struct generic_pm_domain *genpd,
119 : : unsigned int state);
120 : : struct gpd_dev_ops dev_ops;
121 : : s64 max_off_time_ns; /* Maximum allowed "suspended" time. */
122 : : bool max_off_time_changed;
123 : : bool cached_power_down_ok;
124 : : bool cached_power_down_state_idx;
125 : : int (*attach_dev)(struct generic_pm_domain *domain,
126 : : struct device *dev);
127 : : void (*detach_dev)(struct generic_pm_domain *domain,
128 : : struct device *dev);
129 : : unsigned int flags; /* Bit field of configs for genpd */
130 : : struct genpd_power_state *states;
131 : : void (*free_states)(struct genpd_power_state *states,
132 : : unsigned int state_count);
133 : : unsigned int state_count; /* number of states */
134 : : unsigned int state_idx; /* state that genpd will go to when off */
135 : : ktime_t on_time;
136 : : ktime_t accounting_time;
137 : : const struct genpd_lock_ops *lock_ops;
138 : : union {
139 : : struct mutex mlock;
140 : : struct {
141 : : spinlock_t slock;
142 : : unsigned long lock_flags;
143 : : };
144 : : };
145 : :
146 : : };
147 : :
148 : : static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
149 : : {
150 : 207 : return container_of(pd, struct generic_pm_domain, domain);
151 : : }
152 : :
153 : : struct gpd_link {
154 : : struct generic_pm_domain *master;
155 : : struct list_head master_node;
156 : : struct generic_pm_domain *slave;
157 : : struct list_head slave_node;
158 : :
159 : : /* Sub-domain's per-master domain performance state */
160 : : unsigned int performance_state;
161 : : unsigned int prev_performance_state;
162 : : };
163 : :
164 : : struct gpd_timing_data {
165 : : s64 suspend_latency_ns;
166 : : s64 resume_latency_ns;
167 : : s64 effective_constraint_ns;
168 : : bool constraint_changed;
169 : : bool cached_suspend_ok;
170 : : };
171 : :
172 : : struct pm_domain_data {
173 : : struct list_head list_node;
174 : : struct device *dev;
175 : : };
176 : :
177 : : struct generic_pm_domain_data {
178 : : struct pm_domain_data base;
179 : : struct gpd_timing_data td;
180 : : struct notifier_block nb;
181 : : int cpu;
182 : : unsigned int performance_state;
183 : : void *data;
184 : : };
185 : :
186 : : #ifdef CONFIG_PM_GENERIC_DOMAINS
187 : : static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd)
188 : : {
189 : : return container_of(pdd, struct generic_pm_domain_data, base);
190 : : }
191 : :
192 : : static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
193 : : {
194 : 0 : return to_gpd_data(dev->power.subsys_data->domain_data);
195 : : }
196 : :
197 : : int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev);
198 : : int pm_genpd_remove_device(struct device *dev);
199 : : int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
200 : : struct generic_pm_domain *subdomain);
201 : : int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
202 : : struct generic_pm_domain *subdomain);
203 : : int pm_genpd_init(struct generic_pm_domain *genpd,
204 : : struct dev_power_governor *gov, bool is_off);
205 : : int pm_genpd_remove(struct generic_pm_domain *genpd);
206 : : int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state);
207 : :
208 : : extern struct dev_power_governor simple_qos_governor;
209 : : extern struct dev_power_governor pm_domain_always_on_gov;
210 : : #ifdef CONFIG_CPU_IDLE
211 : : extern struct dev_power_governor pm_domain_cpu_gov;
212 : : #endif
213 : : #else
214 : :
215 : : static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
216 : : {
217 : : return ERR_PTR(-ENOSYS);
218 : : }
219 : : static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
220 : : struct device *dev)
221 : : {
222 : : return -ENOSYS;
223 : : }
224 : : static inline int pm_genpd_remove_device(struct device *dev)
225 : : {
226 : : return -ENOSYS;
227 : : }
228 : : static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
229 : : struct generic_pm_domain *subdomain)
230 : : {
231 : : return -ENOSYS;
232 : : }
233 : : static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
234 : : struct generic_pm_domain *subdomain)
235 : : {
236 : : return -ENOSYS;
237 : : }
238 : : static inline int pm_genpd_init(struct generic_pm_domain *genpd,
239 : : struct dev_power_governor *gov, bool is_off)
240 : : {
241 : : return -ENOSYS;
242 : : }
243 : : static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
244 : : {
245 : : return -ENOTSUPP;
246 : : }
247 : :
248 : : static inline int dev_pm_genpd_set_performance_state(struct device *dev,
249 : : unsigned int state)
250 : : {
251 : : return -ENOTSUPP;
252 : : }
253 : :
254 : : #define simple_qos_governor (*(struct dev_power_governor *)(NULL))
255 : : #define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL))
256 : : #endif
257 : :
258 : : #ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
259 : : void pm_genpd_syscore_poweroff(struct device *dev);
260 : : void pm_genpd_syscore_poweron(struct device *dev);
261 : : #else
262 : : static inline void pm_genpd_syscore_poweroff(struct device *dev) {}
263 : : static inline void pm_genpd_syscore_poweron(struct device *dev) {}
264 : : #endif
265 : :
266 : : /* OF PM domain providers */
267 : : struct of_device_id;
268 : :
269 : : typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
270 : : void *data);
271 : :
272 : : struct genpd_onecell_data {
273 : : struct generic_pm_domain **domains;
274 : : unsigned int num_domains;
275 : : genpd_xlate_t xlate;
276 : : };
277 : :
278 : : #ifdef CONFIG_PM_GENERIC_DOMAINS_OF
279 : : int of_genpd_add_provider_simple(struct device_node *np,
280 : : struct generic_pm_domain *genpd);
281 : : int of_genpd_add_provider_onecell(struct device_node *np,
282 : : struct genpd_onecell_data *data);
283 : : void of_genpd_del_provider(struct device_node *np);
284 : : int of_genpd_add_device(struct of_phandle_args *args, struct device *dev);
285 : : int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
286 : : struct of_phandle_args *subdomain_spec);
287 : : struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
288 : : int of_genpd_parse_idle_states(struct device_node *dn,
289 : : struct genpd_power_state **states, int *n);
290 : : unsigned int pm_genpd_opp_to_performance_state(struct device *genpd_dev,
291 : : struct dev_pm_opp *opp);
292 : :
293 : : int genpd_dev_pm_attach(struct device *dev);
294 : : struct device *genpd_dev_pm_attach_by_id(struct device *dev,
295 : : unsigned int index);
296 : : struct device *genpd_dev_pm_attach_by_name(struct device *dev,
297 : : const char *name);
298 : : #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
299 : : static inline int of_genpd_add_provider_simple(struct device_node *np,
300 : : struct generic_pm_domain *genpd)
301 : : {
302 : : return -ENOTSUPP;
303 : : }
304 : :
305 : : static inline int of_genpd_add_provider_onecell(struct device_node *np,
306 : : struct genpd_onecell_data *data)
307 : : {
308 : : return -ENOTSUPP;
309 : : }
310 : :
311 : : static inline void of_genpd_del_provider(struct device_node *np) {}
312 : :
313 : : static inline int of_genpd_add_device(struct of_phandle_args *args,
314 : : struct device *dev)
315 : : {
316 : : return -ENODEV;
317 : : }
318 : :
319 : : static inline int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
320 : : struct of_phandle_args *subdomain_spec)
321 : : {
322 : : return -ENODEV;
323 : : }
324 : :
325 : : static inline int of_genpd_parse_idle_states(struct device_node *dn,
326 : : struct genpd_power_state **states, int *n)
327 : : {
328 : : return -ENODEV;
329 : : }
330 : :
331 : : static inline unsigned int
332 : : pm_genpd_opp_to_performance_state(struct device *genpd_dev,
333 : : struct dev_pm_opp *opp)
334 : : {
335 : : return 0;
336 : : }
337 : :
338 : : static inline int genpd_dev_pm_attach(struct device *dev)
339 : : {
340 : : return 0;
341 : : }
342 : :
343 : : static inline struct device *genpd_dev_pm_attach_by_id(struct device *dev,
344 : : unsigned int index)
345 : : {
346 : : return NULL;
347 : : }
348 : :
349 : : static inline struct device *genpd_dev_pm_attach_by_name(struct device *dev,
350 : : const char *name)
351 : : {
352 : : return NULL;
353 : : }
354 : :
355 : : static inline
356 : : struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
357 : : {
358 : : return ERR_PTR(-ENOTSUPP);
359 : : }
360 : : #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
361 : :
362 : : #ifdef CONFIG_PM
363 : : int dev_pm_domain_attach(struct device *dev, bool power_on);
364 : : struct device *dev_pm_domain_attach_by_id(struct device *dev,
365 : : unsigned int index);
366 : : struct device *dev_pm_domain_attach_by_name(struct device *dev,
367 : : const char *name);
368 : : void dev_pm_domain_detach(struct device *dev, bool power_off);
369 : : void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
370 : : #else
371 : : static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
372 : : {
373 : : return 0;
374 : : }
375 : : static inline struct device *dev_pm_domain_attach_by_id(struct device *dev,
376 : : unsigned int index)
377 : : {
378 : : return NULL;
379 : : }
380 : : static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
381 : : const char *name)
382 : : {
383 : : return NULL;
384 : : }
385 : : static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
386 : : static inline void dev_pm_domain_set(struct device *dev,
387 : : struct dev_pm_domain *pd) {}
388 : : #endif
389 : :
390 : : #endif /* _LINUX_PM_DOMAIN_H */
|