/* SPDX-License-Identifier: GPL-2.0-or-later */1/*2* Copyright 2002 Embedded Edge, LLC3* Author: [email protected]4*5* Sleep helper for Au1xxx sleep mode.6*/78#include <asm/asm.h>9#include <asm/mipsregs.h>10#include <asm/regdef.h>11#include <asm/stackframe.h>1213.extern __flush_cache_all1415.text16.set noreorder17.set noat18.align 5192021/* preparatory stuff */22.macro SETUP_SLEEP23subu sp, PT_SIZE24sw $1, PT_R1(sp)25sw $2, PT_R2(sp)26sw $3, PT_R3(sp)27sw $4, PT_R4(sp)28sw $5, PT_R5(sp)29sw $6, PT_R6(sp)30sw $7, PT_R7(sp)31sw $16, PT_R16(sp)32sw $17, PT_R17(sp)33sw $18, PT_R18(sp)34sw $19, PT_R19(sp)35sw $20, PT_R20(sp)36sw $21, PT_R21(sp)37sw $22, PT_R22(sp)38sw $23, PT_R23(sp)39sw $26, PT_R26(sp)40sw $27, PT_R27(sp)41sw $28, PT_R28(sp)42sw $30, PT_R30(sp)43sw $31, PT_R31(sp)44mfc0 k0, CP0_STATUS45sw k0, 0x20(sp)46mfc0 k0, CP0_CONTEXT47sw k0, 0x1c(sp)48mfc0 k0, CP0_PAGEMASK49sw k0, 0x18(sp)50mfc0 k0, CP0_CONFIG51sw k0, 0x14(sp)5253/* flush caches to make sure context is in memory */54la t1, __flush_cache_all55lw t0, 0(t1)56jalr t057nop5859/* Now set up the scratch registers so the boot rom will60* return to this point upon wakeup.61* sys_scratch0 : SP62* sys_scratch1 : RA63*/64lui t3, 0xb190 /* sys_xxx */65sw sp, 0x0018(t3)66la k0, alchemy_sleep_wakeup /* resume path */67sw k0, 0x001c(t3)68.endm6970.macro DO_SLEEP71/* put power supply and processor to sleep */72sw zero, 0x0078(t3) /* sys_slppwr */73sync74sw zero, 0x007c(t3) /* sys_sleep */75sync76nop77nop78nop79nop80nop81nop82nop83nop84.endm8586/* sleep code for Au1000/Au1100/Au1500 memory controller type */87LEAF(alchemy_sleep_au1000)8889SETUP_SLEEP9091/* cache following instructions, as memory gets put to sleep */92la t0, 1f93.set arch=r400094cache 0x14, 0(t0)95cache 0x14, 32(t0)96cache 0x14, 64(t0)97cache 0x14, 96(t0)98.set mips0991001: lui a0, 0xb400 /* mem_xxx */101sw zero, 0x001c(a0) /* Precharge */102sync103sw zero, 0x0020(a0) /* Auto Refresh */104sync105sw zero, 0x0030(a0) /* Sleep */106sync107108DO_SLEEP109110END(alchemy_sleep_au1000)111112/* sleep code for Au1550/Au1200 memory controller type */113LEAF(alchemy_sleep_au1550)114115SETUP_SLEEP116117/* cache following instructions, as memory gets put to sleep */118la t0, 1f119.set arch=r4000120cache 0x14, 0(t0)121cache 0x14, 32(t0)122cache 0x14, 64(t0)123cache 0x14, 96(t0)124.set mips01251261: lui a0, 0xb400 /* mem_xxx */127sw zero, 0x08c0(a0) /* Precharge */128sync129sw zero, 0x08d0(a0) /* Self Refresh */130sync131132/* wait for sdram to enter self-refresh mode */133lui t0, 0x01001342: lw t1, 0x0850(a0) /* mem_sdstat */135and t2, t1, t0136beq t2, zero, 2b137nop138139/* disable SDRAM clocks */140lui t0, 0xcfff141ori t0, t0, 0xffff142lw t1, 0x0840(a0) /* mem_sdconfiga */143and t1, t0, t1 /* clear CE[1:0] */144sw t1, 0x0840(a0) /* mem_sdconfiga */145sync146147DO_SLEEP148149END(alchemy_sleep_au1550)150151/* sleepcode for Au1300 memory controller type */152LEAF(alchemy_sleep_au1300)153154SETUP_SLEEP155156/* cache following instructions, as memory gets put to sleep */157la t0, 2f158la t1, 4f159subu t2, t1, t0160161.set arch=r40001621631: cache 0x14, 0(t0)164subu t2, t2, 32165bgez t2, 1b166addu t0, t0, 32167168.set mips01691702: lui a0, 0xb400 /* mem_xxx */171172/* disable all ports in mem_sdportcfga */173sw zero, 0x868(a0) /* mem_sdportcfga */174sync175176/* disable ODT */177li t0, 0x03010000178sw t0, 0x08d8(a0) /* mem_sdcmd0 */179sw t0, 0x08dc(a0) /* mem_sdcmd1 */180sync181182/* precharge */183li t0, 0x23000400184sw t0, 0x08dc(a0) /* mem_sdcmd1 */185sw t0, 0x08d8(a0) /* mem_sdcmd0 */186sync187188/* auto refresh */189sw zero, 0x08c8(a0) /* mem_sdautoref */190sync191192/* block access to the DDR */193lw t0, 0x0848(a0) /* mem_sdconfigb */194li t1, (1 << 7 | 0x3F)195or t0, t0, t1196sw t0, 0x0848(a0) /* mem_sdconfigb */197sync198199/* issue the Self Refresh command */200li t0, 0x10000000201sw t0, 0x08dc(a0) /* mem_sdcmd1 */202sw t0, 0x08d8(a0) /* mem_sdcmd0 */203sync204205/* wait for sdram to enter self-refresh mode */206lui t0, 0x03002073: lw t1, 0x0850(a0) /* mem_sdstat */208and t2, t1, t0209bne t2, t0, 3b210nop211212/* disable SDRAM clocks */213li t0, ~(3<<28)214lw t1, 0x0840(a0) /* mem_sdconfiga */215and t1, t1, t0 /* clear CE[1:0] */216sw t1, 0x0840(a0) /* mem_sdconfiga */217sync218219DO_SLEEP2204:221222END(alchemy_sleep_au1300)223224225/* This is where we return upon wakeup.226* Reload all of the registers and return.227*/228LEAF(alchemy_sleep_wakeup)229lw k0, 0x20(sp)230mtc0 k0, CP0_STATUS231lw k0, 0x1c(sp)232mtc0 k0, CP0_CONTEXT233lw k0, 0x18(sp)234mtc0 k0, CP0_PAGEMASK235lw k0, 0x14(sp)236mtc0 k0, CP0_CONFIG237238/* We need to catch the early Alchemy SOCs with239* the write-only Config[OD] bit and set it back to one...240*/241jal au1x00_fixup_config_od242nop243lw $1, PT_R1(sp)244lw $2, PT_R2(sp)245lw $3, PT_R3(sp)246lw $4, PT_R4(sp)247lw $5, PT_R5(sp)248lw $6, PT_R6(sp)249lw $7, PT_R7(sp)250lw $16, PT_R16(sp)251lw $17, PT_R17(sp)252lw $18, PT_R18(sp)253lw $19, PT_R19(sp)254lw $20, PT_R20(sp)255lw $21, PT_R21(sp)256lw $22, PT_R22(sp)257lw $23, PT_R23(sp)258lw $26, PT_R26(sp)259lw $27, PT_R27(sp)260lw $28, PT_R28(sp)261lw $30, PT_R30(sp)262lw $31, PT_R31(sp)263jr ra264addiu sp, PT_SIZE265END(alchemy_sleep_wakeup)266267268