blob: fe1775cdc881d3e7f6a8852651e4d74c80326ebb [file] [log] [blame]
Kumar Gala36d6b3f2008-01-17 16:48:33 -06001#include <config.h>
2#include <mpc85xx.h>
3#include <version.h>
4
5#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
6
7#include <ppc_asm.tmpl>
8#include <ppc_defs.h>
9
10#include <asm/cache.h>
11#include <asm/mmu.h>
12
13/* To boot secondary cpus, we need a place for them to start up.
14 * Normally, they start at 0xfffffffc, but that's usually the
15 * firmware, and we don't want to have to run the firmware again.
16 * Instead, the primary cpu will set the BPTR to point here to
17 * this page. We then set up the core, and head to
18 * start_secondary. Note that this means that the code below
19 * must never exceed 1023 instructions (the branch at the end
20 * would then be the 1024th).
21 */
22 .globl __secondary_start_page
23 .align 12
24__secondary_start_page:
25/* First do some preliminary setup */
26 lis r3, HID0_EMCP@h /* enable machine check */
27 ori r3,r3,HID0_TBEN@l /* enable Timebase */
28#ifdef CONFIG_PHYS_64BIT
29 ori r3,r3,HID0_ENMAS7@l /* enable MAS7 updates */
30#endif
31 mtspr SPRN_HID0,r3
32
33 li r3,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
34 mtspr SPRN_HID1,r3
35
36 /* Enable branch prediction */
37 li r3,0x201
38 mtspr SPRN_BUCSR,r3
39
40 /* Enable/invalidate the I-Cache */
41 mfspr r0,SPRN_L1CSR1
42 ori r0,r0,(L1CSR1_ICFI|L1CSR1_ICE)
43 mtspr SPRN_L1CSR1,r0
44 isync
45
46 /* Enable/invalidate the D-Cache */
47 mfspr r0,SPRN_L1CSR0
48 ori r0,r0,(L1CSR0_DCFI|L1CSR0_DCE)
49 msync
50 isync
51 mtspr SPRN_L1CSR0,r0
52 isync
53
54#define toreset(x) (x - __secondary_start_page + 0xfffff000)
55
56 /* get our PIR to figure out our table entry */
57 lis r3,toreset(__spin_table)@h
58 ori r3,r3,toreset(__spin_table)@l
59
60 /* r9 has the base address for the entry */
61 mfspr r0,SPRN_PIR
62 mr r4,r0
63 slwi r8,r4,4
64 slwi r9,r4,3
65 add r8,r8,r9
66 add r9,r3,r8
67
68#define EPAPR_MAGIC (0x65504150)
69#define ENTRY_ADDR 0
70#define ENTRY_PIR 4
71#define ENTRY_R3 8
72#define ENTRY_R4 12
73#define ENTRY_R6 16
74#define ENTRY_R7 20
75
76 /* setup the entry */
77 li r4,0
78 li r8,1
79 lis r6,EPAPR_MAGIC@h
80 ori r6,r6,EPAPR_MAGIC@l
81 stw r0,ENTRY_PIR(r9)
82 stw r8,ENTRY_ADDR(r9)
83 stw r4,ENTRY_R3(r9)
84 stw r4,ENTRY_R4(r9)
85 stw r6,ENTRY_R6(r9)
86 stw r4,ENTRY_R7(r9)
87
88 /* spin waiting for addr */
891: lwz r4,ENTRY_ADDR(r9)
90 andi. r11,r4,1
91 bne 1b
92
93 /* setup branch addr */
94 mtctr r4
95
96 /* mark the entry as released */
97 li r8,3
98 stw r8,ENTRY_ADDR(r9)
99
100 /* mask by ~64M to setup our tlb we will jump to */
101 rlwinm r8,r4,0,0,5
102
103 /* setup r3, r5, r6, r7 */
104 lwz r3,ENTRY_R3(r9)
105 lwz r4,ENTRY_R4(r9)
106 li r5,0
107 lwz r6,ENTRY_R6(r9)
108 lwz r7,ENTRY_R7(r9)
109
110 /* load up the pir */
111 lwz r0,ENTRY_PIR(r9)
112 mtspr SPRN_PIR,r0
113 mfspr r0,SPRN_PIR
114 stw r0,ENTRY_PIR(r9)
115
116/*
117 * Coming here, we know the cpu has one TLB mapping in TLB1[0]
118 * which maps 0xfffff000-0xffffffff one-to-one. We set up a
119 * second mapping that maps addr 1:1 for 64M, and then we jump to
120 * addr
121 */
122 lis r9,(MAS0_TLBSEL(1)|MAS0_ESEL(1))@h
123 mtspr SPRN_MAS0,r9
124 lis r9,(MAS1_VALID|MAS1_IPROT)@h
125 ori r9,r9,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l
126 mtspr SPRN_MAS1,r9
127 /* WIMGE = 0b00000 for now */
128 mtspr SPRN_MAS2,r8
129 ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR)
130 mtspr SPRN_MAS3,r8
131 tlbwe
132
133/* Now we have another mapping for this page, so we jump to that
134 * mapping
135 */
136 bctr
137
138 .align 3
139 .globl __spin_table
140__spin_table:
141 .space CONFIG_NR_CPUS*24
142
143 /* Fill in the empty space. The actual reset vector is
144 * the last word of the page */
145__secondary_start_code_end:
146 .space 4092 - (__secondary_start_code_end - __secondary_start_page)
147__secondary_reset_vector:
148 b __secondary_start_page