diff options
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/common.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/sh7372.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/intc-sh7372.c | 49 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/pm-sh7372.c | 66 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/setup-sh7372.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/sleep-sh7372.S | 21 |
6 files changed, 118 insertions, 31 deletions
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 834bd6cd508f..4807623fb71c 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h | |||
@@ -35,8 +35,8 @@ extern void sh7372_add_standard_devices(void); | |||
35 | extern void sh7372_clock_init(void); | 35 | extern void sh7372_clock_init(void); |
36 | extern void sh7372_pinmux_init(void); | 36 | extern void sh7372_pinmux_init(void); |
37 | extern void sh7372_pm_init(void); | 37 | extern void sh7372_pm_init(void); |
38 | extern void sh7372_resume_core_standby_a3sm(void); | 38 | extern void sh7372_resume_core_standby_sysc(void); |
39 | extern int sh7372_do_idle_a3sm(unsigned long unused); | 39 | extern int sh7372_do_idle_sysc(unsigned long sleep_mode); |
40 | extern struct clk sh7372_extal1_clk; | 40 | extern struct clk sh7372_extal1_clk; |
41 | extern struct clk sh7372_extal2_clk; | 41 | extern struct clk sh7372_extal2_clk; |
42 | 42 | ||
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 84532f9629b2..d0731d973f1f 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h | |||
@@ -499,6 +499,7 @@ extern struct sh7372_pm_domain sh7372_d4; | |||
499 | extern struct sh7372_pm_domain sh7372_a4r; | 499 | extern struct sh7372_pm_domain sh7372_a4r; |
500 | extern struct sh7372_pm_domain sh7372_a3rv; | 500 | extern struct sh7372_pm_domain sh7372_a3rv; |
501 | extern struct sh7372_pm_domain sh7372_a3ri; | 501 | extern struct sh7372_pm_domain sh7372_a3ri; |
502 | extern struct sh7372_pm_domain sh7372_a4s; | ||
502 | extern struct sh7372_pm_domain sh7372_a3sp; | 503 | extern struct sh7372_pm_domain sh7372_a3sp; |
503 | extern struct sh7372_pm_domain sh7372_a3sg; | 504 | extern struct sh7372_pm_domain sh7372_a3sg; |
504 | 505 | ||
@@ -515,5 +516,7 @@ extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, | |||
515 | 516 | ||
516 | extern void sh7372_intcs_suspend(void); | 517 | extern void sh7372_intcs_suspend(void); |
517 | extern void sh7372_intcs_resume(void); | 518 | extern void sh7372_intcs_resume(void); |
519 | extern void sh7372_intca_suspend(void); | ||
520 | extern void sh7372_intca_resume(void); | ||
518 | 521 | ||
519 | #endif /* __ASM_SH7372_H__ */ | 522 | #endif /* __ASM_SH7372_H__ */ |
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c index 2d8856df80e2..d087b31b5d12 100644 --- a/arch/arm/mach-shmobile/intc-sh7372.c +++ b/arch/arm/mach-shmobile/intc-sh7372.c | |||
@@ -611,3 +611,52 @@ void sh7372_intcs_resume(void) | |||
611 | for (k = 0x80; k <= 0x9c; k += 4) | 611 | for (k = 0x80; k <= 0x9c; k += 4) |
612 | __raw_writeb(ffd5[k], intcs_ffd5 + k); | 612 | __raw_writeb(ffd5[k], intcs_ffd5 + k); |
613 | } | 613 | } |
614 | |||
615 | static unsigned short e694[0x200]; | ||
616 | static unsigned short e695[0x200]; | ||
617 | |||
618 | void sh7372_intca_suspend(void) | ||
619 | { | ||
620 | int k; | ||
621 | |||
622 | for (k = 0x00; k <= 0x38; k += 4) | ||
623 | e694[k] = __raw_readw(0xe6940000 + k); | ||
624 | |||
625 | for (k = 0x80; k <= 0xb4; k += 4) | ||
626 | e694[k] = __raw_readb(0xe6940000 + k); | ||
627 | |||
628 | for (k = 0x180; k <= 0x1b4; k += 4) | ||
629 | e694[k] = __raw_readb(0xe6940000 + k); | ||
630 | |||
631 | for (k = 0x00; k <= 0x50; k += 4) | ||
632 | e695[k] = __raw_readw(0xe6950000 + k); | ||
633 | |||
634 | for (k = 0x80; k <= 0xa8; k += 4) | ||
635 | e695[k] = __raw_readb(0xe6950000 + k); | ||
636 | |||
637 | for (k = 0x180; k <= 0x1a8; k += 4) | ||
638 | e695[k] = __raw_readb(0xe6950000 + k); | ||
639 | } | ||
640 | |||
641 | void sh7372_intca_resume(void) | ||
642 | { | ||
643 | int k; | ||
644 | |||
645 | for (k = 0x00; k <= 0x38; k += 4) | ||
646 | __raw_writew(e694[k], 0xe6940000 + k); | ||
647 | |||
648 | for (k = 0x80; k <= 0xb4; k += 4) | ||
649 | __raw_writeb(e694[k], 0xe6940000 + k); | ||
650 | |||
651 | for (k = 0x180; k <= 0x1b4; k += 4) | ||
652 | __raw_writeb(e694[k], 0xe6940000 + k); | ||
653 | |||
654 | for (k = 0x00; k <= 0x50; k += 4) | ||
655 | __raw_writew(e695[k], 0xe6950000 + k); | ||
656 | |||
657 | for (k = 0x80; k <= 0xa8; k += 4) | ||
658 | __raw_writeb(e695[k], 0xe6950000 + k); | ||
659 | |||
660 | for (k = 0x180; k <= 0x1a8; k += 4) | ||
661 | __raw_writeb(e695[k], 0xe6950000 + k); | ||
662 | } | ||
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index f742c61c8902..1e659d7360d1 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c | |||
@@ -256,6 +256,14 @@ struct sh7372_pm_domain sh7372_a3ri = { | |||
256 | .bit_shift = 8, | 256 | .bit_shift = 8, |
257 | }; | 257 | }; |
258 | 258 | ||
259 | struct sh7372_pm_domain sh7372_a4s = { | ||
260 | .genpd.name = "A4S", | ||
261 | .bit_shift = 10, | ||
262 | .gov = &pm_domain_always_on_gov, | ||
263 | .no_debug = true, | ||
264 | .stay_on = true, | ||
265 | }; | ||
266 | |||
259 | struct sh7372_pm_domain sh7372_a3sp = { | 267 | struct sh7372_pm_domain sh7372_a3sp = { |
260 | .genpd.name = "A3SP", | 268 | .genpd.name = "A3SP", |
261 | .bit_shift = 11, | 269 | .bit_shift = 11, |
@@ -289,11 +297,16 @@ static int sh7372_do_idle_core_standby(unsigned long unused) | |||
289 | return 0; | 297 | return 0; |
290 | } | 298 | } |
291 | 299 | ||
292 | static void sh7372_enter_core_standby(void) | 300 | static void sh7372_set_reset_vector(unsigned long address) |
293 | { | 301 | { |
294 | /* set reset vector, translate 4k */ | 302 | /* set reset vector, translate 4k */ |
295 | __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); | 303 | __raw_writel(address, SBAR); |
296 | __raw_writel(0, APARMBAREA); | 304 | __raw_writel(0, APARMBAREA); |
305 | } | ||
306 | |||
307 | static void sh7372_enter_core_standby(void) | ||
308 | { | ||
309 | sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); | ||
297 | 310 | ||
298 | /* enter sleep mode with SYSTBCR to 0x10 */ | 311 | /* enter sleep mode with SYSTBCR to 0x10 */ |
299 | __raw_writel(0x10, SYSTBCR); | 312 | __raw_writel(0x10, SYSTBCR); |
@@ -306,27 +319,22 @@ static void sh7372_enter_core_standby(void) | |||
306 | #endif | 319 | #endif |
307 | 320 | ||
308 | #ifdef CONFIG_SUSPEND | 321 | #ifdef CONFIG_SUSPEND |
309 | static void sh7372_enter_a3sm_common(int pllc0_on) | 322 | static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode) |
310 | { | 323 | { |
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) | 324 | if (pllc0_on) |
316 | __raw_writel(0, PLLC01STPCR); | 325 | __raw_writel(0, PLLC01STPCR); |
317 | else | 326 | else |
318 | __raw_writel(1 << 28, PLLC01STPCR); | 327 | __raw_writel(1 << 28, PLLC01STPCR); |
319 | 328 | ||
320 | __raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */ | ||
321 | __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */ | 329 | __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */ |
322 | cpu_suspend(0, sh7372_do_idle_a3sm); | 330 | cpu_suspend(sleep_mode, sh7372_do_idle_sysc); |
323 | __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */ | 331 | __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */ |
324 | 332 | ||
325 | /* disable reset vector translation */ | 333 | /* disable reset vector translation */ |
326 | __raw_writel(0, SBAR); | 334 | __raw_writel(0, SBAR); |
327 | } | 335 | } |
328 | 336 | ||
329 | static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p) | 337 | static int sh7372_sysc_valid(unsigned long *mskp, unsigned long *msk2p) |
330 | { | 338 | { |
331 | unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4; | 339 | unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4; |
332 | unsigned long msk, msk2; | 340 | unsigned long msk, msk2; |
@@ -414,7 +422,7 @@ static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p) | |||
414 | *irqcr2p = irqcr2; | 422 | *irqcr2p = irqcr2; |
415 | } | 423 | } |
416 | 424 | ||
417 | static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) | 425 | static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2) |
418 | { | 426 | { |
419 | u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high; | 427 | u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high; |
420 | unsigned long tmp; | 428 | unsigned long tmp; |
@@ -447,6 +455,22 @@ static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) | |||
447 | __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3); | 455 | __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3); |
448 | __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4); | 456 | __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4); |
449 | } | 457 | } |
458 | |||
459 | static void sh7372_enter_a3sm_common(int pllc0_on) | ||
460 | { | ||
461 | sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); | ||
462 | sh7372_enter_sysc(pllc0_on, 1 << 12); | ||
463 | } | ||
464 | |||
465 | static void sh7372_enter_a4s_common(int pllc0_on) | ||
466 | { | ||
467 | sh7372_intca_suspend(); | ||
468 | memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); | ||
469 | sh7372_set_reset_vector(SMFRAM); | ||
470 | sh7372_enter_sysc(pllc0_on, 1 << 10); | ||
471 | sh7372_intca_resume(); | ||
472 | } | ||
473 | |||
450 | #endif | 474 | #endif |
451 | 475 | ||
452 | #ifdef CONFIG_CPU_IDLE | 476 | #ifdef CONFIG_CPU_IDLE |
@@ -480,14 +504,20 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state) | |||
480 | unsigned long msk, msk2; | 504 | unsigned long msk, msk2; |
481 | 505 | ||
482 | /* check active clocks to determine potential wakeup sources */ | 506 | /* check active clocks to determine potential wakeup sources */ |
483 | if (sh7372_a3sm_valid(&msk, &msk2)) { | 507 | if (sh7372_sysc_valid(&msk, &msk2)) { |
484 | |||
485 | /* convert INTC mask and sense to SYSC mask and sense */ | 508 | /* convert INTC mask and sense to SYSC mask and sense */ |
486 | sh7372_setup_a3sm(msk, msk2); | 509 | sh7372_setup_sysc(msk, msk2); |
487 | 510 | ||
488 | /* enter A3SM sleep with PLLC0 off */ | 511 | if (!sh7372_a3sp.stay_on && |
489 | pr_debug("entering A3SM\n"); | 512 | sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) { |
490 | sh7372_enter_a3sm_common(0); | 513 | /* enter A4S sleep with PLLC0 off */ |
514 | pr_debug("entering A4S\n"); | ||
515 | sh7372_enter_a4s_common(0); | ||
516 | } else { | ||
517 | /* enter A3SM sleep with PLLC0 off */ | ||
518 | pr_debug("entering A3SM\n"); | ||
519 | sh7372_enter_a3sm_common(0); | ||
520 | } | ||
491 | } else { | 521 | } else { |
492 | /* default to Core Standby that supports all wakeup sources */ | 522 | /* default to Core Standby that supports all wakeup sources */ |
493 | pr_debug("entering Core Standby\n"); | 523 | pr_debug("entering Core Standby\n"); |
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 2380389e6ac5..c197f9d29d04 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c | |||
@@ -994,12 +994,16 @@ void __init sh7372_add_standard_devices(void) | |||
994 | sh7372_init_pm_domain(&sh7372_a4r); | 994 | sh7372_init_pm_domain(&sh7372_a4r); |
995 | sh7372_init_pm_domain(&sh7372_a3rv); | 995 | sh7372_init_pm_domain(&sh7372_a3rv); |
996 | sh7372_init_pm_domain(&sh7372_a3ri); | 996 | sh7372_init_pm_domain(&sh7372_a3ri); |
997 | sh7372_init_pm_domain(&sh7372_a3sg); | 997 | sh7372_init_pm_domain(&sh7372_a4s); |
998 | sh7372_init_pm_domain(&sh7372_a3sp); | 998 | sh7372_init_pm_domain(&sh7372_a3sp); |
999 | sh7372_init_pm_domain(&sh7372_a3sg); | ||
999 | 1000 | ||
1000 | sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv); | 1001 | sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv); |
1001 | sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc); | 1002 | sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc); |
1002 | 1003 | ||
1004 | sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sg); | ||
1005 | sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sp); | ||
1006 | |||
1003 | platform_add_devices(sh7372_early_devices, | 1007 | platform_add_devices(sh7372_early_devices, |
1004 | ARRAY_SIZE(sh7372_early_devices)); | 1008 | ARRAY_SIZE(sh7372_early_devices)); |
1005 | 1009 | ||
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S index f3ab3c5810ea..1d564674451d 100644 --- a/arch/arm/mach-shmobile/sleep-sh7372.S +++ b/arch/arm/mach-shmobile/sleep-sh7372.S | |||
@@ -37,13 +37,18 @@ | |||
37 | #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) | 37 | #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) |
38 | .align 12 | 38 | .align 12 |
39 | .text | 39 | .text |
40 | .global sh7372_resume_core_standby_a3sm | 40 | .global sh7372_resume_core_standby_sysc |
41 | sh7372_resume_core_standby_a3sm: | 41 | sh7372_resume_core_standby_sysc: |
42 | ldr pc, 1f | 42 | ldr pc, 1f |
43 | 1: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET | 43 | 1: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET |
44 | 44 | ||
45 | .global sh7372_do_idle_a3sm | 45 | #define SPDCR 0xe6180008 |
46 | sh7372_do_idle_a3sm: | 46 | |
47 | /* A3SM & A4S power down */ | ||
48 | .global sh7372_do_idle_sysc | ||
49 | sh7372_do_idle_sysc: | ||
50 | mov r8, r0 /* sleep mode passed in r0 */ | ||
51 | |||
47 | /* | 52 | /* |
48 | * Clear the SCTLR.C bit to prevent further data cache | 53 | * Clear the SCTLR.C bit to prevent further data cache |
49 | * allocation. Clearing SCTLR.C would make all the data accesses | 54 | * allocation. Clearing SCTLR.C would make all the data accesses |
@@ -80,13 +85,9 @@ sh7372_do_idle_a3sm: | |||
80 | dsb | 85 | dsb |
81 | dmb | 86 | dmb |
82 | 87 | ||
83 | #define SPDCR 0xe6180008 | 88 | /* SYSC power down */ |
84 | #define A3SM (1 << 12) | ||
85 | |||
86 | /* A3SM power down */ | ||
87 | ldr r0, =SPDCR | 89 | ldr r0, =SPDCR |
88 | ldr r1, =A3SM | 90 | str r8, [r0] |
89 | str r1, [r0] | ||
90 | 1: | 91 | 1: |
91 | b 1b | 92 | b 1b |
92 | 93 | ||