]>
Commit | Line | Data |
---|---|---|
0e870980 | 1 | /* |
69bcf5bc | 2 | * Copyright 2008-2010 Freescale Semiconductor, Inc. |
0e870980 PA |
3 | * Kumar Gala <kumar.gala@freescale.com> |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
ec2b74ff KG |
24 | #include <config.h> |
25 | #include <mpc85xx.h> | |
26 | #include <version.h> | |
27 | ||
28 | #define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ | |
29 | ||
30 | #include <ppc_asm.tmpl> | |
31 | #include <ppc_defs.h> | |
32 | ||
33 | #include <asm/cache.h> | |
34 | #include <asm/mmu.h> | |
35 | ||
36 | /* To boot secondary cpus, we need a place for them to start up. | |
37 | * Normally, they start at 0xfffffffc, but that's usually the | |
38 | * firmware, and we don't want to have to run the firmware again. | |
39 | * Instead, the primary cpu will set the BPTR to point here to | |
40 | * this page. We then set up the core, and head to | |
41 | * start_secondary. Note that this means that the code below | |
42 | * must never exceed 1023 instructions (the branch at the end | |
43 | * would then be the 1024th). | |
44 | */ | |
45 | .globl __secondary_start_page | |
46 | .align 12 | |
47 | __secondary_start_page: | |
48 | /* First do some preliminary setup */ | |
49 | lis r3, HID0_EMCP@h /* enable machine check */ | |
0f060c3b | 50 | #ifndef CONFIG_E500MC |
ec2b74ff | 51 | ori r3,r3,HID0_TBEN@l /* enable Timebase */ |
0f060c3b | 52 | #endif |
ec2b74ff KG |
53 | #ifdef CONFIG_PHYS_64BIT |
54 | ori r3,r3,HID0_ENMAS7@l /* enable MAS7 updates */ | |
55 | #endif | |
56 | mtspr SPRN_HID0,r3 | |
57 | ||
0f060c3b | 58 | #ifndef CONFIG_E500MC |
ec2b74ff | 59 | li r3,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */ |
ff8473e9 SG |
60 | mfspr r0,PVR |
61 | andi. r0,r0,0xff | |
62 | cmpwi r0,0x50@l /* if we are rev 5.0 or greater set MBDD */ | |
63 | blt 1f | |
64 | /* Set MBDD bit also */ | |
65 | ori r3, r3, HID1_MBDD@l | |
66 | 1: | |
ec2b74ff | 67 | mtspr SPRN_HID1,r3 |
0f060c3b | 68 | #endif |
ec2b74ff KG |
69 | |
70 | /* Enable branch prediction */ | |
69bcf5bc KG |
71 | lis r3,BUCSR_ENABLE@h |
72 | ori r3,r3,BUCSR_ENABLE@l | |
ec2b74ff KG |
73 | mtspr SPRN_BUCSR,r3 |
74 | ||
e0ff3d35 KG |
75 | /* Ensure TB is 0 */ |
76 | li r3,0 | |
77 | mttbl r3 | |
78 | mttbu r3 | |
79 | ||
ec2b74ff | 80 | /* Enable/invalidate the I-Cache */ |
33f57bd5 KG |
81 | lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h |
82 | ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l | |
83 | mtspr SPRN_L1CSR1,r2 | |
84 | 1: | |
85 | mfspr r3,SPRN_L1CSR1 | |
86 | and. r1,r3,r2 | |
87 | bne 1b | |
88 | ||
89 | lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h | |
90 | ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l | |
91 | mtspr SPRN_L1CSR1,r3 | |
ec2b74ff | 92 | isync |
33f57bd5 KG |
93 | 2: |
94 | mfspr r3,SPRN_L1CSR1 | |
95 | andi. r1,r3,L1CSR1_ICE@l | |
96 | beq 2b | |
ec2b74ff KG |
97 | |
98 | /* Enable/invalidate the D-Cache */ | |
33f57bd5 KG |
99 | lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h |
100 | ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l | |
101 | mtspr SPRN_L1CSR0,r2 | |
102 | 1: | |
103 | mfspr r3,SPRN_L1CSR0 | |
104 | and. r1,r3,r2 | |
105 | bne 1b | |
106 | ||
107 | lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h | |
108 | ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l | |
109 | mtspr SPRN_L1CSR0,r3 | |
ec2b74ff | 110 | isync |
33f57bd5 KG |
111 | 2: |
112 | mfspr r3,SPRN_L1CSR0 | |
113 | andi. r1,r3,L1CSR0_DCE@l | |
114 | beq 2b | |
ec2b74ff KG |
115 | |
116 | #define toreset(x) (x - __secondary_start_page + 0xfffff000) | |
117 | ||
118 | /* get our PIR to figure out our table entry */ | |
119 | lis r3,toreset(__spin_table)@h | |
120 | ori r3,r3,toreset(__spin_table)@l | |
121 | ||
79679d80 | 122 | /* r10 has the base address for the entry */ |
ec2b74ff | 123 | mfspr r0,SPRN_PIR |
0f060c3b KG |
124 | #ifdef CONFIG_E500MC |
125 | rlwinm r4,r0,27,27,31 | |
126 | #else | |
ec2b74ff | 127 | mr r4,r0 |
0f060c3b | 128 | #endif |
79679d80 KG |
129 | slwi r8,r4,5 |
130 | add r10,r3,r8 | |
131 | ||
82fd1f8d KG |
132 | #if defined(CONFIG_E500MC) && defined(CONFIG_SYS_CACHE_STASHING) |
133 | /* set stash id to (coreID) * 2 + 32 + L1 CT (0) */ | |
134 | slwi r8,r4,1 | |
135 | addi r8,r8,32 | |
136 | mtspr L1CSR2,r8 | |
137 | #endif | |
138 | ||
1b3e4044 KG |
139 | #ifdef CONFIG_BACKSIDE_L2_CACHE |
140 | /* Enable/invalidate the L2 cache */ | |
141 | msync | |
ff882295 DL |
142 | lis r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@h |
143 | ori r2,r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@l | |
144 | mtspr SPRN_L2CSR0,r2 | |
1b3e4044 KG |
145 | 1: |
146 | mfspr r3,SPRN_L2CSR0 | |
ff882295 | 147 | and. r1,r3,r2 |
1b3e4044 KG |
148 | bne 1b |
149 | ||
82fd1f8d KG |
150 | #ifdef CONFIG_SYS_CACHE_STASHING |
151 | /* set stash id to (coreID) * 2 + 32 + L2 (1) */ | |
152 | addi r3,r8,1 | |
153 | mtspr SPRN_L2CSR1,r3 | |
154 | #endif | |
155 | ||
1b3e4044 KG |
156 | lis r3,CONFIG_SYS_INIT_L2CSR0@h |
157 | ori r3,r3,CONFIG_SYS_INIT_L2CSR0@l | |
158 | mtspr SPRN_L2CSR0,r3 | |
159 | isync | |
ff882295 DL |
160 | 2: |
161 | mfspr r3,SPRN_L2CSR0 | |
162 | andis. r1,r3,L2CSR0_L2E@h | |
163 | beq 2b | |
1b3e4044 KG |
164 | #endif |
165 | ||
79679d80 KG |
166 | #define EPAPR_MAGIC (0x45504150) |
167 | #define ENTRY_ADDR_UPPER 0 | |
168 | #define ENTRY_ADDR_LOWER 4 | |
169 | #define ENTRY_R3_UPPER 8 | |
170 | #define ENTRY_R3_LOWER 12 | |
171 | #define ENTRY_RESV 16 | |
172 | #define ENTRY_PIR 20 | |
173 | #define ENTRY_R6_UPPER 24 | |
174 | #define ENTRY_R6_LOWER 28 | |
175 | #define ENTRY_SIZE 32 | |
ec2b74ff KG |
176 | |
177 | /* setup the entry */ | |
79679d80 | 178 | li r3,0 |
ec2b74ff | 179 | li r8,1 |
79679d80 KG |
180 | stw r0,ENTRY_PIR(r10) |
181 | stw r3,ENTRY_ADDR_UPPER(r10) | |
182 | stw r8,ENTRY_ADDR_LOWER(r10) | |
183 | stw r3,ENTRY_R3_UPPER(r10) | |
184 | stw r4,ENTRY_R3_LOWER(r10) | |
185 | stw r3,ENTRY_R6_UPPER(r10) | |
186 | stw r3,ENTRY_R6_LOWER(r10) | |
187 | ||
5ccd29c3 PT |
188 | /* load r13 with the address of the 'bootpg' in SDRAM */ |
189 | lis r13,toreset(__bootpg_addr)@h | |
190 | ori r13,r13,toreset(__bootpg_addr)@l | |
191 | lwz r13,0(r13) | |
192 | ||
79679d80 KG |
193 | /* setup mapping for AS = 1, and jump there */ |
194 | lis r11,(MAS0_TLBSEL(1)|MAS0_ESEL(1))@h | |
195 | mtspr SPRN_MAS0,r11 | |
196 | lis r11,(MAS1_VALID|MAS1_IPROT)@h | |
197 | ori r11,r11,(MAS1_TS|MAS1_TSIZE(BOOKE_PAGESZ_4K))@l | |
198 | mtspr SPRN_MAS1,r11 | |
abc76eb6 KG |
199 | oris r11,r13,(MAS2_I|MAS2_G)@h |
200 | ori r11,r13,(MAS2_I|MAS2_G)@l | |
79679d80 | 201 | mtspr SPRN_MAS2,r11 |
5ccd29c3 PT |
202 | oris r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@h |
203 | ori r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@l | |
79679d80 KG |
204 | mtspr SPRN_MAS3,r11 |
205 | tlbwe | |
206 | ||
207 | bl 1f | |
208 | 1: mflr r11 | |
5ccd29c3 PT |
209 | /* |
210 | * OR in 0xfff to create a mask of the bootpg SDRAM address. We use | |
211 | * this mask to fixup the cpu spin table and the address that we want | |
212 | * to jump to, eg change them from 0xfffffxxx to 0x7ffffxxx if the | |
213 | * bootpg is at 0x7ffff000 in SDRAM. | |
214 | */ | |
215 | ori r13,r13,0xfff | |
216 | and r11, r11, r13 | |
217 | and r10, r10, r13 | |
218 | ||
219 | addi r11,r11,(2f-1b) | |
79679d80 KG |
220 | mfmsr r13 |
221 | ori r12,r13,MSR_IS|MSR_DS@l | |
222 | ||
223 | mtspr SPRN_SRR0,r11 | |
224 | mtspr SPRN_SRR1,r12 | |
225 | rfi | |
ec2b74ff KG |
226 | |
227 | /* spin waiting for addr */ | |
79679d80 KG |
228 | 2: |
229 | lwz r4,ENTRY_ADDR_LOWER(r10) | |
ec2b74ff | 230 | andi. r11,r4,1 |
79679d80 | 231 | bne 2b |
cf6cc014 | 232 | isync |
79679d80 | 233 | |
26f4cdba KG |
234 | /* setup IVORs to match fixed offsets */ |
235 | #include "fixed_ivor.S" | |
236 | ||
79679d80 KG |
237 | /* get the upper bits of the addr */ |
238 | lwz r11,ENTRY_ADDR_UPPER(r10) | |
ec2b74ff KG |
239 | |
240 | /* setup branch addr */ | |
79679d80 | 241 | mtspr SPRN_SRR0,r4 |
ec2b74ff KG |
242 | |
243 | /* mark the entry as released */ | |
244 | li r8,3 | |
79679d80 | 245 | stw r8,ENTRY_ADDR_LOWER(r10) |
ec2b74ff KG |
246 | |
247 | /* mask by ~64M to setup our tlb we will jump to */ | |
79679d80 | 248 | rlwinm r12,r4,0,0,5 |
ec2b74ff | 249 | |
79679d80 KG |
250 | /* setup r3, r4, r5, r6, r7, r8, r9 */ |
251 | lwz r3,ENTRY_R3_LOWER(r10) | |
252 | li r4,0 | |
ec2b74ff | 253 | li r5,0 |
79679d80 KG |
254 | lwz r6,ENTRY_R6_LOWER(r10) |
255 | lis r7,(64*1024*1024)@h | |
256 | li r8,0 | |
257 | li r9,0 | |
ec2b74ff KG |
258 | |
259 | /* load up the pir */ | |
79679d80 | 260 | lwz r0,ENTRY_PIR(r10) |
ec2b74ff KG |
261 | mtspr SPRN_PIR,r0 |
262 | mfspr r0,SPRN_PIR | |
79679d80 | 263 | stw r0,ENTRY_PIR(r10) |
ec2b74ff | 264 | |
181a3650 | 265 | mtspr IVPR,r12 |
ec2b74ff KG |
266 | /* |
267 | * Coming here, we know the cpu has one TLB mapping in TLB1[0] | |
268 | * which maps 0xfffff000-0xffffffff one-to-one. We set up a | |
269 | * second mapping that maps addr 1:1 for 64M, and then we jump to | |
270 | * addr | |
271 | */ | |
79679d80 KG |
272 | lis r10,(MAS0_TLBSEL(1)|MAS0_ESEL(0))@h |
273 | mtspr SPRN_MAS0,r10 | |
274 | lis r10,(MAS1_VALID|MAS1_IPROT)@h | |
275 | ori r10,r10,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l | |
276 | mtspr SPRN_MAS1,r10 | |
ec2b74ff | 277 | /* WIMGE = 0b00000 for now */ |
79679d80 KG |
278 | mtspr SPRN_MAS2,r12 |
279 | ori r12,r12,(MAS3_SX|MAS3_SW|MAS3_SR) | |
280 | mtspr SPRN_MAS3,r12 | |
281 | #ifdef CONFIG_ENABLE_36BIT_PHYS | |
282 | mtspr SPRN_MAS7,r11 | |
283 | #endif | |
ec2b74ff KG |
284 | tlbwe |
285 | ||
286 | /* Now we have another mapping for this page, so we jump to that | |
287 | * mapping | |
288 | */ | |
79679d80 KG |
289 | mtspr SPRN_SRR1,r13 |
290 | rfi | |
ec2b74ff | 291 | |
5ccd29c3 PT |
292 | /* |
293 | * Allocate some space for the SDRAM address of the bootpg. | |
294 | * This variable has to be in the boot page so that it can | |
295 | * be accessed by secondary cores when they come out of reset. | |
296 | */ | |
297 | .globl __bootpg_addr | |
298 | __bootpg_addr: | |
299 | .long 0 | |
300 | ||
cf6cc014 | 301 | .align L1_CACHE_SHIFT |
ec2b74ff KG |
302 | .globl __spin_table |
303 | __spin_table: | |
0e870980 | 304 | .space CONFIG_MAX_CPUS*ENTRY_SIZE |
ec2b74ff KG |
305 | |
306 | /* Fill in the empty space. The actual reset vector is | |
307 | * the last word of the page */ | |
308 | __secondary_start_code_end: | |
309 | .space 4092 - (__secondary_start_code_end - __secondary_start_page) | |
310 | __secondary_reset_vector: | |
311 | b __secondary_start_page |