root/drivers/soc/bcm/brcmstb/pm/s3-mips.S
/* 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)