diff options
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/board-mackerel.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/clock-sh7372.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/sh7372.h | 29 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/pm-sh7372.c | 160 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/pm_runtime.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/setup-sh7372.c | 11 |
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 | ||
1416 | static void __init ap4evb_timer_init(void) | 1421 | static 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 | ||
1589 | static void __init mackerel_timer_init(void) | 1594 | static 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 | ||
667 | void __init sh7372_clock_init(void) | 668 | void __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; | |||
470 | extern struct clk sh7372_fsidiva_clk; | 471 | extern struct clk sh7372_fsidiva_clk; |
471 | extern struct clk sh7372_fsidivb_clk; | 472 | extern struct clk sh7372_fsidivb_clk; |
472 | 473 | ||
474 | struct platform_device; | ||
475 | |||
476 | struct sh7372_pm_domain { | ||
477 | struct generic_pm_domain genpd; | ||
478 | unsigned int bit_shift; | ||
479 | }; | ||
480 | |||
481 | static 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 | ||
487 | extern struct sh7372_pm_domain sh7372_a4lc; | ||
488 | extern struct sh7372_pm_domain sh7372_a4mp; | ||
489 | extern struct sh7372_pm_domain sh7372_d4; | ||
490 | extern struct sh7372_pm_domain sh7372_a3rv; | ||
491 | extern struct sh7372_pm_domain sh7372_a3ri; | ||
492 | extern struct sh7372_pm_domain sh7372_a3sg; | ||
493 | |||
494 | extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd); | ||
495 | extern 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 | |||
41 | static 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 | |||
64 | static 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 | |||
94 | static 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 | |||
104 | static 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 | |||
114 | static 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 | |||
123 | static bool pd_active_wakeup(struct device *dev) | ||
124 | { | ||
125 | return true; | ||
126 | } | ||
127 | |||
128 | void 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 | |||
150 | void 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 | |||
162 | struct sh7372_pm_domain sh7372_a4lc = { | ||
163 | .bit_shift = 1, | ||
164 | }; | ||
165 | |||
166 | struct sh7372_pm_domain sh7372_a4mp = { | ||
167 | .bit_shift = 2, | ||
168 | }; | ||
169 | |||
170 | struct sh7372_pm_domain sh7372_d4 = { | ||
171 | .bit_shift = 3, | ||
172 | }; | ||
173 | |||
174 | struct sh7372_pm_domain sh7372_a3rv = { | ||
175 | .bit_shift = 6, | ||
176 | }; | ||
177 | |||
178 | struct sh7372_pm_domain sh7372_a3ri = { | ||
179 | .bit_shift = 8, | ||
180 | }; | ||
181 | |||
182 | struct sh7372_pm_domain sh7372_a3sg = { | ||
183 | .bit_shift = 13, | ||
184 | }; | ||
185 | |||
186 | #endif /* CONFIG_PM */ | ||
187 | |||
28 | static void sh7372_enter_core_standby(void) | 188 | static 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 | ||
31 | static struct dev_power_domain default_power_domain = { | 32 | static 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 | ||
48 | static struct pm_clk_notifier_block platform_bus_notifier = { | 49 | static 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 | ||
53 | static int __init sh_pm_runtime_init(void) | 54 | static 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 | } |
58 | core_initcall(sh_pm_runtime_init); | 59 | core_initcall(sh_pm_runtime_init); |
60 | |||
61 | static int __init sh_pm_runtime_late_init(void) | ||
62 | { | ||
63 | pm_genpd_poweroff_unused(); | ||
64 | return 0; | ||
65 | } | ||
66 | late_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 | ||
842 | void __init sh7372_add_standard_devices(void) | 842 | void __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 | ||
851 | void __init sh7372_add_early_devices(void) | 862 | void __init sh7372_add_early_devices(void) |