aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
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/kernel
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/kernel')
-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
3 files changed, 117 insertions, 0 deletions
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