| /* |
| * 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 |
| # |
| |
| # This is the variable where the next core to boot os stored |
| PTR_LA t0, octeon_processor_boot |
| octeon_spin_wait_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 |
| |
| #endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */ |