diff options
-rw-r--r-- | arch/sh/include/asm/suspend.h | 5 | ||||
-rw-r--r-- | arch/sh/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/shmobile/pm.c | 13 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/shmobile/sleep.S | 12 |
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 */ |
39 | struct sh_sleep_regs { | 39 | struct 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 |