1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * Copyright (C) 2016 Broadcom Corporation 4*4882a593Smuzhiyun */ 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun#include <asm/asm.h> 7*4882a593Smuzhiyun#include <asm/regdef.h> 8*4882a593Smuzhiyun#include <asm/mipsregs.h> 9*4882a593Smuzhiyun#include <asm/bmips.h> 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun#include "pm.h" 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun .text 14*4882a593Smuzhiyun .set noreorder 15*4882a593Smuzhiyun .align 5 16*4882a593Smuzhiyun .global s3_reentry 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun/* 19*4882a593Smuzhiyun * a0: AON_CTRL base register 20*4882a593Smuzhiyun * a1: D-Cache line size 21*4882a593Smuzhiyun */ 22*4882a593SmuzhiyunLEAF(brcm_pm_do_s3) 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun /* Get the address of s3_context */ 25*4882a593Smuzhiyun la t0, gp_regs 26*4882a593Smuzhiyun sw ra, 0(t0) 27*4882a593Smuzhiyun sw s0, 4(t0) 28*4882a593Smuzhiyun sw s1, 8(t0) 29*4882a593Smuzhiyun sw s2, 12(t0) 30*4882a593Smuzhiyun sw s3, 16(t0) 31*4882a593Smuzhiyun sw s4, 20(t0) 32*4882a593Smuzhiyun sw s5, 24(t0) 33*4882a593Smuzhiyun sw s6, 28(t0) 34*4882a593Smuzhiyun sw s7, 32(t0) 35*4882a593Smuzhiyun sw gp, 36(t0) 36*4882a593Smuzhiyun sw sp, 40(t0) 37*4882a593Smuzhiyun sw fp, 44(t0) 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun /* Save CP0 Status */ 40*4882a593Smuzhiyun mfc0 t1, CP0_STATUS 41*4882a593Smuzhiyun sw t1, 48(t0) 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun /* Write-back gp registers - cache will be gone */ 44*4882a593Smuzhiyun addiu t1, a1, -1 45*4882a593Smuzhiyun not t1 46*4882a593Smuzhiyun and t0, t1 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun /* Flush at least 64 bytes */ 49*4882a593Smuzhiyun addiu t2, t0, 64 50*4882a593Smuzhiyun and t2, t1 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun1: cache 0x17, 0(t0) 53*4882a593Smuzhiyun bne t0, t2, 1b 54*4882a593Smuzhiyun addu t0, a1 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun /* Drop to deep standby */ 57*4882a593Smuzhiyun li t1, PM_WARM_CONFIG 58*4882a593Smuzhiyun sw zero, AON_CTRL_PM_CTRL(a0) 59*4882a593Smuzhiyun lw zero, AON_CTRL_PM_CTRL(a0) 60*4882a593Smuzhiyun sw t1, AON_CTRL_PM_CTRL(a0) 61*4882a593Smuzhiyun lw t1, AON_CTRL_PM_CTRL(a0) 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun li t1, (PM_WARM_CONFIG | PM_PWR_DOWN) 64*4882a593Smuzhiyun sw t1, AON_CTRL_PM_CTRL(a0) 65*4882a593Smuzhiyun lw t1, AON_CTRL_PM_CTRL(a0) 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun /* Enable CP0 interrupt 2 and wait for interrupt */ 68*4882a593Smuzhiyun mfc0 t0, CP0_STATUS 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun li t1, ~(ST0_IM | ST0_IE) 71*4882a593Smuzhiyun and t0, t1 72*4882a593Smuzhiyun ori t0, STATUSF_IP2 73*4882a593Smuzhiyun mtc0 t0, CP0_STATUS 74*4882a593Smuzhiyun nop 75*4882a593Smuzhiyun nop 76*4882a593Smuzhiyun nop 77*4882a593Smuzhiyun ori t0, ST0_IE 78*4882a593Smuzhiyun mtc0 t0, CP0_STATUS 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun /* Wait for interrupt */ 81*4882a593Smuzhiyun wait 82*4882a593Smuzhiyun nop 83*4882a593Smuzhiyun 84*4882a593Smuzhiyuns3_reentry: 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun /* Clear call/return stack */ 87*4882a593Smuzhiyun li t0, (0x06 << 16) 88*4882a593Smuzhiyun mtc0 t0, $22, 2 89*4882a593Smuzhiyun ssnop 90*4882a593Smuzhiyun ssnop 91*4882a593Smuzhiyun ssnop 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun /* Clear jump target buffer */ 94*4882a593Smuzhiyun li t0, (0x04 << 16) 95*4882a593Smuzhiyun mtc0 t0, $22, 2 96*4882a593Smuzhiyun ssnop 97*4882a593Smuzhiyun ssnop 98*4882a593Smuzhiyun ssnop 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun sync 101*4882a593Smuzhiyun nop 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun /* Setup mmu defaults */ 104*4882a593Smuzhiyun mtc0 zero, CP0_WIRED 105*4882a593Smuzhiyun mtc0 zero, CP0_ENTRYHI 106*4882a593Smuzhiyun li k0, PM_DEFAULT_MASK 107*4882a593Smuzhiyun mtc0 k0, CP0_PAGEMASK 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun li sp, BMIPS_WARM_RESTART_VEC 110*4882a593Smuzhiyun la k0, plat_wired_tlb_setup 111*4882a593Smuzhiyun jalr k0 112*4882a593Smuzhiyun nop 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun /* Restore general purpose registers */ 115*4882a593Smuzhiyun la t0, gp_regs 116*4882a593Smuzhiyun lw fp, 44(t0) 117*4882a593Smuzhiyun lw sp, 40(t0) 118*4882a593Smuzhiyun lw gp, 36(t0) 119*4882a593Smuzhiyun lw s7, 32(t0) 120*4882a593Smuzhiyun lw s6, 28(t0) 121*4882a593Smuzhiyun lw s5, 24(t0) 122*4882a593Smuzhiyun lw s4, 20(t0) 123*4882a593Smuzhiyun lw s3, 16(t0) 124*4882a593Smuzhiyun lw s2, 12(t0) 125*4882a593Smuzhiyun lw s1, 8(t0) 126*4882a593Smuzhiyun lw s0, 4(t0) 127*4882a593Smuzhiyun lw ra, 0(t0) 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun /* Restore CP0 status */ 130*4882a593Smuzhiyun lw t1, 48(t0) 131*4882a593Smuzhiyun mtc0 t1, CP0_STATUS 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun /* Return to caller */ 134*4882a593Smuzhiyun li v0, 0 135*4882a593Smuzhiyun jr ra 136*4882a593Smuzhiyun nop 137*4882a593Smuzhiyun 138*4882a593SmuzhiyunEND(brcm_pm_do_s3) 139