123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- /*
- * Copyright 2002 Embedded Edge, LLC
- * Author: dan@embeddededge.com
- *
- * Sleep helper for Au1xxx sleep mode.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
- #include <asm/asm.h>
- #include <asm/mipsregs.h>
- #include <asm/regdef.h>
- #include <asm/stackframe.h>
- .extern __flush_cache_all
- .text
- .set noreorder
- .set noat
- .align 5
- /* preparatory stuff */
- .macro SETUP_SLEEP
- subu sp, PT_SIZE
- sw $1, PT_R1(sp)
- sw $2, PT_R2(sp)
- sw $3, PT_R3(sp)
- sw $4, PT_R4(sp)
- sw $5, PT_R5(sp)
- sw $6, PT_R6(sp)
- sw $7, PT_R7(sp)
- sw $16, PT_R16(sp)
- sw $17, PT_R17(sp)
- sw $18, PT_R18(sp)
- sw $19, PT_R19(sp)
- sw $20, PT_R20(sp)
- sw $21, PT_R21(sp)
- sw $22, PT_R22(sp)
- sw $23, PT_R23(sp)
- sw $26, PT_R26(sp)
- sw $27, PT_R27(sp)
- sw $28, PT_R28(sp)
- sw $30, PT_R30(sp)
- sw $31, PT_R31(sp)
- mfc0 k0, CP0_STATUS
- sw k0, 0x20(sp)
- mfc0 k0, CP0_CONTEXT
- sw k0, 0x1c(sp)
- mfc0 k0, CP0_PAGEMASK
- sw k0, 0x18(sp)
- mfc0 k0, CP0_CONFIG
- sw k0, 0x14(sp)
- /* flush caches to make sure context is in memory */
- la t1, __flush_cache_all
- lw t0, 0(t1)
- jalr t0
- nop
- /* Now set up the scratch registers so the boot rom will
- * return to this point upon wakeup.
- * sys_scratch0 : SP
- * sys_scratch1 : RA
- */
- lui t3, 0xb190 /* sys_xxx */
- sw sp, 0x0018(t3)
- la k0, alchemy_sleep_wakeup /* resume path */
- sw k0, 0x001c(t3)
- .endm
- .macro DO_SLEEP
- /* put power supply and processor to sleep */
- sw zero, 0x0078(t3) /* sys_slppwr */
- sync
- sw zero, 0x007c(t3) /* sys_sleep */
- sync
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- .endm
- /* sleep code for Au1000/Au1100/Au1500 memory controller type */
- LEAF(alchemy_sleep_au1000)
- SETUP_SLEEP
- /* cache following instructions, as memory gets put to sleep */
- la t0, 1f
- .set arch=r4000
- cache 0x14, 0(t0)
- cache 0x14, 32(t0)
- cache 0x14, 64(t0)
- cache 0x14, 96(t0)
- .set mips0
- 1: lui a0, 0xb400 /* mem_xxx */
- sw zero, 0x001c(a0) /* Precharge */
- sync
- sw zero, 0x0020(a0) /* Auto Refresh */
- sync
- sw zero, 0x0030(a0) /* Sleep */
- sync
- DO_SLEEP
- END(alchemy_sleep_au1000)
- /* sleep code for Au1550/Au1200 memory controller type */
- LEAF(alchemy_sleep_au1550)
- SETUP_SLEEP
- /* cache following instructions, as memory gets put to sleep */
- la t0, 1f
- .set arch=r4000
- cache 0x14, 0(t0)
- cache 0x14, 32(t0)
- cache 0x14, 64(t0)
- cache 0x14, 96(t0)
- .set mips0
- 1: lui a0, 0xb400 /* mem_xxx */
- sw zero, 0x08c0(a0) /* Precharge */
- sync
- sw zero, 0x08d0(a0) /* Self Refresh */
- sync
- /* wait for sdram to enter self-refresh mode */
- lui t0, 0x0100
- 2: lw t1, 0x0850(a0) /* mem_sdstat */
- and t2, t1, t0
- beq t2, zero, 2b
- nop
- /* disable SDRAM clocks */
- lui t0, 0xcfff
- ori t0, t0, 0xffff
- lw t1, 0x0840(a0) /* mem_sdconfiga */
- and t1, t0, t1 /* clear CE[1:0] */
- sw t1, 0x0840(a0) /* mem_sdconfiga */
- sync
- DO_SLEEP
- END(alchemy_sleep_au1550)
- /* sleepcode for Au1300 memory controller type */
- LEAF(alchemy_sleep_au1300)
- SETUP_SLEEP
- /* cache following instructions, as memory gets put to sleep */
- la t0, 2f
- la t1, 4f
- subu t2, t1, t0
- .set arch=r4000
- 1: cache 0x14, 0(t0)
- subu t2, t2, 32
- bgez t2, 1b
- addu t0, t0, 32
- .set mips0
- 2: lui a0, 0xb400 /* mem_xxx */
- /* disable all ports in mem_sdportcfga */
- sw zero, 0x868(a0) /* mem_sdportcfga */
- sync
- /* disable ODT */
- li t0, 0x03010000
- sw t0, 0x08d8(a0) /* mem_sdcmd0 */
- sw t0, 0x08dc(a0) /* mem_sdcmd1 */
- sync
- /* precharge */
- li t0, 0x23000400
- sw t0, 0x08dc(a0) /* mem_sdcmd1 */
- sw t0, 0x08d8(a0) /* mem_sdcmd0 */
- sync
- /* auto refresh */
- sw zero, 0x08c8(a0) /* mem_sdautoref */
- sync
- /* block access to the DDR */
- lw t0, 0x0848(a0) /* mem_sdconfigb */
- li t1, (1 << 7 | 0x3F)
- or t0, t0, t1
- sw t0, 0x0848(a0) /* mem_sdconfigb */
- sync
- /* issue the Self Refresh command */
- li t0, 0x10000000
- sw t0, 0x08dc(a0) /* mem_sdcmd1 */
- sw t0, 0x08d8(a0) /* mem_sdcmd0 */
- sync
- /* wait for sdram to enter self-refresh mode */
- lui t0, 0x0300
- 3: lw t1, 0x0850(a0) /* mem_sdstat */
- and t2, t1, t0
- bne t2, t0, 3b
- nop
- /* disable SDRAM clocks */
- li t0, ~(3<<28)
- lw t1, 0x0840(a0) /* mem_sdconfiga */
- and t1, t1, t0 /* clear CE[1:0] */
- sw t1, 0x0840(a0) /* mem_sdconfiga */
- sync
- DO_SLEEP
- 4:
- END(alchemy_sleep_au1300)
- /* This is where we return upon wakeup.
- * Reload all of the registers and return.
- */
- LEAF(alchemy_sleep_wakeup)
- lw k0, 0x20(sp)
- mtc0 k0, CP0_STATUS
- lw k0, 0x1c(sp)
- mtc0 k0, CP0_CONTEXT
- lw k0, 0x18(sp)
- mtc0 k0, CP0_PAGEMASK
- lw k0, 0x14(sp)
- mtc0 k0, CP0_CONFIG
- /* We need to catch the early Alchemy SOCs with
- * the write-only Config[OD] bit and set it back to one...
- */
- jal au1x00_fixup_config_od
- nop
- lw $1, PT_R1(sp)
- lw $2, PT_R2(sp)
- lw $3, PT_R3(sp)
- lw $4, PT_R4(sp)
- lw $5, PT_R5(sp)
- lw $6, PT_R6(sp)
- lw $7, PT_R7(sp)
- lw $16, PT_R16(sp)
- lw $17, PT_R17(sp)
- lw $18, PT_R18(sp)
- lw $19, PT_R19(sp)
- lw $20, PT_R20(sp)
- lw $21, PT_R21(sp)
- lw $22, PT_R22(sp)
- lw $23, PT_R23(sp)
- lw $26, PT_R26(sp)
- lw $27, PT_R27(sp)
- lw $28, PT_R28(sp)
- lw $30, PT_R30(sp)
- lw $31, PT_R31(sp)
- jr ra
- addiu sp, PT_SIZE
- END(alchemy_sleep_wakeup)
|