1e9edb3feSPaul Mundt/* 2e9edb3feSPaul Mundt * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S 3e9edb3feSPaul Mundt * 4e9edb3feSPaul Mundt * Sleep mode and Standby modes support for SuperH Mobile 5e9edb3feSPaul Mundt * 6e9edb3feSPaul Mundt * Copyright (C) 2009 Magnus Damm 7e9edb3feSPaul Mundt * 8e9edb3feSPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 9e9edb3feSPaul Mundt * License. See the file "COPYING" in the main directory of this archive 10e9edb3feSPaul Mundt * for more details. 11e9edb3feSPaul Mundt */ 12e9edb3feSPaul Mundt 13e9edb3feSPaul Mundt#include <linux/sys.h> 14e9edb3feSPaul Mundt#include <linux/errno.h> 15e9edb3feSPaul Mundt#include <linux/linkage.h> 16e9edb3feSPaul Mundt#include <asm/asm-offsets.h> 17e9edb3feSPaul Mundt#include <asm/suspend.h> 18e9edb3feSPaul Mundt 19309214afSMagnus Damm/* 20309214afSMagnus Damm * Kernel mode register usage, see entry.S: 21309214afSMagnus Damm * k0 scratch 22309214afSMagnus Damm * k1 scratch 23309214afSMagnus Damm * k4 scratch 24309214afSMagnus Damm */ 25309214afSMagnus Damm#define k0 r0 26309214afSMagnus Damm#define k1 r1 27309214afSMagnus Damm#define k4 r4 28309214afSMagnus Damm 29e9edb3feSPaul Mundt/* manage self-refresh and enter standby mode. 30e9edb3feSPaul Mundt * this code will be copied to on-chip memory and executed from there. 31e9edb3feSPaul Mundt */ 32e9edb3feSPaul Mundt 33e9edb3feSPaul Mundt .balign 4096,0,4096 34e9edb3feSPaul MundtENTRY(sh_mobile_standby) 35309214afSMagnus Damm 36309214afSMagnus Damm /* save original vbr */ 37309214afSMagnus Damm stc vbr, r1 38309214afSMagnus Damm mova saved_vbr, r0 39309214afSMagnus Damm mov.l r1, @r0 40309214afSMagnus Damm 41309214afSMagnus Damm /* point vbr to our on-chip memory page */ 42309214afSMagnus Damm ldc r5, vbr 43309214afSMagnus Damm 44309214afSMagnus Damm /* save return address */ 45309214afSMagnus Damm mova saved_spc, r0 46309214afSMagnus Damm sts pr, r5 47309214afSMagnus Damm mov.l r5, @r0 48309214afSMagnus Damm 49309214afSMagnus Damm /* save sr */ 50309214afSMagnus Damm mova saved_sr, r0 51309214afSMagnus Damm stc sr, r5 52309214afSMagnus Damm mov.l r5, @r0 53309214afSMagnus Damm 54309214afSMagnus Damm /* save mode flags */ 55309214afSMagnus Damm mova saved_mode, r0 56309214afSMagnus Damm mov.l r4, @r0 57309214afSMagnus Damm 58309214afSMagnus Damm /* put mode flags in r0 */ 59e9edb3feSPaul Mundt mov r4, r0 60e9edb3feSPaul Mundt 61e9edb3feSPaul Mundt tst #SUSP_SH_SF, r0 62e9edb3feSPaul Mundt bt skip_set_sf 63237674e0SMagnus Damm#ifdef CONFIG_CPU_SUBTYPE_SH7724 64237674e0SMagnus Damm /* DBSC: put memory in self-refresh mode */ 65237674e0SMagnus Damm mov.l dben_reg, r4 66237674e0SMagnus Damm mov.l dben_data0, r1 67237674e0SMagnus Damm mov.l r1, @r4 68237674e0SMagnus Damm 69237674e0SMagnus Damm mov.l dbrfpdn0_reg, r4 70237674e0SMagnus Damm mov.l dbrfpdn0_data0, r1 71237674e0SMagnus Damm mov.l r1, @r4 72237674e0SMagnus Damm 73237674e0SMagnus Damm mov.l dbcmdcnt_reg, r4 74237674e0SMagnus Damm mov.l dbcmdcnt_data0, r1 75237674e0SMagnus Damm mov.l r1, @r4 76237674e0SMagnus Damm 77237674e0SMagnus Damm mov.l dbcmdcnt_reg, r4 78237674e0SMagnus Damm mov.l dbcmdcnt_data1, r1 79237674e0SMagnus Damm mov.l r1, @r4 80237674e0SMagnus Damm 81237674e0SMagnus Damm mov.l dbrfpdn0_reg, r4 82237674e0SMagnus Damm mov.l dbrfpdn0_data1, r1 83237674e0SMagnus Damm mov.l r1, @r4 84237674e0SMagnus Damm#else 85237674e0SMagnus Damm /* SBSC: disable power down and put in self-refresh mode */ 86e9edb3feSPaul Mundt mov.l 1f, r4 87e9edb3feSPaul Mundt mov.l 2f, r1 88e9edb3feSPaul Mundt mov.l @r4, r2 89e9edb3feSPaul Mundt or r1, r2 90e9edb3feSPaul Mundt mov.l 3f, r3 91e9edb3feSPaul Mundt and r3, r2 92e9edb3feSPaul Mundt mov.l r2, @r4 93237674e0SMagnus Damm#endif 94e9edb3feSPaul Mundt 95e9edb3feSPaul Mundtskip_set_sf: 96e9edb3feSPaul Mundt tst #SUSP_SH_STANDBY, r0 97e9edb3feSPaul Mundt bt test_rstandby 98e9edb3feSPaul Mundt 99e9edb3feSPaul Mundt /* set mode to "software standby mode" */ 100e9edb3feSPaul Mundt bra do_sleep 101e9edb3feSPaul Mundt mov #0x80, r1 102e9edb3feSPaul Mundt 103e9edb3feSPaul Mundttest_rstandby: 104e9edb3feSPaul Mundt tst #SUSP_SH_RSTANDBY, r0 105e9edb3feSPaul Mundt bt test_ustandby 106e9edb3feSPaul Mundt 107e9edb3feSPaul Mundt /* set mode to "r-standby mode" */ 108e9edb3feSPaul Mundt bra do_sleep 109e9edb3feSPaul Mundt mov #0x20, r1 110e9edb3feSPaul Mundt 111e9edb3feSPaul Mundttest_ustandby: 112e9edb3feSPaul Mundt tst #SUSP_SH_USTANDBY, r0 113309214afSMagnus Damm bt force_sleep 114e9edb3feSPaul Mundt 115e9edb3feSPaul Mundt /* set mode to "u-standby mode" */ 116309214afSMagnus Damm bra do_sleep 117e9edb3feSPaul Mundt mov #0x10, r1 118e9edb3feSPaul Mundt 119309214afSMagnus Dammforce_sleep: 120309214afSMagnus Damm 121309214afSMagnus Damm /* set mode to "sleep mode" */ 122309214afSMagnus Damm mov #0x00, r1 123e9edb3feSPaul Mundt 124e9edb3feSPaul Mundtdo_sleep: 125e9edb3feSPaul Mundt /* setup and enter selected standby mode */ 126e9edb3feSPaul Mundt mov.l 5f, r4 127e9edb3feSPaul Mundt mov.l r1, @r4 128309214afSMagnus Dammagain: 129e9edb3feSPaul Mundt sleep 130309214afSMagnus Damm bra again 131309214afSMagnus Damm nop 132309214afSMagnus Damm 133309214afSMagnus Dammrestore_jump_vbr: 134309214afSMagnus Damm /* setup spc with return address to c code */ 135309214afSMagnus Damm mov.l saved_spc, k0 136309214afSMagnus Damm ldc k0, spc 137309214afSMagnus Damm 138309214afSMagnus Damm /* restore vbr */ 139309214afSMagnus Damm mov.l saved_vbr, k0 140309214afSMagnus Damm ldc k0, vbr 141309214afSMagnus Damm 142309214afSMagnus Damm /* setup ssr with saved sr */ 143309214afSMagnus Damm mov.l saved_sr, k0 144309214afSMagnus Damm ldc k0, ssr 145309214afSMagnus Damm 146309214afSMagnus Damm /* get mode flags */ 147309214afSMagnus Damm mov.l saved_mode, k0 148e9edb3feSPaul Mundt 149e9edb3feSPaul Mundtdone_sleep: 150e9edb3feSPaul Mundt /* reset standby mode to sleep mode */ 151309214afSMagnus Damm mov.l 5f, k4 152309214afSMagnus Damm mov #0x00, k1 153309214afSMagnus Damm mov.l k1, @k4 154e9edb3feSPaul Mundt 155309214afSMagnus Damm tst #SUSP_SH_SF, k0 156e9edb3feSPaul Mundt bt skip_restore_sf 157e9edb3feSPaul Mundt 158237674e0SMagnus Damm#ifdef CONFIG_CPU_SUBTYPE_SH7724 159237674e0SMagnus Damm /* DBSC: put memory in auto-refresh mode */ 160309214afSMagnus Damm mov.l dbrfpdn0_reg, k4 161309214afSMagnus Damm mov.l dbrfpdn0_data0, k1 162309214afSMagnus Damm mov.l k1, @k4 163237674e0SMagnus Damm 164309214afSMagnus Damm nop /* sleep 140 ns */ 165237674e0SMagnus Damm nop 166237674e0SMagnus Damm nop 167237674e0SMagnus Damm nop 168237674e0SMagnus Damm 169309214afSMagnus Damm mov.l dbcmdcnt_reg, k4 170309214afSMagnus Damm mov.l dbcmdcnt_data0, k1 171309214afSMagnus Damm mov.l k1, @k4 172237674e0SMagnus Damm 173309214afSMagnus Damm mov.l dbcmdcnt_reg, k4 174309214afSMagnus Damm mov.l dbcmdcnt_data1, k1 175309214afSMagnus Damm mov.l k1, @k4 176237674e0SMagnus Damm 177309214afSMagnus Damm mov.l dben_reg, k4 178309214afSMagnus Damm mov.l dben_data1, k1 179309214afSMagnus Damm mov.l k1, @k4 180237674e0SMagnus Damm 181309214afSMagnus Damm mov.l dbrfpdn0_reg, k4 182309214afSMagnus Damm mov.l dbrfpdn0_data2, k1 183309214afSMagnus Damm mov.l k1, @k4 184237674e0SMagnus Damm#else 185237674e0SMagnus Damm /* SBSC: set auto-refresh mode */ 186309214afSMagnus Damm mov.l 1f, k4 187309214afSMagnus Damm mov.l @k4, k0 188309214afSMagnus Damm mov.l 4f, k1 189309214afSMagnus Damm and k1, k0 190309214afSMagnus Damm mov.l k0, @k4 191309214afSMagnus Damm mov.l 6f, k4 192309214afSMagnus Damm mov.l 8f, k0 193309214afSMagnus Damm mov.l @k4, k1 194309214afSMagnus Damm mov #-1, k4 195309214afSMagnus Damm add k4, k1 196309214afSMagnus Damm or k1, k0 197309214afSMagnus Damm mov.l 7f, k1 198309214afSMagnus Damm mov.l k0, @k1 199237674e0SMagnus Damm#endif 200e9edb3feSPaul Mundtskip_restore_sf: 201309214afSMagnus Damm /* jump to vbr vector */ 202309214afSMagnus Damm mov.l saved_vbr, k0 203309214afSMagnus Damm mov.l offset_vbr, k4 204309214afSMagnus Damm add k4, k0 205309214afSMagnus Damm jmp @k0 206e9edb3feSPaul Mundt nop 207e9edb3feSPaul Mundt 208e9edb3feSPaul Mundt .balign 4 209309214afSMagnus Dammsaved_mode: .long 0 210309214afSMagnus Dammsaved_spc: .long 0 211309214afSMagnus Dammsaved_sr: .long 0 212309214afSMagnus Dammsaved_vbr: .long 0 213309214afSMagnus Dammoffset_vbr: .long 0x600 214237674e0SMagnus Damm#ifdef CONFIG_CPU_SUBTYPE_SH7724 215237674e0SMagnus Dammdben_reg: .long 0xfd000010 /* DBEN */ 216237674e0SMagnus Dammdben_data0: .long 0 217237674e0SMagnus Dammdben_data1: .long 1 218237674e0SMagnus Dammdbrfpdn0_reg: .long 0xfd000040 /* DBRFPDN0 */ 219237674e0SMagnus Dammdbrfpdn0_data0: .long 0 220237674e0SMagnus Dammdbrfpdn0_data1: .long 1 221237674e0SMagnus Dammdbrfpdn0_data2: .long 0x00010000 222237674e0SMagnus Dammdbcmdcnt_reg: .long 0xfd000014 /* DBCMDCNT */ 223237674e0SMagnus Dammdbcmdcnt_data0: .long 2 224237674e0SMagnus Dammdbcmdcnt_data1: .long 4 225237674e0SMagnus Damm#else 226e9edb3feSPaul Mundt1: .long 0xfe400008 /* SDCR0 */ 227e9edb3feSPaul Mundt2: .long 0x00000400 228e9edb3feSPaul Mundt3: .long 0xffff7fff 229e9edb3feSPaul Mundt4: .long 0xfffffbff 230237674e0SMagnus Damm#endif 231e9edb3feSPaul Mundt5: .long 0xa4150020 /* STBCR */ 232e9edb3feSPaul Mundt6: .long 0xfe40001c /* RTCOR */ 233e9edb3feSPaul Mundt7: .long 0xfe400018 /* RTCNT */ 234e9edb3feSPaul Mundt8: .long 0xa55a0000 235e9edb3feSPaul Mundt 236309214afSMagnus Damm 237e9edb3feSPaul Mundt/* interrupt vector @ 0x600 */ 238e9edb3feSPaul Mundt .balign 0x400,0,0x400 239e9edb3feSPaul Mundt .long 0xdeadbeef 240e9edb3feSPaul Mundt .balign 0x200,0,0x200 241309214afSMagnus Damm bra restore_jump_vbr 242e9edb3feSPaul Mundt nop 243e9edb3feSPaul Mundtsh_mobile_standby_end: 244e9edb3feSPaul Mundt 245e9edb3feSPaul MundtENTRY(sh_mobile_standby_size) 246e9edb3feSPaul Mundt .long sh_mobile_standby_end - sh_mobile_standby 247