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        const char *name;
  55        atomic_t sd_count;      /* Number of subdomains with power "on" */
  56        enum gpd_status status; /* Current state of the domain */
  57        unsigned int device_count;      /* Number of devices */
  58        unsigned int suspended_count;   /* System suspend device counter */
  59        unsigned int prepared_count;    /* Suspend counter of prepared devices */
  60        int (*power_off)(struct generic_pm_domain *domain);
  61        int (*power_on)(struct generic_pm_domain *domain);
  62        struct gpd_dev_ops dev_ops;
  63        s64 max_off_time_ns;    /* Maximum allowed "suspended" time. */
  64        bool max_off_time_changed;
  65        bool cached_power_down_ok;
  66        int (*attach_dev)(struct generic_pm_domain *domain,
  67                          struct device *dev);
  68        void (*detach_dev)(struct generic_pm_domain *domain,
  69                           struct device *dev);
  70        unsigned int flags;             /* Bit field of configs for genpd */
  71        struct genpd_power_state states[GENPD_MAX_NUM_STATES];
  72        unsigned int state_count; /* number of states */
  73        unsigned int state_idx; /* state that genpd will go to when off */
  74
  75};
  76
  77static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
  78{
  79        return container_of(pd, struct generic_pm_domain, domain);
  80}
  81
  82struct gpd_link {
  83        struct generic_pm_domain *master;
  84        struct list_head master_node;
  85        struct generic_pm_domain *slave;
  86        struct list_head slave_node;
  87};
  88
  89struct gpd_timing_data {
  90        s64 suspend_latency_ns;
  91        s64 resume_latency_ns;
  92        s64 effective_constraint_ns;
  93        bool constraint_changed;
  94        bool cached_suspend_ok;
  95};
  96
  97struct pm_domain_data {
  98        struct list_head list_node;
  99        struct device *dev;
 100};
 101
 102struct generic_pm_domain_data {
 103        struct pm_domain_data base;
 104        struct gpd_timing_data td;
 105        struct notifier_block nb;
 106};
 107
 108#ifdef CONFIG_PM_GENERIC_DOMAINS
 109static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd)
 110{
 111        return container_of(pdd, struct generic_pm_domain_data, base);
 112}
 113
 114static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 115{
 116        return to_gpd_data(dev->power.subsys_data->domain_data);
 117}
 118
 119extern struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev);
 120extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
 121                                 struct device *dev,
 122                                 struct gpd_timing_data *td);
 123
 124extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 125                                  struct device *dev);
 126extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 127                                  struct generic_pm_domain *new_subdomain);
 128extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 129                                     struct generic_pm_domain *target);
 130extern int pm_genpd_init(struct generic_pm_domain *genpd,
 131                         struct dev_power_governor *gov, bool is_off);
 132
 133extern struct dev_power_governor simple_qos_governor;
 134extern struct dev_power_governor pm_domain_always_on_gov;
 135#else
 136
 137static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 138{
 139        return ERR_PTR(-ENOSYS);
 140}
 141static inline struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
 142{
 143        return NULL;
 144}
 145static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
 146                                        struct device *dev,
 147                                        struct gpd_timing_data *td)
 148{
 149        return -ENOSYS;
 150}
 151static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 152                                         struct device *dev)
 153{
 154        return -ENOSYS;
 155}
 156static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 157                                         struct generic_pm_domain *new_sd)
 158{
 159        return -ENOSYS;
 160}
 161static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 162                                            struct generic_pm_domain *target)
 163{
 164        return -ENOSYS;
 165}
 166static inline int pm_genpd_init(struct generic_pm_domain *genpd,
 167                                struct dev_power_governor *gov, bool is_off)
 168{
 169        return -ENOSYS;
 170}
 171#endif
 172
 173static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
 174                                      struct device *dev)
 175{
 176        return __pm_genpd_add_device(genpd, dev, NULL);
 177}
 178
 179#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
 180extern void pm_genpd_syscore_poweroff(struct device *dev);
 181extern void pm_genpd_syscore_poweron(struct device *dev);
 182#else
 183static inline void pm_genpd_syscore_poweroff(struct device *dev) {}
 184static inline void pm_genpd_syscore_poweron(struct device *dev) {}
 185#endif
 186
 187/* OF PM domain providers */
 188struct of_device_id;
 189
 190struct genpd_onecell_data {
 191        struct generic_pm_domain **domains;
 192        unsigned int num_domains;
 193};
 194
 195typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
 196                                                void *data);
 197
 198#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 199int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
 200                        void *data);
 201void of_genpd_del_provider(struct device_node *np);
 202struct generic_pm_domain *of_genpd_get_from_provider(
 203                        struct of_phandle_args *genpdspec);
 204
 205struct generic_pm_domain *__of_genpd_xlate_simple(
 206                                        struct of_phandle_args *genpdspec,
 207                                        void *data);
 208struct generic_pm_domain *__of_genpd_xlate_onecell(
 209                                        struct of_phandle_args *genpdspec,
 210                                        void *data);
 211
 212int genpd_dev_pm_attach(struct device *dev);
 213#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
 214static inline int __of_genpd_add_provider(struct device_node *np,
 215                                        genpd_xlate_t xlate, void *data)
 216{
 217        return 0;
 218}
 219static inline void of_genpd_del_provider(struct device_node *np) {}
 220
 221static inline struct generic_pm_domain *of_genpd_get_from_provider(
 222                        struct of_phandle_args *genpdspec)
 223{
 224        return NULL;
 225}
 226
 227#define __of_genpd_xlate_simple         NULL
 228#define __of_genpd_xlate_onecell        NULL
 229
 230static inline int genpd_dev_pm_attach(struct device *dev)
 231{
 232        return -ENODEV;
 233}
 234#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 235
 236static inline int of_genpd_add_provider_simple(struct device_node *np,
 237                                        struct generic_pm_domain *genpd)
 238{
 239        return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd);
 240}
 241static inline int of_genpd_add_provider_onecell(struct device_node *np,
 242                                        struct genpd_onecell_data *data)
 243{
 244        return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data);
 245}
 246
 247#ifdef CONFIG_PM
 248extern int dev_pm_domain_attach(struct device *dev, bool power_on);
 249extern void dev_pm_domain_detach(struct device *dev, bool power_off);
 250extern void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
 251#else
 252static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
 253{
 254        return -ENODEV;
 255}
 256static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
 257static inline void dev_pm_domain_set(struct device *dev,
 258                                     struct dev_pm_domain *pd) {}
 259#endif
 260
 261#endif /* _LINUX_PM_DOMAIN_H */
 262