/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2016 Broadcom Corporation */ #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