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  */
22 LEAF(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 
52 1:	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 
84 s3_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 
138 END(brcm_pm_do_s3)
139