aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-omap1/pm_bus.c14
-rw-r--r--arch/arm/mach-omap2/gpio.c2
-rw-r--r--arch/arm/mach-omap2/serial.c1
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c5
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c5
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c1
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h29
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c160
-rw-r--r--arch/arm/mach-shmobile/pm_runtime.c22
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c11
-rw-r--r--arch/arm/plat-omap/include/plat/omap_device.h9
-rw-r--r--arch/arm/plat-omap/omap_device.c53
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm_runtime.c6
14 files changed, 297 insertions, 22 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9adc278a22ab..e04fa9d7637c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -642,6 +642,7 @@ config ARCH_SHMOBILE
642 select NO_IOPORT 642 select NO_IOPORT
643 select SPARSE_IRQ 643 select SPARSE_IRQ
644 select MULTI_IRQ_HANDLER 644 select MULTI_IRQ_HANDLER
645 select PM_GENERIC_DOMAINS if PM
645 help 646 help
646 Support for Renesas's SH-Mobile and R-Mobile ARM platforms. 647 Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
647 648
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
index 334fb8871bc3..943072d5a1d5 100644
--- a/arch/arm/mach-omap1/pm_bus.c
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -32,7 +32,7 @@ static int omap1_pm_runtime_suspend(struct device *dev)
32 if (ret) 32 if (ret)
33 return ret; 33 return ret;
34 34
35 ret = pm_runtime_clk_suspend(dev); 35 ret = pm_clk_suspend(dev);
36 if (ret) { 36 if (ret) {
37 pm_generic_runtime_resume(dev); 37 pm_generic_runtime_resume(dev);
38 return ret; 38 return ret;
@@ -45,24 +45,24 @@ static int omap1_pm_runtime_resume(struct device *dev)
45{ 45{
46 dev_dbg(dev, "%s\n", __func__); 46 dev_dbg(dev, "%s\n", __func__);
47 47
48 pm_runtime_clk_resume(dev); 48 pm_clk_resume(dev);
49 return pm_generic_runtime_resume(dev); 49 return pm_generic_runtime_resume(dev);
50} 50}
51 51
52static struct dev_power_domain default_power_domain = { 52static struct dev_pm_domain default_pm_domain = {
53 .ops = { 53 .ops = {
54 .runtime_suspend = omap1_pm_runtime_suspend, 54 .runtime_suspend = omap1_pm_runtime_suspend,
55 .runtime_resume = omap1_pm_runtime_resume, 55 .runtime_resume = omap1_pm_runtime_resume,
56 USE_PLATFORM_PM_SLEEP_OPS 56 USE_PLATFORM_PM_SLEEP_OPS
57 }, 57 },
58}; 58};
59#define OMAP1_PWR_DOMAIN (&default_power_domain) 59#define OMAP1_PM_DOMAIN (&default_pm_domain)
60#else 60#else
61#define OMAP1_PWR_DOMAIN NULL 61#define OMAP1_PM_DOMAIN NULL
62#endif /* CONFIG_PM_RUNTIME */ 62#endif /* CONFIG_PM_RUNTIME */
63 63
64static struct pm_clk_notifier_block platform_bus_notifier = { 64static struct pm_clk_notifier_block platform_bus_notifier = {
65 .pwr_domain = OMAP1_PWR_DOMAIN, 65 .pm_domain = OMAP1_PM_DOMAIN,
66 .con_ids = { "ick", "fck", NULL, }, 66 .con_ids = { "ick", "fck", NULL, },
67}; 67};
68 68
@@ -71,7 +71,7 @@ static int __init omap1_pm_runtime_init(void)
71 if (!cpu_class_is_omap1()) 71 if (!cpu_class_is_omap1())
72 return -ENODEV; 72 return -ENODEV;
73 73
74 pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); 74 pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
75 75
76 return 0; 76 return 0;
77} 77}
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 9a46d7773a48..2765cdc3152d 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -119,6 +119,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
119 return PTR_ERR(od); 119 return PTR_ERR(od);
120 } 120 }
121 121
122 omap_device_disable_idle_on_suspend(od);
123
122 gpio_bank_count++; 124 gpio_bank_count++;
123 return 0; 125 return 0;
124} 126}
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 1ac361b7b8cb..466fc722fa0f 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -805,6 +805,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
805 WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", 805 WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
806 name, oh->name); 806 name, oh->name);
807 807
808 omap_device_disable_idle_on_suspend(od);
808 oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); 809 oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
809 810
810 uart->irq = oh->mpu_irqs[0].irq; 811 uart->irq = oh->mpu_irqs[0].irq;
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 803bc6edfca4..b473b8efac68 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1408,9 +1408,14 @@ static void __init ap4evb_init(void)
1408 1408
1409 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); 1409 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
1410 1410
1411 sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc1_device);
1412 sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
1413 sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
1414
1411 hdmi_init_pm_clock(); 1415 hdmi_init_pm_clock();
1412 fsi_init_pm_clock(); 1416 fsi_init_pm_clock();
1413 sh7372_pm_init(); 1417 sh7372_pm_init();
1418 pm_clk_add(&fsi_device.dev, "spu2");
1414} 1419}
1415 1420
1416static void __init ap4evb_timer_init(void) 1421static void __init ap4evb_timer_init(void)
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 3802f2afabef..5b36b6c5b448 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1582,8 +1582,13 @@ static void __init mackerel_init(void)
1582 1582
1583 platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); 1583 platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
1584 1584
1585 sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
1586 sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
1587 sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
1588
1585 hdmi_init_pm_clock(); 1589 hdmi_init_pm_clock();
1586 sh7372_pm_init(); 1590 sh7372_pm_init();
1591 pm_clk_add(&fsi_device.dev, "spu2");
1587} 1592}
1588 1593
1589static void __init mackerel_timer_init(void) 1594static void __init mackerel_timer_init(void)
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index c0800d83971e..91f5779abdd3 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -662,6 +662,7 @@ static struct clk_lookup lookups[] = {
662 CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), 662 CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
663 CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), 663 CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
664 CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), 664 CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
665 CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
665}; 666};
666 667
667void __init sh7372_clock_init(void) 668void __init sh7372_clock_init(void)
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index df20d7670172..ce595cee86cd 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -12,6 +12,7 @@
12#define __ASM_SH7372_H__ 12#define __ASM_SH7372_H__
13 13
14#include <linux/sh_clk.h> 14#include <linux/sh_clk.h>
15#include <linux/pm_domain.h>
15 16
16/* 17/*
17 * Pin Function Controller: 18 * Pin Function Controller:
@@ -470,4 +471,32 @@ extern struct clk sh7372_fsibck_clk;
470extern struct clk sh7372_fsidiva_clk; 471extern struct clk sh7372_fsidiva_clk;
471extern struct clk sh7372_fsidivb_clk; 472extern struct clk sh7372_fsidivb_clk;
472 473
474struct platform_device;
475
476struct sh7372_pm_domain {
477 struct generic_pm_domain genpd;
478 unsigned int bit_shift;
479};
480
481static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
482{
483 return container_of(d, struct sh7372_pm_domain, genpd);
484}
485
486#ifdef CONFIG_PM
487extern struct sh7372_pm_domain sh7372_a4lc;
488extern struct sh7372_pm_domain sh7372_a4mp;
489extern struct sh7372_pm_domain sh7372_d4;
490extern struct sh7372_pm_domain sh7372_a3rv;
491extern struct sh7372_pm_domain sh7372_a3ri;
492extern struct sh7372_pm_domain sh7372_a3sg;
493
494extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd);
495extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
496 struct platform_device *pdev);
497#else
498#define sh7372_init_pm_domain(pd) do { } while(0)
499#define sh7372_add_device_to_domain(pd, pdev) do { } while(0)
500#endif /* CONFIG_PM */
501
473#endif /* __ASM_SH7372_H__ */ 502#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 8e4aadf14c9f..933fb411be0f 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -15,16 +15,176 @@
15#include <linux/list.h> 15#include <linux/list.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/pm_runtime.h>
19#include <linux/platform_device.h>
20#include <linux/delay.h>
18#include <asm/system.h> 21#include <asm/system.h>
19#include <asm/io.h> 22#include <asm/io.h>
20#include <asm/tlbflush.h> 23#include <asm/tlbflush.h>
21#include <mach/common.h> 24#include <mach/common.h>
25#include <mach/sh7372.h>
22 26
23#define SMFRAM 0xe6a70000 27#define SMFRAM 0xe6a70000
24#define SYSTBCR 0xe6150024 28#define SYSTBCR 0xe6150024
25#define SBAR 0xe6180020 29#define SBAR 0xe6180020
26#define APARMBAREA 0xe6f10020 30#define APARMBAREA 0xe6f10020
27 31
32#define SPDCR 0xe6180008
33#define SWUCR 0xe6180014
34#define PSTR 0xe6180080
35
36#define PSTR_RETRIES 100
37#define PSTR_DELAY_US 10
38
39#ifdef CONFIG_PM
40
41static int pd_power_down(struct generic_pm_domain *genpd)
42{
43 struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
44 unsigned int mask = 1 << sh7372_pd->bit_shift;
45
46 if (__raw_readl(PSTR) & mask) {
47 unsigned int retry_count;
48
49 __raw_writel(mask, SPDCR);
50
51 for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
52 if (!(__raw_readl(SPDCR) & mask))
53 break;
54 cpu_relax();
55 }
56 }
57
58 pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
59 mask, __raw_readl(PSTR));
60
61 return 0;
62}
63
64static int pd_power_up(struct generic_pm_domain *genpd)
65{
66 struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
67 unsigned int mask = 1 << sh7372_pd->bit_shift;
68 unsigned int retry_count;
69 int ret = 0;
70
71 if (__raw_readl(PSTR) & mask)
72 goto out;
73
74 __raw_writel(mask, SWUCR);
75
76 for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
77 if (!(__raw_readl(SWUCR) & mask))
78 goto out;
79 if (retry_count > PSTR_RETRIES)
80 udelay(PSTR_DELAY_US);
81 else
82 cpu_relax();
83 }
84 if (__raw_readl(SWUCR) & mask)
85 ret = -EIO;
86
87 out:
88 pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
89 mask, __raw_readl(PSTR));
90
91 return ret;
92}
93
94static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
95{
96 int ret = pd_power_up(genpd);
97
98 /* force A4LC on after A3RV has been requested on */
99 pm_genpd_poweron(&sh7372_a4lc.genpd);
100
101 return ret;
102}
103
104static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
105{
106 int ret = pd_power_down(genpd);
107
108 /* try to power down A4LC after A3RV is requested off */
109 genpd_queue_power_off_work(&sh7372_a4lc.genpd);
110
111 return ret;
112}
113
114static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
115{
116 /* only power down A4LC if A3RV is off */
117 if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
118 return pd_power_down(genpd);
119
120 return -EBUSY;
121}
122
123static bool pd_active_wakeup(struct device *dev)
124{
125 return true;
126}
127
128void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
129{
130 struct generic_pm_domain *genpd = &sh7372_pd->genpd;
131
132 pm_genpd_init(genpd, NULL, false);
133 genpd->stop_device = pm_clk_suspend;
134 genpd->start_device = pm_clk_resume;
135 genpd->active_wakeup = pd_active_wakeup;
136
137 if (sh7372_pd == &sh7372_a4lc) {
138 genpd->power_off = pd_power_down_a4lc;
139 genpd->power_on = pd_power_up;
140 } else if (sh7372_pd == &sh7372_a3rv) {
141 genpd->power_off = pd_power_down_a3rv;
142 genpd->power_on = pd_power_up_a3rv;
143 } else {
144 genpd->power_off = pd_power_down;
145 genpd->power_on = pd_power_up;
146 }
147 genpd->power_on(&sh7372_pd->genpd);
148}
149
150void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
151 struct platform_device *pdev)
152{
153 struct device *dev = &pdev->dev;
154
155 if (!dev->power.subsys_data) {
156 pm_clk_init(dev);
157 pm_clk_add(dev, NULL);
158 }
159 pm_genpd_add_device(&sh7372_pd->genpd, dev);
160}
161
162struct sh7372_pm_domain sh7372_a4lc = {
163 .bit_shift = 1,
164};
165
166struct sh7372_pm_domain sh7372_a4mp = {
167 .bit_shift = 2,
168};
169
170struct sh7372_pm_domain sh7372_d4 = {
171 .bit_shift = 3,
172};
173
174struct sh7372_pm_domain sh7372_a3rv = {
175 .bit_shift = 6,
176};
177
178struct sh7372_pm_domain sh7372_a3ri = {
179 .bit_shift = 8,
180};
181
182struct sh7372_pm_domain sh7372_a3sg = {
183 .bit_shift = 13,
184};
185
186#endif /* CONFIG_PM */
187
28static void sh7372_enter_core_standby(void) 188static void sh7372_enter_core_standby(void)
29{ 189{
30 void __iomem *smfram = (void __iomem *)SMFRAM; 190 void __iomem *smfram = (void __iomem *)SMFRAM;
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
index 2d1b67a59e4a..6ec454e1e063 100644
--- a/arch/arm/mach-shmobile/pm_runtime.c
+++ b/arch/arm/mach-shmobile/pm_runtime.c
@@ -14,6 +14,7 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
17#include <linux/pm_domain.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
18#include <linux/clk.h> 19#include <linux/clk.h>
19#include <linux/sh_clk.h> 20#include <linux/sh_clk.h>
@@ -28,31 +29,38 @@ static int default_platform_runtime_idle(struct device *dev)
28 return pm_runtime_suspend(dev); 29 return pm_runtime_suspend(dev);
29} 30}
30 31
31static struct dev_power_domain default_power_domain = { 32static struct dev_pm_domain default_pm_domain = {
32 .ops = { 33 .ops = {
33 .runtime_suspend = pm_runtime_clk_suspend, 34 .runtime_suspend = pm_clk_suspend,
34 .runtime_resume = pm_runtime_clk_resume, 35 .runtime_resume = pm_clk_resume,
35 .runtime_idle = default_platform_runtime_idle, 36 .runtime_idle = default_platform_runtime_idle,
36 USE_PLATFORM_PM_SLEEP_OPS 37 USE_PLATFORM_PM_SLEEP_OPS
37 }, 38 },
38}; 39};
39 40
40#define DEFAULT_PWR_DOMAIN_PTR (&default_power_domain) 41#define DEFAULT_PM_DOMAIN_PTR (&default_pm_domain)
41 42
42#else 43#else
43 44
44#define DEFAULT_PWR_DOMAIN_PTR NULL 45#define DEFAULT_PM_DOMAIN_PTR NULL
45 46
46#endif /* CONFIG_PM_RUNTIME */ 47#endif /* CONFIG_PM_RUNTIME */
47 48
48static struct pm_clk_notifier_block platform_bus_notifier = { 49static struct pm_clk_notifier_block platform_bus_notifier = {
49 .pwr_domain = DEFAULT_PWR_DOMAIN_PTR, 50 .pm_domain = DEFAULT_PM_DOMAIN_PTR,
50 .con_ids = { NULL, }, 51 .con_ids = { NULL, },
51}; 52};
52 53
53static int __init sh_pm_runtime_init(void) 54static int __init sh_pm_runtime_init(void)
54{ 55{
55 pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); 56 pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
56 return 0; 57 return 0;
57} 58}
58core_initcall(sh_pm_runtime_init); 59core_initcall(sh_pm_runtime_init);
60
61static int __init sh_pm_runtime_late_init(void)
62{
63 pm_genpd_poweroff_unused();
64 return 0;
65}
66late_initcall(sh_pm_runtime_late_init);
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index cd807eea69e2..79f0413d8725 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -841,11 +841,22 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
841 841
842void __init sh7372_add_standard_devices(void) 842void __init sh7372_add_standard_devices(void)
843{ 843{
844 sh7372_init_pm_domain(&sh7372_a4lc);
845 sh7372_init_pm_domain(&sh7372_a4mp);
846 sh7372_init_pm_domain(&sh7372_d4);
847 sh7372_init_pm_domain(&sh7372_a3rv);
848 sh7372_init_pm_domain(&sh7372_a3ri);
849 sh7372_init_pm_domain(&sh7372_a3sg);
850
844 platform_add_devices(sh7372_early_devices, 851 platform_add_devices(sh7372_early_devices,
845 ARRAY_SIZE(sh7372_early_devices)); 852 ARRAY_SIZE(sh7372_early_devices));
846 853
847 platform_add_devices(sh7372_late_devices, 854 platform_add_devices(sh7372_late_devices,
848 ARRAY_SIZE(sh7372_late_devices)); 855 ARRAY_SIZE(sh7372_late_devices));
856
857 sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device);
858 sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device);
859 sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device);
849} 860}
850 861
851void __init sh7372_add_early_devices(void) 862void __init sh7372_add_early_devices(void)
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349ff9fd8..ee405b36df4b 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -44,6 +44,10 @@ extern struct device omap_device_parent;
44#define OMAP_DEVICE_STATE_IDLE 2 44#define OMAP_DEVICE_STATE_IDLE 2
45#define OMAP_DEVICE_STATE_SHUTDOWN 3 45#define OMAP_DEVICE_STATE_SHUTDOWN 3
46 46
47/* omap_device.flags values */
48#define OMAP_DEVICE_SUSPENDED BIT(0)
49#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1)
50
47/** 51/**
48 * struct omap_device - omap_device wrapper for platform_devices 52 * struct omap_device - omap_device wrapper for platform_devices
49 * @pdev: platform_device 53 * @pdev: platform_device
@@ -73,6 +77,7 @@ struct omap_device {
73 s8 pm_lat_level; 77 s8 pm_lat_level;
74 u8 hwmods_cnt; 78 u8 hwmods_cnt;
75 u8 _state; 79 u8 _state;
80 u8 flags;
76}; 81};
77 82
78/* Device driver interface (call via platform_data fn ptrs) */ 83/* Device driver interface (call via platform_data fn ptrs) */
@@ -117,6 +122,10 @@ int omap_device_enable_hwmods(struct omap_device *od);
117int omap_device_disable_clocks(struct omap_device *od); 122int omap_device_disable_clocks(struct omap_device *od);
118int omap_device_enable_clocks(struct omap_device *od); 123int omap_device_enable_clocks(struct omap_device *od);
119 124
125static inline void omap_device_disable_idle_on_suspend(struct omap_device *od)
126{
127 od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
128}
120 129
121/* 130/*
122 * Entries should be kept in latency order ascending 131 * Entries should be kept in latency order ascending
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 49fc0df0c21f..2526fa312b8a 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -537,6 +537,7 @@ int omap_early_device_register(struct omap_device *od)
537 return 0; 537 return 0;
538} 538}
539 539
540#ifdef CONFIG_PM_RUNTIME
540static int _od_runtime_suspend(struct device *dev) 541static int _od_runtime_suspend(struct device *dev)
541{ 542{
542 struct platform_device *pdev = to_platform_device(dev); 543 struct platform_device *pdev = to_platform_device(dev);
@@ -563,13 +564,55 @@ static int _od_runtime_resume(struct device *dev)
563 564
564 return pm_generic_runtime_resume(dev); 565 return pm_generic_runtime_resume(dev);
565} 566}
567#endif
566 568
567static struct dev_power_domain omap_device_power_domain = { 569#ifdef CONFIG_SUSPEND
570static int _od_suspend_noirq(struct device *dev)
571{
572 struct platform_device *pdev = to_platform_device(dev);
573 struct omap_device *od = to_omap_device(pdev);
574 int ret;
575
576 if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
577 return pm_generic_suspend_noirq(dev);
578
579 ret = pm_generic_suspend_noirq(dev);
580
581 if (!ret && !pm_runtime_status_suspended(dev)) {
582 if (pm_generic_runtime_suspend(dev) == 0) {
583 omap_device_idle(pdev);
584 od->flags |= OMAP_DEVICE_SUSPENDED;
585 }
586 }
587
588 return ret;
589}
590
591static int _od_resume_noirq(struct device *dev)
592{
593 struct platform_device *pdev = to_platform_device(dev);
594 struct omap_device *od = to_omap_device(pdev);
595
596 if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
597 return pm_generic_resume_noirq(dev);
598
599 if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
600 !pm_runtime_status_suspended(dev)) {
601 od->flags &= ~OMAP_DEVICE_SUSPENDED;
602 omap_device_enable(pdev);
603 pm_generic_runtime_resume(dev);
604 }
605
606 return pm_generic_resume_noirq(dev);
607}
608#endif
609
610static struct dev_pm_domain omap_device_pm_domain = {
568 .ops = { 611 .ops = {
569 .runtime_suspend = _od_runtime_suspend, 612 SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
570 .runtime_idle = _od_runtime_idle, 613 _od_runtime_idle)
571 .runtime_resume = _od_runtime_resume,
572 USE_PLATFORM_PM_SLEEP_OPS 614 USE_PLATFORM_PM_SLEEP_OPS
615 SET_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, _od_resume_noirq)
573 } 616 }
574}; 617};
575 618
@@ -586,7 +629,7 @@ int omap_device_register(struct omap_device *od)
586 pr_debug("omap_device: %s: registering\n", od->pdev.name); 629 pr_debug("omap_device: %s: registering\n", od->pdev.name);
587 630
588 od->pdev.dev.parent = &omap_device_parent; 631 od->pdev.dev.parent = &omap_device_parent;
589 od->pdev.dev.pwr_domain = &omap_device_power_domain; 632 od->pdev.dev.pm_domain = &omap_device_pm_domain;
590 return platform_device_register(&od->pdev); 633 return platform_device_register(&od->pdev);
591} 634}
592 635
diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
index 64c807c39208..bf280c812d2f 100644
--- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c
+++ b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
@@ -256,7 +256,7 @@ out:
256 return ret; 256 return ret;
257} 257}
258 258
259static struct dev_power_domain default_power_domain = { 259static struct dev_pm_domain default_pm_domain = {
260 .ops = { 260 .ops = {
261 .runtime_suspend = default_platform_runtime_suspend, 261 .runtime_suspend = default_platform_runtime_suspend,
262 .runtime_resume = default_platform_runtime_resume, 262 .runtime_resume = default_platform_runtime_resume,
@@ -285,7 +285,7 @@ static int platform_bus_notify(struct notifier_block *nb,
285 hwblk_disable(hwblk_info, hwblk); 285 hwblk_disable(hwblk_info, hwblk);
286 /* make sure driver re-inits itself once */ 286 /* make sure driver re-inits itself once */
287 __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); 287 __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
288 dev->pwr_domain = &default_power_domain; 288 dev->pm_domain = &default_pm_domain;
289 break; 289 break;
290 /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */ 290 /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
291 case BUS_NOTIFY_BOUND_DRIVER: 291 case BUS_NOTIFY_BOUND_DRIVER:
@@ -299,7 +299,7 @@ static int platform_bus_notify(struct notifier_block *nb,
299 __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); 299 __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
300 break; 300 break;
301 case BUS_NOTIFY_DEL_DEVICE: 301 case BUS_NOTIFY_DEL_DEVICE:
302 dev->pwr_domain = NULL; 302 dev->pm_domain = NULL;
303 break; 303 break;
304 } 304 }
305 return 0; 305 return 0;