Commit ba1389d7 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'pm-domains' into for-linus

* pm-domains: (33 commits)
  ARM / shmobile: Return -EBUSY from A4LC power off if A3RV is active
  PM / Domains: Take .power_off() error code into account
  ARM / shmobile: Use genpd_queue_power_off_work()
  ARM / shmobile: Use pm_genpd_poweroff_unused()
  PM / Domains: Introduce function to power off all unused PM domains
  PM / Domains: Queue up power off work only if it is not pending
  PM / Domains: Improve handling of wakeup devices during system suspend
  PM / Domains: Do not restore all devices on power off error
  PM / Domains: Allow callbacks to execute all runtime PM helpers
  PM / Domains: Do not execute device callbacks under locks
  PM / Domains: Make failing pm_genpd_prepare() clean up properly
  PM / Domains: Set device state to "active" during system resume
  ARM: mach-shmobile: sh7372 A3RV requires A4LC
  PM / Domains: Export pm_genpd_poweron() in header
  ARM: mach-shmobile: sh7372 late pm domain off
  ARM: mach-shmobile: Runtime PM late init callback
  ARM: mach-shmobile: sh7372 D4 support
  ARM: mach-shmobile: sh7372 A4MP support
  ARM: mach-shmobile: sh7372: make sure that fsi is peripheral of spu2
  ARM: mach-shmobile: sh7372 A3SG support
  ...
parents f0c077a8 5ca80817
...@@ -506,8 +506,8 @@ routines. Nevertheless, different callback pointers are used in case there is a ...@@ -506,8 +506,8 @@ routines. Nevertheless, different callback pointers are used in case there is a
situation where it actually matters. situation where it actually matters.
Device Power Domains Device Power Management Domains
-------------------- -------------------------------
Sometimes devices share reference clocks or other power resources. In those Sometimes devices share reference clocks or other power resources. In those
cases it generally is not possible to put devices into low-power states cases it generally is not possible to put devices into low-power states
individually. Instead, a set of devices sharing a power resource can be put individually. Instead, a set of devices sharing a power resource can be put
...@@ -516,8 +516,8 @@ power resource. Of course, they also need to be put into the full-power state ...@@ -516,8 +516,8 @@ power resource. Of course, they also need to be put into the full-power state
together, by turning the shared power resource on. A set of devices with this together, by turning the shared power resource on. A set of devices with this
property is often referred to as a power domain. property is often referred to as a power domain.
Support for power domains is provided through the pwr_domain field of struct Support for power domains is provided through the pm_domain field of struct
device. This field is a pointer to an object of type struct dev_power_domain, device. This field is a pointer to an object of type struct dev_pm_domain,
defined in include/linux/pm.h, providing a set of power management callbacks defined in include/linux/pm.h, providing a set of power management callbacks
analogous to the subsystem-level and device driver callbacks that are executed analogous to the subsystem-level and device driver callbacks that are executed
for the given device during all power transitions, instead of the respective for the given device during all power transitions, instead of the respective
......
...@@ -606,32 +606,60 @@ driver/base/power/generic_ops.c: ...@@ -606,32 +606,60 @@ driver/base/power/generic_ops.c:
callback provided by its driver and return its result, or return 0 if not callback provided by its driver and return its result, or return 0 if not
defined defined
int pm_generic_suspend_noirq(struct device *dev);
- if pm_runtime_suspended(dev) returns "false", invoke the ->suspend_noirq()
callback provided by the device's driver and return its result, or return
0 if not defined
int pm_generic_resume(struct device *dev); int pm_generic_resume(struct device *dev);
- invoke the ->resume() callback provided by the driver of this device and, - invoke the ->resume() callback provided by the driver of this device and,
if successful, change the device's runtime PM status to 'active' if successful, change the device's runtime PM status to 'active'
int pm_generic_resume_noirq(struct device *dev);
- invoke the ->resume_noirq() callback provided by the driver of this device
int pm_generic_freeze(struct device *dev); int pm_generic_freeze(struct device *dev);
- if the device has not been suspended at run time, invoke the ->freeze() - if the device has not been suspended at run time, invoke the ->freeze()
callback provided by its driver and return its result, or return 0 if not callback provided by its driver and return its result, or return 0 if not
defined defined
int pm_generic_freeze_noirq(struct device *dev);
- if pm_runtime_suspended(dev) returns "false", invoke the ->freeze_noirq()
callback provided by the device's driver and return its result, or return
0 if not defined
int pm_generic_thaw(struct device *dev); int pm_generic_thaw(struct device *dev);
- if the device has not been suspended at run time, invoke the ->thaw() - if the device has not been suspended at run time, invoke the ->thaw()
callback provided by its driver and return its result, or return 0 if not callback provided by its driver and return its result, or return 0 if not
defined defined
int pm_generic_thaw_noirq(struct device *dev);
- if pm_runtime_suspended(dev) returns "false", invoke the ->thaw_noirq()
callback provided by the device's driver and return its result, or return
0 if not defined
int pm_generic_poweroff(struct device *dev); int pm_generic_poweroff(struct device *dev);
- if the device has not been suspended at run time, invoke the ->poweroff() - if the device has not been suspended at run time, invoke the ->poweroff()
callback provided by its driver and return its result, or return 0 if not callback provided by its driver and return its result, or return 0 if not
defined defined
int pm_generic_poweroff_noirq(struct device *dev);
- if pm_runtime_suspended(dev) returns "false", run the ->poweroff_noirq()
callback provided by the device's driver and return its result, or return
0 if not defined
int pm_generic_restore(struct device *dev); int pm_generic_restore(struct device *dev);
- invoke the ->restore() callback provided by the driver of this device and, - invoke the ->restore() callback provided by the driver of this device and,
if successful, change the device's runtime PM status to 'active' if successful, change the device's runtime PM status to 'active'
int pm_generic_restore_noirq(struct device *dev);
- invoke the ->restore_noirq() callback provided by the device's driver
These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(), These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(),
->runtime_resume(), ->suspend(), ->resume(), ->freeze(), ->thaw(), ->poweroff(), ->runtime_resume(), ->suspend(), ->suspend_noirq(), ->resume(),
or ->restore() callback pointers in the subsystem-level dev_pm_ops structures. ->resume_noirq(), ->freeze(), ->freeze_noirq(), ->thaw(), ->thaw_noirq(),
->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() callback
pointers in the subsystem-level dev_pm_ops structures.
If a subsystem wishes to use all of them at the same time, it can simply assign If a subsystem wishes to use all of them at the same time, it can simply assign
the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its
......
...@@ -642,6 +642,7 @@ config ARCH_SHMOBILE ...@@ -642,6 +642,7 @@ config ARCH_SHMOBILE
select NO_IOPORT select NO_IOPORT
select SPARSE_IRQ select SPARSE_IRQ
select MULTI_IRQ_HANDLER select MULTI_IRQ_HANDLER
select PM_GENERIC_DOMAINS if PM
help help
Support for Renesas's SH-Mobile and R-Mobile ARM platforms. Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
......
...@@ -32,7 +32,7 @@ static int omap1_pm_runtime_suspend(struct device *dev) ...@@ -32,7 +32,7 @@ static int omap1_pm_runtime_suspend(struct device *dev)
if (ret) if (ret)
return ret; return ret;
ret = pm_runtime_clk_suspend(dev); ret = pm_clk_suspend(dev);
if (ret) { if (ret) {
pm_generic_runtime_resume(dev); pm_generic_runtime_resume(dev);
return ret; return ret;
...@@ -45,24 +45,24 @@ static int omap1_pm_runtime_resume(struct device *dev) ...@@ -45,24 +45,24 @@ static int omap1_pm_runtime_resume(struct device *dev)
{ {
dev_dbg(dev, "%s\n", __func__); dev_dbg(dev, "%s\n", __func__);
pm_runtime_clk_resume(dev); pm_clk_resume(dev);
return pm_generic_runtime_resume(dev); return pm_generic_runtime_resume(dev);
} }
static struct dev_power_domain default_power_domain = { static struct dev_pm_domain default_pm_domain = {
.ops = { .ops = {
.runtime_suspend = omap1_pm_runtime_suspend, .runtime_suspend = omap1_pm_runtime_suspend,
.runtime_resume = omap1_pm_runtime_resume, .runtime_resume = omap1_pm_runtime_resume,
USE_PLATFORM_PM_SLEEP_OPS USE_PLATFORM_PM_SLEEP_OPS
}, },
}; };
#define OMAP1_PWR_DOMAIN (&default_power_domain) #define OMAP1_PM_DOMAIN (&default_pm_domain)
#else #else
#define OMAP1_PWR_DOMAIN NULL #define OMAP1_PM_DOMAIN NULL
#endif /* CONFIG_PM_RUNTIME */ #endif /* CONFIG_PM_RUNTIME */
static struct pm_clk_notifier_block platform_bus_notifier = { static struct pm_clk_notifier_block platform_bus_notifier = {
.pwr_domain = OMAP1_PWR_DOMAIN, .pm_domain = OMAP1_PM_DOMAIN,
.con_ids = { "ick", "fck", NULL, }, .con_ids = { "ick", "fck", NULL, },
}; };
...@@ -71,7 +71,7 @@ static int __init omap1_pm_runtime_init(void) ...@@ -71,7 +71,7 @@ static int __init omap1_pm_runtime_init(void)
if (!cpu_class_is_omap1()) if (!cpu_class_is_omap1())
return -ENODEV; return -ENODEV;
pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
return 0; return 0;
} }
......
...@@ -1408,9 +1408,14 @@ static void __init ap4evb_init(void) ...@@ -1408,9 +1408,14 @@ static void __init ap4evb_init(void)
platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc1_device);
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
hdmi_init_pm_clock(); hdmi_init_pm_clock();
fsi_init_pm_clock(); fsi_init_pm_clock();
sh7372_pm_init(); sh7372_pm_init();
pm_clk_add(&fsi_device.dev, "spu2");
} }
static void __init ap4evb_timer_init(void) static void __init ap4evb_timer_init(void)
......
...@@ -1582,8 +1582,13 @@ static void __init mackerel_init(void) ...@@ -1582,8 +1582,13 @@ static void __init mackerel_init(void)
platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
hdmi_init_pm_clock(); hdmi_init_pm_clock();
sh7372_pm_init(); sh7372_pm_init();
pm_clk_add(&fsi_device.dev, "spu2");
} }
static void __init mackerel_timer_init(void) static void __init mackerel_timer_init(void)
......
...@@ -662,6 +662,7 @@ static struct clk_lookup lookups[] = { ...@@ -662,6 +662,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
}; };
void __init sh7372_clock_init(void) void __init sh7372_clock_init(void)
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define __ASM_SH7372_H__ #define __ASM_SH7372_H__
#include <linux/sh_clk.h> #include <linux/sh_clk.h>
#include <linux/pm_domain.h>
/* /*
* Pin Function Controller: * Pin Function Controller:
...@@ -470,4 +471,32 @@ extern struct clk sh7372_fsibck_clk; ...@@ -470,4 +471,32 @@ extern struct clk sh7372_fsibck_clk;
extern struct clk sh7372_fsidiva_clk; extern struct clk sh7372_fsidiva_clk;
extern struct clk sh7372_fsidivb_clk; extern struct clk sh7372_fsidivb_clk;
struct platform_device;
struct sh7372_pm_domain {
struct generic_pm_domain genpd;
unsigned int bit_shift;
};
static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
{
return container_of(d, struct sh7372_pm_domain, genpd);
}
#ifdef CONFIG_PM
extern struct sh7372_pm_domain sh7372_a4lc;
extern struct sh7372_pm_domain sh7372_a4mp;
extern struct sh7372_pm_domain sh7372_d4;
extern struct sh7372_pm_domain sh7372_a3rv;
extern struct sh7372_pm_domain sh7372_a3ri;
extern struct sh7372_pm_domain sh7372_a3sg;
extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd);
extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
struct platform_device *pdev);
#else
#define sh7372_init_pm_domain(pd) do { } while(0)
#define sh7372_add_device_to_domain(pd, pdev) do { } while(0)
#endif /* CONFIG_PM */
#endif /* __ASM_SH7372_H__ */ #endif /* __ASM_SH7372_H__ */
...@@ -15,16 +15,176 @@ ...@@ -15,16 +15,176 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <mach/common.h> #include <mach/common.h>
#include <mach/sh7372.h>
#define SMFRAM 0xe6a70000 #define SMFRAM 0xe6a70000
#define SYSTBCR 0xe6150024 #define SYSTBCR 0xe6150024
#define SBAR 0xe6180020 #define SBAR 0xe6180020
#define APARMBAREA 0xe6f10020 #define APARMBAREA 0xe6f10020
#define SPDCR 0xe6180008
#define SWUCR 0xe6180014
#define PSTR 0xe6180080
#define PSTR_RETRIES 100
#define PSTR_DELAY_US 10
#ifdef CONFIG_PM
static int pd_power_down(struct generic_pm_domain *genpd)
{
struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
unsigned int mask = 1 << sh7372_pd->bit_shift;
if (__raw_readl(PSTR) & mask) {
unsigned int retry_count;
__raw_writel(mask, SPDCR);
for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
if (!(__raw_readl(SPDCR) & mask))
break;
cpu_relax();
}
}
pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
mask, __raw_readl(PSTR));
return 0;
}
static int pd_power_up(struct generic_pm_domain *genpd)
{
struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
unsigned int mask = 1 << sh7372_pd->bit_shift;
unsigned int retry_count;
int ret = 0;
if (__raw_readl(PSTR) & mask)
goto out;
__raw_writel(mask, SWUCR);
for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
if (!(__raw_readl(SWUCR) & mask))
goto out;
if (retry_count > PSTR_RETRIES)
udelay(PSTR_DELAY_US);
else
cpu_relax();
}
if (__raw_readl(SWUCR) & mask)
ret = -EIO;
out:
pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
mask, __raw_readl(PSTR));
return ret;
}
static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
{
int ret = pd_power_up(genpd);
/* force A4LC on after A3RV has been requested on */
pm_genpd_poweron(&sh7372_a4lc.genpd);
return ret;
}
static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
{
int ret = pd_power_down(genpd);
/* try to power down A4LC after A3RV is requested off */
genpd_queue_power_off_work(&sh7372_a4lc.genpd);
return ret;
}
static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
{
/* only power down A4LC if A3RV is off */
if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
return pd_power_down(genpd);
return -EBUSY;
}
static bool pd_active_wakeup(struct device *dev)
{
return true;
}
void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
{
struct generic_pm_domain *genpd = &sh7372_pd->genpd;
pm_genpd_init(genpd, NULL, false);
genpd->stop_device = pm_clk_suspend;
genpd->start_device = pm_clk_resume;
genpd->active_wakeup = pd_active_wakeup;
if (sh7372_pd == &sh7372_a4lc) {
genpd->power_off = pd_power_down_a4lc;
genpd->power_on = pd_power_up;
} else if (sh7372_pd == &sh7372_a3rv) {
genpd->power_off = pd_power_down_a3rv;
genpd->power_on = pd_power_up_a3rv;
} else {
genpd->power_off = pd_power_down;
genpd->power_on = pd_power_up;
}
genpd->power_on(&sh7372_pd->genpd);
}
void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
if (!dev->power.subsys_data) {
pm_clk_init(dev);
pm_clk_add(dev, NULL);
}
pm_genpd_add_device(&sh7372_pd->genpd, dev);
}
struct sh7372_pm_domain sh7372_a4lc = {
.bit_shift = 1,
};
struct sh7372_pm_domain sh7372_a4mp = {
.bit_shift = 2,
};
struct sh7372_pm_domain sh7372_d4 = {
.bit_shift = 3,
};
struct sh7372_pm_domain sh7372_a3rv = {
.bit_shift = 6,
};
struct sh7372_pm_domain sh7372_a3ri = {
.bit_shift = 8,
};
struct sh7372_pm_domain sh7372_a3sg = {
.bit_shift = 13,
};
#endif /* CONFIG_PM */
static void sh7372_enter_core_standby(void) static void sh7372_enter_core_standby(void)
{ {
void __iomem *smfram = (void __iomem *)SMFRAM; void __iomem *smfram = (void __iomem *)SMFRAM;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/sh_clk.h> #include <linux/sh_clk.h>
...@@ -28,31 +29,38 @@ static int default_platform_runtime_idle(struct device *dev) ...@@ -28,31 +29,38 @@ static int default_platform_runtime_idle(struct device *dev)
return pm_runtime_suspend(dev); return pm_runtime_suspend(dev);
} }
static struct dev_power_domain default_power_domain = { static struct dev_pm_domain default_pm_domain = {
.ops = { .ops = {
.runtime_suspend = pm_runtime_clk_suspend, .runtime_suspend = pm_clk_suspend,
.runtime_resume = pm_runtime_clk_resume, .runtime_resume = pm_clk_resume,
.runtime_idle = default_platform_runtime_idle, .runtime_idle = default_platform_runtime_idle,
USE_PLATFORM_PM_SLEEP_OPS USE_PLATFORM_PM_SLEEP_OPS
}, },
}; };
#define DEFAULT_PWR_DOMAIN_PTR (&default_power_domain) #define DEFAULT_PM_DOMAIN_PTR (&default_pm_domain)
#else #else
#define DEFAULT_PWR_DOMAIN_PTR NULL #define DEFAULT_PM_DOMAIN_PTR NULL
#endif /* CONFIG_PM_RUNTIME */ #endif /* CONFIG_PM_RUNTIME */
static struct pm_clk_notifier_block platform_bus_notifier = { static struct pm_clk_notifier_block platform_bus_notifier = {
.pwr_domain = DEFAULT_PWR_DOMAIN_PTR, .pm_domain = DEFAULT_PM_DOMAIN_PTR,
.con_ids = { NULL, }, .con_ids = { NULL, },
}; };
static int __init sh_pm_runtime_init(void) static int __init sh_pm_runtime_init(void)
{ {
pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
return 0; return 0;
} }
core_initcall(sh_pm_runtime_init); core_initcall(sh_pm_runtime_init);
static int __init sh_pm_runtime_late_init(void)
{
pm_genpd_poweroff_unused();
return 0;
}
late_initcall(sh_pm_runtime_late_init);
...@@ -841,11 +841,22 @@ static struct platform_device *sh7372_late_devices[] __initdata = { ...@@ -841,11 +841,22 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
void __init sh7372_add_standard_devices(void) void __init sh7372_add_standard_devices(void)
{ {
sh7372_init_pm_domain(&sh7372_a4lc);
sh7372_init_pm_domain(&sh7372_a4mp);
sh7372_init_pm_domain(&sh7372_d4);
sh7372_init_pm_domain(&sh7372_a3rv);
sh7372_init_pm_domain(&sh7372_a3ri);
sh7372_init_pm_domain(&sh7372_a3sg);
platform_add_devices(sh7372_early_devices, platform_add_devices(sh7372_early_devices,
ARRAY_SIZE(sh7372_early_devices)); ARRAY_SIZE(sh7372_early_devices));
platform_add_devices(sh7372_late_devices, platform_add_devices(sh7372_late_devices,
ARRAY_SIZE(sh7372_late_devices)); ARRAY_SIZE(sh7372_late_devices));
sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device);
} }
void __init sh7372_add_early_devices(void) void __init sh7372_add_early_devices(void)
......
...@@ -564,7 +564,7 @@ static int _od_runtime_resume(struct device *dev) ...@@ -564,7 +564,7 @@ static int _od_runtime_resume(struct device *dev)
return pm_generic_runtime_resume(dev); return pm_generic_runtime_resume(dev);
} }
static struct dev_power_domain omap_device_power_domain = { static struct dev_pm_domain omap_device_pm_domain = {
.ops = { .ops = {
.runtime_suspend = _od_runtime_suspend, .runtime_suspend = _od_runtime_suspend,
.runtime_idle = _od_runtime_idle, .runtime_idle = _od_runtime_idle,
...@@ -586,7 +586,7 @@ int omap_device_register(struct omap_device *od) ...@@ -586,7 +586,7 @@ int omap_device_register(struct omap_device *od)
pr_debug("omap_device: %s: registering\n", od->pdev.name); pr_debug("omap_device: %s: registering\n", od->pdev.name);
od->pdev.dev.parent = &omap_device_parent; od->pdev.dev.parent = &omap_device_parent;
od->pdev.dev.pwr_domain = &omap_device_power_domain; od->pdev.dev.pm_domain = &omap_device_pm_domain;
return platform_device_register(&od->pdev); return platform_device_register(&od->pdev);
} }
......
...@@ -256,7 +256,7 @@ static int default_platform_runtime_idle(struct device *dev) ...@@ -256,7 +256,7 @@ static int default_platform_runtime_idle(struct device *dev)
return ret; return ret;
} }
static struct dev_power_domain default_power_domain = { static struct dev_pm_domain default_pm_domain = {
.ops = { .ops = {
.runtime_suspend = default_platform_runtime_suspend, .runtime_suspend = default_platform_runtime_suspend,
.runtime_resume = default_platform_runtime_resume, .runtime_resume = default_platform_runtime_resume,
...@@ -285,7 +285,7 @@ static int platform_bus_notify(struct notifier_block *nb, ...@@ -285,7 +285,7 @@ static int platform_bus_notify(struct notifier_block *nb,
hwblk_disable(hwblk_info, hwblk); hwblk_disable(hwblk_info, hwblk);
/* make sure driver re-inits itself once */ /* make sure driver re-inits itself once */
__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
dev->pwr_domain = &default_power_domain; dev->pm_domain = &default_pm_domain;
break; break;
/* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */ /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
case BUS_NOTIFY_BOUND_DRIVER: case BUS_NOTIFY_BOUND_DRIVER:
...@@ -299,7 +299,7 @@ static int platform_bus_notify(struct notifier_block *nb, ...@@ -299,7 +299,7 @@ static int platform_bus_notify(struct notifier_block *nb,
__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
break; break;
case BUS_NOTIFY_DEL_DEVICE: case BUS_NOTIFY_DEL_DEVICE:
dev->pwr_domain = NULL; dev->pm_domain = NULL;
break; break;
} }
return 0; return 0;
......
...@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o ...@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o obj-$(CONFIG_PM_TRACE_RTC) += trace.o
obj-$(CONFIG_PM_OPP) += opp.o obj-$(CONFIG_PM_OPP) += opp.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o
obj-$(CONFIG_HAVE_CLK) += clock_ops.o obj-$(CONFIG_HAVE_CLK) += clock_ops.o
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
...@@ -94,12 +94,13 @@ int pm_generic_prepare(struct device *dev) ...@@ -94,12 +94,13 @@ int pm_generic_prepare(struct device *dev)
* __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback. * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
* @dev: Device to handle. * @dev: Device to handle.
* @event: PM transition of the system under way. * @event: PM transition of the system under way.
* @bool: Whether or not this is the "noirq" stage.
* *
* If the device has not been suspended at run time, execute the * If the device has not been suspended at run time, execute the
* suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and
* return its error code. Otherwise, return zero. * return its error code. Otherwise, return zero.
*/ */
static int __pm_generic_call(struct device *dev, int event) static int __pm_generic_call(struct device *dev, int event, bool noirq)
{ {
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int (*callback)(struct device *); int (*callback)(struct device *);
...@@ -109,16 +110,16 @@ static int __pm_generic_call(struct device *dev, int event) ...@@ -109,16 +110,16 @@ static int __pm_generic_call(struct device *dev, int event)
switch (event) { switch (event) {
case PM_EVENT_SUSPEND: case PM_EVENT_SUSPEND:
callback = pm->suspend; callback = noirq ? pm->suspend_noirq : pm->suspend;
break; break;
case PM_EVENT_FREEZE: case PM_EVENT_FREEZE:
callback = pm->freeze; callback = noirq ? pm->freeze_noirq : pm->freeze;
break; break;
case PM_EVENT_HIBERNATE: case PM_EVENT_HIBERNATE:
callback = pm->poweroff; callback = noirq ? pm->poweroff_noirq : pm->poweroff;
break; break;
case PM_EVENT_THAW: case PM_EVENT_THAW:
callback = pm->thaw; callback = noirq ? pm->thaw_noirq : pm->thaw;
break; break;
default: default:
callback = NULL; callback = NULL;
...@@ -128,43 +129,83 @@ static int __pm_generic_call(struct device *dev, int event) ...@@ -128,43 +129,83 @@ static int __pm_generic_call(struct device *dev, int event)
return callback ? callback(dev) : 0; return callback ? callback(dev) : 0;
} }
/**
* pm_generic_suspend_noirq - Generic suspend_noirq callback for subsystems.
* @dev: Device to suspend.
*/
int pm_generic_suspend_noirq(struct device *dev)
{
return __pm_generic_call(dev, PM_EVENT_SUSPEND, true);
}
EXPORT_SYMBOL_GPL(pm_generic_suspend_noirq);
/** /**
* pm_generic_suspend - Generic suspend callback for subsystems. * pm_generic_suspend - Generic suspend callback for subsystems.
* @dev: Device to suspend. * @dev: Device to suspend.
*/ */
int pm_generic_suspend(struct device *dev) int pm_generic_suspend(struct device *dev)
{ {
return __pm_generic_call(dev, PM_EVENT_SUSPEND); return __pm_generic_call(dev, PM_EVENT_SUSPEND, false);
} }
EXPORT_SYMBOL_GPL(pm_generic_suspend); EXPORT_SYMBOL_GPL(pm_generic_suspend);
/**
* pm_generic_freeze_noirq - Generic freeze_noirq callback for subsystems.
* @dev: Device to freeze.
*/
int pm_generic_freeze_noirq(struct device *dev)
{
return __pm_generic_call(dev, PM_EVENT_FREEZE, true);
}
EXPORT_SYMBOL_GPL(pm_generic_freeze_noirq);
/** /**
* pm_generic_freeze - Generic freeze callback for subsystems. * pm_generic_freeze - Generic freeze callback for subsystems.
* @dev: Device to freeze. * @dev: Device to freeze.
*/ */
int pm_generic_freeze(struct device *dev) int pm_generic_freeze(struct device *dev)
{ {
return __pm_generic_call(dev, PM_EVENT_FREEZE); return __pm_generic_call(dev, PM_EVENT_FREEZE, false);
} }
EXPORT_SYMBOL_GPL(pm_generic_freeze); EXPORT_SYMBOL_GPL(pm_generic_freeze);
/**
* pm_generic_poweroff_noirq - Generic poweroff_noirq callback for subsystems.
* @dev: Device to handle.
*/
int pm_generic_poweroff_noirq(struct device *dev)
{
return __pm_generic_call(dev, PM_EVENT_HIBERNATE, true);
}
EXPORT_SYMBOL_GPL(pm_generic_poweroff_noirq);
/** /**
* pm_generic_poweroff - Generic poweroff callback for subsystems. * pm_generic_poweroff - Generic poweroff callback for subsystems.
* @dev: Device to handle. * @dev: Device to handle.
*/ */
int pm_generic_poweroff(struct device *dev) int pm_generic_poweroff(struct device *dev)
{ {
return __pm_generic_call(dev, PM_EVENT_HIBERNATE); return __pm_generic_call(dev, PM_EVENT_HIBERNATE, false);
} }
EXPORT_SYMBOL_GPL(pm_generic_poweroff); EXPORT_SYMBOL_GPL(pm_generic_poweroff);
/**
* pm_generic_thaw_noirq - Generic thaw_noirq callback for subsystems.
* @dev: Device to thaw.
*/
int pm_generic_thaw_noirq(struct device *dev)
{
return __pm_generic_call(dev, PM_EVENT_THAW, true);
}
EXPORT_SYMBOL_GPL(pm_generic_thaw_noirq);
/** /**
* pm_generic_thaw - Generic thaw callback for subsystems. * pm_generic_thaw - Generic thaw callback for subsystems.
* @dev: Device to thaw. * @dev: Device to thaw.
*/ */
int pm_generic_thaw(struct device *dev) int pm_generic_thaw(struct device *dev)
{ {
return __pm_generic_call(dev, PM_EVENT_THAW); return __pm_generic_call(dev, PM_EVENT_THAW, false);
} }
EXPORT_SYMBOL_GPL(pm_generic_thaw); EXPORT_SYMBOL_GPL(pm_generic_thaw);
...@@ -172,12 +213,13 @@ EXPORT_SYMBOL_GPL(pm_generic_thaw); ...@@ -172,12 +213,13 @@ EXPORT_SYMBOL_GPL(pm_generic_thaw);
* __pm_generic_resume - Generic resume/restore callback for subsystems. * __pm_generic_resume - Generic resume/restore callback for subsystems.
* @dev: Device to handle. * @dev: Device to handle.
* @event: PM transition of the system under way. * @event: PM transition of the system under way.
* @bool: Whether or not this is the "noirq" stage.
* *
* Execute the resume/resotre callback provided by the @dev's driver, if * Execute the resume/resotre callback provided by the @dev's driver, if
* defined. If it returns 0, change the device's runtime PM status to 'active'. * defined. If it returns 0, change the device's runtime PM status to 'active'.
* Return the callback's error code. * Return the callback's error code.
*/ */
static int __pm_generic_resume(struct device *dev, int event) static int __pm_generic_resume(struct device *dev, int event, bool noirq)
{ {
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int (*callback)(struct device *); int (*callback)(struct device *);
...@@ -188,10 +230,10 @@ static int __pm_generic_resume(struct device *dev, int event) ...@@ -188,10 +230,10 @@ static int __pm_generic_resume(struct device *dev, int event)
switch (event) { switch (event) {
case PM_EVENT_RESUME: case PM_EVENT_RESUME:
callback = pm->resume; callback = noirq ? pm->resume_noirq : pm->resume;
break; break;
case PM_EVENT_RESTORE: case PM_EVENT_RESTORE:
callback = pm->restore; callback = noirq ? pm->restore_noirq : pm->restore;
break; break;
default: default:
callback = NULL; callback = NULL;
...@@ -202,7 +244,7 @@ static int __pm_generic_resume(struct device *dev, int event) ...@@ -202,7 +244,7 @@ static int __pm_generic_resume(struct device *dev, int event)
return 0; return 0;
ret = callback(dev); ret = callback(dev);
if (!ret && pm_runtime_enabled(dev)) { if (!ret && !noirq && pm_runtime_enabled(dev)) {
pm_runtime_disable(dev); pm_runtime_disable(dev);
pm_runtime_set_active(dev); pm_runtime_set_active(dev);
pm_runtime_enable(dev); pm_runtime_enable(dev);
...@@ -211,23 +253,43 @@ static int __pm_generic_resume(struct device *dev, int event) ...@@ -211,23 +253,43 @@ static int __pm_generic_resume(struct device *dev, int event)
return ret; return ret;
} }
/**
* pm_generic_resume_noirq - Generic resume_noirq callback for subsystems.
* @dev: Device to resume.
*/
int pm_generic_resume_noirq(struct device *dev)
{
return __pm_generic_resume(dev, PM_EVENT_RESUME, true);
}
EXPORT_SYMBOL_GPL(pm_generic_resume_noirq);
/** /**
* pm_generic_resume - Generic resume callback for subsystems. * pm_generic_resume - Generic resume callback for subsystems.
* @dev: Device to resume. * @dev: Device to resume.
*/ */
int pm_generic_resume(struct device *dev) int pm_generic_resume(struct device *dev)
{ {
return __pm_generic_resume(dev, PM_EVENT_RESUME); return __pm_generic_resume(dev, PM_EVENT_RESUME, false);
} }
EXPORT_SYMBOL_GPL(pm_generic_resume); EXPORT_SYMBOL_GPL(pm_generic_resume);
/**
* pm_generic_restore_noirq - Generic restore_noirq callback for subsystems.
* @dev: Device to restore.
*/
int pm_generic_restore_noirq(struct device *dev)
{
return __pm_generic_resume(dev, PM_EVENT_RESTORE, true);
}
EXPORT_SYMBOL_GPL(pm_generic_restore_noirq);
/** /**
* pm_generic_restore - Generic restore callback for subsystems. * pm_generic_restore - Generic restore callback for subsystems.
* @dev: Device to restore. * @dev: Device to restore.
*/ */
int pm_generic_restore(struct device *dev) int pm_generic_restore(struct device *dev)
{ {
return __pm_generic_resume(dev, PM_EVENT_RESTORE); return __pm_generic_resume(dev, PM_EVENT_RESTORE, false);
} }
EXPORT_SYMBOL_GPL(pm_generic_restore); EXPORT_SYMBOL_GPL(pm_generic_restore);
...@@ -256,11 +318,17 @@ struct dev_pm_ops generic_subsys_pm_ops = { ...@@ -256,11 +318,17 @@ struct dev_pm_ops generic_subsys_pm_ops = {
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
.prepare = pm_generic_prepare, .prepare = pm_generic_prepare,
.suspend = pm_generic_suspend, .suspend = pm_generic_suspend,
.suspend_noirq = pm_generic_suspend_noirq,
.resume = pm_generic_resume, .resume = pm_generic_resume,
.resume_noirq = pm_generic_resume_noirq,
.freeze = pm_generic_freeze, .freeze = pm_generic_freeze,
.freeze_noirq = pm_generic_freeze_noirq,
.thaw = pm_generic_thaw, .thaw = pm_generic_thaw,
.thaw_noirq = pm_generic_thaw_noirq,
.poweroff = pm_generic_poweroff, .poweroff = pm_generic_poweroff,
.poweroff_noirq = pm_generic_poweroff_noirq,
.restore = pm_generic_restore, .restore = pm_generic_restore,
.restore_noirq = pm_generic_restore_noirq,
.complete = pm_generic_complete, .complete = pm_generic_complete,
#endif #endif
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
......
...@@ -425,9 +425,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) ...@@ -425,9 +425,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
TRACE_DEVICE(dev); TRACE_DEVICE(dev);
TRACE_RESUME(0); TRACE_RESUME(0);
if (dev->pwr_domain) { if (dev->pm_domain) {
pm_dev_dbg(dev, state, "EARLY power domain "); pm_dev_dbg(dev, state, "EARLY power domain ");
error = pm_noirq_op(dev, &dev->pwr_domain->ops, state); error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
} else if (dev->type && dev->type->pm) { } else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "EARLY type "); pm_dev_dbg(dev, state, "EARLY type ");
error = pm_noirq_op(dev, dev->type->pm, state); error = pm_noirq_op(dev, dev->type->pm, state);
...@@ -521,9 +521,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) ...@@ -521,9 +521,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
if (!dev->power.is_suspended) if (!dev->power.is_suspended)
goto Unlock; goto Unlock;
if (dev->pwr_domain) { if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain "); pm_dev_dbg(dev, state, "power domain ");
error = pm_op(dev, &dev->pwr_domain->ops, state); error = pm_op(dev, &dev->pm_domain->ops, state);
goto End; goto End;
} }
...@@ -641,10 +641,10 @@ static void device_complete(struct device *dev, pm_message_t state) ...@@ -641,10 +641,10 @@ static void device_complete(struct device *dev, pm_message_t state)
{ {
device_lock(dev); device_lock(dev);
if (dev->pwr_domain) { if (dev->pm_domain) {
pm_dev_dbg(dev, state, "completing power domain "); pm_dev_dbg(dev, state, "completing power domain ");
if (dev->pwr_domain->ops.complete) if (dev->pm_domain->ops.complete)
dev->pwr_domain->ops.complete(dev); dev->pm_domain->ops.complete(dev);
} else if (dev->type && dev->type->pm) { } else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "completing type "); pm_dev_dbg(dev, state, "completing type ");
if (dev->type->pm->complete) if (dev->type->pm->complete)
...@@ -744,9 +744,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) ...@@ -744,9 +744,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
{ {
int error; int error;
if (dev->pwr_domain) { if (dev->pm_domain) {
pm_dev_dbg(dev, state, "LATE power domain "); pm_dev_dbg(dev, state, "LATE power domain ");
error = pm_noirq_op(dev, &dev->pwr_domain->ops, state); error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
if (error) if (error)
return error; return error;
} else if (dev->type && dev->type->pm) { } else if (dev->type && dev->type->pm) {
...@@ -853,9 +853,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) ...@@ -853,9 +853,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
goto Unlock; goto Unlock;
} }
if (dev->pwr_domain) { if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain "); pm_dev_dbg(dev, state, "power domain ");
error = pm_op(dev, &dev->pwr_domain->ops, state); error = pm_op(dev, &dev->pm_domain->ops, state);
goto End; goto End;
} }
...@@ -982,11 +982,11 @@ static int device_prepare(struct device *dev, pm_message_t state) ...@@ -982,11 +982,11 @@ static int device_prepare(struct device *dev, pm_message_t state)
device_lock(dev); device_lock(dev);
if (dev->pwr_domain) { if (dev->pm_domain) {
pm_dev_dbg(dev, state, "preparing power domain "); pm_dev_dbg(dev, state, "preparing power domain ");
if (dev->pwr_domain->ops.prepare) if (dev->pm_domain->ops.prepare)
error = dev->pwr_domain->ops.prepare(dev); error = dev->pm_domain->ops.prepare(dev);
suspend_report_result(dev->pwr_domain->ops.prepare, error); suspend_report_result(dev->pm_domain->ops.prepare, error);
if (error) if (error)
goto End; goto End;
} else if (dev->type && dev->type->pm) { } else if (dev->type && dev->type->pm) {
......
...@@ -213,8 +213,8 @@ static int rpm_idle(struct device *dev, int rpmflags) ...@@ -213,8 +213,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
dev->power.idle_notification = true; dev->power.idle_notification = true;
if (dev->pwr_domain) if (dev->pm_domain)
callback = dev->pwr_domain->ops.runtime_idle; callback = dev->pm_domain->ops.runtime_idle;
else if (dev->type && dev->type->pm) else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_idle; callback = dev->type->pm->runtime_idle;
else if (dev->class && dev->class->pm) else if (dev->class && dev->class->pm)
...@@ -374,8 +374,8 @@ static int rpm_suspend(struct device *dev, int rpmflags) ...@@ -374,8 +374,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_SUSPENDING); __update_runtime_status(dev, RPM_SUSPENDING);
if (dev->pwr_domain) if (dev->pm_domain)
callback = dev->pwr_domain->ops.runtime_suspend; callback = dev->pm_domain->ops.runtime_suspend;
else if (dev->type && dev->type->pm) else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_suspend; callback = dev->type->pm->runtime_suspend;
else if (dev->class && dev->class->pm) else if (dev->class && dev->class->pm)
...@@ -573,8 +573,8 @@ static int rpm_resume(struct device *dev, int rpmflags) ...@@ -573,8 +573,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_RESUMING); __update_runtime_status(dev, RPM_RESUMING);
if (dev->pwr_domain) if (dev->pm_domain)
callback = dev->pwr_domain->ops.runtime_resume; callback = dev->pm_domain->ops.runtime_resume;
else if (dev->type && dev->type->pm) else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_resume; callback = dev->type->pm->runtime_resume;
else if (dev->class && dev->class->pm) else if (dev->class && dev->class->pm)
......
...@@ -516,7 +516,7 @@ struct device_dma_parameters { ...@@ -516,7 +516,7 @@ struct device_dma_parameters {
* minimizes board-specific #ifdefs in drivers. * minimizes board-specific #ifdefs in drivers.
* @power: For device power management. * @power: For device power management.
* See Documentation/power/devices.txt for details. * See Documentation/power/devices.txt for details.
* @pwr_domain: Provide callbacks that are executed during system suspend, * @pm_domain: Provide callbacks that are executed during system suspend,
* hibernation, system resume and during runtime PM transitions * hibernation, system resume and during runtime PM transitions
* along with subsystem-level and driver-level callbacks. * along with subsystem-level and driver-level callbacks.
* @numa_node: NUMA node this device is close to. * @numa_node: NUMA node this device is close to.
...@@ -567,7 +567,7 @@ struct device { ...@@ -567,7 +567,7 @@ struct device {
void *platform_data; /* Platform specific data, device void *platform_data; /* Platform specific data, device
core doesn't touch it */ core doesn't touch it */
struct dev_pm_info power; struct dev_pm_info power;
struct dev_power_domain *pwr_domain; struct dev_pm_domain *pm_domain;
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */ int numa_node; /* NUMA node this device is close to */
......
...@@ -461,8 +461,8 @@ struct dev_pm_info { ...@@ -461,8 +461,8 @@ struct dev_pm_info {
unsigned long active_jiffies; unsigned long active_jiffies;
unsigned long suspended_jiffies; unsigned long suspended_jiffies;
unsigned long accounting_timestamp; unsigned long accounting_timestamp;
void *subsys_data; /* Owned by the subsystem. */
#endif #endif
void *subsys_data; /* Owned by the subsystem. */
}; };
extern void update_pm_runtime_accounting(struct device *dev); extern void update_pm_runtime_accounting(struct device *dev);
...@@ -472,7 +472,7 @@ extern void update_pm_runtime_accounting(struct device *dev); ...@@ -472,7 +472,7 @@ extern void update_pm_runtime_accounting(struct device *dev);
* hibernation, system resume and during runtime PM transitions along with * hibernation, system resume and during runtime PM transitions along with
* subsystem-level and driver-level callbacks. * subsystem-level and driver-level callbacks.
*/ */
struct dev_power_domain { struct dev_pm_domain {
struct dev_pm_ops ops; struct dev_pm_ops ops;
}; };
...@@ -553,11 +553,17 @@ extern void __suspend_report_result(const char *function, void *fn, int ret); ...@@ -553,11 +553,17 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
extern int device_pm_wait_for_dev(struct device *sub, struct device *dev); extern int device_pm_wait_for_dev(struct device *sub, struct device *dev);
extern int pm_generic_prepare(struct device *dev); extern int pm_generic_prepare(struct device *dev);
extern int pm_generic_suspend_noirq(struct device *dev);
extern int pm_generic_suspend(struct device *dev); extern int pm_generic_suspend(struct device *dev);
extern int pm_generic_resume_noirq(struct device *dev);
extern int pm_generic_resume(struct device *dev); extern int pm_generic_resume(struct device *dev);
extern int pm_generic_freeze_noirq(struct device *dev);
extern int pm_generic_freeze(struct device *dev); extern int pm_generic_freeze(struct device *dev);
extern int pm_generic_thaw_noirq(struct device *dev);
extern int pm_generic_thaw(struct device *dev); extern int pm_generic_thaw(struct device *dev);
extern int pm_generic_restore_noirq(struct device *dev);
extern int pm_generic_restore(struct device *dev); extern int pm_generic_restore(struct device *dev);
extern int pm_generic_poweroff_noirq(struct device *dev);
extern int pm_generic_poweroff(struct device *dev); extern int pm_generic_poweroff(struct device *dev);
extern void pm_generic_complete(struct device *dev); extern void pm_generic_complete(struct device *dev);
......
/*
* pm_domain.h - Definitions and headers related to device power domains.
*
* Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
*
* This file is released under the GPLv2.
*/
#ifndef _LINUX_PM_DOMAIN_H
#define _LINUX_PM_DOMAIN_H
#include <linux/device.h>
enum gpd_status {
GPD_STATE_ACTIVE = 0, /* PM domain is active */
GPD_STATE_BUSY, /* Something is happening to the PM domain */
GPD_STATE_REPEAT, /* Power off in progress, to be repeated */
GPD_STATE_POWER_OFF, /* PM domain is off */
};
struct dev_power_governor {
bool (*power_down_ok)(struct dev_pm_domain *domain);
};
struct generic_pm_domain {
struct dev_pm_domain domain; /* PM domain operations */
struct list_head gpd_list_node; /* Node in the global PM domains list */
struct list_head sd_node; /* Node in the parent's subdomain list */
struct generic_pm_domain *parent; /* Parent PM domain */
struct list_head sd_list; /* List of dubdomains */
struct list_head dev_list; /* List of devices */
struct mutex lock;
struct dev_power_governor *gov;
struct work_struct power_off_work;
unsigned int in_progress; /* Number of devices being suspended now */
unsigned int sd_count; /* Number of subdomains with power "on" */
enum gpd_status status; /* Current state of the domain */
wait_queue_head_t status_wait_queue;
struct task_struct *poweroff_task; /* Powering off task */
unsigned int resume_count; /* Number of devices being resumed */
unsigned int device_count; /* Number of devices */
unsigned int suspended_count; /* System suspend device counter */
unsigned int prepared_count; /* Suspend counter of prepared devices */
bool suspend_power_off; /* Power status before system suspend */
int (*power_off)(struct generic_pm_domain *domain);
int (*power_on)(struct generic_pm_domain *domain);
int (*start_device)(struct device *dev);
int (*stop_device)(struct device *dev);
bool (*active_wakeup)(struct device *dev);
};
static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
{
return container_of(pd, struct generic_pm_domain, domain);
}
struct dev_list_entry {
struct list_head node;
struct device *dev;
bool need_restore;
};
#ifdef CONFIG_PM_GENERIC_DOMAINS
extern int pm_genpd_add_device(struct generic_pm_domain *genpd,
struct device *dev);
extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
struct device *dev);
extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_subdomain);
extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *target);
extern void pm_genpd_init(struct generic_pm_domain *genpd,
struct dev_power_governor *gov, bool is_off);
extern int pm_genpd_poweron(struct generic_pm_domain *genpd);
extern void pm_genpd_poweroff_unused(void);
extern void genpd_queue_power_off_work(struct generic_pm_domain *genpd);
#else
static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
struct device *dev)
{
return -ENOSYS;
}
static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd,
struct device *dev)
{
return -ENOSYS;
}
static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_sd)
{
return -ENOSYS;
}
static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *target)
{
return -ENOSYS;
}
static inline void pm_genpd_init(struct generic_pm_domain *genpd,
struct dev_power_governor *gov, bool is_off) {}
static inline int pm_genpd_poweron(struct generic_pm_domain *genpd)
{
return -ENOSYS;
}
static inline void pm_genpd_poweroff_unused(void) {}
static inline void genpd_queue_power_off_work(struct generic_pm_domain *gpd) {}
#endif
#endif /* _LINUX_PM_DOMAIN_H */
...@@ -247,41 +247,41 @@ static inline void pm_runtime_dont_use_autosuspend(struct device *dev) ...@@ -247,41 +247,41 @@ static inline void pm_runtime_dont_use_autosuspend(struct device *dev)
struct pm_clk_notifier_block { struct pm_clk_notifier_block {
struct notifier_block nb; struct notifier_block nb;
struct dev_power_domain *pwr_domain; struct dev_pm_domain *pm_domain;
char *con_ids[]; char *con_ids[];
}; };
#ifdef CONFIG_PM_RUNTIME_CLK #ifdef CONFIG_PM_CLK
extern int pm_runtime_clk_init(struct device *dev); extern int pm_clk_init(struct device *dev);
extern void pm_runtime_clk_destroy(struct device *dev); extern void pm_clk_destroy(struct device *dev);
extern int pm_runtime_clk_add(struct device *dev, const char *con_id); extern int pm_clk_add(struct device *dev, const char *con_id);
extern void pm_runtime_clk_remove(struct device *dev, const char *con_id); extern void pm_clk_remove(struct device *dev, const char *con_id);
extern int pm_runtime_clk_suspend(struct device *dev); extern int pm_clk_suspend(struct device *dev);
extern int pm_runtime_clk_resume(struct device *dev); extern int pm_clk_resume(struct device *dev);
#else #else
static inline int pm_runtime_clk_init(struct device *dev) static inline int pm_clk_init(struct device *dev)
{ {
return -EINVAL; return -EINVAL;
} }
static inline void pm_runtime_clk_destroy(struct device *dev) static inline void pm_clk_destroy(struct device *dev)
{ {
} }
static inline int pm_runtime_clk_add(struct device *dev, const char *con_id) static inline int pm_clk_add(struct device *dev, const char *con_id)
{ {
return -EINVAL; return -EINVAL;
} }
static inline void pm_runtime_clk_remove(struct device *dev, const char *con_id) static inline void pm_clk_remove(struct device *dev, const char *con_id)
{ {
} }
#define pm_runtime_clock_suspend NULL #define pm_clk_suspend NULL
#define pm_runtime_clock_resume NULL #define pm_clk_resume NULL
#endif #endif
#ifdef CONFIG_HAVE_CLK #ifdef CONFIG_HAVE_CLK
extern void pm_runtime_clk_add_notifier(struct bus_type *bus, extern void pm_clk_add_notifier(struct bus_type *bus,
struct pm_clk_notifier_block *clknb); struct pm_clk_notifier_block *clknb);
#else #else
static inline void pm_runtime_clk_add_notifier(struct bus_type *bus, static inline void pm_clk_add_notifier(struct bus_type *bus,
struct pm_clk_notifier_block *clknb) struct pm_clk_notifier_block *clknb)
{ {
} }
......
...@@ -224,6 +224,10 @@ config PM_OPP ...@@ -224,6 +224,10 @@ config PM_OPP
implementations a ready to use framework to manage OPPs. implementations a ready to use framework to manage OPPs.
For more information, read <file:Documentation/power/opp.txt> For more information, read <file:Documentation/power/opp.txt>
config PM_RUNTIME_CLK config PM_CLK
def_bool y def_bool y
depends on PM_RUNTIME && HAVE_CLK depends on PM && HAVE_CLK
config PM_GENERIC_DOMAINS
bool
depends on PM
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment