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/stackframe.h>
10
11#include "pm.h"
12
13	.text
14	.set	noreorder
15	.align	5
16
17/*
18 * a0: u32 params array
19 */
20LEAF(brcm_pm_do_s2)
21
22	subu	sp, 64
23	sw	ra, 0(sp)
24	sw	s0, 4(sp)
25	sw	s1, 8(sp)
26	sw	s2, 12(sp)
27	sw	s3, 16(sp)
28	sw	s4, 20(sp)
29	sw	s5, 24(sp)
30	sw	s6, 28(sp)
31	sw	s7, 32(sp)
32
33	/*
34	 * Dereference the params array
35	 * s0: AON_CTRL base register
36	 * s1: DDR_PHY base register
37	 * s2: TIMERS base register
38	 * s3: I-Cache line size
39	 * s4: Restart vector address
40	 * s5: Restart vector size
41	 */
42	move	t0, a0
43
44	lw	s0, 0(t0)
45	lw	s1, 4(t0)
46	lw	s2, 8(t0)
47	lw	s3, 12(t0)
48	lw	s4, 16(t0)
49	lw	s5, 20(t0)
50
51	/* Lock this asm section into the I-cache */
52	addiu	t1, s3, -1
53	not	t1
54
55	la	t0, brcm_pm_do_s2
56	and	t0, t1
57
58	la	t2, asm_end
59	and	t2, t1
60
611:	cache	0x1c, 0(t0)
62	bne	t0, t2, 1b
63	addu	t0, s3
64
65	/* Lock the interrupt vector into the I-cache */
66	move	t0, zero
67
682:	move	t1, s4
69	cache 	0x1c, 0(t1)
70	addu	t1, s3
71	addu	t0, s3
72	ble	t0, s5, 2b
73	nop
74
75	sync
76
77	/* Power down request */
78	li	t0, PM_S2_COMMAND
79	sw	zero, AON_CTRL_PM_CTRL(s0)
80	lw	zero, AON_CTRL_PM_CTRL(s0)
81	sw	t0, AON_CTRL_PM_CTRL(s0)
82	lw	t0, AON_CTRL_PM_CTRL(s0)
83
84	/* Enable CP0 interrupt 2 and wait for interrupt */
85	mfc0	t0, CP0_STATUS
86	/* Save cp0 sr for restoring later */
87	move	s6, t0
88
89	li	t1, ~(ST0_IM | ST0_IE)
90	and	t0, t1
91	ori	t0, STATUSF_IP2
92	mtc0	t0, CP0_STATUS
93	nop
94	nop
95	nop
96	ori	t0, ST0_IE
97	mtc0	t0, CP0_STATUS
98
99	/* Wait for interrupt */
100	wait
101	nop
102
103	/* Wait for memc0 */
1041:	lw	t0, DDR40_PHY_CONTROL_REGS_0_PLL_STATUS(s1)
105	andi	t0, 1
106	beqz	t0, 1b
107	nop
108
109	/* 1ms delay needed for stable recovery */
110	/* Use TIMER1 to count 1 ms */
111	li	t0, RESET_TIMER
112	sw	t0, TIMER_TIMER1_CTRL(s2)
113	lw	t0, TIMER_TIMER1_CTRL(s2)
114
115	li	t0, START_TIMER
116	sw	t0, TIMER_TIMER1_CTRL(s2)
117	lw	t0, TIMER_TIMER1_CTRL(s2)
118
119	/* Prepare delay */
120	li	t0, TIMER_MASK
121	lw	t1, TIMER_TIMER1_STAT(s2)
122	and	t1, t0
123	/* 1ms delay */
124	addi	t1, 27000
125
126	/* Wait for the timer value to exceed t1 */
1271:	lw	t0, TIMER_TIMER1_STAT(s2)
128	sgtu	t2, t1, t0
129	bnez	t2, 1b
130	nop
131
132	/* Power back up */
133	li	t1, 1
134	sw	t1, AON_CTRL_HOST_MISC_CMDS(s0)
135	lw	t1, AON_CTRL_HOST_MISC_CMDS(s0)
136
137	sw	zero, AON_CTRL_PM_CTRL(s0)
138	lw	zero, AON_CTRL_PM_CTRL(s0)
139
140	/* Unlock I-cache */
141	addiu	t1, s3, -1
142	not	t1
143
144	la	t0, brcm_pm_do_s2
145	and 	t0, t1
146
147	la	t2, asm_end
148	and	t2, t1
149
1501:	cache	0x00, 0(t0)
151	bne	t0, t2, 1b
152	addu	t0, s3
153
154	/* Unlock interrupt vector */
155	move	t0, zero
156
1572:	move	t1, s4
158	cache 	0x00, 0(t1)
159	addu	t1, s3
160	addu	t0, s3
161	ble	t0, s5, 2b
162	nop
163
164	/* Restore cp0 sr */
165	sync
166	nop
167	mtc0	s6, CP0_STATUS
168	nop
169
170	/* Set return value to success */
171	li	v0, 0
172
173	/* Return to caller */
174	lw	s7, 32(sp)
175	lw	s6, 28(sp)
176	lw	s5, 24(sp)
177	lw	s4, 20(sp)
178	lw	s3, 16(sp)
179	lw	s2, 12(sp)
180	lw	s1, 8(sp)
181	lw	s0, 4(sp)
182	lw	ra, 0(sp)
183	addiu	sp, 64
184
185	jr ra
186	nop
187END(brcm_pm_do_s2)
188
189	.globl asm_end
190asm_end:
191	nop
192
193