mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
4.0 KiB
168 lines
4.0 KiB
/* |
|
* 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 */
|
|
|