aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-shmobile')
-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
7 files changed, 226 insertions, 7 deletions
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)