1/* 2 * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S 3 * 4 * Sleep mode and Standby modes support for SuperH Mobile 5 * 6 * Copyright (C) 2009 Magnus Damm 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12 13#include <linux/sys.h> 14#include <linux/errno.h> 15#include <linux/linkage.h> 16#include <asm/asm-offsets.h> 17#include <asm/suspend.h> 18 19/* 20 * Kernel mode register usage, see entry.S: 21 * k0 scratch 22 * k1 scratch 23 * k4 scratch 24 */ 25#define k0 r0 26#define k1 r1 27#define k4 r4 28 29/* manage self-refresh and enter standby mode. 30 * this code will be copied to on-chip memory and executed from there. 31 */ 32 33 .balign 4096,0,4096 34ENTRY(sh_mobile_standby) 35 36 /* save original vbr */ 37 stc vbr, r1 38 mova saved_vbr, r0 39 mov.l r1, @r0 40 41 /* point vbr to our on-chip memory page */ 42 ldc r5, vbr 43 44 /* save return address */ 45 mova saved_spc, r0 46 sts pr, r5 47 mov.l r5, @r0 48 49 /* save sr */ 50 mova saved_sr, r0 51 stc sr, r5 52 mov.l r5, @r0 53 54 /* save mode flags */ 55 mova saved_mode, r0 56 mov.l r4, @r0 57 58 /* put mode flags in r0 */ 59 mov r4, r0 60 61 tst #SUSP_SH_SF, r0 62 bt skip_set_sf 63#ifdef CONFIG_CPU_SUBTYPE_SH7724 64 /* DBSC: put memory in self-refresh mode */ 65 mov.l dben_reg, r4 66 mov.l dben_data0, r1 67 mov.l r1, @r4 68 69 mov.l dbrfpdn0_reg, r4 70 mov.l dbrfpdn0_data0, r1 71 mov.l r1, @r4 72 73 mov.l dbcmdcnt_reg, r4 74 mov.l dbcmdcnt_data0, r1 75 mov.l r1, @r4 76 77 mov.l dbcmdcnt_reg, r4 78 mov.l dbcmdcnt_data1, r1 79 mov.l r1, @r4 80 81 mov.l dbrfpdn0_reg, r4 82 mov.l dbrfpdn0_data1, r1 83 mov.l r1, @r4 84#else 85 /* SBSC: disable power down and put in self-refresh mode */ 86 mov.l 1f, r4 87 mov.l 2f, r1 88 mov.l @r4, r2 89 or r1, r2 90 mov.l 3f, r3 91 and r3, r2 92 mov.l r2, @r4 93#endif 94 95skip_set_sf: 96 tst #SUSP_SH_STANDBY, r0 97 bt test_rstandby 98 99 /* set mode to "software standby mode" */ 100 bra do_sleep 101 mov #0x80, r1 102 103test_rstandby: 104 tst #SUSP_SH_RSTANDBY, r0 105 bt test_ustandby 106 107 /* set mode to "r-standby mode" */ 108 bra do_sleep 109 mov #0x20, r1 110 111test_ustandby: 112 tst #SUSP_SH_USTANDBY, r0 113 bt force_sleep 114 115 /* set mode to "u-standby mode" */ 116 bra do_sleep 117 mov #0x10, r1 118 119force_sleep: 120 121 /* set mode to "sleep mode" */ 122 mov #0x00, r1 123 124do_sleep: 125 /* setup and enter selected standby mode */ 126 mov.l 5f, r4 127 mov.l r1, @r4 128again: 129 sleep 130 bra again 131 nop 132 133restore_jump_vbr: 134 /* setup spc with return address to c code */ 135 mov.l saved_spc, k0 136 ldc k0, spc 137 138 /* restore vbr */ 139 mov.l saved_vbr, k0 140 ldc k0, vbr 141 142 /* setup ssr with saved sr */ 143 mov.l saved_sr, k0 144 ldc k0, ssr 145 146 /* get mode flags */ 147 mov.l saved_mode, k0 148 149done_sleep: 150 /* reset standby mode to sleep mode */ 151 mov.l 5f, k4 152 mov #0x00, k1 153 mov.l k1, @k4 154 155 tst #SUSP_SH_SF, k0 156 bt skip_restore_sf 157 158#ifdef CONFIG_CPU_SUBTYPE_SH7724 159 /* DBSC: put memory in auto-refresh mode */ 160 mov.l dbrfpdn0_reg, k4 161 mov.l dbrfpdn0_data0, k1 162 mov.l k1, @k4 163 164 nop /* sleep 140 ns */ 165 nop 166 nop 167 nop 168 169 mov.l dbcmdcnt_reg, k4 170 mov.l dbcmdcnt_data0, k1 171 mov.l k1, @k4 172 173 mov.l dbcmdcnt_reg, k4 174 mov.l dbcmdcnt_data1, k1 175 mov.l k1, @k4 176 177 mov.l dben_reg, k4 178 mov.l dben_data1, k1 179 mov.l k1, @k4 180 181 mov.l dbrfpdn0_reg, k4 182 mov.l dbrfpdn0_data2, k1 183 mov.l k1, @k4 184#else 185 /* SBSC: set auto-refresh mode */ 186 mov.l 1f, k4 187 mov.l @k4, k0 188 mov.l 4f, k1 189 and k1, k0 190 mov.l k0, @k4 191 mov.l 6f, k4 192 mov.l 8f, k0 193 mov.l @k4, k1 194 mov #-1, k4 195 add k4, k1 196 or k1, k0 197 mov.l 7f, k1 198 mov.l k0, @k1 199#endif 200skip_restore_sf: 201 /* jump to vbr vector */ 202 mov.l saved_vbr, k0 203 mov.l offset_vbr, k4 204 add k4, k0 205 jmp @k0 206 nop 207 208 .balign 4 209saved_mode: .long 0 210saved_spc: .long 0 211saved_sr: .long 0 212saved_vbr: .long 0 213offset_vbr: .long 0x600 214#ifdef CONFIG_CPU_SUBTYPE_SH7724 215dben_reg: .long 0xfd000010 /* DBEN */ 216dben_data0: .long 0 217dben_data1: .long 1 218dbrfpdn0_reg: .long 0xfd000040 /* DBRFPDN0 */ 219dbrfpdn0_data0: .long 0 220dbrfpdn0_data1: .long 1 221dbrfpdn0_data2: .long 0x00010000 222dbcmdcnt_reg: .long 0xfd000014 /* DBCMDCNT */ 223dbcmdcnt_data0: .long 2 224dbcmdcnt_data1: .long 4 225#else 2261: .long 0xfe400008 /* SDCR0 */ 2272: .long 0x00000400 2283: .long 0xffff7fff 2294: .long 0xfffffbff 230#endif 2315: .long 0xa4150020 /* STBCR */ 2326: .long 0xfe40001c /* RTCOR */ 2337: .long 0xfe400018 /* RTCNT */ 2348: .long 0xa55a0000 235 236 237/* interrupt vector @ 0x600 */ 238 .balign 0x400,0,0x400 239 .long 0xdeadbeef 240 .balign 0x200,0,0x200 241 bra restore_jump_vbr 242 nop 243sh_mobile_standby_end: 244 245ENTRY(sh_mobile_standby_size) 246 .long sh_mobile_standby_end - sh_mobile_standby 247