at v5.10 427 lines 13 kB view raw
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 66enum gpd_status { 67 GENPD_STATE_ON = 0, /* PM domain is on */ 68 GENPD_STATE_OFF, /* PM domain is off */ 69}; 70 71enum genpd_notication { 72 GENPD_NOTIFY_PRE_OFF = 0, 73 GENPD_NOTIFY_OFF, 74 GENPD_NOTIFY_PRE_ON, 75 GENPD_NOTIFY_ON, 76}; 77 78struct dev_power_governor { 79 bool (*power_down_ok)(struct dev_pm_domain *domain); 80 bool (*suspend_ok)(struct device *dev); 81}; 82 83struct gpd_dev_ops { 84 int (*start)(struct device *dev); 85 int (*stop)(struct device *dev); 86}; 87 88struct genpd_power_state { 89 s64 power_off_latency_ns; 90 s64 power_on_latency_ns; 91 s64 residency_ns; 92 u64 usage; 93 u64 rejected; 94 struct fwnode_handle *fwnode; 95 ktime_t idle_time; 96 void *data; 97}; 98 99struct genpd_lock_ops; 100struct dev_pm_opp; 101struct opp_table; 102 103struct generic_pm_domain { 104 struct device dev; 105 struct dev_pm_domain domain; /* PM domain operations */ 106 struct list_head gpd_list_node; /* Node in the global PM domains list */ 107 struct list_head parent_links; /* Links with PM domain as a parent */ 108 struct list_head child_links; /* Links with PM domain as a child */ 109 struct list_head dev_list; /* List of devices */ 110 struct dev_power_governor *gov; 111 struct work_struct power_off_work; 112 struct fwnode_handle *provider; /* Identity of the domain provider */ 113 bool has_provider; 114 const char *name; 115 atomic_t sd_count; /* Number of subdomains with power "on" */ 116 enum gpd_status status; /* Current state of the domain */ 117 unsigned int device_count; /* Number of devices */ 118 unsigned int suspended_count; /* System suspend device counter */ 119 unsigned int prepared_count; /* Suspend counter of prepared devices */ 120 unsigned int performance_state; /* Aggregated max performance state */ 121 cpumask_var_t cpus; /* A cpumask of the attached CPUs */ 122 int (*power_off)(struct generic_pm_domain *domain); 123 int (*power_on)(struct generic_pm_domain *domain); 124 struct raw_notifier_head power_notifiers; /* Power on/off notifiers */ 125 struct opp_table *opp_table; /* OPP table of the genpd */ 126 unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd, 127 struct dev_pm_opp *opp); 128 int (*set_performance_state)(struct generic_pm_domain *genpd, 129 unsigned int state); 130 struct gpd_dev_ops dev_ops; 131 s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ 132 bool max_off_time_changed; 133 bool cached_power_down_ok; 134 bool cached_power_down_state_idx; 135 int (*attach_dev)(struct generic_pm_domain *domain, 136 struct device *dev); 137 void (*detach_dev)(struct generic_pm_domain *domain, 138 struct device *dev); 139 unsigned int flags; /* Bit field of configs for genpd */ 140 struct genpd_power_state *states; 141 void (*free_states)(struct genpd_power_state *states, 142 unsigned int state_count); 143 unsigned int state_count; /* number of states */ 144 unsigned int state_idx; /* state that genpd will go to when off */ 145 ktime_t on_time; 146 ktime_t accounting_time; 147 const struct genpd_lock_ops *lock_ops; 148 union { 149 struct mutex mlock; 150 struct { 151 spinlock_t slock; 152 unsigned long lock_flags; 153 }; 154 }; 155 156}; 157 158static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd) 159{ 160 return container_of(pd, struct generic_pm_domain, domain); 161} 162 163struct gpd_link { 164 struct generic_pm_domain *parent; 165 struct list_head parent_node; 166 struct generic_pm_domain *child; 167 struct list_head child_node; 168 169 /* Sub-domain's per-master domain performance state */ 170 unsigned int performance_state; 171 unsigned int prev_performance_state; 172}; 173 174struct gpd_timing_data { 175 s64 suspend_latency_ns; 176 s64 resume_latency_ns; 177 s64 effective_constraint_ns; 178 bool constraint_changed; 179 bool cached_suspend_ok; 180}; 181 182struct pm_domain_data { 183 struct list_head list_node; 184 struct device *dev; 185}; 186 187struct generic_pm_domain_data { 188 struct pm_domain_data base; 189 struct gpd_timing_data td; 190 struct notifier_block nb; 191 struct notifier_block *power_nb; 192 int cpu; 193 unsigned int performance_state; 194 void *data; 195}; 196 197#ifdef CONFIG_PM_GENERIC_DOMAINS 198static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd) 199{ 200 return container_of(pdd, struct generic_pm_domain_data, base); 201} 202 203static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) 204{ 205 return to_gpd_data(dev->power.subsys_data->domain_data); 206} 207 208int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev); 209int pm_genpd_remove_device(struct device *dev); 210int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, 211 struct generic_pm_domain *subdomain); 212int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, 213 struct generic_pm_domain *subdomain); 214int pm_genpd_init(struct generic_pm_domain *genpd, 215 struct dev_power_governor *gov, bool is_off); 216int pm_genpd_remove(struct generic_pm_domain *genpd); 217int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state); 218int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb); 219int dev_pm_genpd_remove_notifier(struct device *dev); 220 221extern struct dev_power_governor simple_qos_governor; 222extern struct dev_power_governor pm_domain_always_on_gov; 223#ifdef CONFIG_CPU_IDLE 224extern struct dev_power_governor pm_domain_cpu_gov; 225#endif 226#else 227 228static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) 229{ 230 return ERR_PTR(-ENOSYS); 231} 232static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, 233 struct device *dev) 234{ 235 return -ENOSYS; 236} 237static inline int pm_genpd_remove_device(struct device *dev) 238{ 239 return -ENOSYS; 240} 241static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, 242 struct generic_pm_domain *subdomain) 243{ 244 return -ENOSYS; 245} 246static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, 247 struct generic_pm_domain *subdomain) 248{ 249 return -ENOSYS; 250} 251static inline int pm_genpd_init(struct generic_pm_domain *genpd, 252 struct dev_power_governor *gov, bool is_off) 253{ 254 return -ENOSYS; 255} 256static inline int pm_genpd_remove(struct generic_pm_domain *genpd) 257{ 258 return -ENOTSUPP; 259} 260 261static inline int dev_pm_genpd_set_performance_state(struct device *dev, 262 unsigned int state) 263{ 264 return -ENOTSUPP; 265} 266 267static inline int dev_pm_genpd_add_notifier(struct device *dev, 268 struct notifier_block *nb) 269{ 270 return -ENOTSUPP; 271} 272 273static inline int dev_pm_genpd_remove_notifier(struct device *dev) 274{ 275 return -ENOTSUPP; 276} 277 278#define simple_qos_governor (*(struct dev_power_governor *)(NULL)) 279#define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL)) 280#endif 281 282#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP 283void pm_genpd_syscore_poweroff(struct device *dev); 284void pm_genpd_syscore_poweron(struct device *dev); 285#else 286static inline void pm_genpd_syscore_poweroff(struct device *dev) {} 287static inline void pm_genpd_syscore_poweron(struct device *dev) {} 288#endif 289 290/* OF PM domain providers */ 291struct of_device_id; 292 293typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args, 294 void *data); 295 296struct genpd_onecell_data { 297 struct generic_pm_domain **domains; 298 unsigned int num_domains; 299 genpd_xlate_t xlate; 300}; 301 302#ifdef CONFIG_PM_GENERIC_DOMAINS_OF 303int of_genpd_add_provider_simple(struct device_node *np, 304 struct generic_pm_domain *genpd); 305int of_genpd_add_provider_onecell(struct device_node *np, 306 struct genpd_onecell_data *data); 307void of_genpd_del_provider(struct device_node *np); 308int of_genpd_add_device(struct of_phandle_args *args, struct device *dev); 309int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, 310 struct of_phandle_args *subdomain_spec); 311int of_genpd_remove_subdomain(struct of_phandle_args *parent_spec, 312 struct of_phandle_args *subdomain_spec); 313struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); 314int of_genpd_parse_idle_states(struct device_node *dn, 315 struct genpd_power_state **states, int *n); 316unsigned int pm_genpd_opp_to_performance_state(struct device *genpd_dev, 317 struct dev_pm_opp *opp); 318 319int genpd_dev_pm_attach(struct device *dev); 320struct device *genpd_dev_pm_attach_by_id(struct device *dev, 321 unsigned int index); 322struct device *genpd_dev_pm_attach_by_name(struct device *dev, 323 const char *name); 324#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */ 325static inline int of_genpd_add_provider_simple(struct device_node *np, 326 struct generic_pm_domain *genpd) 327{ 328 return -ENOTSUPP; 329} 330 331static inline int of_genpd_add_provider_onecell(struct device_node *np, 332 struct genpd_onecell_data *data) 333{ 334 return -ENOTSUPP; 335} 336 337static inline void of_genpd_del_provider(struct device_node *np) {} 338 339static inline int of_genpd_add_device(struct of_phandle_args *args, 340 struct device *dev) 341{ 342 return -ENODEV; 343} 344 345static inline int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, 346 struct of_phandle_args *subdomain_spec) 347{ 348 return -ENODEV; 349} 350 351static inline int of_genpd_remove_subdomain(struct of_phandle_args *parent_spec, 352 struct of_phandle_args *subdomain_spec) 353{ 354 return -ENODEV; 355} 356 357static inline int of_genpd_parse_idle_states(struct device_node *dn, 358 struct genpd_power_state **states, int *n) 359{ 360 return -ENODEV; 361} 362 363static inline unsigned int 364pm_genpd_opp_to_performance_state(struct device *genpd_dev, 365 struct dev_pm_opp *opp) 366{ 367 return 0; 368} 369 370static inline int genpd_dev_pm_attach(struct device *dev) 371{ 372 return 0; 373} 374 375static inline struct device *genpd_dev_pm_attach_by_id(struct device *dev, 376 unsigned int index) 377{ 378 return NULL; 379} 380 381static inline struct device *genpd_dev_pm_attach_by_name(struct device *dev, 382 const char *name) 383{ 384 return NULL; 385} 386 387static inline 388struct generic_pm_domain *of_genpd_remove_last(struct device_node *np) 389{ 390 return ERR_PTR(-ENOTSUPP); 391} 392#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ 393 394#ifdef CONFIG_PM 395int dev_pm_domain_attach(struct device *dev, bool power_on); 396struct device *dev_pm_domain_attach_by_id(struct device *dev, 397 unsigned int index); 398struct device *dev_pm_domain_attach_by_name(struct device *dev, 399 const char *name); 400void dev_pm_domain_detach(struct device *dev, bool power_off); 401int dev_pm_domain_start(struct device *dev); 402void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd); 403#else 404static inline int dev_pm_domain_attach(struct device *dev, bool power_on) 405{ 406 return 0; 407} 408static inline struct device *dev_pm_domain_attach_by_id(struct device *dev, 409 unsigned int index) 410{ 411 return NULL; 412} 413static inline struct device *dev_pm_domain_attach_by_name(struct device *dev, 414 const char *name) 415{ 416 return NULL; 417} 418static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {} 419static inline int dev_pm_domain_start(struct device *dev) 420{ 421 return 0; 422} 423static inline void dev_pm_domain_set(struct device *dev, 424 struct dev_pm_domain *pd) {} 425#endif 426 427#endif /* _LINUX_PM_DOMAIN_H */