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