1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | * This file contains low level CPU setup functions. |
4 | * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) |
5 | */ |
6 | |
7 | #include <asm/processor.h> |
8 | #include <asm/page.h> |
9 | #include <asm/cputable.h> |
10 | #include <asm/ppc_asm.h> |
11 | #include <asm/asm-offsets.h> |
12 | #include <asm/cache.h> |
13 | |
14 | _GLOBAL(__cpu_preinit_ppc970) |
15 | /* Do nothing if not running in HV mode */ |
16 | mfmsr r0 |
17 | rldicl. r0,r0,4,63 |
18 | beqlr |
19 | |
20 | /* Make sure HID4:rm_ci is off before MMU is turned off, that large |
21 | * pages are enabled with HID4:61 and clear HID5:DCBZ_size and |
22 | * HID5:DCBZ32_ill |
23 | */ |
24 | li r0,0 |
25 | mfspr r3,SPRN_HID4 |
26 | rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */ |
27 | rldimi r3,r0,2,61 /* clear bit 61 (lg_pg_en) */ |
28 | sync |
29 | mtspr SPRN_HID4,r3 |
30 | isync |
31 | sync |
32 | mfspr r3,SPRN_HID5 |
33 | rldimi r3,r0,6,56 /* clear bits 56 & 57 (DCBZ*) */ |
34 | sync |
35 | mtspr SPRN_HID5,r3 |
36 | isync |
37 | sync |
38 | |
39 | /* Setup some basic HID1 features */ |
40 | mfspr r0,SPRN_HID1 |
41 | li r3,0x1200 /* enable i-fetch cacheability */ |
42 | sldi r3,r3,44 /* and prefetch */ |
43 | or r0,r0,r3 |
44 | mtspr SPRN_HID1,r0 |
45 | mtspr SPRN_HID1,r0 |
46 | isync |
47 | |
48 | /* Clear HIOR */ |
49 | li r0,0 |
50 | sync |
51 | mtspr SPRN_HIOR,0 /* Clear interrupt prefix */ |
52 | isync |
53 | blr |
54 | |
55 | /* Definitions for the table use to save CPU states */ |
56 | #define CS_HID0 0 |
57 | #define CS_HID1 8 |
58 | #define CS_HID4 16 |
59 | #define CS_HID5 24 |
60 | #define CS_SIZE 32 |
61 | |
62 | .data |
63 | .balign L1_CACHE_BYTES,0 |
64 | cpu_state_storage: |
65 | .space CS_SIZE |
66 | .balign L1_CACHE_BYTES,0 |
67 | .text |
68 | |
69 | |
70 | _GLOBAL(__setup_cpu_ppc970) |
71 | /* Do nothing if not running in HV mode */ |
72 | mfmsr r0 |
73 | rldicl. r0,r0,4,63 |
74 | beq no_hv_mode |
75 | |
76 | mfspr r0,SPRN_HID0 |
77 | li r11,5 /* clear DOZE and SLEEP */ |
78 | rldimi r0,r11,52,8 /* set NAP and DPM */ |
79 | li r11,0 |
80 | rldimi r0,r11,32,31 /* clear EN_ATTN */ |
81 | b load_hids /* Jump to shared code */ |
82 | |
83 | |
84 | _GLOBAL(__setup_cpu_ppc970MP) |
85 | /* Do nothing if not running in HV mode */ |
86 | mfmsr r0 |
87 | rldicl. r0,r0,4,63 |
88 | beq no_hv_mode |
89 | |
90 | mfspr r0,SPRN_HID0 |
91 | li r11,0x15 /* clear DOZE and SLEEP */ |
92 | rldimi r0,r11,52,6 /* set DEEPNAP, NAP and DPM */ |
93 | li r11,0 |
94 | rldimi r0,r11,32,31 /* clear EN_ATTN */ |
95 | |
96 | load_hids: |
97 | mtspr SPRN_HID0,r0 |
98 | mfspr r0,SPRN_HID0 |
99 | mfspr r0,SPRN_HID0 |
100 | mfspr r0,SPRN_HID0 |
101 | mfspr r0,SPRN_HID0 |
102 | mfspr r0,SPRN_HID0 |
103 | mfspr r0,SPRN_HID0 |
104 | sync |
105 | isync |
106 | |
107 | /* Try to set LPES = 01 in HID4 */ |
108 | mfspr r0,SPRN_HID4 |
109 | clrldi r0,r0,1 /* clear LPES0 */ |
110 | ori r0,r0,HID4_LPES1 /* set LPES1 */ |
111 | sync |
112 | mtspr SPRN_HID4,r0 |
113 | isync |
114 | |
115 | /* Save away cpu state */ |
116 | LOAD_REG_ADDR(r5,cpu_state_storage) |
117 | |
118 | /* Save HID0,1,4 and 5 */ |
119 | mfspr r3,SPRN_HID0 |
120 | std r3,CS_HID0(r5) |
121 | mfspr r3,SPRN_HID1 |
122 | std r3,CS_HID1(r5) |
123 | mfspr r4,SPRN_HID4 |
124 | std r4,CS_HID4(r5) |
125 | mfspr r3,SPRN_HID5 |
126 | std r3,CS_HID5(r5) |
127 | |
128 | /* See if we successfully set LPES1 to 1; if not we are in Apple mode */ |
129 | andi. r4,r4,HID4_LPES1 |
130 | bnelr |
131 | |
132 | no_hv_mode: |
133 | /* Disable CPU_FTR_HVMODE and exit, since we don't have HV mode */ |
134 | ld r5,CPU_SPEC_FEATURES(r4) |
135 | LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE) |
136 | andc r5,r5,r6 |
137 | std r5,CPU_SPEC_FEATURES(r4) |
138 | blr |
139 | |
140 | /* Called with no MMU context (typically MSR:IR/DR off) to |
141 | * restore CPU state as backed up by the previous |
142 | * function. This does not include cache setting |
143 | */ |
144 | _GLOBAL(__restore_cpu_ppc970) |
145 | /* Do nothing if not running in HV mode */ |
146 | mfmsr r0 |
147 | rldicl. r0,r0,4,63 |
148 | beqlr |
149 | |
150 | LOAD_REG_ADDR(r5,cpu_state_storage) |
151 | /* Before accessing memory, we make sure rm_ci is clear */ |
152 | li r0,0 |
153 | mfspr r3,SPRN_HID4 |
154 | rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */ |
155 | sync |
156 | mtspr SPRN_HID4,r3 |
157 | isync |
158 | sync |
159 | |
160 | /* Clear interrupt prefix */ |
161 | li r0,0 |
162 | sync |
163 | mtspr SPRN_HIOR,0 |
164 | isync |
165 | |
166 | /* Restore HID0 */ |
167 | ld r3,CS_HID0(r5) |
168 | sync |
169 | isync |
170 | mtspr SPRN_HID0,r3 |
171 | mfspr r3,SPRN_HID0 |
172 | mfspr r3,SPRN_HID0 |
173 | mfspr r3,SPRN_HID0 |
174 | mfspr r3,SPRN_HID0 |
175 | mfspr r3,SPRN_HID0 |
176 | mfspr r3,SPRN_HID0 |
177 | sync |
178 | isync |
179 | |
180 | /* Restore HID1 */ |
181 | ld r3,CS_HID1(r5) |
182 | sync |
183 | isync |
184 | mtspr SPRN_HID1,r3 |
185 | mtspr SPRN_HID1,r3 |
186 | sync |
187 | isync |
188 | |
189 | /* Restore HID4 */ |
190 | ld r3,CS_HID4(r5) |
191 | sync |
192 | isync |
193 | mtspr SPRN_HID4,r3 |
194 | sync |
195 | isync |
196 | |
197 | /* Restore HID5 */ |
198 | ld r3,CS_HID5(r5) |
199 | sync |
200 | isync |
201 | mtspr SPRN_HID5,r3 |
202 | sync |
203 | isync |
204 | blr |
205 | |
206 | |