Merge branch 'pm-domains'
* pm-domains: (32 commits) PM / Domains: Rename cpu_data to cpuidle_data PM / Domains: Move dev_pm_domain_attach|detach() to pm_domain.h PM / Domains: Remove legacy API for adding devices through DT PM / Domains: Add genpd attach/detach callbacks PM / Domains: add debugfs listing of struct generic_pm_domain-s ACPI / PM: Convert acpi_dev_pm_detach() into a static function ARM: exynos: Move to generic PM domain DT bindings amba: Add support for attach/detach of PM domains spi: core: Convert to dev_pm_domain_attach|detach() mmc: sdio: Convert to dev_pm_domain_attach|detach() i2c: core: Convert to dev_pm_domain_attach|detach() drivercore / platform: Convert to dev_pm_domain_attach|detach() PM / Domains: Add APIs to attach/detach a PM domain for a device PM / Domains: Add generic OF-based PM domain look-up ACPI / PM: Assign the ->detach() callback when attaching the PM domain PM / Domains: Add a detach callback to the struct dev_pm_domain PM / domains: Spelling s/domian/domain/ PM / domains: Keep declaration of dev_power_governors together PM / domains: Remove default_stop_ok() API drivers: sh: Leave disabling of unused PM domains to genpd ...
This commit is contained in:
commit
49a09c9ab0
@ -8,6 +8,8 @@ Required Properties:
|
|||||||
* samsung,exynos4210-pd - for exynos4210 type power domain.
|
* samsung,exynos4210-pd - for exynos4210 type power domain.
|
||||||
- reg: physical base address of the controller and length of memory mapped
|
- reg: physical base address of the controller and length of memory mapped
|
||||||
region.
|
region.
|
||||||
|
- #power-domain-cells: number of cells in power domain specifier;
|
||||||
|
must be 0.
|
||||||
|
|
||||||
Optional Properties:
|
Optional Properties:
|
||||||
- clocks: List of clock handles. The parent clocks of the input clocks to the
|
- clocks: List of clock handles. The parent clocks of the input clocks to the
|
||||||
@ -29,6 +31,7 @@ Example:
|
|||||||
lcd0: power-domain-lcd0 {
|
lcd0: power-domain-lcd0 {
|
||||||
compatible = "samsung,exynos4210-pd";
|
compatible = "samsung,exynos4210-pd";
|
||||||
reg = <0x10023C00 0x10>;
|
reg = <0x10023C00 0x10>;
|
||||||
|
#power-domain-cells = <0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
mfc_pd: power-domain@10044060 {
|
mfc_pd: power-domain@10044060 {
|
||||||
@ -37,12 +40,8 @@ Example:
|
|||||||
clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_SW_ACLK333>,
|
clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_SW_ACLK333>,
|
||||||
<&clock CLK_MOUT_USER_ACLK333>;
|
<&clock CLK_MOUT_USER_ACLK333>;
|
||||||
clock-names = "oscclk", "pclk0", "clk0";
|
clock-names = "oscclk", "pclk0", "clk0";
|
||||||
|
#power-domain-cells = <0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
Example of the node using power domain:
|
See Documentation/devicetree/bindings/power/power_domain.txt for description
|
||||||
|
of consumer-side bindings.
|
||||||
node {
|
|
||||||
/* ... */
|
|
||||||
samsung,power-domain = <&lcd0>;
|
|
||||||
/* ... */
|
|
||||||
};
|
|
||||||
|
49
Documentation/devicetree/bindings/power/power_domain.txt
Normal file
49
Documentation/devicetree/bindings/power/power_domain.txt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
* Generic PM domains
|
||||||
|
|
||||||
|
System on chip designs are often divided into multiple PM domains that can be
|
||||||
|
used for power gating of selected IP blocks for power saving by reduced leakage
|
||||||
|
current.
|
||||||
|
|
||||||
|
This device tree binding can be used to bind PM domain consumer devices with
|
||||||
|
their PM domains provided by PM domain providers. A PM domain provider can be
|
||||||
|
represented by any node in the device tree and can provide one or more PM
|
||||||
|
domains. A consumer node can refer to the provider by a phandle and a set of
|
||||||
|
phandle arguments (so called PM domain specifiers) of length specified by the
|
||||||
|
#power-domain-cells property in the PM domain provider node.
|
||||||
|
|
||||||
|
==PM domain providers==
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- #power-domain-cells : Number of cells in a PM domain specifier;
|
||||||
|
Typically 0 for nodes representing a single PM domain and 1 for nodes
|
||||||
|
providing multiple PM domains (e.g. power controllers), but can be any value
|
||||||
|
as specified by device tree binding documentation of particular provider.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
power: power-controller@12340000 {
|
||||||
|
compatible = "foo,power-controller";
|
||||||
|
reg = <0x12340000 0x1000>;
|
||||||
|
#power-domain-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
The node above defines a power controller that is a PM domain provider and
|
||||||
|
expects one cell as its phandle argument.
|
||||||
|
|
||||||
|
==PM domain consumers==
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- power-domains : A phandle and PM domain specifier as defined by bindings of
|
||||||
|
the power controller specified by phandle.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
leaky-device@12350000 {
|
||||||
|
compatible = "foo,i-leak-current";
|
||||||
|
reg = <0x12350000 0x1000>;
|
||||||
|
power-domains = <&power 0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
The node above defines a typical PM domain consumer device, which is located
|
||||||
|
inside a PM domain with index 0 of a power controller represented by a node
|
||||||
|
with the label "power".
|
@ -193,7 +193,6 @@ static void __init exynos_init_late(void)
|
|||||||
/* to be supported later */
|
/* to be supported later */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pm_genpd_poweroff_unused();
|
|
||||||
exynos_pm_init();
|
exynos_pm_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,78 +105,6 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
|
|||||||
return exynos_pd_power(domain, false);
|
return exynos_pd_power(domain, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exynos_add_device_to_domain(struct exynos_pm_domain *pd,
|
|
||||||
struct device *dev)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
dev_dbg(dev, "adding to power domain %s\n", pd->pd.name);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
ret = pm_genpd_add_device(&pd->pd, dev);
|
|
||||||
if (ret != -EAGAIN)
|
|
||||||
break;
|
|
||||||
cond_resched();
|
|
||||||
}
|
|
||||||
|
|
||||||
pm_genpd_dev_need_restore(dev, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void exynos_remove_device_from_domain(struct device *dev)
|
|
||||||
{
|
|
||||||
struct generic_pm_domain *genpd = dev_to_genpd(dev);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
dev_dbg(dev, "removing from power domain %s\n", genpd->name);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
ret = pm_genpd_remove_device(genpd, dev);
|
|
||||||
if (ret != -EAGAIN)
|
|
||||||
break;
|
|
||||||
cond_resched();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void exynos_read_domain_from_dt(struct device *dev)
|
|
||||||
{
|
|
||||||
struct platform_device *pd_pdev;
|
|
||||||
struct exynos_pm_domain *pd;
|
|
||||||
struct device_node *node;
|
|
||||||
|
|
||||||
node = of_parse_phandle(dev->of_node, "samsung,power-domain", 0);
|
|
||||||
if (!node)
|
|
||||||
return;
|
|
||||||
pd_pdev = of_find_device_by_node(node);
|
|
||||||
if (!pd_pdev)
|
|
||||||
return;
|
|
||||||
pd = platform_get_drvdata(pd_pdev);
|
|
||||||
exynos_add_device_to_domain(pd, dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int exynos_pm_notifier_call(struct notifier_block *nb,
|
|
||||||
unsigned long event, void *data)
|
|
||||||
{
|
|
||||||
struct device *dev = data;
|
|
||||||
|
|
||||||
switch (event) {
|
|
||||||
case BUS_NOTIFY_BIND_DRIVER:
|
|
||||||
if (dev->of_node)
|
|
||||||
exynos_read_domain_from_dt(dev);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BUS_NOTIFY_UNBOUND_DRIVER:
|
|
||||||
exynos_remove_device_from_domain(dev);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct notifier_block platform_nb = {
|
|
||||||
.notifier_call = exynos_pm_notifier_call,
|
|
||||||
};
|
|
||||||
|
|
||||||
static __init int exynos4_pm_init_power_domain(void)
|
static __init int exynos4_pm_init_power_domain(void)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
@ -202,7 +130,6 @@ static __init int exynos4_pm_init_power_domain(void)
|
|||||||
pd->base = of_iomap(np, 0);
|
pd->base = of_iomap(np, 0);
|
||||||
pd->pd.power_off = exynos_pd_power_off;
|
pd->pd.power_off = exynos_pd_power_off;
|
||||||
pd->pd.power_on = exynos_pd_power_on;
|
pd->pd.power_on = exynos_pd_power_on;
|
||||||
pd->pd.of_node = np;
|
|
||||||
|
|
||||||
pd->oscclk = clk_get(dev, "oscclk");
|
pd->oscclk = clk_get(dev, "oscclk");
|
||||||
if (IS_ERR(pd->oscclk))
|
if (IS_ERR(pd->oscclk))
|
||||||
@ -228,15 +155,12 @@ static __init int exynos4_pm_init_power_domain(void)
|
|||||||
clk_put(pd->oscclk);
|
clk_put(pd->oscclk);
|
||||||
|
|
||||||
no_clk:
|
no_clk:
|
||||||
platform_set_drvdata(pdev, pd);
|
|
||||||
|
|
||||||
on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
|
on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
|
||||||
|
|
||||||
pm_genpd_init(&pd->pd, NULL, !on);
|
pm_genpd_init(&pd->pd, NULL, !on);
|
||||||
|
of_genpd_add_provider_simple(np, &pd->pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_register_notifier(&platform_bus_type, &platform_nb);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arch_initcall(exynos4_pm_init_power_domain);
|
arch_initcall(exynos4_pm_init_power_domain);
|
||||||
|
@ -440,8 +440,3 @@ void s3c64xx_restart(enum reboot_mode mode, const char *cmd)
|
|||||||
/* if all else fails, or mode was for soft, jump to 0 */
|
/* if all else fails, or mode was for soft, jump to 0 */
|
||||||
soft_restart(0);
|
soft_restart(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init s3c64xx_init_late(void)
|
|
||||||
{
|
|
||||||
s3c64xx_pm_late_initcall();
|
|
||||||
}
|
|
||||||
|
@ -23,7 +23,6 @@ void s3c64xx_init_irq(u32 vic0, u32 vic1);
|
|||||||
void s3c64xx_init_io(struct map_desc *mach_desc, int size);
|
void s3c64xx_init_io(struct map_desc *mach_desc, int size);
|
||||||
|
|
||||||
void s3c64xx_restart(enum reboot_mode mode, const char *cmd);
|
void s3c64xx_restart(enum reboot_mode mode, const char *cmd);
|
||||||
void s3c64xx_init_late(void);
|
|
||||||
|
|
||||||
void s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
|
void s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
|
||||||
unsigned long xusbxti_f, bool is_s3c6400, void __iomem *reg_base);
|
unsigned long xusbxti_f, bool is_s3c6400, void __iomem *reg_base);
|
||||||
@ -52,12 +51,6 @@ extern void s3c6410_map_io(void);
|
|||||||
#define s3c6410_init NULL
|
#define s3c6410_init NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
|
||||||
int __init s3c64xx_pm_late_initcall(void);
|
|
||||||
#else
|
|
||||||
static inline int s3c64xx_pm_late_initcall(void) { return 0; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_S3C64XX_PL080
|
#ifdef CONFIG_S3C64XX_PL080
|
||||||
extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
|
extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
|
||||||
extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
|
extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
|
||||||
|
@ -233,7 +233,6 @@ MACHINE_START(ANW6410, "A&W6410")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = anw6410_map_io,
|
.map_io = anw6410_map_io,
|
||||||
.init_machine = anw6410_machine_init,
|
.init_machine = anw6410_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -857,7 +857,6 @@ MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = crag6410_map_io,
|
.map_io = crag6410_map_io,
|
||||||
.init_machine = crag6410_machine_init,
|
.init_machine = crag6410_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -277,7 +277,6 @@ MACHINE_START(HMT, "Airgoo-HMT")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = hmt_map_io,
|
.map_io = hmt_map_io,
|
||||||
.init_machine = hmt_machine_init,
|
.init_machine = hmt_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -366,7 +366,6 @@ MACHINE_START(MINI6410, "MINI6410")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = mini6410_map_io,
|
.map_io = mini6410_map_io,
|
||||||
.init_machine = mini6410_machine_init,
|
.init_machine = mini6410_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -103,7 +103,6 @@ MACHINE_START(NCP, "NCP")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = ncp_map_io,
|
.map_io = ncp_map_io,
|
||||||
.init_machine = ncp_machine_init,
|
.init_machine = ncp_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -335,7 +335,6 @@ MACHINE_START(REAL6410, "REAL6410")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = real6410_map_io,
|
.map_io = real6410_map_io,
|
||||||
.init_machine = real6410_machine_init,
|
.init_machine = real6410_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -156,7 +156,6 @@ MACHINE_START(SMARTQ5, "SmartQ 5")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = smartq_map_io,
|
.map_io = smartq_map_io,
|
||||||
.init_machine = smartq5_machine_init,
|
.init_machine = smartq5_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -172,7 +172,6 @@ MACHINE_START(SMARTQ7, "SmartQ 7")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = smartq_map_io,
|
.map_io = smartq_map_io,
|
||||||
.init_machine = smartq7_machine_init,
|
.init_machine = smartq7_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -92,7 +92,6 @@ MACHINE_START(SMDK6400, "SMDK6400")
|
|||||||
.init_irq = s3c6400_init_irq,
|
.init_irq = s3c6400_init_irq,
|
||||||
.map_io = smdk6400_map_io,
|
.map_io = smdk6400_map_io,
|
||||||
.init_machine = smdk6400_machine_init,
|
.init_machine = smdk6400_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -705,7 +705,6 @@ MACHINE_START(SMDK6410, "SMDK6410")
|
|||||||
.init_irq = s3c6410_init_irq,
|
.init_irq = s3c6410_init_irq,
|
||||||
.map_io = smdk6410_map_io,
|
.map_io = smdk6410_map_io,
|
||||||
.init_machine = smdk6410_machine_init,
|
.init_machine = smdk6410_machine_init,
|
||||||
.init_late = s3c64xx_init_late,
|
|
||||||
.init_time = samsung_timer_init,
|
.init_time = samsung_timer_init,
|
||||||
.restart = s3c64xx_restart,
|
.restart = s3c64xx_restart,
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
@ -347,10 +347,3 @@ static __init int s3c64xx_pm_initcall(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arch_initcall(s3c64xx_pm_initcall);
|
arch_initcall(s3c64xx_pm_initcall);
|
||||||
|
|
||||||
int __init s3c64xx_pm_late_initcall(void)
|
|
||||||
{
|
|
||||||
pm_genpd_poweroff_unused();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -87,7 +87,6 @@ static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
|
|||||||
genpd->dev_ops.stop = pm_clk_suspend;
|
genpd->dev_ops.stop = pm_clk_suspend;
|
||||||
genpd->dev_ops.start = pm_clk_resume;
|
genpd->dev_ops.start = pm_clk_resume;
|
||||||
genpd->dev_ops.active_wakeup = pd_active_wakeup;
|
genpd->dev_ops.active_wakeup = pd_active_wakeup;
|
||||||
genpd->dev_irq_safe = true;
|
|
||||||
genpd->power_off = pd_power_down;
|
genpd->power_off = pd_power_down;
|
||||||
genpd->power_on = pd_power_up;
|
genpd->power_on = pd_power_up;
|
||||||
|
|
||||||
|
@ -111,7 +111,6 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
|
|||||||
genpd->dev_ops.stop = pm_clk_suspend;
|
genpd->dev_ops.stop = pm_clk_suspend;
|
||||||
genpd->dev_ops.start = pm_clk_resume;
|
genpd->dev_ops.start = pm_clk_resume;
|
||||||
genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
|
genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
|
||||||
genpd->dev_irq_safe = true;
|
|
||||||
genpd->power_off = rmobile_pd_power_down;
|
genpd->power_off = rmobile_pd_power_down;
|
||||||
genpd->power_on = rmobile_pd_power_up;
|
genpd->power_on = rmobile_pd_power_up;
|
||||||
__rmobile_pd_power_up(rmobile_pd, false);
|
__rmobile_pd_power_up(rmobile_pd, false);
|
||||||
|
@ -1040,6 +1040,40 @@ static struct dev_pm_domain acpi_general_pm_domain = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpi_dev_pm_detach - Remove ACPI power management from the device.
|
||||||
|
* @dev: Device to take care of.
|
||||||
|
* @power_off: Whether or not to try to remove power from the device.
|
||||||
|
*
|
||||||
|
* Remove the device from the general ACPI PM domain and remove its wakeup
|
||||||
|
* notifier. If @power_off is set, additionally remove power from the device if
|
||||||
|
* possible.
|
||||||
|
*
|
||||||
|
* Callers must ensure proper synchronization of this function with power
|
||||||
|
* management callbacks.
|
||||||
|
*/
|
||||||
|
static void acpi_dev_pm_detach(struct device *dev, bool power_off)
|
||||||
|
{
|
||||||
|
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||||
|
|
||||||
|
if (adev && dev->pm_domain == &acpi_general_pm_domain) {
|
||||||
|
dev->pm_domain = NULL;
|
||||||
|
acpi_remove_pm_notifier(adev);
|
||||||
|
if (power_off) {
|
||||||
|
/*
|
||||||
|
* If the device's PM QoS resume latency limit or flags
|
||||||
|
* have been exposed to user space, they have to be
|
||||||
|
* hidden at this point, so that they don't affect the
|
||||||
|
* choice of the low-power state to put the device into.
|
||||||
|
*/
|
||||||
|
dev_pm_qos_hide_latency_limit(dev);
|
||||||
|
dev_pm_qos_hide_flags(dev);
|
||||||
|
acpi_device_wakeup(adev, ACPI_STATE_S0, false);
|
||||||
|
acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_dev_pm_attach - Prepare device for ACPI power management.
|
* acpi_dev_pm_attach - Prepare device for ACPI power management.
|
||||||
* @dev: Device to prepare.
|
* @dev: Device to prepare.
|
||||||
@ -1072,42 +1106,9 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
|
|||||||
acpi_dev_pm_full_power(adev);
|
acpi_dev_pm_full_power(adev);
|
||||||
acpi_device_wakeup(adev, ACPI_STATE_S0, false);
|
acpi_device_wakeup(adev, ACPI_STATE_S0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->pm_domain->detach = acpi_dev_pm_detach;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
|
EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
|
||||||
|
|
||||||
/**
|
|
||||||
* acpi_dev_pm_detach - Remove ACPI power management from the device.
|
|
||||||
* @dev: Device to take care of.
|
|
||||||
* @power_off: Whether or not to try to remove power from the device.
|
|
||||||
*
|
|
||||||
* Remove the device from the general ACPI PM domain and remove its wakeup
|
|
||||||
* notifier. If @power_off is set, additionally remove power from the device if
|
|
||||||
* possible.
|
|
||||||
*
|
|
||||||
* Callers must ensure proper synchronization of this function with power
|
|
||||||
* management callbacks.
|
|
||||||
*/
|
|
||||||
void acpi_dev_pm_detach(struct device *dev, bool power_off)
|
|
||||||
{
|
|
||||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
|
||||||
|
|
||||||
if (adev && dev->pm_domain == &acpi_general_pm_domain) {
|
|
||||||
dev->pm_domain = NULL;
|
|
||||||
acpi_remove_pm_notifier(adev);
|
|
||||||
if (power_off) {
|
|
||||||
/*
|
|
||||||
* If the device's PM QoS resume latency limit or flags
|
|
||||||
* have been exposed to user space, they have to be
|
|
||||||
* hidden at this point, so that they don't affect the
|
|
||||||
* choice of the low-power state to put the device into.
|
|
||||||
*/
|
|
||||||
dev_pm_qos_hide_latency_limit(dev);
|
|
||||||
dev_pm_qos_hide_flags(dev);
|
|
||||||
acpi_device_wakeup(adev, ACPI_STATE_S0, false);
|
|
||||||
acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/amba/bus.h>
|
#include <linux/amba/bus.h>
|
||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
@ -182,10 +183,16 @@ static int amba_probe(struct device *dev)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = amba_get_enable_pclk(pcdev);
|
ret = dev_pm_domain_attach(dev, true);
|
||||||
if (ret)
|
if (ret == -EPROBE_DEFER)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
ret = amba_get_enable_pclk(pcdev);
|
||||||
|
if (ret) {
|
||||||
|
dev_pm_domain_detach(dev, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
pm_runtime_get_noresume(dev);
|
pm_runtime_get_noresume(dev);
|
||||||
pm_runtime_set_active(dev);
|
pm_runtime_set_active(dev);
|
||||||
pm_runtime_enable(dev);
|
pm_runtime_enable(dev);
|
||||||
@ -199,6 +206,7 @@ static int amba_probe(struct device *dev)
|
|||||||
pm_runtime_put_noidle(dev);
|
pm_runtime_put_noidle(dev);
|
||||||
|
|
||||||
amba_put_disable_pclk(pcdev);
|
amba_put_disable_pclk(pcdev);
|
||||||
|
dev_pm_domain_detach(dev, true);
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -220,6 +228,7 @@ static int amba_remove(struct device *dev)
|
|||||||
pm_runtime_put_noidle(dev);
|
pm_runtime_put_noidle(dev);
|
||||||
|
|
||||||
amba_put_disable_pclk(pcdev);
|
amba_put_disable_pclk(pcdev);
|
||||||
|
dev_pm_domain_detach(dev, true);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/idr.h>
|
#include <linux/idr.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/clk/clk-conf.h>
|
#include <linux/clk/clk-conf.h>
|
||||||
@ -506,11 +507,12 @@ static int platform_drv_probe(struct device *_dev)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
acpi_dev_pm_attach(_dev, true);
|
ret = dev_pm_domain_attach(_dev, true);
|
||||||
|
if (ret != -EPROBE_DEFER) {
|
||||||
ret = drv->probe(dev);
|
ret = drv->probe(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
acpi_dev_pm_detach(_dev, true);
|
dev_pm_domain_detach(_dev, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
|
if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
|
||||||
dev_warn(_dev, "probe deferral not supported\n");
|
dev_warn(_dev, "probe deferral not supported\n");
|
||||||
@ -532,7 +534,7 @@ static int platform_drv_remove(struct device *_dev)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = drv->remove(dev);
|
ret = drv->remove(dev);
|
||||||
acpi_dev_pm_detach(_dev, true);
|
dev_pm_domain_detach(_dev, true);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -543,7 +545,7 @@ static void platform_drv_shutdown(struct device *_dev)
|
|||||||
struct platform_device *dev = to_platform_device(_dev);
|
struct platform_device *dev = to_platform_device(_dev);
|
||||||
|
|
||||||
drv->shutdown(dev);
|
drv->shutdown(dev);
|
||||||
acpi_dev_pm_detach(_dev, true);
|
dev_pm_domain_detach(_dev, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pm_clock.h>
|
#include <linux/pm_clock.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dev_pm_get_subsys_data - Create or refcount power.subsys_data for device.
|
* dev_pm_get_subsys_data - Create or refcount power.subsys_data for device.
|
||||||
@ -82,3 +84,53 @@ int dev_pm_put_subsys_data(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
|
EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_pm_domain_attach - Attach a device to its PM domain.
|
||||||
|
* @dev: Device to attach.
|
||||||
|
* @power_on: Used to indicate whether we should power on the device.
|
||||||
|
*
|
||||||
|
* The @dev may only be attached to a single PM domain. By iterating through
|
||||||
|
* the available alternatives we try to find a valid PM domain for the device.
|
||||||
|
* As attachment succeeds, the ->detach() callback in the struct dev_pm_domain
|
||||||
|
* should be assigned by the corresponding attach function.
|
||||||
|
*
|
||||||
|
* This function should typically be invoked from subsystem level code during
|
||||||
|
* the probe phase. Especially for those that holds devices which requires
|
||||||
|
* power management through PM domains.
|
||||||
|
*
|
||||||
|
* Callers must ensure proper synchronization of this function with power
|
||||||
|
* management callbacks.
|
||||||
|
*
|
||||||
|
* Returns 0 on successfully attached PM domain or negative error code.
|
||||||
|
*/
|
||||||
|
int dev_pm_domain_attach(struct device *dev, bool power_on)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = acpi_dev_pm_attach(dev, power_on);
|
||||||
|
if (ret)
|
||||||
|
ret = genpd_dev_pm_attach(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dev_pm_domain_attach);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_pm_domain_detach - Detach a device from its PM domain.
|
||||||
|
* @dev: Device to attach.
|
||||||
|
* @power_off: Used to indicate whether we should power off the device.
|
||||||
|
*
|
||||||
|
* This functions will reverse the actions from dev_pm_domain_attach() and thus
|
||||||
|
* try to detach the @dev from its PM domain. Typically it should be invoked
|
||||||
|
* from subsystem level code during the remove phase.
|
||||||
|
*
|
||||||
|
* Callers must ensure proper synchronization of this function with power
|
||||||
|
* management callbacks.
|
||||||
|
*/
|
||||||
|
void dev_pm_domain_detach(struct device *dev, bool power_off)
|
||||||
|
{
|
||||||
|
if (dev->pm_domain && dev->pm_domain->detach)
|
||||||
|
dev->pm_domain->detach(dev, power_off);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -42,7 +42,7 @@ static int dev_update_qos_constraint(struct device *dev, void *data)
|
|||||||
* default_stop_ok - Default PM domain governor routine for stopping devices.
|
* default_stop_ok - Default PM domain governor routine for stopping devices.
|
||||||
* @dev: Device to check.
|
* @dev: Device to check.
|
||||||
*/
|
*/
|
||||||
bool default_stop_ok(struct device *dev)
|
static bool default_stop_ok(struct device *dev)
|
||||||
{
|
{
|
||||||
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
|
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -229,10 +229,7 @@ static bool always_on_power_down_ok(struct dev_pm_domain *domain)
|
|||||||
|
|
||||||
#else /* !CONFIG_PM_RUNTIME */
|
#else /* !CONFIG_PM_RUNTIME */
|
||||||
|
|
||||||
bool default_stop_ok(struct device *dev)
|
static inline bool default_stop_ok(struct device *dev) { return false; }
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define default_power_down_ok NULL
|
#define default_power_down_ok NULL
|
||||||
#define always_on_power_down_ok NULL
|
#define always_on_power_down_ok NULL
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include <linux/irqflags.h>
|
#include <linux/irqflags.h>
|
||||||
#include <linux/rwsem.h>
|
#include <linux/rwsem.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/jump_label.h>
|
#include <linux/jump_label.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@ -643,10 +644,13 @@ static int i2c_device_probe(struct device *dev)
|
|||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
acpi_dev_pm_attach(&client->dev, true);
|
status = dev_pm_domain_attach(&client->dev, true);
|
||||||
status = driver->probe(client, i2c_match_id(driver->id_table, client));
|
if (status != -EPROBE_DEFER) {
|
||||||
if (status)
|
status = driver->probe(client, i2c_match_id(driver->id_table,
|
||||||
acpi_dev_pm_detach(&client->dev, true);
|
client));
|
||||||
|
if (status)
|
||||||
|
dev_pm_domain_detach(&client->dev, true);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -666,7 +670,7 @@ static int i2c_device_remove(struct device *dev)
|
|||||||
status = driver->remove(client);
|
status = driver->remove(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_dev_pm_detach(&client->dev, true);
|
dev_pm_domain_detach(&client->dev, true);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
|
||||||
#include <linux/mmc/card.h>
|
#include <linux/mmc/card.h>
|
||||||
@ -315,7 +316,7 @@ int sdio_add_func(struct sdio_func *func)
|
|||||||
ret = device_add(&func->dev);
|
ret = device_add(&func->dev);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
sdio_func_set_present(func);
|
sdio_func_set_present(func);
|
||||||
acpi_dev_pm_attach(&func->dev, false);
|
dev_pm_domain_attach(&func->dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -332,7 +333,7 @@ void sdio_remove_func(struct sdio_func *func)
|
|||||||
if (!sdio_func_present(func))
|
if (!sdio_func_present(func))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
acpi_dev_pm_detach(&func->dev, false);
|
dev_pm_domain_detach(&func->dev, false);
|
||||||
device_del(&func->dev);
|
device_del(&func->dev);
|
||||||
put_device(&func->dev);
|
put_device(&func->dev);
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,6 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
|
|||||||
.con_ids = { NULL, },
|
.con_ids = { NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool default_pm_on;
|
|
||||||
|
|
||||||
static int __init sh_pm_runtime_init(void)
|
static int __init sh_pm_runtime_init(void)
|
||||||
{
|
{
|
||||||
if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
|
if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
|
||||||
@ -96,16 +94,7 @@ static int __init sh_pm_runtime_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
default_pm_on = true;
|
|
||||||
pm_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)
|
|
||||||
{
|
|
||||||
if (default_pm_on)
|
|
||||||
pm_genpd_poweroff_unused();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
late_initcall(sh_pm_runtime_late_init);
|
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/sched/rt.h>
|
#include <linux/sched/rt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@ -264,10 +265,12 @@ static int spi_drv_probe(struct device *dev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
acpi_dev_pm_attach(dev, true);
|
ret = dev_pm_domain_attach(dev, true);
|
||||||
ret = sdrv->probe(to_spi_device(dev));
|
if (ret != -EPROBE_DEFER) {
|
||||||
if (ret)
|
ret = sdrv->probe(to_spi_device(dev));
|
||||||
acpi_dev_pm_detach(dev, true);
|
if (ret)
|
||||||
|
dev_pm_domain_detach(dev, true);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -278,7 +281,7 @@ static int spi_drv_remove(struct device *dev)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = sdrv->remove(to_spi_device(dev));
|
ret = sdrv->remove(to_spi_device(dev));
|
||||||
acpi_dev_pm_detach(dev, true);
|
dev_pm_domain_detach(dev, true);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -587,7 +587,6 @@ static inline int acpi_subsys_freeze(struct device *dev) { return 0; }
|
|||||||
#if defined(CONFIG_ACPI) && defined(CONFIG_PM)
|
#if defined(CONFIG_ACPI) && defined(CONFIG_PM)
|
||||||
struct acpi_device *acpi_dev_pm_get_node(struct device *dev);
|
struct acpi_device *acpi_dev_pm_get_node(struct device *dev);
|
||||||
int acpi_dev_pm_attach(struct device *dev, bool power_on);
|
int acpi_dev_pm_attach(struct device *dev, bool power_on);
|
||||||
void acpi_dev_pm_detach(struct device *dev, bool power_off);
|
|
||||||
#else
|
#else
|
||||||
static inline struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
|
static inline struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
|
||||||
{
|
{
|
||||||
@ -597,7 +596,6 @@ static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
|
|||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
static inline void acpi_dev_pm_detach(struct device *dev, bool power_off) {}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
|
@ -619,6 +619,7 @@ extern int dev_pm_put_subsys_data(struct device *dev);
|
|||||||
*/
|
*/
|
||||||
struct dev_pm_domain {
|
struct dev_pm_domain {
|
||||||
struct dev_pm_ops ops;
|
struct dev_pm_ops ops;
|
||||||
|
void (*detach)(struct device *dev, bool power_off);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -35,18 +35,10 @@ struct gpd_dev_ops {
|
|||||||
int (*stop)(struct device *dev);
|
int (*stop)(struct device *dev);
|
||||||
int (*save_state)(struct device *dev);
|
int (*save_state)(struct device *dev);
|
||||||
int (*restore_state)(struct device *dev);
|
int (*restore_state)(struct device *dev);
|
||||||
int (*suspend)(struct device *dev);
|
|
||||||
int (*suspend_late)(struct device *dev);
|
|
||||||
int (*resume_early)(struct device *dev);
|
|
||||||
int (*resume)(struct device *dev);
|
|
||||||
int (*freeze)(struct device *dev);
|
|
||||||
int (*freeze_late)(struct device *dev);
|
|
||||||
int (*thaw_early)(struct device *dev);
|
|
||||||
int (*thaw)(struct device *dev);
|
|
||||||
bool (*active_wakeup)(struct device *dev);
|
bool (*active_wakeup)(struct device *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gpd_cpu_data {
|
struct gpd_cpuidle_data {
|
||||||
unsigned int saved_exit_latency;
|
unsigned int saved_exit_latency;
|
||||||
struct cpuidle_state *idle_state;
|
struct cpuidle_state *idle_state;
|
||||||
};
|
};
|
||||||
@ -71,7 +63,6 @@ struct generic_pm_domain {
|
|||||||
unsigned int suspended_count; /* System suspend device counter */
|
unsigned int suspended_count; /* System suspend device counter */
|
||||||
unsigned int prepared_count; /* Suspend counter of prepared devices */
|
unsigned int prepared_count; /* Suspend counter of prepared devices */
|
||||||
bool suspend_power_off; /* Power status before system suspend */
|
bool suspend_power_off; /* Power status before system suspend */
|
||||||
bool dev_irq_safe; /* Device callbacks are IRQ-safe */
|
|
||||||
int (*power_off)(struct generic_pm_domain *domain);
|
int (*power_off)(struct generic_pm_domain *domain);
|
||||||
s64 power_off_latency_ns;
|
s64 power_off_latency_ns;
|
||||||
int (*power_on)(struct generic_pm_domain *domain);
|
int (*power_on)(struct generic_pm_domain *domain);
|
||||||
@ -80,8 +71,9 @@ struct generic_pm_domain {
|
|||||||
s64 max_off_time_ns; /* Maximum allowed "suspended" time. */
|
s64 max_off_time_ns; /* Maximum allowed "suspended" time. */
|
||||||
bool max_off_time_changed;
|
bool max_off_time_changed;
|
||||||
bool cached_power_down_ok;
|
bool cached_power_down_ok;
|
||||||
struct device_node *of_node; /* Node in device tree */
|
struct gpd_cpuidle_data *cpuidle_data;
|
||||||
struct gpd_cpu_data *cpu_data;
|
void (*attach_dev)(struct device *dev);
|
||||||
|
void (*detach_dev)(struct device *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
|
static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
|
||||||
@ -108,7 +100,6 @@ struct gpd_timing_data {
|
|||||||
|
|
||||||
struct generic_pm_domain_data {
|
struct generic_pm_domain_data {
|
||||||
struct pm_domain_data base;
|
struct pm_domain_data base;
|
||||||
struct gpd_dev_ops ops;
|
|
||||||
struct gpd_timing_data td;
|
struct gpd_timing_data td;
|
||||||
struct notifier_block nb;
|
struct notifier_block nb;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
@ -127,17 +118,11 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
|
|||||||
return to_gpd_data(dev->power.subsys_data->domain_data);
|
return to_gpd_data(dev->power.subsys_data->domain_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct dev_power_governor simple_qos_governor;
|
|
||||||
|
|
||||||
extern struct generic_pm_domain *dev_to_genpd(struct device *dev);
|
extern struct generic_pm_domain *dev_to_genpd(struct device *dev);
|
||||||
extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
|
extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct gpd_timing_data *td);
|
struct gpd_timing_data *td);
|
||||||
|
|
||||||
extern int __pm_genpd_of_add_device(struct device_node *genpd_node,
|
|
||||||
struct device *dev,
|
|
||||||
struct gpd_timing_data *td);
|
|
||||||
|
|
||||||
extern int __pm_genpd_name_add_device(const char *domain_name,
|
extern int __pm_genpd_name_add_device(const char *domain_name,
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct gpd_timing_data *td);
|
struct gpd_timing_data *td);
|
||||||
@ -151,10 +136,6 @@ extern int pm_genpd_add_subdomain_names(const char *master_name,
|
|||||||
const char *subdomain_name);
|
const char *subdomain_name);
|
||||||
extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
|
extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
|
||||||
struct generic_pm_domain *target);
|
struct generic_pm_domain *target);
|
||||||
extern int pm_genpd_add_callbacks(struct device *dev,
|
|
||||||
struct gpd_dev_ops *ops,
|
|
||||||
struct gpd_timing_data *td);
|
|
||||||
extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td);
|
|
||||||
extern int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state);
|
extern int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state);
|
||||||
extern int pm_genpd_name_attach_cpuidle(const char *name, int state);
|
extern int pm_genpd_name_attach_cpuidle(const char *name, int state);
|
||||||
extern int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd);
|
extern int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd);
|
||||||
@ -165,8 +146,7 @@ extern void pm_genpd_init(struct generic_pm_domain *genpd,
|
|||||||
extern int pm_genpd_poweron(struct generic_pm_domain *genpd);
|
extern int pm_genpd_poweron(struct generic_pm_domain *genpd);
|
||||||
extern int pm_genpd_name_poweron(const char *domain_name);
|
extern int pm_genpd_name_poweron(const char *domain_name);
|
||||||
|
|
||||||
extern bool default_stop_ok(struct device *dev);
|
extern struct dev_power_governor simple_qos_governor;
|
||||||
|
|
||||||
extern struct dev_power_governor pm_domain_always_on_gov;
|
extern struct dev_power_governor pm_domain_always_on_gov;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -184,12 +164,6 @@ static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
|
|||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
static inline int __pm_genpd_of_add_device(struct device_node *genpd_node,
|
|
||||||
struct device *dev,
|
|
||||||
struct gpd_timing_data *td)
|
|
||||||
{
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
static inline int __pm_genpd_name_add_device(const char *domain_name,
|
static inline int __pm_genpd_name_add_device(const char *domain_name,
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct gpd_timing_data *td)
|
struct gpd_timing_data *td)
|
||||||
@ -217,16 +191,6 @@ static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
|
|||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
static inline int pm_genpd_add_callbacks(struct device *dev,
|
|
||||||
struct gpd_dev_ops *ops,
|
|
||||||
struct gpd_timing_data *td)
|
|
||||||
{
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
static inline int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
|
|
||||||
{
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
static inline int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st)
|
static inline int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st)
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
@ -255,10 +219,6 @@ static inline int pm_genpd_name_poweron(const char *domain_name)
|
|||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
static inline bool default_stop_ok(struct device *dev)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#define simple_qos_governor NULL
|
#define simple_qos_governor NULL
|
||||||
#define pm_domain_always_on_gov NULL
|
#define pm_domain_always_on_gov NULL
|
||||||
#endif
|
#endif
|
||||||
@ -269,45 +229,87 @@ static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
|
|||||||
return __pm_genpd_add_device(genpd, dev, NULL);
|
return __pm_genpd_add_device(genpd, dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int pm_genpd_of_add_device(struct device_node *genpd_node,
|
|
||||||
struct device *dev)
|
|
||||||
{
|
|
||||||
return __pm_genpd_of_add_device(genpd_node, dev, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int pm_genpd_name_add_device(const char *domain_name,
|
static inline int pm_genpd_name_add_device(const char *domain_name,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
return __pm_genpd_name_add_device(domain_name, dev, NULL);
|
return __pm_genpd_name_add_device(domain_name, dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int pm_genpd_remove_callbacks(struct device *dev)
|
|
||||||
{
|
|
||||||
return __pm_genpd_remove_callbacks(dev, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_RUNTIME
|
#ifdef CONFIG_PM_GENERIC_DOMAINS_RUNTIME
|
||||||
extern void genpd_queue_power_off_work(struct generic_pm_domain *genpd);
|
|
||||||
extern void pm_genpd_poweroff_unused(void);
|
extern void pm_genpd_poweroff_unused(void);
|
||||||
#else
|
#else
|
||||||
static inline void genpd_queue_power_off_work(struct generic_pm_domain *gpd) {}
|
|
||||||
static inline void pm_genpd_poweroff_unused(void) {}
|
static inline void pm_genpd_poweroff_unused(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
|
#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
|
||||||
extern void pm_genpd_syscore_switch(struct device *dev, bool suspend);
|
extern void pm_genpd_syscore_poweroff(struct device *dev);
|
||||||
|
extern void pm_genpd_syscore_poweron(struct device *dev);
|
||||||
#else
|
#else
|
||||||
static inline void pm_genpd_syscore_switch(struct device *dev, bool suspend) {}
|
static inline void pm_genpd_syscore_poweroff(struct device *dev) {}
|
||||||
|
static inline void pm_genpd_syscore_poweron(struct device *dev) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void pm_genpd_syscore_poweroff(struct device *dev)
|
/* OF PM domain providers */
|
||||||
|
struct of_device_id;
|
||||||
|
|
||||||
|
struct genpd_onecell_data {
|
||||||
|
struct generic_pm_domain **domains;
|
||||||
|
unsigned int num_domains;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||||
|
int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
|
||||||
|
void *data);
|
||||||
|
void of_genpd_del_provider(struct device_node *np);
|
||||||
|
|
||||||
|
struct generic_pm_domain *__of_genpd_xlate_simple(
|
||||||
|
struct of_phandle_args *genpdspec,
|
||||||
|
void *data);
|
||||||
|
struct generic_pm_domain *__of_genpd_xlate_onecell(
|
||||||
|
struct of_phandle_args *genpdspec,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
int genpd_dev_pm_attach(struct device *dev);
|
||||||
|
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||||
|
static inline int __of_genpd_add_provider(struct device_node *np,
|
||||||
|
genpd_xlate_t xlate, void *data)
|
||||||
{
|
{
|
||||||
pm_genpd_syscore_switch(dev, true);
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void of_genpd_del_provider(struct device_node *np) {}
|
||||||
|
|
||||||
|
#define __of_genpd_xlate_simple NULL
|
||||||
|
#define __of_genpd_xlate_onecell NULL
|
||||||
|
|
||||||
|
static inline int genpd_dev_pm_attach(struct device *dev)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||||
|
|
||||||
|
static inline int of_genpd_add_provider_simple(struct device_node *np,
|
||||||
|
struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd);
|
||||||
|
}
|
||||||
|
static inline int of_genpd_add_provider_onecell(struct device_node *np,
|
||||||
|
struct genpd_onecell_data *data)
|
||||||
|
{
|
||||||
|
return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pm_genpd_syscore_poweron(struct device *dev)
|
#ifdef CONFIG_PM
|
||||||
|
extern int dev_pm_domain_attach(struct device *dev, bool power_on);
|
||||||
|
extern void dev_pm_domain_detach(struct device *dev, bool power_off);
|
||||||
|
#else
|
||||||
|
static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
|
||||||
{
|
{
|
||||||
pm_genpd_syscore_switch(dev, false);
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _LINUX_PM_DOMAIN_H */
|
#endif /* _LINUX_PM_DOMAIN_H */
|
||||||
|
@ -302,6 +302,10 @@ config PM_GENERIC_DOMAINS_RUNTIME
|
|||||||
def_bool y
|
def_bool y
|
||||||
depends on PM_RUNTIME && PM_GENERIC_DOMAINS
|
depends on PM_RUNTIME && PM_GENERIC_DOMAINS
|
||||||
|
|
||||||
|
config PM_GENERIC_DOMAINS_OF
|
||||||
|
def_bool y
|
||||||
|
depends on PM_GENERIC_DOMAINS && OF
|
||||||
|
|
||||||
config CPU_PM
|
config CPU_PM
|
||||||
bool
|
bool
|
||||||
depends on SUSPEND || CPU_IDLE
|
depends on SUSPEND || CPU_IDLE
|
||||||
|
Loading…
Reference in New Issue
Block a user