aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/include/asm/suspend.h5
-rw-r--r--arch/sh/kernel/asm-offsets.c3
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm.c13
-rw-r--r--arch/sh/kernel/cpu/shmobile/sleep.S12
4 files changed, 26 insertions, 7 deletions
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
index 702025d960a0..fe9c2a1ad047 100644
--- a/arch/sh/include/asm/suspend.h
+++ b/arch/sh/include/asm/suspend.h
@@ -38,6 +38,7 @@ void sh_mobile_register_self_refresh(unsigned long flags,
38/* register structure for address/data information */ 38/* register structure for address/data information */
39struct sh_sleep_regs { 39struct sh_sleep_regs {
40 unsigned long stbcr; 40 unsigned long stbcr;
41 unsigned long bar;
41 42
42 /* MMU */ 43 /* MMU */
43 unsigned long pteh; 44 unsigned long pteh;
@@ -63,10 +64,14 @@ struct sh_sleep_data {
63 unsigned long sf_pre; 64 unsigned long sf_pre;
64 unsigned long sf_post; 65 unsigned long sf_post;
65 66
67 /* address of resume code */
68 unsigned long resume;
69
66 /* register state saved and restored by the assembly code */ 70 /* register state saved and restored by the assembly code */
67 unsigned long vbr; 71 unsigned long vbr;
68 unsigned long spc; 72 unsigned long spc;
69 unsigned long sr; 73 unsigned long sr;
74 unsigned long sp;
70 75
71 /* structure for keeping register addresses */ 76 /* structure for keeping register addresses */
72 struct sh_sleep_regs addr; 77 struct sh_sleep_regs addr;
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
index 6026b0f849a1..08a2be775b6c 100644
--- a/arch/sh/kernel/asm-offsets.c
+++ b/arch/sh/kernel/asm-offsets.c
@@ -38,12 +38,15 @@ int main(void)
38 DEFINE(SH_SLEEP_MODE, offsetof(struct sh_sleep_data, mode)); 38 DEFINE(SH_SLEEP_MODE, offsetof(struct sh_sleep_data, mode));
39 DEFINE(SH_SLEEP_SF_PRE, offsetof(struct sh_sleep_data, sf_pre)); 39 DEFINE(SH_SLEEP_SF_PRE, offsetof(struct sh_sleep_data, sf_pre));
40 DEFINE(SH_SLEEP_SF_POST, offsetof(struct sh_sleep_data, sf_post)); 40 DEFINE(SH_SLEEP_SF_POST, offsetof(struct sh_sleep_data, sf_post));
41 DEFINE(SH_SLEEP_RESUME, offsetof(struct sh_sleep_data, resume));
41 DEFINE(SH_SLEEP_VBR, offsetof(struct sh_sleep_data, vbr)); 42 DEFINE(SH_SLEEP_VBR, offsetof(struct sh_sleep_data, vbr));
42 DEFINE(SH_SLEEP_SPC, offsetof(struct sh_sleep_data, spc)); 43 DEFINE(SH_SLEEP_SPC, offsetof(struct sh_sleep_data, spc));
43 DEFINE(SH_SLEEP_SR, offsetof(struct sh_sleep_data, sr)); 44 DEFINE(SH_SLEEP_SR, offsetof(struct sh_sleep_data, sr));
45 DEFINE(SH_SLEEP_SP, offsetof(struct sh_sleep_data, sp));
44 DEFINE(SH_SLEEP_BASE_ADDR, offsetof(struct sh_sleep_data, addr)); 46 DEFINE(SH_SLEEP_BASE_ADDR, offsetof(struct sh_sleep_data, addr));
45 DEFINE(SH_SLEEP_BASE_DATA, offsetof(struct sh_sleep_data, data)); 47 DEFINE(SH_SLEEP_BASE_DATA, offsetof(struct sh_sleep_data, data));
46 DEFINE(SH_SLEEP_REG_STBCR, offsetof(struct sh_sleep_regs, stbcr)); 48 DEFINE(SH_SLEEP_REG_STBCR, offsetof(struct sh_sleep_regs, stbcr));
49 DEFINE(SH_SLEEP_REG_BAR, offsetof(struct sh_sleep_regs, bar));
47 DEFINE(SH_SLEEP_REG_PTEH, offsetof(struct sh_sleep_regs, pteh)); 50 DEFINE(SH_SLEEP_REG_PTEH, offsetof(struct sh_sleep_regs, pteh));
48 DEFINE(SH_SLEEP_REG_PTEL, offsetof(struct sh_sleep_regs, ptel)); 51 DEFINE(SH_SLEEP_REG_PTEL, offsetof(struct sh_sleep_regs, ptel));
49 DEFINE(SH_SLEEP_REG_TTB, offsetof(struct sh_sleep_regs, ttb)); 52 DEFINE(SH_SLEEP_REG_TTB, offsetof(struct sh_sleep_regs, ttb));
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index 4bd5e5302bfb..ca029a44743c 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -33,13 +33,10 @@ ATOMIC_NOTIFIER_HEAD(sh_mobile_post_sleep_notifier_list);
33#define SUSP_MODE_SLEEP (SUSP_SH_SLEEP) 33#define SUSP_MODE_SLEEP (SUSP_SH_SLEEP)
34#define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF) 34#define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF)
35#define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF) 35#define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF)
36 36#define SUSP_MODE_RSTANDBY (SUSP_SH_RSTANDBY | SUSP_SH_MMU | SUSP_SH_SF)
37/* 37 /*
38 * The following modes are not there yet: 38 * U-standby mode is unsupported since it needs bootloader hacks
39 * 39 */
40 * R-standby mode is unsupported, but will be added in the future
41 * U-standby mode is low priority since it needs bootloader hacks
42 */
43 40
44#ifdef CONFIG_CPU_SUBTYPE_SH7724 41#ifdef CONFIG_CPU_SUBTYPE_SH7724
45#define RAM_BASE 0xfd800000 /* RSMEM */ 42#define RAM_BASE 0xfd800000 /* RSMEM */
@@ -90,6 +87,7 @@ void sh_mobile_register_self_refresh(unsigned long flags,
90 /* part 0: data area */ 87 /* part 0: data area */
91 sdp = onchip_mem; 88 sdp = onchip_mem;
92 sdp->addr.stbcr = 0xa4150020; /* STBCR */ 89 sdp->addr.stbcr = 0xa4150020; /* STBCR */
90 sdp->addr.bar = 0xa4150040; /* BAR */
93 sdp->addr.pteh = 0xff000000; /* PTEH */ 91 sdp->addr.pteh = 0xff000000; /* PTEH */
94 sdp->addr.ptel = 0xff000004; /* PTEL */ 92 sdp->addr.ptel = 0xff000004; /* PTEL */
95 sdp->addr.ttb = 0xff000008; /* TTB */ 93 sdp->addr.ttb = 0xff000008; /* TTB */
@@ -124,6 +122,7 @@ void sh_mobile_register_self_refresh(unsigned long flags,
124 vp = onchip_mem + 0x600; /* located at interrupt vector */ 122 vp = onchip_mem + 0x600; /* located at interrupt vector */
125 n = &sh_mobile_sleep_resume_end - &sh_mobile_sleep_resume_start; 123 n = &sh_mobile_sleep_resume_end - &sh_mobile_sleep_resume_start;
126 memcpy(vp, &sh_mobile_sleep_resume_start, n); 124 memcpy(vp, &sh_mobile_sleep_resume_start, n);
125 sdp->resume = (unsigned long)vp;
127 126
128 sh_mobile_sleep_supported |= flags; 127 sh_mobile_sleep_supported |= flags;
129} 128}
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S
index e620bf397af5..e9dd7fa0abd2 100644
--- a/arch/sh/kernel/cpu/shmobile/sleep.S
+++ b/arch/sh/kernel/cpu/shmobile/sleep.S
@@ -48,6 +48,9 @@ ENTRY(sh_mobile_sleep_enter_start)
48 stc sr, r0 48 stc sr, r0
49 mov.l r0, @(SH_SLEEP_SR, r5) 49 mov.l r0, @(SH_SLEEP_SR, r5)
50 50
51 /* save sp */
52 mov.l r15, @(SH_SLEEP_SP, r5)
53
51 /* save stbcr */ 54 /* save stbcr */
52 bsr save_register 55 bsr save_register
53 mov #SH_SLEEP_REG_STBCR, r0 56 mov #SH_SLEEP_REG_STBCR, r0
@@ -125,6 +128,12 @@ test_rstandby:
125 tst #SUSP_SH_RSTANDBY, r0 128 tst #SUSP_SH_RSTANDBY, r0
126 bt test_ustandby 129 bt test_ustandby
127 130
131 /* setup BAR register */
132 bsr get_register
133 mov #SH_SLEEP_REG_BAR, r0
134 mov.l @(SH_SLEEP_RESUME, r5), r1
135 mov.l r1, @r0
136
128 /* set mode to "r-standby mode" */ 137 /* set mode to "r-standby mode" */
129 bra do_sleep 138 bra do_sleep
130 mov #0x20, r1 139 mov #0x20, r1
@@ -203,6 +212,9 @@ ENTRY(sh_mobile_sleep_resume_start)
203 mov.l @(SH_SLEEP_SR, r5), r0 212 mov.l @(SH_SLEEP_SR, r5), r0
204 ldc r0, ssr 213 ldc r0, ssr
205 214
215 /* restore sp */
216 mov.l @(SH_SLEEP_SP, r5), r15
217
206 /* restore sleep mode register */ 218 /* restore sleep mode register */
207 bsr restore_register 219 bsr restore_register
208 mov #SH_SLEEP_REG_STBCR, r0 220 mov #SH_SLEEP_REG_STBCR, r0