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/bmips.h> 100e9b1141SJustin Chen 110e9b1141SJustin Chen#include "pm.h" 120e9b1141SJustin Chen 130e9b1141SJustin Chen .text 140e9b1141SJustin Chen .set noreorder 150e9b1141SJustin Chen .align 5 160e9b1141SJustin Chen .global s3_reentry 170e9b1141SJustin Chen 180e9b1141SJustin Chen/* 190e9b1141SJustin Chen * a0: AON_CTRL base register 200e9b1141SJustin Chen * a1: D-Cache line size 210e9b1141SJustin Chen */ 220e9b1141SJustin ChenLEAF(brcm_pm_do_s3) 230e9b1141SJustin Chen 240e9b1141SJustin Chen /* Get the address of s3_context */ 250e9b1141SJustin Chen la t0, gp_regs 260e9b1141SJustin Chen sw ra, 0(t0) 270e9b1141SJustin Chen sw s0, 4(t0) 280e9b1141SJustin Chen sw s1, 8(t0) 290e9b1141SJustin Chen sw s2, 12(t0) 300e9b1141SJustin Chen sw s3, 16(t0) 310e9b1141SJustin Chen sw s4, 20(t0) 320e9b1141SJustin Chen sw s5, 24(t0) 330e9b1141SJustin Chen sw s6, 28(t0) 340e9b1141SJustin Chen sw s7, 32(t0) 350e9b1141SJustin Chen sw gp, 36(t0) 360e9b1141SJustin Chen sw sp, 40(t0) 370e9b1141SJustin Chen sw fp, 44(t0) 380e9b1141SJustin Chen 390e9b1141SJustin Chen /* Save CP0 Status */ 400e9b1141SJustin Chen mfc0 t1, CP0_STATUS 410e9b1141SJustin Chen sw t1, 48(t0) 420e9b1141SJustin Chen 430e9b1141SJustin Chen /* Write-back gp registers - cache will be gone */ 440e9b1141SJustin Chen addiu t1, a1, -1 450e9b1141SJustin Chen not t1 460e9b1141SJustin Chen and t0, t1 470e9b1141SJustin Chen 480e9b1141SJustin Chen /* Flush at least 64 bytes */ 490e9b1141SJustin Chen addiu t2, t0, 64 500e9b1141SJustin Chen and t2, t1 510e9b1141SJustin Chen 520e9b1141SJustin Chen1: cache 0x17, 0(t0) 530e9b1141SJustin Chen bne t0, t2, 1b 540e9b1141SJustin Chen addu t0, a1 550e9b1141SJustin Chen 560e9b1141SJustin Chen /* Drop to deep standby */ 570e9b1141SJustin Chen li t1, PM_WARM_CONFIG 580e9b1141SJustin Chen sw zero, AON_CTRL_PM_CTRL(a0) 590e9b1141SJustin Chen lw zero, AON_CTRL_PM_CTRL(a0) 600e9b1141SJustin Chen sw t1, AON_CTRL_PM_CTRL(a0) 610e9b1141SJustin Chen lw t1, AON_CTRL_PM_CTRL(a0) 620e9b1141SJustin Chen 630e9b1141SJustin Chen li t1, (PM_WARM_CONFIG | PM_PWR_DOWN) 640e9b1141SJustin Chen sw t1, AON_CTRL_PM_CTRL(a0) 650e9b1141SJustin Chen lw t1, AON_CTRL_PM_CTRL(a0) 660e9b1141SJustin Chen 670e9b1141SJustin Chen /* Enable CP0 interrupt 2 and wait for interrupt */ 680e9b1141SJustin Chen mfc0 t0, CP0_STATUS 690e9b1141SJustin Chen 700e9b1141SJustin Chen li t1, ~(ST0_IM | ST0_IE) 710e9b1141SJustin Chen and t0, t1 720e9b1141SJustin Chen ori t0, STATUSF_IP2 730e9b1141SJustin Chen mtc0 t0, CP0_STATUS 740e9b1141SJustin Chen nop 750e9b1141SJustin Chen nop 760e9b1141SJustin Chen nop 770e9b1141SJustin Chen ori t0, ST0_IE 780e9b1141SJustin Chen mtc0 t0, CP0_STATUS 790e9b1141SJustin Chen 800e9b1141SJustin Chen /* Wait for interrupt */ 810e9b1141SJustin Chen wait 820e9b1141SJustin Chen nop 830e9b1141SJustin Chen 840e9b1141SJustin Chens3_reentry: 850e9b1141SJustin Chen 860e9b1141SJustin Chen /* Clear call/return stack */ 870e9b1141SJustin Chen li t0, (0x06 << 16) 880e9b1141SJustin Chen mtc0 t0, $22, 2 890e9b1141SJustin Chen ssnop 900e9b1141SJustin Chen ssnop 910e9b1141SJustin Chen ssnop 920e9b1141SJustin Chen 930e9b1141SJustin Chen /* Clear jump target buffer */ 940e9b1141SJustin Chen li t0, (0x04 << 16) 950e9b1141SJustin Chen mtc0 t0, $22, 2 960e9b1141SJustin Chen ssnop 970e9b1141SJustin Chen ssnop 980e9b1141SJustin Chen ssnop 990e9b1141SJustin Chen 1000e9b1141SJustin Chen sync 1010e9b1141SJustin Chen nop 1020e9b1141SJustin Chen 1030e9b1141SJustin Chen /* Setup mmu defaults */ 1040e9b1141SJustin Chen mtc0 zero, CP0_WIRED 1050e9b1141SJustin Chen mtc0 zero, CP0_ENTRYHI 1060e9b1141SJustin Chen li k0, PM_DEFAULT_MASK 1070e9b1141SJustin Chen mtc0 k0, CP0_PAGEMASK 1080e9b1141SJustin Chen 1090e9b1141SJustin Chen li sp, BMIPS_WARM_RESTART_VEC 1100e9b1141SJustin Chen la k0, plat_wired_tlb_setup 1110e9b1141SJustin Chen jalr k0 1120e9b1141SJustin Chen nop 1130e9b1141SJustin Chen 1140e9b1141SJustin Chen /* Restore general purpose registers */ 1150e9b1141SJustin Chen la t0, gp_regs 1160e9b1141SJustin Chen lw fp, 44(t0) 1170e9b1141SJustin Chen lw sp, 40(t0) 1180e9b1141SJustin Chen lw gp, 36(t0) 1190e9b1141SJustin Chen lw s7, 32(t0) 1200e9b1141SJustin Chen lw s6, 28(t0) 1210e9b1141SJustin Chen lw s5, 24(t0) 1220e9b1141SJustin Chen lw s4, 20(t0) 1230e9b1141SJustin Chen lw s3, 16(t0) 1240e9b1141SJustin Chen lw s2, 12(t0) 1250e9b1141SJustin Chen lw s1, 8(t0) 1260e9b1141SJustin Chen lw s0, 4(t0) 1270e9b1141SJustin Chen lw ra, 0(t0) 1280e9b1141SJustin Chen 1290e9b1141SJustin Chen /* Restore CP0 status */ 1300e9b1141SJustin Chen lw t1, 48(t0) 1310e9b1141SJustin Chen mtc0 t1, CP0_STATUS 1320e9b1141SJustin Chen 1330e9b1141SJustin Chen /* Return to caller */ 1340e9b1141SJustin Chen li v0, 0 1350e9b1141SJustin Chen jr ra 1360e9b1141SJustin Chen nop 1370e9b1141SJustin Chen 1380e9b1141SJustin ChenEND(brcm_pm_do_s3) 139