aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2009-10-30 00:24:23 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-10-30 01:37:56 -0400
commit99675a7a45ed3cec54d6e1d11f13bcaacaf0909b (patch)
tree7a23202a0071dc26015741d296270449e76922a6 /arch/sh
parent02bf89347c7d6a6aeae64f02536dac038c402fce (diff)
sh: Add MMU and Cache handling sleep mode code
Add MMU and cache handling functionality to the SuperH Mobile sleep code. The MMU and cache registers are saved and restored. The MMU is disabled and the cache is flushed and disabled before entering sleep modes if the SUSP_SH_MMU flag is set. This flag should be set in the case of R-standby and most likely for future U-standby support as well. Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
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