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 : 3 : 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 */