| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright 2002 Embedded Edge, LLC | 
|  | 3 | * Author: dan@embeddededge.com | 
|  | 4 | * | 
|  | 5 | * Sleep helper for Au1xxx sleep mode. | 
|  | 6 | * | 
|  | 7 | * This program is free software; you can redistribute	it and/or modify it | 
|  | 8 | * under  the terms of	the GNU General	 Public License as published by the | 
|  | 9 | * Free Software Foundation;  either version 2 of the  License, or (at your | 
|  | 10 | * option) any later version. | 
|  | 11 | */ | 
| Sergei Shtylyov | ce28f94 | 2008-04-23 22:43:55 +0400 | [diff] [blame] | 12 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | #include <asm/asm.h> | 
|  | 14 | #include <asm/mipsregs.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 15 | #include <asm/regdef.h> | 
|  | 16 | #include <asm/stackframe.h> | 
|  | 17 |  | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 18 | .extern __flush_cache_all | 
|  | 19 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 20 | .text | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 21 | .set noreorder | 
|  | 22 | .set noat | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 23 | .align	5 | 
|  | 24 |  | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 25 |  | 
|  | 26 | /* preparatory stuff */ | 
|  | 27 | .macro	SETUP_SLEEP | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 28 | subu	sp, PT_SIZE | 
|  | 29 | sw	$1, PT_R1(sp) | 
|  | 30 | sw	$2, PT_R2(sp) | 
|  | 31 | sw	$3, PT_R3(sp) | 
|  | 32 | sw	$4, PT_R4(sp) | 
|  | 33 | sw	$5, PT_R5(sp) | 
|  | 34 | sw	$6, PT_R6(sp) | 
|  | 35 | sw	$7, PT_R7(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 36 | sw	$16, PT_R16(sp) | 
|  | 37 | sw	$17, PT_R17(sp) | 
|  | 38 | sw	$18, PT_R18(sp) | 
|  | 39 | sw	$19, PT_R19(sp) | 
|  | 40 | sw	$20, PT_R20(sp) | 
|  | 41 | sw	$21, PT_R21(sp) | 
|  | 42 | sw	$22, PT_R22(sp) | 
|  | 43 | sw	$23, PT_R23(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 | sw	$26, PT_R26(sp) | 
|  | 45 | sw	$27, PT_R27(sp) | 
|  | 46 | sw	$28, PT_R28(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 47 | sw	$30, PT_R30(sp) | 
|  | 48 | sw	$31, PT_R31(sp) | 
|  | 49 | mfc0	k0, CP0_STATUS | 
|  | 50 | sw	k0, 0x20(sp) | 
|  | 51 | mfc0	k0, CP0_CONTEXT | 
|  | 52 | sw	k0, 0x1c(sp) | 
|  | 53 | mfc0	k0, CP0_PAGEMASK | 
|  | 54 | sw	k0, 0x18(sp) | 
|  | 55 | mfc0	k0, CP0_CONFIG | 
|  | 56 | sw	k0, 0x14(sp) | 
|  | 57 |  | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 58 | /* flush caches to make sure context is in memory */ | 
|  | 59 | la	t1, __flush_cache_all | 
|  | 60 | lw	t0, 0(t1) | 
|  | 61 | jalr	t0 | 
|  | 62 | nop | 
|  | 63 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 64 | /* Now set up the scratch registers so the boot rom will | 
|  | 65 | * return to this point upon wakeup. | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 66 | * sys_scratch0 : SP | 
|  | 67 | * sys_scratch1 : RA | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 68 | */ | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 69 | lui	t3, 0xb190		/* sys_xxx */ | 
|  | 70 | sw	sp, 0x0018(t3) | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 71 | la	k0, alchemy_sleep_wakeup	/* resume path */ | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 72 | sw	k0, 0x001c(t3) | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 73 | .endm | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 74 |  | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 75 | .macro	DO_SLEEP | 
|  | 76 | /* put power supply and processor to sleep */ | 
|  | 77 | sw	zero, 0x0078(t3)	/* sys_slppwr */ | 
|  | 78 | sync | 
|  | 79 | sw	zero, 0x007c(t3)	/* sys_sleep */ | 
|  | 80 | sync | 
|  | 81 | nop | 
|  | 82 | nop | 
|  | 83 | nop | 
|  | 84 | nop | 
|  | 85 | nop | 
|  | 86 | nop | 
|  | 87 | nop | 
|  | 88 | nop | 
|  | 89 | .endm | 
|  | 90 |  | 
|  | 91 | /* sleep code for Au1000/Au1100/Au1500 memory controller type */ | 
|  | 92 | LEAF(alchemy_sleep_au1000) | 
|  | 93 |  | 
|  | 94 | SETUP_SLEEP | 
|  | 95 |  | 
|  | 96 | /* cache following instructions, as memory gets put to sleep */ | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 97 | la	t0, 1f | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | .set	mips3 | 
| Ralf Baechle | e8c7c48 | 2008-09-16 19:12:16 +0200 | [diff] [blame] | 99 | cache	0x14, 0(t0) | 
|  | 100 | cache	0x14, 32(t0) | 
|  | 101 | cache	0x14, 64(t0) | 
|  | 102 | cache	0x14, 96(t0) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 103 | .set	mips0 | 
|  | 104 |  | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 105 | 1:	lui 	a0, 0xb400		/* mem_xxx */ | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 106 | sw	zero, 0x001c(a0) 	/* Precharge */ | 
|  | 107 | sync | 
|  | 108 | sw	zero, 0x0020(a0)	/* Auto Refresh */ | 
|  | 109 | sync | 
|  | 110 | sw	zero, 0x0030(a0)  	/* Sleep */ | 
|  | 111 | sync | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 112 |  | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 113 | DO_SLEEP | 
|  | 114 |  | 
|  | 115 | END(alchemy_sleep_au1000) | 
|  | 116 |  | 
|  | 117 | /* sleep code for Au1550/Au1200 memory controller type */ | 
|  | 118 | LEAF(alchemy_sleep_au1550) | 
|  | 119 |  | 
|  | 120 | SETUP_SLEEP | 
|  | 121 |  | 
|  | 122 | /* cache following instructions, as memory gets put to sleep */ | 
|  | 123 | la	t0, 1f | 
|  | 124 | .set	mips3 | 
|  | 125 | cache	0x14, 0(t0) | 
|  | 126 | cache	0x14, 32(t0) | 
|  | 127 | cache	0x14, 64(t0) | 
|  | 128 | cache	0x14, 96(t0) | 
|  | 129 | .set	mips0 | 
|  | 130 |  | 
|  | 131 | 1:	lui 	a0, 0xb400		/* mem_xxx */ | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 132 | sw	zero, 0x08c0(a0) 	/* Precharge */ | 
|  | 133 | sync | 
|  | 134 | sw	zero, 0x08d0(a0)	/* Self Refresh */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 135 | sync | 
|  | 136 |  | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 137 | /* wait for sdram to enter self-refresh mode */ | 
|  | 138 | lui 	t0, 0x0100 | 
|  | 139 | 2:	lw 	t1, 0x0850(a0)		/* mem_sdstat */ | 
|  | 140 | and	t2, t1, t0 | 
|  | 141 | beq	t2, zero, 2b | 
|  | 142 | nop | 
|  | 143 |  | 
|  | 144 | /* disable SDRAM clocks */ | 
|  | 145 | lui	t0, 0xcfff | 
|  | 146 | ori	t0, t0, 0xffff | 
|  | 147 | lw 	t1, 0x0840(a0)		/* mem_sdconfiga */ | 
|  | 148 | and 	t1, t0, t1		/* clear CE[1:0] */ | 
|  | 149 | sw 	t1, 0x0840(a0)		/* mem_sdconfiga */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 150 | sync | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 151 |  | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 152 | DO_SLEEP | 
|  | 153 |  | 
|  | 154 | END(alchemy_sleep_au1550) | 
|  | 155 |  | 
| Manuel Lauss | 809f36c | 2011-11-01 20:03:30 +0100 | [diff] [blame] | 156 | /* sleepcode for Au1300 memory controller type */ | 
|  | 157 | LEAF(alchemy_sleep_au1300) | 
|  | 158 |  | 
|  | 159 | SETUP_SLEEP | 
|  | 160 |  | 
|  | 161 | /* cache following instructions, as memory gets put to sleep */ | 
|  | 162 | la	t0, 2f | 
|  | 163 | la	t1, 4f | 
|  | 164 | subu	t2, t1, t0 | 
|  | 165 |  | 
|  | 166 | .set	mips3 | 
|  | 167 |  | 
|  | 168 | 1:	cache	0x14, 0(t0) | 
|  | 169 | subu	t2, t2, 32 | 
|  | 170 | bgez	t2, 1b | 
|  | 171 | addu	t0, t0, 32 | 
|  | 172 |  | 
|  | 173 | .set	mips0 | 
|  | 174 |  | 
|  | 175 | 2:	lui	a0, 0xb400		/* mem_xxx */ | 
|  | 176 |  | 
|  | 177 | /* disable all ports in mem_sdportcfga */ | 
|  | 178 | sw	zero, 0x868(a0)		/* mem_sdportcfga */ | 
|  | 179 | sync | 
|  | 180 |  | 
|  | 181 | /* disable ODT */ | 
|  | 182 | li	t0, 0x03010000 | 
|  | 183 | sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */ | 
|  | 184 | sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */ | 
|  | 185 | sync | 
|  | 186 |  | 
|  | 187 | /* precharge */ | 
|  | 188 | li	t0, 0x23000400 | 
|  | 189 | sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */ | 
|  | 190 | sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */ | 
|  | 191 | sync | 
|  | 192 |  | 
|  | 193 | /* auto refresh */ | 
|  | 194 | sw	zero, 0x08c8(a0)	/* mem_sdautoref */ | 
|  | 195 | sync | 
|  | 196 |  | 
|  | 197 | /* block access to the DDR */ | 
|  | 198 | lw	t0, 0x0848(a0)		/* mem_sdconfigb */ | 
|  | 199 | li	t1, (1 << 7 | 0x3F) | 
|  | 200 | or	t0, t0, t1 | 
|  | 201 | sw	t0, 0x0848(a0)		/* mem_sdconfigb */ | 
|  | 202 | sync | 
|  | 203 |  | 
|  | 204 | /* issue the Self Refresh command */ | 
|  | 205 | li	t0, 0x10000000 | 
|  | 206 | sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */ | 
|  | 207 | sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */ | 
|  | 208 | sync | 
|  | 209 |  | 
|  | 210 | /* wait for sdram to enter self-refresh mode */ | 
|  | 211 | lui	t0, 0x0300 | 
|  | 212 | 3:	lw	t1, 0x0850(a0)		/* mem_sdstat */ | 
|  | 213 | and	t2, t1, t0 | 
|  | 214 | bne	t2, t0, 3b | 
|  | 215 | nop | 
|  | 216 |  | 
|  | 217 | /* disable SDRAM clocks */ | 
|  | 218 | li	t0, ~(3<<28) | 
|  | 219 | lw	t1, 0x0840(a0)		/* mem_sdconfiga */ | 
|  | 220 | and	t1, t1, t0		/* clear CE[1:0] */ | 
|  | 221 | sw	t1, 0x0840(a0)		/* mem_sdconfiga */ | 
|  | 222 | sync | 
|  | 223 |  | 
|  | 224 | DO_SLEEP | 
|  | 225 | 4: | 
|  | 226 |  | 
|  | 227 | END(alchemy_sleep_au1300) | 
|  | 228 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 229 |  | 
|  | 230 | /* This is where we return upon wakeup. | 
|  | 231 | * Reload all of the registers and return. | 
|  | 232 | */ | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 233 | LEAF(alchemy_sleep_wakeup) | 
|  | 234 | lw	k0, 0x20(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 235 | mtc0	k0, CP0_STATUS | 
|  | 236 | lw	k0, 0x1c(sp) | 
|  | 237 | mtc0	k0, CP0_CONTEXT | 
|  | 238 | lw	k0, 0x18(sp) | 
|  | 239 | mtc0	k0, CP0_PAGEMASK | 
|  | 240 | lw	k0, 0x14(sp) | 
|  | 241 | mtc0	k0, CP0_CONFIG | 
| Sergei Shtylyov | 9370b35 | 2006-05-26 19:44:54 +0400 | [diff] [blame] | 242 |  | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 243 | /* We need to catch the early Alchemy SOCs with | 
| Sergei Shtylyov | 9370b35 | 2006-05-26 19:44:54 +0400 | [diff] [blame] | 244 | * the write-only Config[OD] bit and set it back to one... | 
|  | 245 | */ | 
|  | 246 | jal	au1x00_fixup_config_od | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 247 | nop | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 248 | lw	$1, PT_R1(sp) | 
|  | 249 | lw	$2, PT_R2(sp) | 
|  | 250 | lw	$3, PT_R3(sp) | 
|  | 251 | lw	$4, PT_R4(sp) | 
|  | 252 | lw	$5, PT_R5(sp) | 
|  | 253 | lw	$6, PT_R6(sp) | 
|  | 254 | lw	$7, PT_R7(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 255 | lw	$16, PT_R16(sp) | 
|  | 256 | lw	$17, PT_R17(sp) | 
|  | 257 | lw	$18, PT_R18(sp) | 
|  | 258 | lw	$19, PT_R19(sp) | 
|  | 259 | lw	$20, PT_R20(sp) | 
|  | 260 | lw	$21, PT_R21(sp) | 
|  | 261 | lw	$22, PT_R22(sp) | 
|  | 262 | lw	$23, PT_R23(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 263 | lw	$26, PT_R26(sp) | 
|  | 264 | lw	$27, PT_R27(sp) | 
|  | 265 | lw	$28, PT_R28(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 266 | lw	$30, PT_R30(sp) | 
|  | 267 | lw	$31, PT_R31(sp) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 268 | jr	ra | 
| Manuel Lauss | 564365b | 2008-12-21 09:26:25 +0100 | [diff] [blame] | 269 | addiu	sp, PT_SIZE | 
| Manuel Lauss | 2e93d1e | 2010-05-24 19:42:52 +0200 | [diff] [blame] | 270 | END(alchemy_sleep_wakeup) |