201 lines
3.3 KiB
ArmAsm
201 lines
3.3 KiB
ArmAsm
/*
|
|
* 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
|
|
|