| /* 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/bmips.h> |
| |
| #include "pm.h" |
| |
| .text |
| .set noreorder |
| .align 5 |
| .global s3_reentry |
| |
| /* |
| * a0: AON_CTRL base register |
| * a1: D-Cache line size |
| */ |
| LEAF(brcm_pm_do_s3) |
| |
| /* Get the address of s3_context */ |
| la t0, gp_regs |
| sw ra, 0(t0) |
| sw s0, 4(t0) |
| sw s1, 8(t0) |
| sw s2, 12(t0) |
| sw s3, 16(t0) |
| sw s4, 20(t0) |
| sw s5, 24(t0) |
| sw s6, 28(t0) |
| sw s7, 32(t0) |
| sw gp, 36(t0) |
| sw sp, 40(t0) |
| sw fp, 44(t0) |
| |
| /* Save CP0 Status */ |
| mfc0 t1, CP0_STATUS |
| sw t1, 48(t0) |
| |
| /* Write-back gp registers - cache will be gone */ |
| addiu t1, a1, -1 |
| not t1 |
| and t0, t1 |
| |
| /* Flush at least 64 bytes */ |
| addiu t2, t0, 64 |
| and t2, t1 |
| |
| 1: cache 0x17, 0(t0) |
| bne t0, t2, 1b |
| addu t0, a1 |
| |
| /* Drop to deep standby */ |
| li t1, PM_WARM_CONFIG |
| sw zero, AON_CTRL_PM_CTRL(a0) |
| lw zero, AON_CTRL_PM_CTRL(a0) |
| sw t1, AON_CTRL_PM_CTRL(a0) |
| lw t1, AON_CTRL_PM_CTRL(a0) |
| |
| li t1, (PM_WARM_CONFIG | PM_PWR_DOWN) |
| sw t1, AON_CTRL_PM_CTRL(a0) |
| lw t1, AON_CTRL_PM_CTRL(a0) |
| |
| /* Enable CP0 interrupt 2 and wait for interrupt */ |
| mfc0 t0, CP0_STATUS |
| |
| 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 |
| |
| s3_reentry: |
| |
| /* Clear call/return stack */ |
| li t0, (0x06 << 16) |
| mtc0 t0, $22, 2 |
| ssnop |
| ssnop |
| ssnop |
| |
| /* Clear jump target buffer */ |
| li t0, (0x04 << 16) |
| mtc0 t0, $22, 2 |
| ssnop |
| ssnop |
| ssnop |
| |
| sync |
| nop |
| |
| /* Setup mmu defaults */ |
| mtc0 zero, CP0_WIRED |
| mtc0 zero, CP0_ENTRYHI |
| li k0, PM_DEFAULT_MASK |
| mtc0 k0, CP0_PAGEMASK |
| |
| li sp, BMIPS_WARM_RESTART_VEC |
| la k0, plat_wired_tlb_setup |
| jalr k0 |
| nop |
| |
| /* Restore general purpose registers */ |
| la t0, gp_regs |
| lw fp, 44(t0) |
| lw sp, 40(t0) |
| lw gp, 36(t0) |
| lw s7, 32(t0) |
| lw s6, 28(t0) |
| lw s5, 24(t0) |
| lw s4, 20(t0) |
| lw s3, 16(t0) |
| lw s2, 12(t0) |
| lw s1, 8(t0) |
| lw s0, 4(t0) |
| lw ra, 0(t0) |
| |
| /* Restore CP0 status */ |
| lw t1, 48(t0) |
| mtc0 t1, CP0_STATUS |
| |
| /* Return to caller */ |
| li v0, 0 |
| jr ra |
| nop |
| |
| END(brcm_pm_do_s3) |