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