diff options
Diffstat (limited to 'arch/mips/cavium-octeon/executive/cvmx-boot-vector.c')
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-boot-vector.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/arch/mips/cavium-octeon/executive/cvmx-boot-vector.c b/arch/mips/cavium-octeon/executive/cvmx-boot-vector.c new file mode 100644 index 000000000..b7019d218 --- /dev/null +++ b/arch/mips/cavium-octeon/executive/cvmx-boot-vector.c @@ -0,0 +1,167 @@ +/* + * 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) 2004-2017 Cavium, Inc. + */ + + +/* + We install this program at the bootvector: +------------------------------------ + .set noreorder + .set nomacro + .set noat +reset_vector: + dmtc0 $k0, $31, 0 # Save $k0 to DESAVE + dmtc0 $k1, $31, 3 # Save $k1 to KScratch2 + + mfc0 $k0, $12, 0 # Status + mfc0 $k1, $15, 1 # Ebase + + ori $k0, 0x84 # Enable 64-bit addressing, set + # ERL (should already be set) + andi $k1, 0x3ff # mask out core ID + + mtc0 $k0, $12, 0 # Status + sll $k1, 5 + + lui $k0, 0xbfc0 + cache 17, 0($0) # Core-14345, clear L1 Dcache virtual + # tags if the core hit an NMI + + ld $k0, 0x78($k0) # k0 <- (bfc00078) pointer to the reset vector + synci 0($0) # Invalidate ICache to get coherent + # view of target code. + + daddu $k0, $k0, $k1 + nop + + ld $k0, 0($k0) # k0 <- core specific target address + dmfc0 $k1, $31, 3 # Restore $k1 from KScratch2 + + beqz $k0, wait_loop # Spin in wait loop + nop + + jr $k0 + nop + + nop # NOPs needed here to fill delay slots + nop # on endian reversal of previous instructions + +wait_loop: + wait + nop + + b wait_loop + nop + + nop + nop +------------------------------------ + +0000000000000000 <reset_vector>: + 0: 40baf800 dmtc0 k0,c0_desave + 4: 40bbf803 dmtc0 k1,c0_kscratch2 + + 8: 401a6000 mfc0 k0,c0_status + c: 401b7801 mfc0 k1,c0_ebase + + 10: 375a0084 ori k0,k0,0x84 + 14: 337b03ff andi k1,k1,0x3ff + + 18: 409a6000 mtc0 k0,c0_status + 1c: 001bd940 sll k1,k1,0x5 + + 20: 3c1abfc0 lui k0,0xbfc0 + 24: bc110000 cache 0x11,0(zero) + + 28: df5a0078 ld k0,120(k0) + 2c: 041f0000 synci 0(zero) + + 30: 035bd02d daddu k0,k0,k1 + 34: 00000000 nop + + 38: df5a0000 ld k0,0(k0) + 3c: 403bf803 dmfc0 k1,c0_kscratch2 + + 40: 13400005 beqz k0,58 <wait_loop> + 44: 00000000 nop + + 48: 03400008 jr k0 + 4c: 00000000 nop + + 50: 00000000 nop + 54: 00000000 nop + +0000000000000058 <wait_loop>: + 58: 42000020 wait + 5c: 00000000 nop + + 60: 1000fffd b 58 <wait_loop> + 64: 00000000 nop + + 68: 00000000 nop + 6c: 00000000 nop + + */ + +#include <asm/octeon/cvmx-boot-vector.h> + +static unsigned long long _cvmx_bootvector_data[16] = { + 0x40baf80040bbf803ull, /* patch low order 8-bits if no KScratch*/ + 0x401a6000401b7801ull, + 0x375a0084337b03ffull, + 0x409a6000001bd940ull, + 0x3c1abfc0bc110000ull, + 0xdf5a0078041f0000ull, + 0x035bd02d00000000ull, + 0xdf5a0000403bf803ull, /* patch low order 8-bits if no KScratch*/ + 0x1340000500000000ull, + 0x0340000800000000ull, + 0x0000000000000000ull, + 0x4200002000000000ull, + 0x1000fffd00000000ull, + 0x0000000000000000ull, + OCTEON_BOOT_MOVEABLE_MAGIC1, + 0 /* To be filled in with address of vector block*/ +}; + +/* 2^10 CPUs */ +#define VECTOR_TABLE_SIZE (1024 * sizeof(struct cvmx_boot_vector_element)) + +static void cvmx_boot_vector_init(void *mem) +{ + uint64_t kseg0_mem; + int i; + + memset(mem, 0, VECTOR_TABLE_SIZE); + kseg0_mem = cvmx_ptr_to_phys(mem) | 0x8000000000000000ull; + + for (i = 0; i < 15; i++) { + uint64_t v = _cvmx_bootvector_data[i]; + + if (OCTEON_IS_OCTEON1PLUS() && (i == 0 || i == 7)) + v &= 0xffffffff00000000ull; /* KScratch not availble. */ + cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8); + cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, v); + } + cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, 15 * 8); + cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, kseg0_mem); + cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000); +} + +/** + * Get a pointer to the per-core table of reset vector pointers + * + */ +struct cvmx_boot_vector_element *cvmx_boot_vector_get(void) +{ + struct cvmx_boot_vector_element *ret; + + ret = cvmx_bootmem_alloc_named_range_once(VECTOR_TABLE_SIZE, 0, + (1ull << 32) - 1, 8, "__boot_vector1__", cvmx_boot_vector_init); + return ret; +} +EXPORT_SYMBOL(cvmx_boot_vector_get); |