|  | /* 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 | 
|  |  |