diff options
Diffstat (limited to 'arch/arm/mach-shmobile/pm-sh7372.c')
-rw-r--r-- | arch/arm/mach-shmobile/pm-sh7372.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 8e4aadf14c9..933fb411be0 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; |