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 | |
7716e654 CC |
40 | # First clear off CvmCtl[IPPCI] bit and move the performance |
41 | # counters interrupt to IRQ 6 | |
726da2f8 | 42 | dli v1, ~(7 << 7) |
7716e654 CC |
43 | and v0, v0, v1 |
44 | ori v0, v0, (6 << 7) | |
664d699a DD |
45 | |
46 | mfc0 v1, CP0_PRID_REG | |
47 | and t1, v1, 0xfff8 | |
48 | xor t1, t1, 0x9000 # 63-P1 | |
49 | beqz t1, 4f | |
50 | and t1, v1, 0xfff8 | |
51 | xor t1, t1, 0x9008 # 63-P2 | |
52 | beqz t1, 4f | |
53 | and t1, v1, 0xfff8 | |
54 | xor t1, t1, 0x9100 # 68-P1 | |
55 | beqz t1, 4f | |
56 | and t1, v1, 0xff00 | |
57 | xor t1, t1, 0x9200 # 66-PX | |
58 | bnez t1, 5f # Skip WAR for others. | |
59 | and t1, v1, 0x00ff | |
60 | slti t1, t1, 2 # 66-P1.2 and later good. | |
61 | beqz t1, 5f | |
62 | ||
63 | 4: # core-16057 work around | |
64 | or v0, v0, 0x2000 # Set IPREF bit. | |
65 | ||
66 | 5: # No core-16057 work around | |
5b3b1688 | 67 | # Write the cavium control register |
70342287 | 68 | dmtc0 v0, CP0_CVMCTL_REG |
5b3b1688 DD |
69 | sync |
70 | # Flush dcache after config change | |
70342287 | 71 | cache 9, 0($0) |
726da2f8 DD |
72 | # Zero all of CVMSEG to make sure parity is correct |
73 | dli v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE | |
74 | dsll v0, 7 | |
75 | beqz v0, 2f | |
76 | 1: dsubu v0, 8 | |
77 | sd $0, -32768(v0) | |
78 | bnez v0, 1b | |
79 | 2: | |
80 | mfc0 v0, CP0_PRID_REG | |
81 | bbit0 v0, 15, 1f | |
82 | # OCTEON II or better have bit 15 set. Clear the error bits. | |
ac6d9b3a CC |
83 | and t1, v0, 0xff00 |
84 | dli v0, 0x9500 | |
85 | bge t1, v0, 1f # OCTEON III has no DCACHE_ERR_REG COP0 | |
726da2f8 DD |
86 | dli v0, 0x27 |
87 | dmtc0 v0, CP0_DCACHE_ERR_REG | |
88 | 1: | |
5b3b1688 | 89 | # Get my core id |
70342287 | 90 | rdhwr v0, $0 |
5b3b1688 | 91 | # Jump the master to kernel_entry |
70342287 | 92 | bne a2, zero, octeon_main_processor |
5b3b1688 DD |
93 | nop |
94 | ||
95 | #ifdef CONFIG_SMP | |
96 | ||
97 | # | |
98 | # All cores other than the master need to wait here for SMP bootstrap | |
99 | # to begin | |
100 | # | |
101 | ||
102 | # This is the variable where the next core to boot os stored | |
70342287 | 103 | PTR_LA t0, octeon_processor_boot |
5b3b1688 DD |
104 | octeon_spin_wait_boot: |
105 | # Get the core id of the next to be booted | |
70342287 | 106 | LONG_L t1, (t0) |
5b3b1688 DD |
107 | # Keep looping if it isn't me |
108 | bne t1, v0, octeon_spin_wait_boot | |
109 | nop | |
110 | # Get my GP from the global variable | |
70342287 RB |
111 | PTR_LA t0, octeon_processor_gp |
112 | LONG_L gp, (t0) | |
5b3b1688 | 113 | # Get my SP from the global variable |
70342287 RB |
114 | PTR_LA t0, octeon_processor_sp |
115 | LONG_L sp, (t0) | |
5b3b1688 | 116 | # Set the SP global variable to zero so the master knows we've started |
70342287 | 117 | LONG_S zero, (t0) |
5b3b1688 DD |
118 | #ifdef __OCTEON__ |
119 | syncw | |
120 | syncw | |
121 | #else | |
122 | sync | |
123 | #endif | |
124 | # Jump to the normal Linux SMP entry point | |
125 | j smp_bootstrap | |
126 | nop | |
127 | #else /* CONFIG_SMP */ | |
128 | ||
129 | # | |
130 | # Someone tried to boot SMP with a non SMP kernel. All extra cores | |
131 | # will halt here. | |
132 | # | |
133 | octeon_wait_forever: | |
134 | wait | |
135 | b octeon_wait_forever | |
136 | nop | |
137 | ||
138 | #endif /* CONFIG_SMP */ | |
139 | octeon_main_processor: | |
140 | .set pop | |
141 | .endm | |
142 | ||
143 | /* | |
144 | * Do SMP slave processor setup necessary before we can savely execute C code. | |
145 | */ | |
70342287 | 146 | .macro smp_slave_setup |
5b3b1688 DD |
147 | .endm |
148 | ||
149 | #endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */ |