1*2874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */ 2e8c7c482SRalf Baechle/* 3e8c7c482SRalf Baechle * Copyright 2002 Embedded Edge, LLC 4e8c7c482SRalf Baechle * Author: dan@embeddededge.com 5e8c7c482SRalf Baechle * 6e8c7c482SRalf Baechle * Sleep helper for Au1xxx sleep mode. 7e8c7c482SRalf Baechle */ 8e8c7c482SRalf Baechle 9e8c7c482SRalf Baechle#include <asm/asm.h> 10e8c7c482SRalf Baechle#include <asm/mipsregs.h> 11e8c7c482SRalf Baechle#include <asm/regdef.h> 12e8c7c482SRalf Baechle#include <asm/stackframe.h> 13e8c7c482SRalf Baechle 14564365b0SManuel Lauss .extern __flush_cache_all 15564365b0SManuel Lauss 16e8c7c482SRalf Baechle .text 17564365b0SManuel Lauss .set noreorder 18e8c7c482SRalf Baechle .set noat 19e8c7c482SRalf Baechle .align 5 20e8c7c482SRalf Baechle 212e93d1ecSManuel Lauss 222e93d1ecSManuel Lauss/* preparatory stuff */ 232e93d1ecSManuel Lauss.macro SETUP_SLEEP 24e8c7c482SRalf Baechle subu sp, PT_SIZE 25e8c7c482SRalf Baechle sw $1, PT_R1(sp) 26e8c7c482SRalf Baechle sw $2, PT_R2(sp) 27e8c7c482SRalf Baechle sw $3, PT_R3(sp) 28e8c7c482SRalf Baechle sw $4, PT_R4(sp) 29e8c7c482SRalf Baechle sw $5, PT_R5(sp) 30e8c7c482SRalf Baechle sw $6, PT_R6(sp) 31e8c7c482SRalf Baechle sw $7, PT_R7(sp) 32e8c7c482SRalf Baechle sw $16, PT_R16(sp) 33e8c7c482SRalf Baechle sw $17, PT_R17(sp) 34e8c7c482SRalf Baechle sw $18, PT_R18(sp) 35e8c7c482SRalf Baechle sw $19, PT_R19(sp) 36e8c7c482SRalf Baechle sw $20, PT_R20(sp) 37e8c7c482SRalf Baechle sw $21, PT_R21(sp) 38e8c7c482SRalf Baechle sw $22, PT_R22(sp) 39e8c7c482SRalf Baechle sw $23, PT_R23(sp) 40e8c7c482SRalf Baechle sw $26, PT_R26(sp) 41e8c7c482SRalf Baechle sw $27, PT_R27(sp) 42e8c7c482SRalf Baechle sw $28, PT_R28(sp) 43e8c7c482SRalf Baechle sw $30, PT_R30(sp) 44e8c7c482SRalf Baechle sw $31, PT_R31(sp) 45e8c7c482SRalf Baechle mfc0 k0, CP0_STATUS 46e8c7c482SRalf Baechle sw k0, 0x20(sp) 47e8c7c482SRalf Baechle mfc0 k0, CP0_CONTEXT 48e8c7c482SRalf Baechle sw k0, 0x1c(sp) 49e8c7c482SRalf Baechle mfc0 k0, CP0_PAGEMASK 50e8c7c482SRalf Baechle sw k0, 0x18(sp) 51e8c7c482SRalf Baechle mfc0 k0, CP0_CONFIG 52e8c7c482SRalf Baechle sw k0, 0x14(sp) 53e8c7c482SRalf Baechle 54564365b0SManuel Lauss /* flush caches to make sure context is in memory */ 55564365b0SManuel Lauss la t1, __flush_cache_all 56564365b0SManuel Lauss lw t0, 0(t1) 57564365b0SManuel Lauss jalr t0 58564365b0SManuel Lauss nop 59564365b0SManuel Lauss 60e8c7c482SRalf Baechle /* Now set up the scratch registers so the boot rom will 61e8c7c482SRalf Baechle * return to this point upon wakeup. 62564365b0SManuel Lauss * sys_scratch0 : SP 63564365b0SManuel Lauss * sys_scratch1 : RA 64e8c7c482SRalf Baechle */ 65564365b0SManuel Lauss lui t3, 0xb190 /* sys_xxx */ 66564365b0SManuel Lauss sw sp, 0x0018(t3) 672e93d1ecSManuel Lauss la k0, alchemy_sleep_wakeup /* resume path */ 68564365b0SManuel Lauss sw k0, 0x001c(t3) 692e93d1ecSManuel Lauss.endm 70e8c7c482SRalf Baechle 712e93d1ecSManuel Lauss.macro DO_SLEEP 722e93d1ecSManuel Lauss /* put power supply and processor to sleep */ 732e93d1ecSManuel Lauss sw zero, 0x0078(t3) /* sys_slppwr */ 742e93d1ecSManuel Lauss sync 752e93d1ecSManuel Lauss sw zero, 0x007c(t3) /* sys_sleep */ 762e93d1ecSManuel Lauss sync 772e93d1ecSManuel Lauss nop 782e93d1ecSManuel Lauss nop 792e93d1ecSManuel Lauss nop 802e93d1ecSManuel Lauss nop 812e93d1ecSManuel Lauss nop 822e93d1ecSManuel Lauss nop 832e93d1ecSManuel Lauss nop 842e93d1ecSManuel Lauss nop 852e93d1ecSManuel Lauss.endm 862e93d1ecSManuel Lauss 872e93d1ecSManuel Lauss/* sleep code for Au1000/Au1100/Au1500 memory controller type */ 882e93d1ecSManuel LaussLEAF(alchemy_sleep_au1000) 892e93d1ecSManuel Lauss 902e93d1ecSManuel Lauss SETUP_SLEEP 912e93d1ecSManuel Lauss 922e93d1ecSManuel Lauss /* cache following instructions, as memory gets put to sleep */ 93564365b0SManuel Lauss la t0, 1f 94a809d460SRalf Baechle .set arch=r4000 95e8c7c482SRalf Baechle cache 0x14, 0(t0) 96e8c7c482SRalf Baechle cache 0x14, 32(t0) 97e8c7c482SRalf Baechle cache 0x14, 64(t0) 98e8c7c482SRalf Baechle cache 0x14, 96(t0) 99e8c7c482SRalf Baechle .set mips0 100e8c7c482SRalf Baechle 101564365b0SManuel Lauss1: lui a0, 0xb400 /* mem_xxx */ 102564365b0SManuel Lauss sw zero, 0x001c(a0) /* Precharge */ 103564365b0SManuel Lauss sync 104564365b0SManuel Lauss sw zero, 0x0020(a0) /* Auto Refresh */ 105564365b0SManuel Lauss sync 106564365b0SManuel Lauss sw zero, 0x0030(a0) /* Sleep */ 107564365b0SManuel Lauss sync 108564365b0SManuel Lauss 1092e93d1ecSManuel Lauss DO_SLEEP 1102e93d1ecSManuel Lauss 1112e93d1ecSManuel LaussEND(alchemy_sleep_au1000) 1122e93d1ecSManuel Lauss 1132e93d1ecSManuel Lauss/* sleep code for Au1550/Au1200 memory controller type */ 1142e93d1ecSManuel LaussLEAF(alchemy_sleep_au1550) 1152e93d1ecSManuel Lauss 1162e93d1ecSManuel Lauss SETUP_SLEEP 1172e93d1ecSManuel Lauss 1182e93d1ecSManuel Lauss /* cache following instructions, as memory gets put to sleep */ 1192e93d1ecSManuel Lauss la t0, 1f 120a809d460SRalf Baechle .set arch=r4000 1212e93d1ecSManuel Lauss cache 0x14, 0(t0) 1222e93d1ecSManuel Lauss cache 0x14, 32(t0) 1232e93d1ecSManuel Lauss cache 0x14, 64(t0) 1242e93d1ecSManuel Lauss cache 0x14, 96(t0) 1252e93d1ecSManuel Lauss .set mips0 1262e93d1ecSManuel Lauss 1272e93d1ecSManuel Lauss1: lui a0, 0xb400 /* mem_xxx */ 128564365b0SManuel Lauss sw zero, 0x08c0(a0) /* Precharge */ 129564365b0SManuel Lauss sync 130564365b0SManuel Lauss sw zero, 0x08d0(a0) /* Self Refresh */ 131e8c7c482SRalf Baechle sync 132e8c7c482SRalf Baechle 133564365b0SManuel Lauss /* wait for sdram to enter self-refresh mode */ 134564365b0SManuel Lauss lui t0, 0x0100 135564365b0SManuel Lauss2: lw t1, 0x0850(a0) /* mem_sdstat */ 136564365b0SManuel Lauss and t2, t1, t0 137564365b0SManuel Lauss beq t2, zero, 2b 138564365b0SManuel Lauss nop 139564365b0SManuel Lauss 140564365b0SManuel Lauss /* disable SDRAM clocks */ 141564365b0SManuel Lauss lui t0, 0xcfff 142564365b0SManuel Lauss ori t0, t0, 0xffff 143564365b0SManuel Lauss lw t1, 0x0840(a0) /* mem_sdconfiga */ 144564365b0SManuel Lauss and t1, t0, t1 /* clear CE[1:0] */ 145564365b0SManuel Lauss sw t1, 0x0840(a0) /* mem_sdconfiga */ 146e8c7c482SRalf Baechle sync 147564365b0SManuel Lauss 1482e93d1ecSManuel Lauss DO_SLEEP 1492e93d1ecSManuel Lauss 1502e93d1ecSManuel LaussEND(alchemy_sleep_au1550) 1512e93d1ecSManuel Lauss 152809f36c6SManuel Lauss/* sleepcode for Au1300 memory controller type */ 153809f36c6SManuel LaussLEAF(alchemy_sleep_au1300) 154809f36c6SManuel Lauss 155809f36c6SManuel Lauss SETUP_SLEEP 156809f36c6SManuel Lauss 157809f36c6SManuel Lauss /* cache following instructions, as memory gets put to sleep */ 158809f36c6SManuel Lauss la t0, 2f 159809f36c6SManuel Lauss la t1, 4f 160809f36c6SManuel Lauss subu t2, t1, t0 161809f36c6SManuel Lauss 162a809d460SRalf Baechle .set arch=r4000 163809f36c6SManuel Lauss 164809f36c6SManuel Lauss1: cache 0x14, 0(t0) 165809f36c6SManuel Lauss subu t2, t2, 32 166809f36c6SManuel Lauss bgez t2, 1b 167809f36c6SManuel Lauss addu t0, t0, 32 168809f36c6SManuel Lauss 169809f36c6SManuel Lauss .set mips0 170809f36c6SManuel Lauss 171809f36c6SManuel Lauss2: lui a0, 0xb400 /* mem_xxx */ 172809f36c6SManuel Lauss 173809f36c6SManuel Lauss /* disable all ports in mem_sdportcfga */ 174809f36c6SManuel Lauss sw zero, 0x868(a0) /* mem_sdportcfga */ 175809f36c6SManuel Lauss sync 176809f36c6SManuel Lauss 177809f36c6SManuel Lauss /* disable ODT */ 178809f36c6SManuel Lauss li t0, 0x03010000 179809f36c6SManuel Lauss sw t0, 0x08d8(a0) /* mem_sdcmd0 */ 180809f36c6SManuel Lauss sw t0, 0x08dc(a0) /* mem_sdcmd1 */ 181809f36c6SManuel Lauss sync 182809f36c6SManuel Lauss 183809f36c6SManuel Lauss /* precharge */ 184809f36c6SManuel Lauss li t0, 0x23000400 185809f36c6SManuel Lauss sw t0, 0x08dc(a0) /* mem_sdcmd1 */ 186809f36c6SManuel Lauss sw t0, 0x08d8(a0) /* mem_sdcmd0 */ 187809f36c6SManuel Lauss sync 188809f36c6SManuel Lauss 189809f36c6SManuel Lauss /* auto refresh */ 190809f36c6SManuel Lauss sw zero, 0x08c8(a0) /* mem_sdautoref */ 191809f36c6SManuel Lauss sync 192809f36c6SManuel Lauss 193809f36c6SManuel Lauss /* block access to the DDR */ 194809f36c6SManuel Lauss lw t0, 0x0848(a0) /* mem_sdconfigb */ 195809f36c6SManuel Lauss li t1, (1 << 7 | 0x3F) 196809f36c6SManuel Lauss or t0, t0, t1 197809f36c6SManuel Lauss sw t0, 0x0848(a0) /* mem_sdconfigb */ 198809f36c6SManuel Lauss sync 199809f36c6SManuel Lauss 200809f36c6SManuel Lauss /* issue the Self Refresh command */ 201809f36c6SManuel Lauss li t0, 0x10000000 202809f36c6SManuel Lauss sw t0, 0x08dc(a0) /* mem_sdcmd1 */ 203809f36c6SManuel Lauss sw t0, 0x08d8(a0) /* mem_sdcmd0 */ 204809f36c6SManuel Lauss sync 205809f36c6SManuel Lauss 206809f36c6SManuel Lauss /* wait for sdram to enter self-refresh mode */ 207809f36c6SManuel Lauss lui t0, 0x0300 208809f36c6SManuel Lauss3: lw t1, 0x0850(a0) /* mem_sdstat */ 209809f36c6SManuel Lauss and t2, t1, t0 210809f36c6SManuel Lauss bne t2, t0, 3b 211809f36c6SManuel Lauss nop 212809f36c6SManuel Lauss 213809f36c6SManuel Lauss /* disable SDRAM clocks */ 214809f36c6SManuel Lauss li t0, ~(3<<28) 215809f36c6SManuel Lauss lw t1, 0x0840(a0) /* mem_sdconfiga */ 216809f36c6SManuel Lauss and t1, t1, t0 /* clear CE[1:0] */ 217809f36c6SManuel Lauss sw t1, 0x0840(a0) /* mem_sdconfiga */ 218809f36c6SManuel Lauss sync 219809f36c6SManuel Lauss 220809f36c6SManuel Lauss DO_SLEEP 221809f36c6SManuel Lauss4: 222809f36c6SManuel Lauss 223809f36c6SManuel LaussEND(alchemy_sleep_au1300) 224809f36c6SManuel Lauss 225e8c7c482SRalf Baechle 226e8c7c482SRalf Baechle /* This is where we return upon wakeup. 227e8c7c482SRalf Baechle * Reload all of the registers and return. 228e8c7c482SRalf Baechle */ 2292e93d1ecSManuel LaussLEAF(alchemy_sleep_wakeup) 2302e93d1ecSManuel Lauss lw k0, 0x20(sp) 231e8c7c482SRalf Baechle mtc0 k0, CP0_STATUS 232e8c7c482SRalf Baechle lw k0, 0x1c(sp) 233e8c7c482SRalf Baechle mtc0 k0, CP0_CONTEXT 234e8c7c482SRalf Baechle lw k0, 0x18(sp) 235e8c7c482SRalf Baechle mtc0 k0, CP0_PAGEMASK 236e8c7c482SRalf Baechle lw k0, 0x14(sp) 237e8c7c482SRalf Baechle mtc0 k0, CP0_CONFIG 238e8c7c482SRalf Baechle 239564365b0SManuel Lauss /* We need to catch the early Alchemy SOCs with 240e8c7c482SRalf Baechle * the write-only Config[OD] bit and set it back to one... 241e8c7c482SRalf Baechle */ 242e8c7c482SRalf Baechle jal au1x00_fixup_config_od 243564365b0SManuel Lauss nop 244e8c7c482SRalf Baechle lw $1, PT_R1(sp) 245e8c7c482SRalf Baechle lw $2, PT_R2(sp) 246e8c7c482SRalf Baechle lw $3, PT_R3(sp) 247e8c7c482SRalf Baechle lw $4, PT_R4(sp) 248e8c7c482SRalf Baechle lw $5, PT_R5(sp) 249e8c7c482SRalf Baechle lw $6, PT_R6(sp) 250e8c7c482SRalf Baechle lw $7, PT_R7(sp) 251e8c7c482SRalf Baechle lw $16, PT_R16(sp) 252e8c7c482SRalf Baechle lw $17, PT_R17(sp) 253e8c7c482SRalf Baechle lw $18, PT_R18(sp) 254e8c7c482SRalf Baechle lw $19, PT_R19(sp) 255e8c7c482SRalf Baechle lw $20, PT_R20(sp) 256e8c7c482SRalf Baechle lw $21, PT_R21(sp) 257e8c7c482SRalf Baechle lw $22, PT_R22(sp) 258e8c7c482SRalf Baechle lw $23, PT_R23(sp) 259e8c7c482SRalf Baechle lw $26, PT_R26(sp) 260e8c7c482SRalf Baechle lw $27, PT_R27(sp) 261e8c7c482SRalf Baechle lw $28, PT_R28(sp) 262e8c7c482SRalf Baechle lw $30, PT_R30(sp) 263e8c7c482SRalf Baechle lw $31, PT_R31(sp) 264e8c7c482SRalf Baechle jr ra 265564365b0SManuel Lauss addiu sp, PT_SIZE 2662e93d1ecSManuel LaussEND(alchemy_sleep_wakeup) 267