linux/include/linux/pm_domain.h
<<
>>
Prefs
   1/*
   2 * pm_domain.h - Definitions and headers related to device power domains.
   3 *
   4 * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
   5 *
   6 * This file is released under the GPLv2.
   7 */
   8
   9#ifndef _LINUX_PM_DOMAIN_H
  10#define _LINUX_PM_DOMAIN_H
  11
  12#include <linux/device.h>
  13#include <linux/mutex.h>
  14#include <linux/pm.h>
  15#include <linux/err.h>
  16#include <linux/of.h>
  17#include <linux/notifier.h>
  18
  19/* Defines used for the flags field in the struct generic_pm_domain */
  20#define GENPD_FLAG_PM_CLK       (1U << 0) /* PM domain uses PM clk */
  21
  22#define GENPD_MAX_NUM_STATES    8 /* Number of possible low power states */
  23
  24enum gpd_status {
  25        GPD_STATE_ACTIVE = 0,   /* PM domain is active */
  26        GPD_STATE_POWER_OFF,    /* PM domain is off */
  27};
  28
  29struct dev_power_governor {
  30        bool (*power_down_ok)(struct dev_pm_domain *domain);
  31        bool (*suspend_ok)(struct device *dev);
  32};
  33
  34struct gpd_dev_ops {
  35        int (*start)(struct device *dev);
  36        int (*stop)(struct device *dev);
  37        bool (*active_wakeup)(struct device *dev);
  38};
  39
  40struct genpd_power_state {
  41        s64 power_off_latency_ns;
  42        s64 power_on_latency_ns;
  43};
  44
  45struct generic_pm_domain {
  46        struct dev_pm_domain domain;    /* PM domain operations */
  47        struct list_head gpd_list_node; /* Node in the global PM domains list */
  48        struct list_head master_links;  /* Links with PM domain as a master */
  49        struct list_head slave_links;   /* Links with PM domain as a slave */
  50        struct list_head dev_list;      /* List of devices */
  51        struct mutex lock;
  52        struct dev_power_governor *gov;
  53        struct work_struct power_off_work;
  54        struct fwnode_handle *provider; /* Identity of the domain provider */
  55        bool has_provider;
  56        const char *name;
  57        atomic_t sd_count;      /* Number of subdomains with power "on" */
  58        enum gpd_status status; /* Current state of the domain */
  59        unsigned int device_count;      /* Number of devices */
  60        unsigned int suspended_count;   /* System suspend device counter */
  61        unsigned int prepared_count;    /* Suspend counter of prepared devices */
  62        int (*power_off)(struct generic_pm_domain *domain);
  63        int (*power_on)(struct generic_pm_domain *domain);
  64        struct gpd_dev_ops dev_ops;
  65        s64 max_off_time_ns;    /* Maximum allowed "suspended" time. */
  66        bool max_off_time_changed;
  67        bool cached_power_down_ok;
  68        int (*attach_dev)(struct generic_pm_domain *domain,
  69                          struct device *dev);
  70        void (*detach_dev)(struct generic_pm_domain *domain,
  71                           struct device *dev);
  72        unsigned int flags;             /* Bit field of configs for genpd */
  73        struct genpd_power_state states[GENPD_MAX_NUM_STATES];
  74        unsigned int state_count; /* number of states */
  75        unsigned int state_idx; /* state that genpd will go to when off */
  76
  77};
  78
  79static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
  80{
  81        return container_of(pd, struct generic_pm_domain, domain);
  82}
  83
  84struct gpd_link {
  85        struct generic_pm_domain *master;
  86        struct list_head master_node;
  87        struct generic_pm_domain *slave;
  88        struct list_head slave_node;
  89};
  90
  91struct gpd_timing_data {
  92        s64 suspend_latency_ns;
  93        s64 resume_latency_ns;
  94        s64 effective_constraint_ns;
  95        bool constraint_changed;
  96        bool cached_suspend_ok;
  97};
  98
  99struct pm_domain_data {
 100        struct list_head list_node;
 101        struct device *dev;
 102};
 103
 104struct generic_pm_domain_data {
 105        struct pm_domain_data base;
 106        struct gpd_timing_data td;
 107        struct notifier_block nb;
 108};
 109
 110#ifdef CONFIG_PM_GENERIC_DOMAINS
 111static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd)
 112{
 113        return container_of(pdd, struct generic_pm_domain_data, base);
 114}
 115
 116static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 117{
 118        return to_gpd_data(dev->power.subsys_data->domain_data);
 119}
 120
 121extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
 122                                 struct device *dev,
 123                                 struct gpd_timing_data *td);
 124
 125extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 126                                  struct device *dev);
 127extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 128                                  struct generic_pm_domain *new_subdomain);
 129extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 130                                     struct generic_pm_domain *target);
 131extern int pm_genpd_init(struct generic_pm_domain *genpd,
 132                         struct dev_power_governor *gov, bool is_off);
 133extern int pm_genpd_remove(struct generic_pm_domain *genpd);
 134
 135extern struct dev_power_governor simple_qos_governor;
 136extern struct dev_power_governor pm_domain_always_on_gov;
 137#else
 138
 139static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 140{
 141        return ERR_PTR(-ENOSYS);
 142}
 143static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
 144                                        struct device *dev,
 145                                        struct gpd_timing_data *td)
 146{
 147        return -ENOSYS;
 148}
 149static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 150                                         struct device *dev)
 151{
 152        return -ENOSYS;
 153}
 154static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 155                                         struct generic_pm_domain *new_sd)
 156{
 157        return -ENOSYS;
 158}
 159static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 160                                            struct generic_pm_domain *target)
 161{
 162        return -ENOSYS;
 163}
 164static inline int pm_genpd_init(struct generic_pm_domain *genpd,
 165                                struct dev_power_governor *gov, bool is_off)
 166{
 167        return -ENOSYS;
 168}
 169static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
 170{
 171        return -ENOTSUPP;
 172}
 173#endif
 174
 175static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
 176                                      struct device *dev)
 177{
 178        return __pm_genpd_add_device(genpd, dev, NULL);
 179}
 180
 181#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
 182extern void pm_genpd_syscore_poweroff(struct device *dev);
 183extern void pm_genpd_syscore_poweron(struct device *dev);
 184#else
 185static inline void pm_genpd_syscore_poweroff(struct device *dev) {}
 186static inline void pm_genpd_syscore_poweron(struct device *dev) {}
 187#endif
 188
 189/* OF PM domain providers */
 190struct of_device_id;
 191
 192struct genpd_onecell_data {
 193        struct generic_pm_domain **domains;
 194        unsigned int num_domains;
 195};
 196
 197#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 198int of_genpd_add_provider_simple(struct device_node *np,
 199                                 struct generic_pm_domain *genpd);
 200int of_genpd_add_provider_onecell(struct device_node *np,
 201                                  struct genpd_onecell_data *data);
 202void of_genpd_del_provider(struct device_node *np);
 203extern int of_genpd_add_device(struct of_phandle_args *args,
 204                               struct device *dev);
 205extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
 206                                  struct of_phandle_args *new_subdomain);
 207extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
 208
 209int genpd_dev_pm_attach(struct device *dev);
 210#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
 211static inline int of_genpd_add_provider_simple(struct device_node *np,
 212                                        struct generic_pm_domain *genpd)
 213{
 214        return -ENOTSUPP;
 215}
 216
 217static inline int of_genpd_add_provider_onecell(struct device_node *np,
 218                                        struct genpd_onecell_data *data)
 219{
 220        return -ENOTSUPP;
 221}
 222
 223static inline void of_genpd_del_provider(struct device_node *np) {}
 224
 225static inline int of_genpd_add_device(struct of_phandle_args *args,
 226                                      struct device *dev)
 227{
 228        return -ENODEV;
 229}
 230
 231static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
 232                                         struct of_phandle_args *new_subdomain)
 233{
 234        return -ENODEV;
 235}
 236
 237static inline int genpd_dev_pm_attach(struct device *dev)
 238{
 239        return -ENODEV;
 240}
 241
 242static inline
 243struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
 244{
 245        return ERR_PTR(-ENOTSUPP);
 246}
 247#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 248
 249#ifdef CONFIG_PM
 250extern int dev_pm_domain_attach(struct device *dev, bool power_on);
 251extern void dev_pm_domain_detach(struct device *dev, bool power_off);
 252extern void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
 253#else
 254static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
 255{
 256        return -ENODEV;
 257}
 258static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
 259static inline void dev_pm_domain_set(struct device *dev,
 260                                     struct dev_pm_domain *pd) {}
 261#endif
 262
 263#endif /* _LINUX_PM_DOMAIN_H */
 264