David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 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 | |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 11 | #define CP0_CVMCTL_REG $9, 7 |
| 12 | #define CP0_CVMMEMCTL_REG $11,7 |
| 13 | #define CP0_PRID_REG $15, 0 |
David Daney | 726da2f | 2015-01-15 16:11:15 +0300 | [diff] [blame] | 14 | #define CP0_DCACHE_ERR_REG $27, 1 |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 15 | #define CP0_PRID_OCTEON_PASS1 0x000d0000 |
| 16 | #define CP0_PRID_OCTEON_CN30XX 0x000d0200 |
| 17 | |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 18 | .macro kernel_entry_setup |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 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 |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 30 | dmfc0 v0, CP0_CVMMEMCTL_REG |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 31 | # Clear the lower 6 bits, the CVMSEG size |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 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 |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 36 | # Disable unaligned load/store support but leave HW fixup enabled |
David Daney | 0ec3151 | 2013-05-22 20:46:44 +0000 | [diff] [blame] | 37 | # Needed for octeon specific memcpy |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 38 | or v0, v0, 0x5001 |
| 39 | xor v0, v0, 0x1001 |
Chandrakala Chavva | 7716e65 | 2011-02-17 13:57:52 -0800 | [diff] [blame] | 40 | # First clear off CvmCtl[IPPCI] bit and move the performance |
| 41 | # counters interrupt to IRQ 6 |
David Daney | 726da2f | 2015-01-15 16:11:15 +0300 | [diff] [blame] | 42 | dli v1, ~(7 << 7) |
Chandrakala Chavva | 7716e65 | 2011-02-17 13:57:52 -0800 | [diff] [blame] | 43 | and v0, v0, v1 |
| 44 | ori v0, v0, (6 << 7) |
David Daney | 664d699 | 2015-01-15 16:11:10 +0300 | [diff] [blame] | 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 |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 67 | # Write the cavium control register |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 68 | dmtc0 v0, CP0_CVMCTL_REG |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 69 | sync |
| 70 | # Flush dcache after config change |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 71 | cache 9, 0($0) |
David Daney | 726da2f | 2015-01-15 16:11:15 +0300 | [diff] [blame] | 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. |
Chandrakala Chavva | ac6d9b3 | 2015-01-15 16:11:17 +0300 | [diff] [blame] | 83 | and t1, v0, 0xff00 |
| 84 | dli v0, 0x9500 |
| 85 | bge t1, v0, 1f # OCTEON III has no DCACHE_ERR_REG COP0 |
David Daney | 726da2f | 2015-01-15 16:11:15 +0300 | [diff] [blame] | 86 | dli v0, 0x27 |
| 87 | dmtc0 v0, CP0_DCACHE_ERR_REG |
| 88 | 1: |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 89 | # Get my core id |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 90 | rdhwr v0, $0 |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 91 | # Jump the master to kernel_entry |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 92 | bne a2, zero, octeon_main_processor |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 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 |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 103 | PTR_LA t0, octeon_processor_boot |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 104 | octeon_spin_wait_boot: |
| 105 | # Get the core id of the next to be booted |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 106 | LONG_L t1, (t0) |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 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 |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 111 | PTR_LA t0, octeon_processor_gp |
| 112 | LONG_L gp, (t0) |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 113 | # Get my SP from the global variable |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 114 | PTR_LA t0, octeon_processor_sp |
| 115 | LONG_L sp, (t0) |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 116 | # Set the SP global variable to zero so the master knows we've started |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 117 | LONG_S zero, (t0) |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 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 | */ |
Ralf Baechle | 7034228 | 2013-01-22 12:59:30 +0100 | [diff] [blame] | 146 | .macro smp_slave_setup |
David Daney | 5b3b168 | 2009-01-08 16:46:40 -0800 | [diff] [blame] | 147 | .endm |
| 148 | |
| 149 | #endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */ |