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 | |