aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h4
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h3
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c49
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c66
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c6
-rw-r--r--arch/arm/mach-shmobile/sleep-sh7372.S21
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);
35extern void sh7372_clock_init(void); 35extern void sh7372_clock_init(void);
36extern void sh7372_pinmux_init(void); 36extern void sh7372_pinmux_init(void);
37extern void sh7372_pm_init(void); 37extern void sh7372_pm_init(void);
38extern void sh7372_resume_core_standby_a3sm(void); 38extern void sh7372_resume_core_standby_sysc(void);
39extern int sh7372_do_idle_a3sm(unsigned long unused); 39extern int sh7372_do_idle_sysc(unsigned long sleep_mode);
40extern struct clk sh7372_extal1_clk; 40extern struct clk sh7372_extal1_clk;
41extern struct clk sh7372_extal2_clk; 41extern 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;
499extern struct sh7372_pm_domain sh7372_a4r; 499extern struct sh7372_pm_domain sh7372_a4r;
500extern struct sh7372_pm_domain sh7372_a3rv; 500extern struct sh7372_pm_domain sh7372_a3rv;
501extern struct sh7372_pm_domain sh7372_a3ri; 501extern struct sh7372_pm_domain sh7372_a3ri;
502extern struct sh7372_pm_domain sh7372_a4s;
502extern struct sh7372_pm_domain sh7372_a3sp; 503extern struct sh7372_pm_domain sh7372_a3sp;
503extern struct sh7372_pm_domain sh7372_a3sg; 504extern 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
516extern void sh7372_intcs_suspend(void); 517extern void sh7372_intcs_suspend(void);
517extern void sh7372_intcs_resume(void); 518extern void sh7372_intcs_resume(void);
519extern void sh7372_intca_suspend(void);
520extern 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
615static unsigned short e694[0x200];
616static unsigned short e695[0x200];
617
618void 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
641void 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
259struct 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
259struct sh7372_pm_domain sh7372_a3sp = { 267struct 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
292static void sh7372_enter_core_standby(void) 300static 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
307static 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
309static void sh7372_enter_a3sm_common(int pllc0_on) 322static 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
329static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p) 337static 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
417static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) 425static 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
459static 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
465static 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
41sh7372_resume_core_standby_a3sm: 41sh7372_resume_core_standby_sysc:
42 ldr pc, 1f 42 ldr pc, 1f
431: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET 431: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
44 44
45 .global sh7372_do_idle_a3sm 45#define SPDCR 0xe6180008
46sh7372_do_idle_a3sm: 46
47 /* A3SM & A4S power down */
48 .global sh7372_do_idle_sysc
49sh7372_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]
901: 911:
91 b 1b 92 b 1b
92 93