123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * Copyright (C) 2016 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <asm/asm.h>
- #include <asm/regdef.h>
- #include <asm/mipsregs.h>
- #include <asm/stackframe.h>
- #include "pm.h"
- .text
- .set noreorder
- .align 5
- /*
- * a0: u32 params array
- */
- LEAF(brcm_pm_do_s2)
- subu sp, 64
- sw ra, 0(sp)
- sw s0, 4(sp)
- sw s1, 8(sp)
- sw s2, 12(sp)
- sw s3, 16(sp)
- sw s4, 20(sp)
- sw s5, 24(sp)
- sw s6, 28(sp)
- sw s7, 32(sp)
- /*
- * Dereference the params array
- * s0: AON_CTRL base register
- * s1: DDR_PHY base register
- * s2: TIMERS base register
- * s3: I-Cache line size
- * s4: Restart vector address
- * s5: Restart vector size
- */
- move t0, a0
- lw s0, 0(t0)
- lw s1, 4(t0)
- lw s2, 8(t0)
- lw s3, 12(t0)
- lw s4, 16(t0)
- lw s5, 20(t0)
- /* Lock this asm section into the I-cache */
- addiu t1, s3, -1
- not t1
- la t0, brcm_pm_do_s2
- and t0, t1
- la t2, asm_end
- and t2, t1
- 1: cache 0x1c, 0(t0)
- bne t0, t2, 1b
- addu t0, s3
- /* Lock the interrupt vector into the I-cache */
- move t0, zero
- 2: move t1, s4
- cache 0x1c, 0(t1)
- addu t1, s3
- addu t0, s3
- ble t0, s5, 2b
- nop
- sync
- /* Power down request */
- li t0, PM_S2_COMMAND
- sw zero, AON_CTRL_PM_CTRL(s0)
- lw zero, AON_CTRL_PM_CTRL(s0)
- sw t0, AON_CTRL_PM_CTRL(s0)
- lw t0, AON_CTRL_PM_CTRL(s0)
- /* Enable CP0 interrupt 2 and wait for interrupt */
- mfc0 t0, CP0_STATUS
- /* Save cp0 sr for restoring later */
- move s6, t0
- li t1, ~(ST0_IM | ST0_IE)
- and t0, t1
- ori t0, STATUSF_IP2
- mtc0 t0, CP0_STATUS
- nop
- nop
- nop
- ori t0, ST0_IE
- mtc0 t0, CP0_STATUS
- /* Wait for interrupt */
- wait
- nop
- /* Wait for memc0 */
- 1: lw t0, DDR40_PHY_CONTROL_REGS_0_PLL_STATUS(s1)
- andi t0, 1
- beqz t0, 1b
- nop
- /* 1ms delay needed for stable recovery */
- /* Use TIMER1 to count 1 ms */
- li t0, RESET_TIMER
- sw t0, TIMER_TIMER1_CTRL(s2)
- lw t0, TIMER_TIMER1_CTRL(s2)
- li t0, START_TIMER
- sw t0, TIMER_TIMER1_CTRL(s2)
- lw t0, TIMER_TIMER1_CTRL(s2)
- /* Prepare delay */
- li t0, TIMER_MASK
- lw t1, TIMER_TIMER1_STAT(s2)
- and t1, t0
- /* 1ms delay */
- addi t1, 27000
- /* Wait for the timer value to exceed t1 */
- 1: lw t0, TIMER_TIMER1_STAT(s2)
- sgtu t2, t1, t0
- bnez t2, 1b
- nop
- /* Power back up */
- li t1, 1
- sw t1, AON_CTRL_HOST_MISC_CMDS(s0)
- lw t1, AON_CTRL_HOST_MISC_CMDS(s0)
- sw zero, AON_CTRL_PM_CTRL(s0)
- lw zero, AON_CTRL_PM_CTRL(s0)
- /* Unlock I-cache */
- addiu t1, s3, -1
- not t1
- la t0, brcm_pm_do_s2
- and t0, t1
- la t2, asm_end
- and t2, t1
- 1: cache 0x00, 0(t0)
- bne t0, t2, 1b
- addu t0, s3
- /* Unlock interrupt vector */
- move t0, zero
- 2: move t1, s4
- cache 0x00, 0(t1)
- addu t1, s3
- addu t0, s3
- ble t0, s5, 2b
- nop
- /* Restore cp0 sr */
- sync
- nop
- mtc0 s6, CP0_STATUS
- nop
- /* Set return value to success */
- li v0, 0
- /* Return to caller */
- lw s7, 32(sp)
- lw s6, 28(sp)
- lw s5, 24(sp)
- lw s4, 20(sp)
- lw s3, 16(sp)
- lw s2, 12(sp)
- lw s1, 8(sp)
- lw s0, 4(sp)
- lw ra, 0(sp)
- addiu sp, 64
- jr ra
- nop
- END(brcm_pm_do_s2)
- .globl asm_end
- asm_end:
- nop
|