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#include <linux/spinlock.h>
  19
  20/* Defines used for the flags field in the struct generic_pm_domain */
  21#define GENPD_FLAG_PM_CLK        (1U << 0) /* PM domain uses PM clk */
  22#define GENPD_FLAG_IRQ_SAFE      (1U << 1) /* PM domain operates in atomic */
  23#define GENPD_FLAG_ALWAYS_ON     (1U << 2) /* PM domain is always powered on */
  24#define GENPD_FLAG_ACTIVE_WAKEUP (1U << 3) /* Keep devices active if wakeup */
  25
  26enum gpd_status {
  27        GPD_STATE_ACTIVE = 0,   /* PM domain is active */
  28        GPD_STATE_POWER_OFF,    /* PM domain is off */
  29};
  30
  31struct dev_power_governor {
  32        bool (*power_down_ok)(struct dev_pm_domain *domain);
  33        bool (*suspend_ok)(struct device *dev);
  34};
  35
  36struct gpd_dev_ops {
  37        int (*start)(struct device *dev);
  38        int (*stop)(struct device *dev);
  39};
  40
  41struct genpd_power_state {
  42        s64 power_off_latency_ns;
  43        s64 power_on_latency_ns;
  44        s64 residency_ns;
  45        struct fwnode_handle *fwnode;
  46        ktime_t idle_time;
  47};
  48
  49struct genpd_lock_ops;
  50struct dev_pm_opp;
  51
  52struct generic_pm_domain {
  53        struct device dev;
  54        struct dev_pm_domain domain;    /* PM domain operations */
  55        struct list_head gpd_list_node; /* Node in the global PM domains list */
  56        struct list_head master_links;  /* Links with PM domain as a master */
  57        struct list_head slave_links;   /* Links with PM domain as a slave */
  58        struct list_head dev_list;      /* List of devices */
  59        struct dev_power_governor *gov;
  60        struct work_struct power_off_work;
  61        struct fwnode_handle *provider; /* Identity of the domain provider */
  62        bool has_provider;
  63        const char *name;
  64        atomic_t sd_count;      /* Number of subdomains with power "on" */
  65        enum gpd_status status; /* Current state of the domain */
  66        unsigned int device_count;      /* Number of devices */
  67        unsigned int suspended_count;   /* System suspend device counter */
  68        unsigned int prepared_count;    /* Suspend counter of prepared devices */
  69        unsigned int performance_state; /* Aggregated max performance state */
  70        int (*power_off)(struct generic_pm_domain *domain);
  71        int (*power_on)(struct generic_pm_domain *domain);
  72        unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd,
  73                                                 struct dev_pm_opp *opp);
  74        int (*set_performance_state)(struct generic_pm_domain *genpd,
  75                                     unsigned int state);
  76        struct gpd_dev_ops dev_ops;
  77        s64 max_off_time_ns;    /* Maximum allowed "suspended" time. */
  78        bool max_off_time_changed;
  79        bool cached_power_down_ok;
  80        int (*attach_dev)(struct generic_pm_domain *domain,
  81                          struct device *dev);
  82        void (*detach_dev)(struct generic_pm_domain *domain,
  83                           struct device *dev);
  84        unsigned int flags;             /* Bit field of configs for genpd */
  85        struct genpd_power_state *states;
  86        unsigned int state_count; /* number of states */
  87        unsigned int state_idx; /* state that genpd will go to when off */
  88        void *free; /* Free the state that was allocated for default */
  89        ktime_t on_time;
  90        ktime_t accounting_time;
  91        const struct genpd_lock_ops *lock_ops;
  92        union {
  93                struct mutex mlock;
  94                struct {
  95                        spinlock_t slock;
  96                        unsigned long lock_flags;
  97                };
  98        };
  99
 100};
 101
 102static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
 103{
 104        return container_of(pd, struct generic_pm_domain, domain);
 105}
 106
 107struct gpd_link {
 108        struct generic_pm_domain *master;
 109        struct list_head master_node;
 110        struct generic_pm_domain *slave;
 111        struct list_head slave_node;
 112};
 113
 114struct gpd_timing_data {
 115        s64 suspend_latency_ns;
 116        s64 resume_latency_ns;
 117        s64 effective_constraint_ns;
 118        bool constraint_changed;
 119        bool cached_suspend_ok;
 120};
 121
 122struct pm_domain_data {
 123        struct list_head list_node;
 124        struct device *dev;
 125};
 126
 127struct generic_pm_domain_data {
 128        struct pm_domain_data base;
 129        struct gpd_timing_data td;
 130        struct notifier_block nb;
 131        unsigned int performance_state;
 132        void *data;
 133};
 134
 135#ifdef CONFIG_PM_GENERIC_DOMAINS
 136static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd)
 137{
 138        return container_of(pdd, struct generic_pm_domain_data, base);
 139}
 140
 141static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 142{
 143        return to_gpd_data(dev->power.subsys_data->domain_data);
 144}
 145
 146int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev);
 147int pm_genpd_remove_device(struct device *dev);
 148int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 149                           struct generic_pm_domain *new_subdomain);
 150int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 151                              struct generic_pm_domain *target);
 152int pm_genpd_init(struct generic_pm_domain *genpd,
 153                  struct dev_power_governor *gov, bool is_off);
 154int pm_genpd_remove(struct generic_pm_domain *genpd);
 155int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state);
 156
 157extern struct dev_power_governor simple_qos_governor;
 158extern struct dev_power_governor pm_domain_always_on_gov;
 159#else
 160
 161static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 162{
 163        return ERR_PTR(-ENOSYS);
 164}
 165static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
 166                                      struct device *dev)
 167{
 168        return -ENOSYS;
 169}
 170static inline int pm_genpd_remove_device(struct device *dev)
 171{
 172        return -ENOSYS;
 173}
 174static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 175                                         struct generic_pm_domain *new_sd)
 176{
 177        return -ENOSYS;
 178}
 179static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 180                                            struct generic_pm_domain *target)
 181{
 182        return -ENOSYS;
 183}
 184static inline int pm_genpd_init(struct generic_pm_domain *genpd,
 185                                struct dev_power_governor *gov, bool is_off)
 186{
 187        return -ENOSYS;
 188}
 189static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
 190{
 191        return -ENOTSUPP;
 192}
 193
 194static inline int dev_pm_genpd_set_performance_state(struct device *dev,
 195                                                     unsigned int state)
 196{
 197        return -ENOTSUPP;
 198}
 199
 200#define simple_qos_governor             (*(struct dev_power_governor *)(NULL))
 201#define pm_domain_always_on_gov         (*(struct dev_power_governor *)(NULL))
 202#endif
 203
 204#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
 205void pm_genpd_syscore_poweroff(struct device *dev);
 206void pm_genpd_syscore_poweron(struct device *dev);
 207#else
 208static inline void pm_genpd_syscore_poweroff(struct device *dev) {}
 209static inline void pm_genpd_syscore_poweron(struct device *dev) {}
 210#endif
 211
 212/* OF PM domain providers */
 213struct of_device_id;
 214
 215typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
 216                                                   void *data);
 217
 218struct genpd_onecell_data {
 219        struct generic_pm_domain **domains;
 220        unsigned int num_domains;
 221        genpd_xlate_t xlate;
 222};
 223
 224#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 225int of_genpd_add_provider_simple(struct device_node *np,
 226                                 struct generic_pm_domain *genpd);
 227int of_genpd_add_provider_onecell(struct device_node *np,
 228                                  struct genpd_onecell_data *data);
 229void of_genpd_del_provider(struct device_node *np);
 230int of_genpd_add_device(struct of_phandle_args *args, struct device *dev);
 231int of_genpd_add_subdomain(struct of_phandle_args *parent,
 232                           struct of_phandle_args *new_subdomain);
 233struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
 234int of_genpd_parse_idle_states(struct device_node *dn,
 235                               struct genpd_power_state **states, int *n);
 236unsigned int of_genpd_opp_to_performance_state(struct device *dev,
 237                                struct device_node *np);
 238
 239int genpd_dev_pm_attach(struct device *dev);
 240struct device *genpd_dev_pm_attach_by_id(struct device *dev,
 241                                         unsigned int index);
 242#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
 243static inline int of_genpd_add_provider_simple(struct device_node *np,
 244                                        struct generic_pm_domain *genpd)
 245{
 246        return -ENOTSUPP;
 247}
 248
 249static inline int of_genpd_add_provider_onecell(struct device_node *np,
 250                                        struct genpd_onecell_data *data)
 251{
 252        return -ENOTSUPP;
 253}
 254
 255static inline void of_genpd_del_provider(struct device_node *np) {}
 256
 257static inline int of_genpd_add_device(struct of_phandle_args *args,
 258                                      struct device *dev)
 259{
 260        return -ENODEV;
 261}
 262
 263static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
 264                                         struct of_phandle_args *new_subdomain)
 265{
 266        return -ENODEV;
 267}
 268
 269static inline int of_genpd_parse_idle_states(struct device_node *dn,
 270                        struct genpd_power_state **states, int *n)
 271{
 272        return -ENODEV;
 273}
 274
 275static inline unsigned int
 276of_genpd_opp_to_performance_state(struct device *dev,
 277                                  struct device_node *np)
 278{
 279        return 0;
 280}
 281
 282static inline int genpd_dev_pm_attach(struct device *dev)
 283{
 284        return 0;
 285}
 286
 287static inline struct device *genpd_dev_pm_attach_by_id(struct device *dev,
 288                                                       unsigned int index)
 289{
 290        return NULL;
 291}
 292
 293static inline
 294struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
 295{
 296        return ERR_PTR(-ENOTSUPP);
 297}
 298#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 299
 300#ifdef CONFIG_PM
 301int dev_pm_domain_attach(struct device *dev, bool power_on);
 302struct device *dev_pm_domain_attach_by_id(struct device *dev,
 303                                          unsigned int index);
 304void dev_pm_domain_detach(struct device *dev, bool power_off);
 305void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
 306#else
 307static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
 308{
 309        return 0;
 310}
 311static inline struct device *dev_pm_domain_attach_by_id(struct device *dev,
 312                                                        unsigned int index)
 313{
 314        return NULL;
 315}
 316static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
 317static inline void dev_pm_domain_set(struct device *dev,
 318                                     struct dev_pm_domain *pd) {}
 319#endif
 320
 321#endif /* _LINUX_PM_DOMAIN_H */
 322