162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2016 Broadcom Corporation 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <asm/asm.h> 762306a36Sopenharmony_ci#include <asm/regdef.h> 862306a36Sopenharmony_ci#include <asm/mipsregs.h> 962306a36Sopenharmony_ci#include <asm/bmips.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "pm.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci .text 1462306a36Sopenharmony_ci .set noreorder 1562306a36Sopenharmony_ci .align 5 1662306a36Sopenharmony_ci .global s3_reentry 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * a0: AON_CTRL base register 2062306a36Sopenharmony_ci * a1: D-Cache line size 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ciLEAF(brcm_pm_do_s3) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci /* Get the address of s3_context */ 2562306a36Sopenharmony_ci la t0, gp_regs 2662306a36Sopenharmony_ci sw ra, 0(t0) 2762306a36Sopenharmony_ci sw s0, 4(t0) 2862306a36Sopenharmony_ci sw s1, 8(t0) 2962306a36Sopenharmony_ci sw s2, 12(t0) 3062306a36Sopenharmony_ci sw s3, 16(t0) 3162306a36Sopenharmony_ci sw s4, 20(t0) 3262306a36Sopenharmony_ci sw s5, 24(t0) 3362306a36Sopenharmony_ci sw s6, 28(t0) 3462306a36Sopenharmony_ci sw s7, 32(t0) 3562306a36Sopenharmony_ci sw gp, 36(t0) 3662306a36Sopenharmony_ci sw sp, 40(t0) 3762306a36Sopenharmony_ci sw fp, 44(t0) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci /* Save CP0 Status */ 4062306a36Sopenharmony_ci mfc0 t1, CP0_STATUS 4162306a36Sopenharmony_ci sw t1, 48(t0) 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci /* Write-back gp registers - cache will be gone */ 4462306a36Sopenharmony_ci addiu t1, a1, -1 4562306a36Sopenharmony_ci not t1 4662306a36Sopenharmony_ci and t0, t1 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci /* Flush at least 64 bytes */ 4962306a36Sopenharmony_ci addiu t2, t0, 64 5062306a36Sopenharmony_ci and t2, t1 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci1: cache 0x17, 0(t0) 5362306a36Sopenharmony_ci bne t0, t2, 1b 5462306a36Sopenharmony_ci addu t0, a1 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /* Drop to deep standby */ 5762306a36Sopenharmony_ci li t1, PM_WARM_CONFIG 5862306a36Sopenharmony_ci sw zero, AON_CTRL_PM_CTRL(a0) 5962306a36Sopenharmony_ci lw zero, AON_CTRL_PM_CTRL(a0) 6062306a36Sopenharmony_ci sw t1, AON_CTRL_PM_CTRL(a0) 6162306a36Sopenharmony_ci lw t1, AON_CTRL_PM_CTRL(a0) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci li t1, (PM_WARM_CONFIG | PM_PWR_DOWN) 6462306a36Sopenharmony_ci sw t1, AON_CTRL_PM_CTRL(a0) 6562306a36Sopenharmony_ci lw t1, AON_CTRL_PM_CTRL(a0) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* Enable CP0 interrupt 2 and wait for interrupt */ 6862306a36Sopenharmony_ci mfc0 t0, CP0_STATUS 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci li t1, ~(ST0_IM | ST0_IE) 7162306a36Sopenharmony_ci and t0, t1 7262306a36Sopenharmony_ci ori t0, STATUSF_IP2 7362306a36Sopenharmony_ci mtc0 t0, CP0_STATUS 7462306a36Sopenharmony_ci nop 7562306a36Sopenharmony_ci nop 7662306a36Sopenharmony_ci nop 7762306a36Sopenharmony_ci ori t0, ST0_IE 7862306a36Sopenharmony_ci mtc0 t0, CP0_STATUS 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* Wait for interrupt */ 8162306a36Sopenharmony_ci wait 8262306a36Sopenharmony_ci nop 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cis3_reentry: 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* Clear call/return stack */ 8762306a36Sopenharmony_ci li t0, (0x06 << 16) 8862306a36Sopenharmony_ci mtc0 t0, $22, 2 8962306a36Sopenharmony_ci ssnop 9062306a36Sopenharmony_ci ssnop 9162306a36Sopenharmony_ci ssnop 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* Clear jump target buffer */ 9462306a36Sopenharmony_ci li t0, (0x04 << 16) 9562306a36Sopenharmony_ci mtc0 t0, $22, 2 9662306a36Sopenharmony_ci ssnop 9762306a36Sopenharmony_ci ssnop 9862306a36Sopenharmony_ci ssnop 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci sync 10162306a36Sopenharmony_ci nop 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Setup mmu defaults */ 10462306a36Sopenharmony_ci mtc0 zero, CP0_WIRED 10562306a36Sopenharmony_ci mtc0 zero, CP0_ENTRYHI 10662306a36Sopenharmony_ci li k0, PM_DEFAULT_MASK 10762306a36Sopenharmony_ci mtc0 k0, CP0_PAGEMASK 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci li sp, BMIPS_WARM_RESTART_VEC 11062306a36Sopenharmony_ci la k0, plat_wired_tlb_setup 11162306a36Sopenharmony_ci jalr k0 11262306a36Sopenharmony_ci nop 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* Restore general purpose registers */ 11562306a36Sopenharmony_ci la t0, gp_regs 11662306a36Sopenharmony_ci lw fp, 44(t0) 11762306a36Sopenharmony_ci lw sp, 40(t0) 11862306a36Sopenharmony_ci lw gp, 36(t0) 11962306a36Sopenharmony_ci lw s7, 32(t0) 12062306a36Sopenharmony_ci lw s6, 28(t0) 12162306a36Sopenharmony_ci lw s5, 24(t0) 12262306a36Sopenharmony_ci lw s4, 20(t0) 12362306a36Sopenharmony_ci lw s3, 16(t0) 12462306a36Sopenharmony_ci lw s2, 12(t0) 12562306a36Sopenharmony_ci lw s1, 8(t0) 12662306a36Sopenharmony_ci lw s0, 4(t0) 12762306a36Sopenharmony_ci lw ra, 0(t0) 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* Restore CP0 status */ 13062306a36Sopenharmony_ci lw t1, 48(t0) 13162306a36Sopenharmony_ci mtc0 t1, CP0_STATUS 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* Return to caller */ 13462306a36Sopenharmony_ci li v0, 0 13562306a36Sopenharmony_ci jr ra 13662306a36Sopenharmony_ci nop 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ciEND(brcm_pm_do_s3) 139