Commit | Line | Data |
---|---|---|
97991657 MD |
1 | /* |
2 | * sh7372 Power management support | |
3 | * | |
4 | * Copyright (C) 2011 Magnus Damm | |
5 | * | |
6 | * This file is subject to the terms and conditions of the GNU General Public | |
7 | * License. See the file "COPYING" in the main directory of this archive | |
8 | * for more details. | |
9 | */ | |
10 | ||
11 | #include <linux/pm.h> | |
12 | #include <linux/suspend.h> | |
082a8ca1 | 13 | #include <linux/cpuidle.h> |
97991657 MD |
14 | #include <linux/module.h> |
15 | #include <linux/list.h> | |
16 | #include <linux/err.h> | |
17 | #include <linux/slab.h> | |
b5e8d269 | 18 | #include <linux/pm_clock.h> |
e3e01091 RW |
19 | #include <linux/platform_device.h> |
20 | #include <linux/delay.h> | |
cf33835c MD |
21 | #include <linux/irq.h> |
22 | #include <linux/bitrev.h> | |
056879d2 | 23 | #include <linux/console.h> |
97991657 MD |
24 | #include <asm/system.h> |
25 | #include <asm/io.h> | |
26 | #include <asm/tlbflush.h> | |
06b84166 | 27 | #include <asm/suspend.h> |
97991657 | 28 | #include <mach/common.h> |
e3e01091 | 29 | #include <mach/sh7372.h> |
97991657 | 30 | |
cf33835c MD |
31 | /* DBG */ |
32 | #define DBGREG1 0xe6100020 | |
33 | #define DBGREG9 0xe6100040 | |
97991657 | 34 | |
cf33835c MD |
35 | /* CPGA */ |
36 | #define SYSTBCR 0xe6150024 | |
37 | #define MSTPSR0 0xe6150030 | |
38 | #define MSTPSR1 0xe6150038 | |
39 | #define MSTPSR2 0xe6150040 | |
40 | #define MSTPSR3 0xe6150048 | |
41 | #define MSTPSR4 0xe615004c | |
42 | #define PLLC01STPCR 0xe61500c8 | |
43 | ||
44 | /* SYSC */ | |
e3e01091 RW |
45 | #define SPDCR 0xe6180008 |
46 | #define SWUCR 0xe6180014 | |
cf33835c | 47 | #define SBAR 0xe6180020 |
382414b9 | 48 | #define WUPRMSK 0xe6180028 |
cf33835c MD |
49 | #define WUPSMSK 0xe618002c |
50 | #define WUPSMSK2 0xe6180048 | |
e3e01091 | 51 | #define PSTR 0xe6180080 |
cf33835c MD |
52 | #define WUPSFAC 0xe6180098 |
53 | #define IRQCR 0xe618022c | |
54 | #define IRQCR2 0xe6180238 | |
55 | #define IRQCR3 0xe6180244 | |
56 | #define IRQCR4 0xe6180248 | |
57 | #define PDNSEL 0xe6180254 | |
58 | ||
59 | /* INTC */ | |
60 | #define ICR1A 0xe6900000 | |
61 | #define ICR2A 0xe6900004 | |
62 | #define ICR3A 0xe6900008 | |
63 | #define ICR4A 0xe690000c | |
64 | #define INTMSK00A 0xe6900040 | |
65 | #define INTMSK10A 0xe6900044 | |
66 | #define INTMSK20A 0xe6900048 | |
67 | #define INTMSK30A 0xe690004c | |
68 | ||
69 | /* MFIS */ | |
70 | #define SMFRAM 0xe6a70000 | |
71 | ||
72 | /* AP-System Core */ | |
73 | #define APARMBAREA 0xe6f10020 | |
e3e01091 RW |
74 | |
75 | #define PSTR_RETRIES 100 | |
76 | #define PSTR_DELAY_US 10 | |
77 | ||
78 | #ifdef CONFIG_PM | |
79 | ||
80 | static int pd_power_down(struct generic_pm_domain *genpd) | |
81 | { | |
82 | struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); | |
83 | unsigned int mask = 1 << sh7372_pd->bit_shift; | |
84 | ||
382414b9 MD |
85 | if (sh7372_pd->suspend) |
86 | sh7372_pd->suspend(); | |
87 | ||
88 | if (sh7372_pd->stay_on) | |
89 | return 0; | |
90 | ||
e3e01091 RW |
91 | if (__raw_readl(PSTR) & mask) { |
92 | unsigned int retry_count; | |
93 | ||
94 | __raw_writel(mask, SPDCR); | |
95 | ||
96 | for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { | |
97 | if (!(__raw_readl(SPDCR) & mask)) | |
98 | break; | |
99 | cpu_relax(); | |
100 | } | |
101 | } | |
102 | ||
d93f5cde MD |
103 | if (!sh7372_pd->no_debug) |
104 | pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n", | |
105 | mask, __raw_readl(PSTR)); | |
e3e01091 RW |
106 | |
107 | return 0; | |
108 | } | |
109 | ||
bc9f5449 | 110 | static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume) |
e3e01091 | 111 | { |
e3e01091 RW |
112 | unsigned int mask = 1 << sh7372_pd->bit_shift; |
113 | unsigned int retry_count; | |
114 | int ret = 0; | |
115 | ||
382414b9 MD |
116 | if (sh7372_pd->stay_on) |
117 | goto out; | |
118 | ||
e3e01091 RW |
119 | if (__raw_readl(PSTR) & mask) |
120 | goto out; | |
121 | ||
122 | __raw_writel(mask, SWUCR); | |
123 | ||
124 | for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { | |
125 | if (!(__raw_readl(SWUCR) & mask)) | |
be2658ff | 126 | break; |
e3e01091 RW |
127 | if (retry_count > PSTR_RETRIES) |
128 | udelay(PSTR_DELAY_US); | |
129 | else | |
130 | cpu_relax(); | |
131 | } | |
be2658ff | 132 | if (!retry_count) |
e3e01091 RW |
133 | ret = -EIO; |
134 | ||
d93f5cde MD |
135 | if (!sh7372_pd->no_debug) |
136 | pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n", | |
137 | mask, __raw_readl(PSTR)); | |
e3e01091 | 138 | |
382414b9 | 139 | out: |
bc9f5449 | 140 | if (ret == 0 && sh7372_pd->resume && do_resume) |
382414b9 MD |
141 | sh7372_pd->resume(); |
142 | ||
e3e01091 RW |
143 | return ret; |
144 | } | |
145 | ||
bc9f5449 RW |
146 | static int pd_power_up(struct generic_pm_domain *genpd) |
147 | { | |
148 | return __pd_power_up(to_sh7372_pd(genpd), true); | |
149 | } | |
150 | ||
382414b9 MD |
151 | static void sh7372_a4r_suspend(void) |
152 | { | |
153 | sh7372_intcs_suspend(); | |
154 | __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ | |
155 | } | |
156 | ||
e3e01091 RW |
157 | static bool pd_active_wakeup(struct device *dev) |
158 | { | |
d5e4cbfe RW |
159 | bool (*active_wakeup)(struct device *dev); |
160 | ||
161 | active_wakeup = dev_gpd_data(dev)->ops.active_wakeup; | |
162 | return active_wakeup ? active_wakeup(dev) : true; | |
e3e01091 RW |
163 | } |
164 | ||
d93f5cde MD |
165 | static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain) |
166 | { | |
167 | return false; | |
168 | } | |
169 | ||
170 | struct dev_power_governor sh7372_always_on_gov = { | |
171 | .power_down_ok = sh7372_power_down_forbidden, | |
172 | }; | |
173 | ||
d5e4cbfe RW |
174 | static int sh7372_stop_dev(struct device *dev) |
175 | { | |
176 | int (*stop)(struct device *dev); | |
177 | ||
178 | stop = dev_gpd_data(dev)->ops.stop; | |
179 | if (stop) { | |
180 | int ret = stop(dev); | |
181 | if (ret) | |
182 | return ret; | |
183 | } | |
184 | return pm_clk_suspend(dev); | |
185 | } | |
186 | ||
187 | static int sh7372_start_dev(struct device *dev) | |
188 | { | |
189 | int (*start)(struct device *dev); | |
190 | int ret; | |
191 | ||
192 | ret = pm_clk_resume(dev); | |
193 | if (ret) | |
194 | return ret; | |
195 | ||
196 | start = dev_gpd_data(dev)->ops.start; | |
197 | if (start) | |
198 | ret = start(dev); | |
199 | ||
200 | return ret; | |
201 | } | |
202 | ||
e3e01091 RW |
203 | void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) |
204 | { | |
205 | struct generic_pm_domain *genpd = &sh7372_pd->genpd; | |
206 | ||
d93f5cde | 207 | pm_genpd_init(genpd, sh7372_pd->gov, false); |
d5e4cbfe RW |
208 | genpd->dev_ops.stop = sh7372_stop_dev; |
209 | genpd->dev_ops.start = sh7372_start_dev; | |
210 | genpd->dev_ops.active_wakeup = pd_active_wakeup; | |
0aa2a221 | 211 | genpd->dev_irq_safe = true; |
111058c3 RW |
212 | genpd->power_off = pd_power_down; |
213 | genpd->power_on = pd_power_up; | |
bc9f5449 | 214 | __pd_power_up(sh7372_pd, false); |
e3e01091 RW |
215 | } |
216 | ||
217 | void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, | |
218 | struct platform_device *pdev) | |
219 | { | |
220 | struct device *dev = &pdev->dev; | |
221 | ||
e3e01091 | 222 | pm_genpd_add_device(&sh7372_pd->genpd, dev); |
4605ab65 RW |
223 | if (pm_clk_no_clocks(dev)) |
224 | pm_clk_add(dev, NULL); | |
e3e01091 RW |
225 | } |
226 | ||
111058c3 RW |
227 | void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, |
228 | struct sh7372_pm_domain *sh7372_sd) | |
229 | { | |
230 | pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd); | |
231 | } | |
232 | ||
e3e01091 RW |
233 | struct sh7372_pm_domain sh7372_a4lc = { |
234 | .bit_shift = 1, | |
235 | }; | |
236 | ||
c1ba5bb5 KM |
237 | struct sh7372_pm_domain sh7372_a4mp = { |
238 | .bit_shift = 2, | |
239 | }; | |
240 | ||
d24771de MD |
241 | struct sh7372_pm_domain sh7372_d4 = { |
242 | .bit_shift = 3, | |
243 | }; | |
244 | ||
382414b9 MD |
245 | struct sh7372_pm_domain sh7372_a4r = { |
246 | .bit_shift = 5, | |
247 | .gov = &sh7372_always_on_gov, | |
248 | .suspend = sh7372_a4r_suspend, | |
249 | .resume = sh7372_intcs_resume, | |
250 | .stay_on = true, | |
251 | }; | |
252 | ||
33afebf3 MD |
253 | struct sh7372_pm_domain sh7372_a3rv = { |
254 | .bit_shift = 6, | |
255 | }; | |
256 | ||
082517aa MD |
257 | struct sh7372_pm_domain sh7372_a3ri = { |
258 | .bit_shift = 8, | |
259 | }; | |
260 | ||
d93f5cde MD |
261 | struct sh7372_pm_domain sh7372_a3sp = { |
262 | .bit_shift = 11, | |
263 | .gov = &sh7372_always_on_gov, | |
264 | .no_debug = true, | |
265 | }; | |
266 | ||
88995e80 RW |
267 | static void sh7372_a3sp_init(void) |
268 | { | |
269 | /* serial consoles make use of SCIF hardware located in A3SP, | |
270 | * keep such power domain on if "no_console_suspend" is set. | |
271 | */ | |
272 | sh7372_a3sp.stay_on = !console_suspend_enabled; | |
273 | } | |
274 | ||
c47586b6 MD |
275 | struct sh7372_pm_domain sh7372_a3sg = { |
276 | .bit_shift = 13, | |
277 | }; | |
278 | ||
88995e80 RW |
279 | #else /* !CONFIG_PM */ |
280 | ||
281 | static inline void sh7372_a3sp_init(void) {} | |
282 | ||
283 | #endif /* !CONFIG_PM */ | |
e3e01091 | 284 | |
a0089bd6 | 285 | #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) |
06b84166 | 286 | static int sh7372_do_idle_core_standby(unsigned long unused) |
97991657 | 287 | { |
06b84166 MD |
288 | cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */ |
289 | return 0; | |
290 | } | |
97991657 | 291 | |
06b84166 MD |
292 | static void sh7372_enter_core_standby(void) |
293 | { | |
294 | /* set reset vector, translate 4k */ | |
cf33835c | 295 | __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); |
06b84166 | 296 | __raw_writel(0, APARMBAREA); |
97991657 | 297 | |
06b84166 MD |
298 | /* enter sleep mode with SYSTBCR to 0x10 */ |
299 | __raw_writel(0x10, SYSTBCR); | |
300 | cpu_suspend(0, sh7372_do_idle_core_standby); | |
301 | __raw_writel(0, SYSTBCR); | |
97991657 | 302 | |
06b84166 MD |
303 | /* disable reset vector translation */ |
304 | __raw_writel(0, SBAR); | |
97991657 | 305 | } |
a0089bd6 | 306 | #endif |
97991657 | 307 | |
a0089bd6 | 308 | #ifdef CONFIG_SUSPEND |
cf33835c MD |
309 | static void sh7372_enter_a3sm_common(int pllc0_on) |
310 | { | |
311 | /* set reset vector, translate 4k */ | |
312 | __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); | |
313 | __raw_writel(0, APARMBAREA); | |
314 | ||
315 | if (pllc0_on) | |
316 | __raw_writel(0, PLLC01STPCR); | |
317 | else | |
318 | __raw_writel(1 << 28, PLLC01STPCR); | |
319 | ||
320 | __raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */ | |
321 | __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */ | |
322 | cpu_suspend(0, sh7372_do_idle_a3sm); | |
323 | __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */ | |
324 | ||
325 | /* disable reset vector translation */ | |
326 | __raw_writel(0, SBAR); | |
327 | } | |
328 | ||
329 | static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p) | |
330 | { | |
331 | unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4; | |
332 | unsigned long msk, msk2; | |
333 | ||
334 | /* check active clocks to determine potential wakeup sources */ | |
335 | ||
336 | mstpsr0 = __raw_readl(MSTPSR0); | |
337 | if ((mstpsr0 & 0x00000003) != 0x00000003) { | |
338 | pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0); | |
339 | return 0; | |
340 | } | |
341 | ||
342 | mstpsr1 = __raw_readl(MSTPSR1); | |
343 | if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) { | |
344 | pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1); | |
345 | return 0; | |
346 | } | |
347 | ||
348 | mstpsr2 = __raw_readl(MSTPSR2); | |
349 | if ((mstpsr2 & 0x000741ff) != 0x000741ff) { | |
350 | pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2); | |
351 | return 0; | |
352 | } | |
353 | ||
354 | mstpsr3 = __raw_readl(MSTPSR3); | |
355 | if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) { | |
356 | pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3); | |
357 | return 0; | |
358 | } | |
359 | ||
360 | mstpsr4 = __raw_readl(MSTPSR4); | |
361 | if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) { | |
362 | pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4); | |
363 | return 0; | |
364 | } | |
365 | ||
366 | msk = 0; | |
367 | msk2 = 0; | |
368 | ||
369 | /* make bitmaps of limited number of wakeup sources */ | |
370 | ||
371 | if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */ | |
372 | msk |= 1 << 31; | |
373 | ||
374 | if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */ | |
375 | msk |= 1 << 21; | |
376 | ||
377 | if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */ | |
378 | msk |= 1 << 2; | |
379 | ||
380 | if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */ | |
381 | msk |= 1 << 1; | |
382 | ||
383 | if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */ | |
384 | msk |= 1 << 1; | |
385 | ||
386 | if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */ | |
387 | msk |= 1 << 1; | |
388 | ||
389 | if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */ | |
390 | msk2 |= 1 << 17; | |
391 | ||
392 | *mskp = msk; | |
393 | *msk2p = msk2; | |
394 | ||
395 | return 1; | |
396 | } | |
397 | ||
398 | static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p) | |
399 | { | |
400 | u16 tmp, irqcr1, irqcr2; | |
401 | int k; | |
402 | ||
403 | irqcr1 = 0; | |
404 | irqcr2 = 0; | |
405 | ||
406 | /* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */ | |
407 | for (k = 0; k <= 7; k++) { | |
408 | tmp = (icr >> ((7 - k) * 4)) & 0xf; | |
409 | irqcr1 |= (tmp & 0x03) << (k * 2); | |
410 | irqcr2 |= (tmp >> 2) << (k * 2); | |
411 | } | |
412 | ||
413 | *irqcr1p = irqcr1; | |
414 | *irqcr2p = irqcr2; | |
415 | } | |
416 | ||
417 | static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) | |
418 | { | |
419 | u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high; | |
420 | unsigned long tmp; | |
421 | ||
422 | /* read IRQ0A -> IRQ15A mask */ | |
423 | tmp = bitrev8(__raw_readb(INTMSK00A)); | |
424 | tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8; | |
425 | ||
426 | /* setup WUPSMSK from clocks and external IRQ mask */ | |
427 | msk = (~msk & 0xc030000f) | (tmp << 4); | |
428 | __raw_writel(msk, WUPSMSK); | |
429 | ||
430 | /* propage level/edge trigger for external IRQ 0->15 */ | |
431 | sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low); | |
432 | sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high); | |
433 | __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR); | |
434 | __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2); | |
435 | ||
436 | /* read IRQ16A -> IRQ31A mask */ | |
437 | tmp = bitrev8(__raw_readb(INTMSK20A)); | |
438 | tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8; | |
439 | ||
440 | /* setup WUPSMSK2 from clocks and external IRQ mask */ | |
441 | msk2 = (~msk2 & 0x00030000) | tmp; | |
442 | __raw_writel(msk2, WUPSMSK2); | |
443 | ||
444 | /* propage level/edge trigger for external IRQ 16->31 */ | |
445 | sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low); | |
446 | sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high); | |
447 | __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3); | |
448 | __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4); | |
449 | } | |
a0089bd6 | 450 | #endif |
cf33835c | 451 | |
082a8ca1 | 452 | #ifdef CONFIG_CPU_IDLE |
cf33835c | 453 | |
b73b5c49 | 454 | static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) |
082a8ca1 | 455 | { |
b73b5c49 | 456 | struct cpuidle_state *state = &drv->states[drv->state_count]; |
082a8ca1 | 457 | |
082a8ca1 MD |
458 | snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); |
459 | strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN); | |
460 | state->exit_latency = 10; | |
461 | state->target_residency = 20 + 10; | |
b73b5c49 MD |
462 | state->flags = CPUIDLE_FLAG_TIME_VALID; |
463 | shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby; | |
082a8ca1 | 464 | |
b73b5c49 | 465 | drv->state_count++; |
082a8ca1 MD |
466 | } |
467 | ||
468 | static void sh7372_cpuidle_init(void) | |
469 | { | |
470 | shmobile_cpuidle_setup = sh7372_cpuidle_setup; | |
471 | } | |
472 | #else | |
473 | static void sh7372_cpuidle_init(void) {} | |
474 | #endif | |
475 | ||
476 | #ifdef CONFIG_SUSPEND | |
cf33835c | 477 | |
97991657 MD |
478 | static int sh7372_enter_suspend(suspend_state_t suspend_state) |
479 | { | |
cf33835c MD |
480 | unsigned long msk, msk2; |
481 | ||
482 | /* check active clocks to determine potential wakeup sources */ | |
483 | if (sh7372_a3sm_valid(&msk, &msk2)) { | |
484 | ||
485 | /* convert INTC mask and sense to SYSC mask and sense */ | |
486 | sh7372_setup_a3sm(msk, msk2); | |
487 | ||
488 | /* enter A3SM sleep with PLLC0 off */ | |
489 | pr_debug("entering A3SM\n"); | |
490 | sh7372_enter_a3sm_common(0); | |
491 | } else { | |
492 | /* default to Core Standby that supports all wakeup sources */ | |
493 | pr_debug("entering Core Standby\n"); | |
494 | sh7372_enter_core_standby(); | |
495 | } | |
97991657 MD |
496 | return 0; |
497 | } | |
498 | ||
499 | static void sh7372_suspend_init(void) | |
500 | { | |
501 | shmobile_suspend_ops.enter = sh7372_enter_suspend; | |
502 | } | |
503 | #else | |
504 | static void sh7372_suspend_init(void) {} | |
505 | #endif | |
506 | ||
97991657 MD |
507 | void __init sh7372_pm_init(void) |
508 | { | |
509 | /* enable DBG hardware block to kick SYSC */ | |
510 | __raw_writel(0x0000a500, DBGREG9); | |
511 | __raw_writel(0x0000a501, DBGREG9); | |
512 | __raw_writel(0x00000000, DBGREG1); | |
513 | ||
d93f5cde MD |
514 | /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ |
515 | __raw_writel(0, PDNSEL); | |
516 | ||
88995e80 | 517 | sh7372_a3sp_init(); |
056879d2 | 518 | |
97991657 | 519 | sh7372_suspend_init(); |
082a8ca1 | 520 | sh7372_cpuidle_init(); |
97991657 | 521 | } |