Commit | Line | Data |
---|---|---|
5b3b1688 DD |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * Copyright (C) 2005-2008 Cavium Networks, Inc | |
7 | */ | |
8 | #ifndef __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H | |
9 | #define __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H | |
10 | ||
5b3b1688 DD |
11 | #define CP0_CVMCTL_REG $9, 7 |
12 | #define CP0_CVMMEMCTL_REG $11,7 | |
13 | #define CP0_PRID_REG $15, 0 | |
726da2f8 | 14 | #define CP0_DCACHE_ERR_REG $27, 1 |
5b3b1688 DD |
15 | #define CP0_PRID_OCTEON_PASS1 0x000d0000 |
16 | #define CP0_PRID_OCTEON_CN30XX 0x000d0200 | |
17 | ||
70342287 | 18 | .macro kernel_entry_setup |
5b3b1688 DD |
19 | # Registers set by bootloader: |
20 | # (only 32 bits set by bootloader, all addresses are physical | |
21 | # addresses, and need to have the appropriate memory region set | |
22 | # by the kernel | |
23 | # a0 = argc | |
24 | # a1 = argv (kseg0 compat addr) | |
25 | # a2 = 1 if init core, zero otherwise | |
26 | # a3 = address of boot descriptor block | |
27 | .set push | |
28 | .set arch=octeon | |
29 | # Read the cavium mem control register | |
70342287 | 30 | dmfc0 v0, CP0_CVMMEMCTL_REG |
5b3b1688 | 31 | # Clear the lower 6 bits, the CVMSEG size |
70342287 RB |
32 | dins v0, $0, 0, 6 |
33 | ori v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE | |
34 | dmtc0 v0, CP0_CVMMEMCTL_REG # Write the cavium mem control register | |
35 | dmfc0 v0, CP0_CVMCTL_REG # Read the cavium control register | |
5b3b1688 | 36 | # Disable unaligned load/store support but leave HW fixup enabled |
0ec31512 | 37 | # Needed for octeon specific memcpy |
5b3b1688 DD |
38 | or v0, v0, 0x5001 |
39 | xor v0, v0, 0x1001 | |
5b3b1688 DD |
40 | # Read the processor ID register |
41 | mfc0 v1, CP0_PRID_REG | |
42 | # Disable instruction prefetching (Octeon Pass1 errata) | |
43 | or v0, v0, 0x2000 | |
44 | # Skip reenable of prefetching for Octeon Pass1 | |
45 | beq v1, CP0_PRID_OCTEON_PASS1, skip | |
46 | nop | |
47 | # Reenable instruction prefetching, not on Pass1 | |
48 | xor v0, v0, 0x2000 | |
49 | # Strip off pass number off of processor id | |
50 | srl v1, 8 | |
51 | sll v1, 8 | |
52 | # CN30XX needs some extra stuff turned off for better performance | |
53 | bne v1, CP0_PRID_OCTEON_CN30XX, skip | |
54 | nop | |
55 | # CN30XX Use random Icache replacement | |
56 | or v0, v0, 0x400 | |
57 | # CN30XX Disable instruction prefetching | |
58 | or v0, v0, 0x2000 | |
59 | skip: | |
7716e654 CC |
60 | # First clear off CvmCtl[IPPCI] bit and move the performance |
61 | # counters interrupt to IRQ 6 | |
726da2f8 | 62 | dli v1, ~(7 << 7) |
7716e654 CC |
63 | and v0, v0, v1 |
64 | ori v0, v0, (6 << 7) | |
664d699a DD |
65 | |
66 | mfc0 v1, CP0_PRID_REG | |
67 | and t1, v1, 0xfff8 | |
68 | xor t1, t1, 0x9000 # 63-P1 | |
69 | beqz t1, 4f | |
70 | and t1, v1, 0xfff8 | |
71 | xor t1, t1, 0x9008 # 63-P2 | |
72 | beqz t1, 4f | |
73 | and t1, v1, 0xfff8 | |
74 | xor t1, t1, 0x9100 # 68-P1 | |
75 | beqz t1, 4f | |
76 | and t1, v1, 0xff00 | |
77 | xor t1, t1, 0x9200 # 66-PX | |
78 | bnez t1, 5f # Skip WAR for others. | |
79 | and t1, v1, 0x00ff | |
80 | slti t1, t1, 2 # 66-P1.2 and later good. | |
81 | beqz t1, 5f | |
82 | ||
83 | 4: # core-16057 work around | |
84 | or v0, v0, 0x2000 # Set IPREF bit. | |
85 | ||
86 | 5: # No core-16057 work around | |
5b3b1688 | 87 | # Write the cavium control register |
70342287 | 88 | dmtc0 v0, CP0_CVMCTL_REG |
5b3b1688 DD |
89 | sync |
90 | # Flush dcache after config change | |
70342287 | 91 | cache 9, 0($0) |
726da2f8 DD |
92 | # Zero all of CVMSEG to make sure parity is correct |
93 | dli v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE | |
94 | dsll v0, 7 | |
95 | beqz v0, 2f | |
96 | 1: dsubu v0, 8 | |
97 | sd $0, -32768(v0) | |
98 | bnez v0, 1b | |
99 | 2: | |
100 | mfc0 v0, CP0_PRID_REG | |
101 | bbit0 v0, 15, 1f | |
102 | # OCTEON II or better have bit 15 set. Clear the error bits. | |
103 | dli v0, 0x27 | |
104 | dmtc0 v0, CP0_DCACHE_ERR_REG | |
105 | 1: | |
5b3b1688 | 106 | # Get my core id |
70342287 | 107 | rdhwr v0, $0 |
5b3b1688 | 108 | # Jump the master to kernel_entry |
70342287 | 109 | bne a2, zero, octeon_main_processor |
5b3b1688 DD |
110 | nop |
111 | ||
112 | #ifdef CONFIG_SMP | |
113 | ||
114 | # | |
115 | # All cores other than the master need to wait here for SMP bootstrap | |
116 | # to begin | |
117 | # | |
118 | ||
119 | # This is the variable where the next core to boot os stored | |
70342287 | 120 | PTR_LA t0, octeon_processor_boot |
5b3b1688 DD |
121 | octeon_spin_wait_boot: |
122 | # Get the core id of the next to be booted | |
70342287 | 123 | LONG_L t1, (t0) |
5b3b1688 DD |
124 | # Keep looping if it isn't me |
125 | bne t1, v0, octeon_spin_wait_boot | |
126 | nop | |
127 | # Get my GP from the global variable | |
70342287 RB |
128 | PTR_LA t0, octeon_processor_gp |
129 | LONG_L gp, (t0) | |
5b3b1688 | 130 | # Get my SP from the global variable |
70342287 RB |
131 | PTR_LA t0, octeon_processor_sp |
132 | LONG_L sp, (t0) | |
5b3b1688 | 133 | # Set the SP global variable to zero so the master knows we've started |
70342287 | 134 | LONG_S zero, (t0) |
5b3b1688 DD |
135 | #ifdef __OCTEON__ |
136 | syncw | |
137 | syncw | |
138 | #else | |
139 | sync | |
140 | #endif | |
141 | # Jump to the normal Linux SMP entry point | |
142 | j smp_bootstrap | |
143 | nop | |
144 | #else /* CONFIG_SMP */ | |
145 | ||
146 | # | |
147 | # Someone tried to boot SMP with a non SMP kernel. All extra cores | |
148 | # will halt here. | |
149 | # | |
150 | octeon_wait_forever: | |
151 | wait | |
152 | b octeon_wait_forever | |
153 | nop | |
154 | ||
155 | #endif /* CONFIG_SMP */ | |
156 | octeon_main_processor: | |
157 | .set pop | |
158 | .endm | |
159 | ||
160 | /* | |
161 | * Do SMP slave processor setup necessary before we can savely execute C code. | |
162 | */ | |
70342287 | 163 | .macro smp_slave_setup |
5b3b1688 DD |
164 | .endm |
165 | ||
166 | #endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */ |