1*1802d0beSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 20e9b1141SJustin Chen/* 30e9b1141SJustin Chen * Copyright (C) 2016 Broadcom Corporation 40e9b1141SJustin Chen */ 50e9b1141SJustin Chen 60e9b1141SJustin Chen#include <asm/asm.h> 70e9b1141SJustin Chen#include <asm/regdef.h> 80e9b1141SJustin Chen#include <asm/mipsregs.h> 90e9b1141SJustin Chen#include <asm/stackframe.h> 100e9b1141SJustin Chen 110e9b1141SJustin Chen#include "pm.h" 120e9b1141SJustin Chen 130e9b1141SJustin Chen .text 140e9b1141SJustin Chen .set noreorder 150e9b1141SJustin Chen .align 5 160e9b1141SJustin Chen 170e9b1141SJustin Chen/* 180e9b1141SJustin Chen * a0: u32 params array 190e9b1141SJustin Chen */ 200e9b1141SJustin ChenLEAF(brcm_pm_do_s2) 210e9b1141SJustin Chen 220e9b1141SJustin Chen subu sp, 64 230e9b1141SJustin Chen sw ra, 0(sp) 240e9b1141SJustin Chen sw s0, 4(sp) 250e9b1141SJustin Chen sw s1, 8(sp) 260e9b1141SJustin Chen sw s2, 12(sp) 270e9b1141SJustin Chen sw s3, 16(sp) 280e9b1141SJustin Chen sw s4, 20(sp) 290e9b1141SJustin Chen sw s5, 24(sp) 300e9b1141SJustin Chen sw s6, 28(sp) 310e9b1141SJustin Chen sw s7, 32(sp) 320e9b1141SJustin Chen 330e9b1141SJustin Chen /* 340e9b1141SJustin Chen * Dereference the params array 350e9b1141SJustin Chen * s0: AON_CTRL base register 360e9b1141SJustin Chen * s1: DDR_PHY base register 370e9b1141SJustin Chen * s2: TIMERS base register 380e9b1141SJustin Chen * s3: I-Cache line size 390e9b1141SJustin Chen * s4: Restart vector address 400e9b1141SJustin Chen * s5: Restart vector size 410e9b1141SJustin Chen */ 420e9b1141SJustin Chen move t0, a0 430e9b1141SJustin Chen 440e9b1141SJustin Chen lw s0, 0(t0) 450e9b1141SJustin Chen lw s1, 4(t0) 460e9b1141SJustin Chen lw s2, 8(t0) 470e9b1141SJustin Chen lw s3, 12(t0) 480e9b1141SJustin Chen lw s4, 16(t0) 490e9b1141SJustin Chen lw s5, 20(t0) 500e9b1141SJustin Chen 510e9b1141SJustin Chen /* Lock this asm section into the I-cache */ 520e9b1141SJustin Chen addiu t1, s3, -1 530e9b1141SJustin Chen not t1 540e9b1141SJustin Chen 550e9b1141SJustin Chen la t0, brcm_pm_do_s2 560e9b1141SJustin Chen and t0, t1 570e9b1141SJustin Chen 580e9b1141SJustin Chen la t2, asm_end 590e9b1141SJustin Chen and t2, t1 600e9b1141SJustin Chen 610e9b1141SJustin Chen1: cache 0x1c, 0(t0) 620e9b1141SJustin Chen bne t0, t2, 1b 630e9b1141SJustin Chen addu t0, s3 640e9b1141SJustin Chen 650e9b1141SJustin Chen /* Lock the interrupt vector into the I-cache */ 660e9b1141SJustin Chen move t0, zero 670e9b1141SJustin Chen 680e9b1141SJustin Chen2: move t1, s4 690e9b1141SJustin Chen cache 0x1c, 0(t1) 700e9b1141SJustin Chen addu t1, s3 710e9b1141SJustin Chen addu t0, s3 720e9b1141SJustin Chen ble t0, s5, 2b 730e9b1141SJustin Chen nop 740e9b1141SJustin Chen 750e9b1141SJustin Chen sync 760e9b1141SJustin Chen 770e9b1141SJustin Chen /* Power down request */ 780e9b1141SJustin Chen li t0, PM_S2_COMMAND 790e9b1141SJustin Chen sw zero, AON_CTRL_PM_CTRL(s0) 800e9b1141SJustin Chen lw zero, AON_CTRL_PM_CTRL(s0) 810e9b1141SJustin Chen sw t0, AON_CTRL_PM_CTRL(s0) 820e9b1141SJustin Chen lw t0, AON_CTRL_PM_CTRL(s0) 830e9b1141SJustin Chen 840e9b1141SJustin Chen /* Enable CP0 interrupt 2 and wait for interrupt */ 850e9b1141SJustin Chen mfc0 t0, CP0_STATUS 860e9b1141SJustin Chen /* Save cp0 sr for restoring later */ 870e9b1141SJustin Chen move s6, t0 880e9b1141SJustin Chen 890e9b1141SJustin Chen li t1, ~(ST0_IM | ST0_IE) 900e9b1141SJustin Chen and t0, t1 910e9b1141SJustin Chen ori t0, STATUSF_IP2 920e9b1141SJustin Chen mtc0 t0, CP0_STATUS 930e9b1141SJustin Chen nop 940e9b1141SJustin Chen nop 950e9b1141SJustin Chen nop 960e9b1141SJustin Chen ori t0, ST0_IE 970e9b1141SJustin Chen mtc0 t0, CP0_STATUS 980e9b1141SJustin Chen 990e9b1141SJustin Chen /* Wait for interrupt */ 1000e9b1141SJustin Chen wait 1010e9b1141SJustin Chen nop 1020e9b1141SJustin Chen 1030e9b1141SJustin Chen /* Wait for memc0 */ 1040e9b1141SJustin Chen1: lw t0, DDR40_PHY_CONTROL_REGS_0_PLL_STATUS(s1) 1050e9b1141SJustin Chen andi t0, 1 1060e9b1141SJustin Chen beqz t0, 1b 1070e9b1141SJustin Chen nop 1080e9b1141SJustin Chen 1090e9b1141SJustin Chen /* 1ms delay needed for stable recovery */ 1100e9b1141SJustin Chen /* Use TIMER1 to count 1 ms */ 1110e9b1141SJustin Chen li t0, RESET_TIMER 1120e9b1141SJustin Chen sw t0, TIMER_TIMER1_CTRL(s2) 1130e9b1141SJustin Chen lw t0, TIMER_TIMER1_CTRL(s2) 1140e9b1141SJustin Chen 1150e9b1141SJustin Chen li t0, START_TIMER 1160e9b1141SJustin Chen sw t0, TIMER_TIMER1_CTRL(s2) 1170e9b1141SJustin Chen lw t0, TIMER_TIMER1_CTRL(s2) 1180e9b1141SJustin Chen 1190e9b1141SJustin Chen /* Prepare delay */ 1200e9b1141SJustin Chen li t0, TIMER_MASK 1210e9b1141SJustin Chen lw t1, TIMER_TIMER1_STAT(s2) 1220e9b1141SJustin Chen and t1, t0 1230e9b1141SJustin Chen /* 1ms delay */ 1240e9b1141SJustin Chen addi t1, 27000 1250e9b1141SJustin Chen 1260e9b1141SJustin Chen /* Wait for the timer value to exceed t1 */ 1270e9b1141SJustin Chen1: lw t0, TIMER_TIMER1_STAT(s2) 1280e9b1141SJustin Chen sgtu t2, t1, t0 1290e9b1141SJustin Chen bnez t2, 1b 1300e9b1141SJustin Chen nop 1310e9b1141SJustin Chen 1320e9b1141SJustin Chen /* Power back up */ 1330e9b1141SJustin Chen li t1, 1 1340e9b1141SJustin Chen sw t1, AON_CTRL_HOST_MISC_CMDS(s0) 1350e9b1141SJustin Chen lw t1, AON_CTRL_HOST_MISC_CMDS(s0) 1360e9b1141SJustin Chen 1370e9b1141SJustin Chen sw zero, AON_CTRL_PM_CTRL(s0) 1380e9b1141SJustin Chen lw zero, AON_CTRL_PM_CTRL(s0) 1390e9b1141SJustin Chen 1400e9b1141SJustin Chen /* Unlock I-cache */ 1410e9b1141SJustin Chen addiu t1, s3, -1 1420e9b1141SJustin Chen not t1 1430e9b1141SJustin Chen 1440e9b1141SJustin Chen la t0, brcm_pm_do_s2 1450e9b1141SJustin Chen and t0, t1 1460e9b1141SJustin Chen 1470e9b1141SJustin Chen la t2, asm_end 1480e9b1141SJustin Chen and t2, t1 1490e9b1141SJustin Chen 1500e9b1141SJustin Chen1: cache 0x00, 0(t0) 1510e9b1141SJustin Chen bne t0, t2, 1b 1520e9b1141SJustin Chen addu t0, s3 1530e9b1141SJustin Chen 1540e9b1141SJustin Chen /* Unlock interrupt vector */ 1550e9b1141SJustin Chen move t0, zero 1560e9b1141SJustin Chen 1570e9b1141SJustin Chen2: move t1, s4 1580e9b1141SJustin Chen cache 0x00, 0(t1) 1590e9b1141SJustin Chen addu t1, s3 1600e9b1141SJustin Chen addu t0, s3 1610e9b1141SJustin Chen ble t0, s5, 2b 1620e9b1141SJustin Chen nop 1630e9b1141SJustin Chen 1640e9b1141SJustin Chen /* Restore cp0 sr */ 1650e9b1141SJustin Chen sync 1660e9b1141SJustin Chen nop 1670e9b1141SJustin Chen mtc0 s6, CP0_STATUS 1680e9b1141SJustin Chen nop 1690e9b1141SJustin Chen 1700e9b1141SJustin Chen /* Set return value to success */ 1710e9b1141SJustin Chen li v0, 0 1720e9b1141SJustin Chen 1730e9b1141SJustin Chen /* Return to caller */ 1740e9b1141SJustin Chen lw s7, 32(sp) 1750e9b1141SJustin Chen lw s6, 28(sp) 1760e9b1141SJustin Chen lw s5, 24(sp) 1770e9b1141SJustin Chen lw s4, 20(sp) 1780e9b1141SJustin Chen lw s3, 16(sp) 1790e9b1141SJustin Chen lw s2, 12(sp) 1800e9b1141SJustin Chen lw s1, 8(sp) 1810e9b1141SJustin Chen lw s0, 4(sp) 1820e9b1141SJustin Chen lw ra, 0(sp) 1830e9b1141SJustin Chen addiu sp, 64 1840e9b1141SJustin Chen 1850e9b1141SJustin Chen jr ra 1860e9b1141SJustin Chen nop 1870e9b1141SJustin ChenEND(brcm_pm_do_s2) 1880e9b1141SJustin Chen 1890e9b1141SJustin Chen .globl asm_end 1900e9b1141SJustin Chenasm_end: 1910e9b1141SJustin Chen nop 1920e9b1141SJustin Chen 193