Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2004-2017 Cavium, Inc.
0007  */
0008 
0009 
0010 /*
0011   We install this program at the bootvector:
0012 ------------------------------------
0013     .set noreorder
0014     .set nomacro
0015     .set noat
0016 reset_vector:
0017     dmtc0   $k0, $31, 0 # Save $k0 to DESAVE
0018     dmtc0   $k1, $31, 3 # Save $k1 to KScratch2
0019 
0020     mfc0    $k0, $12, 0 # Status
0021     mfc0    $k1, $15, 1 # Ebase
0022 
0023     ori $k0, 0x84   # Enable 64-bit addressing, set
0024                 # ERL (should already be set)
0025     andi    $k1, 0x3ff  # mask out core ID
0026 
0027     mtc0    $k0, $12, 0 # Status
0028     sll $k1, 5
0029 
0030     lui $k0, 0xbfc0
0031     cache   17, 0($0)   # Core-14345, clear L1 Dcache virtual
0032                 # tags if the core hit an NMI
0033 
0034     ld  $k0, 0x78($k0)  # k0 <- (bfc00078) pointer to the reset vector
0035     synci   0($0)       # Invalidate ICache to get coherent
0036                 # view of target code.
0037 
0038     daddu   $k0, $k0, $k1
0039     nop
0040 
0041     ld  $k0, 0($k0) # k0 <- core specific target address
0042     dmfc0   $k1, $31, 3 # Restore $k1 from KScratch2
0043 
0044     beqz    $k0, wait_loop  # Spin in wait loop
0045     nop
0046 
0047     jr  $k0
0048     nop
0049 
0050     nop         # NOPs needed here to fill delay slots
0051     nop         # on endian reversal of previous instructions
0052 
0053 wait_loop:
0054     wait
0055     nop
0056 
0057     b   wait_loop
0058     nop
0059 
0060     nop
0061     nop
0062 ------------------------------------
0063 
0064 0000000000000000 <reset_vector>:
0065    0:   40baf800    dmtc0   k0,c0_desave
0066    4:   40bbf803    dmtc0   k1,c0_kscratch2
0067 
0068    8:   401a6000    mfc0    k0,c0_status
0069    c:   401b7801    mfc0    k1,c0_ebase
0070 
0071   10:   375a0084    ori k0,k0,0x84
0072   14:   337b03ff    andi    k1,k1,0x3ff
0073 
0074   18:   409a6000    mtc0    k0,c0_status
0075   1c:   001bd940    sll k1,k1,0x5
0076 
0077   20:   3c1abfc0    lui k0,0xbfc0
0078   24:   bc110000    cache   0x11,0(zero)
0079 
0080   28:   df5a0078    ld  k0,120(k0)
0081   2c:   041f0000    synci   0(zero)
0082 
0083   30:   035bd02d    daddu   k0,k0,k1
0084   34:   00000000    nop
0085 
0086   38:   df5a0000    ld  k0,0(k0)
0087   3c:   403bf803    dmfc0   k1,c0_kscratch2
0088 
0089   40:   13400005    beqz    k0,58 <wait_loop>
0090   44:   00000000    nop
0091 
0092   48:   03400008    jr  k0
0093   4c:   00000000    nop
0094 
0095   50:   00000000    nop
0096   54:   00000000    nop
0097 
0098 0000000000000058 <wait_loop>:
0099   58:   42000020    wait
0100   5c:   00000000    nop
0101 
0102   60:   1000fffd    b   58 <wait_loop>
0103   64:   00000000    nop
0104 
0105   68:   00000000    nop
0106   6c:   00000000    nop
0107 
0108  */
0109 
0110 #include <asm/octeon/cvmx-boot-vector.h>
0111 
0112 static unsigned long long _cvmx_bootvector_data[16] = {
0113     0x40baf80040bbf803ull,  /* patch low order 8-bits if no KScratch*/
0114     0x401a6000401b7801ull,
0115     0x375a0084337b03ffull,
0116     0x409a6000001bd940ull,
0117     0x3c1abfc0bc110000ull,
0118     0xdf5a0078041f0000ull,
0119     0x035bd02d00000000ull,
0120     0xdf5a0000403bf803ull,  /* patch low order 8-bits if no KScratch*/
0121     0x1340000500000000ull,
0122     0x0340000800000000ull,
0123     0x0000000000000000ull,
0124     0x4200002000000000ull,
0125     0x1000fffd00000000ull,
0126     0x0000000000000000ull,
0127     OCTEON_BOOT_MOVEABLE_MAGIC1,
0128     0 /* To be filled in with address of vector block*/
0129 };
0130 
0131 /* 2^10 CPUs */
0132 #define VECTOR_TABLE_SIZE (1024 * sizeof(struct cvmx_boot_vector_element))
0133 
0134 static void cvmx_boot_vector_init(void *mem)
0135 {
0136     uint64_t kseg0_mem;
0137     int i;
0138 
0139     memset(mem, 0, VECTOR_TABLE_SIZE);
0140     kseg0_mem = cvmx_ptr_to_phys(mem) | 0x8000000000000000ull;
0141 
0142     for (i = 0; i < 15; i++) {
0143         uint64_t v = _cvmx_bootvector_data[i];
0144 
0145         if (OCTEON_IS_OCTEON1PLUS() && (i == 0 || i == 7))
0146             v &= 0xffffffff00000000ull; /* KScratch not availble. */
0147         cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
0148         cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, v);
0149     }
0150     cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, 15 * 8);
0151     cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, kseg0_mem);
0152     cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
0153 }
0154 
0155 /**
0156  * Get a pointer to the per-core table of reset vector pointers
0157  *
0158  */
0159 struct cvmx_boot_vector_element *cvmx_boot_vector_get(void)
0160 {
0161     struct cvmx_boot_vector_element *ret;
0162 
0163     ret = cvmx_bootmem_alloc_named_range_once(VECTOR_TABLE_SIZE, 0,
0164         (1ull << 32) - 1, 8, "__boot_vector1__", cvmx_boot_vector_init);
0165     return ret;
0166 }
0167 EXPORT_SYMBOL(cvmx_boot_vector_get);