1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public
3*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive
4*4882a593Smuzhiyun * for more details.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2004-2017 Cavium, Inc.
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun We install this program at the bootvector:
12*4882a593Smuzhiyun ------------------------------------
13*4882a593Smuzhiyun .set noreorder
14*4882a593Smuzhiyun .set nomacro
15*4882a593Smuzhiyun .set noat
16*4882a593Smuzhiyun reset_vector:
17*4882a593Smuzhiyun dmtc0 $k0, $31, 0 # Save $k0 to DESAVE
18*4882a593Smuzhiyun dmtc0 $k1, $31, 3 # Save $k1 to KScratch2
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun mfc0 $k0, $12, 0 # Status
21*4882a593Smuzhiyun mfc0 $k1, $15, 1 # Ebase
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun ori $k0, 0x84 # Enable 64-bit addressing, set
24*4882a593Smuzhiyun # ERL (should already be set)
25*4882a593Smuzhiyun andi $k1, 0x3ff # mask out core ID
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun mtc0 $k0, $12, 0 # Status
28*4882a593Smuzhiyun sll $k1, 5
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun lui $k0, 0xbfc0
31*4882a593Smuzhiyun cache 17, 0($0) # Core-14345, clear L1 Dcache virtual
32*4882a593Smuzhiyun # tags if the core hit an NMI
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun ld $k0, 0x78($k0) # k0 <- (bfc00078) pointer to the reset vector
35*4882a593Smuzhiyun synci 0($0) # Invalidate ICache to get coherent
36*4882a593Smuzhiyun # view of target code.
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun daddu $k0, $k0, $k1
39*4882a593Smuzhiyun nop
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun ld $k0, 0($k0) # k0 <- core specific target address
42*4882a593Smuzhiyun dmfc0 $k1, $31, 3 # Restore $k1 from KScratch2
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun beqz $k0, wait_loop # Spin in wait loop
45*4882a593Smuzhiyun nop
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun jr $k0
48*4882a593Smuzhiyun nop
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun nop # NOPs needed here to fill delay slots
51*4882a593Smuzhiyun nop # on endian reversal of previous instructions
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun wait_loop:
54*4882a593Smuzhiyun wait
55*4882a593Smuzhiyun nop
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun b wait_loop
58*4882a593Smuzhiyun nop
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun nop
61*4882a593Smuzhiyun nop
62*4882a593Smuzhiyun ------------------------------------
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun 0000000000000000 <reset_vector>:
65*4882a593Smuzhiyun 0: 40baf800 dmtc0 k0,c0_desave
66*4882a593Smuzhiyun 4: 40bbf803 dmtc0 k1,c0_kscratch2
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun 8: 401a6000 mfc0 k0,c0_status
69*4882a593Smuzhiyun c: 401b7801 mfc0 k1,c0_ebase
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun 10: 375a0084 ori k0,k0,0x84
72*4882a593Smuzhiyun 14: 337b03ff andi k1,k1,0x3ff
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun 18: 409a6000 mtc0 k0,c0_status
75*4882a593Smuzhiyun 1c: 001bd940 sll k1,k1,0x5
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun 20: 3c1abfc0 lui k0,0xbfc0
78*4882a593Smuzhiyun 24: bc110000 cache 0x11,0(zero)
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun 28: df5a0078 ld k0,120(k0)
81*4882a593Smuzhiyun 2c: 041f0000 synci 0(zero)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun 30: 035bd02d daddu k0,k0,k1
84*4882a593Smuzhiyun 34: 00000000 nop
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun 38: df5a0000 ld k0,0(k0)
87*4882a593Smuzhiyun 3c: 403bf803 dmfc0 k1,c0_kscratch2
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun 40: 13400005 beqz k0,58 <wait_loop>
90*4882a593Smuzhiyun 44: 00000000 nop
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun 48: 03400008 jr k0
93*4882a593Smuzhiyun 4c: 00000000 nop
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun 50: 00000000 nop
96*4882a593Smuzhiyun 54: 00000000 nop
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun 0000000000000058 <wait_loop>:
99*4882a593Smuzhiyun 58: 42000020 wait
100*4882a593Smuzhiyun 5c: 00000000 nop
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun 60: 1000fffd b 58 <wait_loop>
103*4882a593Smuzhiyun 64: 00000000 nop
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun 68: 00000000 nop
106*4882a593Smuzhiyun 6c: 00000000 nop
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun #include <asm/octeon/cvmx-boot-vector.h>
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun static unsigned long long _cvmx_bootvector_data[16] = {
113*4882a593Smuzhiyun 0x40baf80040bbf803ull, /* patch low order 8-bits if no KScratch*/
114*4882a593Smuzhiyun 0x401a6000401b7801ull,
115*4882a593Smuzhiyun 0x375a0084337b03ffull,
116*4882a593Smuzhiyun 0x409a6000001bd940ull,
117*4882a593Smuzhiyun 0x3c1abfc0bc110000ull,
118*4882a593Smuzhiyun 0xdf5a0078041f0000ull,
119*4882a593Smuzhiyun 0x035bd02d00000000ull,
120*4882a593Smuzhiyun 0xdf5a0000403bf803ull, /* patch low order 8-bits if no KScratch*/
121*4882a593Smuzhiyun 0x1340000500000000ull,
122*4882a593Smuzhiyun 0x0340000800000000ull,
123*4882a593Smuzhiyun 0x0000000000000000ull,
124*4882a593Smuzhiyun 0x4200002000000000ull,
125*4882a593Smuzhiyun 0x1000fffd00000000ull,
126*4882a593Smuzhiyun 0x0000000000000000ull,
127*4882a593Smuzhiyun OCTEON_BOOT_MOVEABLE_MAGIC1,
128*4882a593Smuzhiyun 0 /* To be filled in with address of vector block*/
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /* 2^10 CPUs */
132*4882a593Smuzhiyun #define VECTOR_TABLE_SIZE (1024 * sizeof(struct cvmx_boot_vector_element))
133*4882a593Smuzhiyun
cvmx_boot_vector_init(void * mem)134*4882a593Smuzhiyun static void cvmx_boot_vector_init(void *mem)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun uint64_t kseg0_mem;
137*4882a593Smuzhiyun int i;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun memset(mem, 0, VECTOR_TABLE_SIZE);
140*4882a593Smuzhiyun kseg0_mem = cvmx_ptr_to_phys(mem) | 0x8000000000000000ull;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun for (i = 0; i < 15; i++) {
143*4882a593Smuzhiyun uint64_t v = _cvmx_bootvector_data[i];
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun if (OCTEON_IS_OCTEON1PLUS() && (i == 0 || i == 7))
146*4882a593Smuzhiyun v &= 0xffffffff00000000ull; /* KScratch not availble. */
147*4882a593Smuzhiyun cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
148*4882a593Smuzhiyun cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, v);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, 15 * 8);
151*4882a593Smuzhiyun cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, kseg0_mem);
152*4882a593Smuzhiyun cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /**
156*4882a593Smuzhiyun * Get a pointer to the per-core table of reset vector pointers
157*4882a593Smuzhiyun *
158*4882a593Smuzhiyun */
cvmx_boot_vector_get(void)159*4882a593Smuzhiyun struct cvmx_boot_vector_element *cvmx_boot_vector_get(void)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun struct cvmx_boot_vector_element *ret;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun ret = cvmx_bootmem_alloc_named_range_once(VECTOR_TABLE_SIZE, 0,
164*4882a593Smuzhiyun (1ull << 32) - 1, 8, "__boot_vector1__", cvmx_boot_vector_init);
165*4882a593Smuzhiyun return ret;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun EXPORT_SYMBOL(cvmx_boot_vector_get);
168