aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/include/asm/suspend.h15
-rw-r--r--arch/sh/kernel/asm-offsets.c10
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm.c15
-rw-r--r--arch/sh/kernel/cpu/shmobile/sleep.S92
4 files changed, 132 insertions, 0 deletions
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
index 8eddf236fb85..702025d960a0 100644
--- a/arch/sh/include/asm/suspend.h
+++ b/arch/sh/include/asm/suspend.h
@@ -38,6 +38,20 @@ 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
42 /* MMU */
43 unsigned long pteh;
44 unsigned long ptel;
45 unsigned long ttb;
46 unsigned long tea;
47 unsigned long mmucr;
48 unsigned long ptea;
49 unsigned long pascr;
50 unsigned long irmcr;
51
52 /* Cache */
53 unsigned long ccr;
54 unsigned long ramcr;
41}; 55};
42 56
43/* data area for low-level sleep code */ 57/* data area for low-level sleep code */
@@ -72,5 +86,6 @@ extern unsigned long sh_mobile_sleep_supported;
72#define SUSP_SH_RSTANDBY (1 << 2) /* SH-Mobile R-standby mode */ 86#define SUSP_SH_RSTANDBY (1 << 2) /* SH-Mobile R-standby mode */
73#define SUSP_SH_USTANDBY (1 << 3) /* SH-Mobile U-standby mode */ 87#define SUSP_SH_USTANDBY (1 << 3) /* SH-Mobile U-standby mode */
74#define SUSP_SH_SF (1 << 4) /* Enable self-refresh */ 88#define SUSP_SH_SF (1 << 4) /* Enable self-refresh */
89#define SUSP_SH_MMU (1 << 5) /* Save/restore MMU and cache */
75 90
76#endif /* _ASM_SH_SUSPEND_H */ 91#endif /* _ASM_SH_SUSPEND_H */
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
index 9bdeff962e1c..6026b0f849a1 100644
--- a/arch/sh/kernel/asm-offsets.c
+++ b/arch/sh/kernel/asm-offsets.c
@@ -44,5 +44,15 @@ int main(void)
44 DEFINE(SH_SLEEP_BASE_ADDR, offsetof(struct sh_sleep_data, addr)); 44 DEFINE(SH_SLEEP_BASE_ADDR, offsetof(struct sh_sleep_data, addr));
45 DEFINE(SH_SLEEP_BASE_DATA, offsetof(struct sh_sleep_data, data)); 45 DEFINE(SH_SLEEP_BASE_DATA, offsetof(struct sh_sleep_data, data));
46 DEFINE(SH_SLEEP_REG_STBCR, offsetof(struct sh_sleep_regs, stbcr)); 46 DEFINE(SH_SLEEP_REG_STBCR, offsetof(struct sh_sleep_regs, stbcr));
47 DEFINE(SH_SLEEP_REG_PTEH, offsetof(struct sh_sleep_regs, pteh));
48 DEFINE(SH_SLEEP_REG_PTEL, offsetof(struct sh_sleep_regs, ptel));
49 DEFINE(SH_SLEEP_REG_TTB, offsetof(struct sh_sleep_regs, ttb));
50 DEFINE(SH_SLEEP_REG_TEA, offsetof(struct sh_sleep_regs, tea));
51 DEFINE(SH_SLEEP_REG_MMUCR, offsetof(struct sh_sleep_regs, mmucr));
52 DEFINE(SH_SLEEP_REG_PTEA, offsetof(struct sh_sleep_regs, ptea));
53 DEFINE(SH_SLEEP_REG_PASCR, offsetof(struct sh_sleep_regs, pascr));
54 DEFINE(SH_SLEEP_REG_IRMCR, offsetof(struct sh_sleep_regs, irmcr));
55 DEFINE(SH_SLEEP_REG_CCR, offsetof(struct sh_sleep_regs, ccr));
56 DEFINE(SH_SLEEP_REG_RAMCR, offsetof(struct sh_sleep_regs, ramcr));
47 return 0; 57 return 0;
48} 58}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index a94dc480f0c1..ca642f39e2e3 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -15,6 +15,7 @@
15#include <linux/suspend.h> 15#include <linux/suspend.h>
16#include <asm/suspend.h> 16#include <asm/suspend.h>
17#include <asm/uaccess.h> 17#include <asm/uaccess.h>
18#include <asm/cacheflush.h>
18 19
19/* 20/*
20 * Notifier lists for pre/post sleep notification 21 * Notifier lists for pre/post sleep notification
@@ -54,6 +55,10 @@ void sh_mobile_call_standby(unsigned long mode)
54 atomic_notifier_call_chain(&sh_mobile_pre_sleep_notifier_list, 55 atomic_notifier_call_chain(&sh_mobile_pre_sleep_notifier_list,
55 mode, NULL); 56 mode, NULL);
56 57
58 /* flush the caches if MMU flag is set */
59 if (mode & SUSP_SH_MMU)
60 flush_cache_all();
61
57 /* Let assembly snippet in on-chip memory handle the rest */ 62 /* Let assembly snippet in on-chip memory handle the rest */
58 standby_onchip_mem(mode, ILRAM_BASE); 63 standby_onchip_mem(mode, ILRAM_BASE);
59 64
@@ -81,6 +86,16 @@ void sh_mobile_register_self_refresh(unsigned long flags,
81 /* part 0: data area */ 86 /* part 0: data area */
82 sdp = onchip_mem; 87 sdp = onchip_mem;
83 sdp->addr.stbcr = 0xa4150020; /* STBCR */ 88 sdp->addr.stbcr = 0xa4150020; /* STBCR */
89 sdp->addr.pteh = 0xff000000; /* PTEH */
90 sdp->addr.ptel = 0xff000004; /* PTEL */
91 sdp->addr.ttb = 0xff000008; /* TTB */
92 sdp->addr.tea = 0xff00000c; /* TEA */
93 sdp->addr.mmucr = 0xff000010; /* MMUCR */
94 sdp->addr.ptea = 0xff000034; /* PTEA */
95 sdp->addr.pascr = 0xff000070; /* PASCR */
96 sdp->addr.irmcr = 0xff000078; /* IRMCR */
97 sdp->addr.ccr = 0xff00001c; /* CCR */
98 sdp->addr.ramcr = 0xff000074; /* RAMCR */
84 vp = sdp + 1; 99 vp = sdp + 1;
85 100
86 /* part 1: common code to enter sleep mode */ 101 /* part 1: common code to enter sleep mode */
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S
index d3221d9b88be..e620bf397af5 100644
--- a/arch/sh/kernel/cpu/shmobile/sleep.S
+++ b/arch/sh/kernel/cpu/shmobile/sleep.S
@@ -52,6 +52,57 @@ ENTRY(sh_mobile_sleep_enter_start)
52 bsr save_register 52 bsr save_register
53 mov #SH_SLEEP_REG_STBCR, r0 53 mov #SH_SLEEP_REG_STBCR, r0
54 54
55 /* save mmu and cache context if needed */
56 mov.l @(SH_SLEEP_MODE, r5), r0
57 tst #SUSP_SH_MMU, r0
58 bt skip_mmu_save_disable
59
60 /* save mmu state */
61 bsr save_register
62 mov #SH_SLEEP_REG_PTEH, r0
63
64 bsr save_register
65 mov #SH_SLEEP_REG_PTEL, r0
66
67 bsr save_register
68 mov #SH_SLEEP_REG_TTB, r0
69
70 bsr save_register
71 mov #SH_SLEEP_REG_TEA, r0
72
73 bsr save_register
74 mov #SH_SLEEP_REG_MMUCR, r0
75
76 bsr save_register
77 mov #SH_SLEEP_REG_PTEA, r0
78
79 bsr save_register
80 mov #SH_SLEEP_REG_PASCR, r0
81
82 bsr save_register
83 mov #SH_SLEEP_REG_IRMCR, r0
84
85 /* invalidate TLBs and disable the MMU */
86 bsr get_register
87 mov #SH_SLEEP_REG_MMUCR, r0
88 mov #4, r1
89 mov.l r1, @r0
90 icbi @r0
91
92 /* save cache registers and disable caches */
93 bsr save_register
94 mov #SH_SLEEP_REG_CCR, r0
95
96 bsr save_register
97 mov #SH_SLEEP_REG_RAMCR, r0
98
99 bsr get_register
100 mov #SH_SLEEP_REG_CCR, r0
101 mov #0, r1
102 mov.l r1, @r0
103 icbi @r0
104
105skip_mmu_save_disable:
55 /* call self-refresh entering code if needed */ 106 /* call self-refresh entering code if needed */
56 mov.l @(SH_SLEEP_MODE, r5), r0 107 mov.l @(SH_SLEEP_MODE, r5), r0
57 tst #SUSP_SH_SF, r0 108 tst #SUSP_SH_SF, r0
@@ -166,6 +217,47 @@ ENTRY(sh_mobile_sleep_resume_start)
166 nop 217 nop
167 218
168skip_restore_sf: 219skip_restore_sf:
220 /* restore mmu and cache state if needed */
221 mov.l @(SH_SLEEP_MODE, r5), r0
222 tst #SUSP_SH_MMU, r0
223 bt skip_restore_mmu
224
225 /* restore mmu state */
226 bsr restore_register
227 mov #SH_SLEEP_REG_PTEH, r0
228
229 bsr restore_register
230 mov #SH_SLEEP_REG_PTEL, r0
231
232 bsr restore_register
233 mov #SH_SLEEP_REG_TTB, r0
234
235 bsr restore_register
236 mov #SH_SLEEP_REG_TEA, r0
237
238 bsr restore_register
239 mov #SH_SLEEP_REG_PTEA, r0
240
241 bsr restore_register
242 mov #SH_SLEEP_REG_PASCR, r0
243
244 bsr restore_register
245 mov #SH_SLEEP_REG_IRMCR, r0
246
247 bsr restore_register
248 mov #SH_SLEEP_REG_MMUCR, r0
249 icbi @r0
250
251 /* restore cache settings */
252 bsr restore_register
253 mov #SH_SLEEP_REG_RAMCR, r0
254 icbi @r0
255
256 bsr restore_register
257 mov #SH_SLEEP_REG_CCR, r0
258 icbi @r0
259
260skip_restore_mmu:
169 rte 261 rte
170 nop 262 nop
171 263