162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
362306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
462306a36Sopenharmony_ci * for more details.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2004-2017 Cavium, Inc.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/*
1162306a36Sopenharmony_ci  We install this program at the bootvector:
1262306a36Sopenharmony_ci------------------------------------
1362306a36Sopenharmony_ci	.set noreorder
1462306a36Sopenharmony_ci	.set nomacro
1562306a36Sopenharmony_ci	.set noat
1662306a36Sopenharmony_cireset_vector:
1762306a36Sopenharmony_ci	dmtc0	$k0, $31, 0	# Save $k0 to DESAVE
1862306a36Sopenharmony_ci	dmtc0	$k1, $31, 3	# Save $k1 to KScratch2
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	mfc0	$k0, $12, 0	# Status
2162306a36Sopenharmony_ci	mfc0	$k1, $15, 1	# Ebase
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	ori	$k0, 0x84	# Enable 64-bit addressing, set
2462306a36Sopenharmony_ci				# ERL (should already be set)
2562306a36Sopenharmony_ci	andi	$k1, 0x3ff	# mask out core ID
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	mtc0	$k0, $12, 0	# Status
2862306a36Sopenharmony_ci	sll	$k1, 5
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	lui	$k0, 0xbfc0
3162306a36Sopenharmony_ci	cache	17, 0($0)	# Core-14345, clear L1 Dcache virtual
3262306a36Sopenharmony_ci				# tags if the core hit an NMI
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	ld	$k0, 0x78($k0)	# k0 <- (bfc00078) pointer to the reset vector
3562306a36Sopenharmony_ci	synci	0($0)		# Invalidate ICache to get coherent
3662306a36Sopenharmony_ci				# view of target code.
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	daddu	$k0, $k0, $k1
3962306a36Sopenharmony_ci	nop
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	ld	$k0, 0($k0)	# k0 <- core specific target address
4262306a36Sopenharmony_ci	dmfc0	$k1, $31, 3	# Restore $k1 from KScratch2
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	beqz	$k0, wait_loop	# Spin in wait loop
4562306a36Sopenharmony_ci	nop
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	jr	$k0
4862306a36Sopenharmony_ci	nop
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	nop			# NOPs needed here to fill delay slots
5162306a36Sopenharmony_ci	nop			# on endian reversal of previous instructions
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciwait_loop:
5462306a36Sopenharmony_ci	wait
5562306a36Sopenharmony_ci	nop
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	b	wait_loop
5862306a36Sopenharmony_ci	nop
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	nop
6162306a36Sopenharmony_ci	nop
6262306a36Sopenharmony_ci------------------------------------
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci0000000000000000 <reset_vector>:
6562306a36Sopenharmony_ci   0:	40baf800	dmtc0	k0,c0_desave
6662306a36Sopenharmony_ci   4:	40bbf803	dmtc0	k1,c0_kscratch2
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci   8:	401a6000	mfc0	k0,c0_status
6962306a36Sopenharmony_ci   c:	401b7801	mfc0	k1,c0_ebase
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci  10:	375a0084	ori	k0,k0,0x84
7262306a36Sopenharmony_ci  14:	337b03ff	andi	k1,k1,0x3ff
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci  18:	409a6000	mtc0	k0,c0_status
7562306a36Sopenharmony_ci  1c:	001bd940	sll	k1,k1,0x5
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci  20:	3c1abfc0	lui	k0,0xbfc0
7862306a36Sopenharmony_ci  24:	bc110000	cache	0x11,0(zero)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci  28:	df5a0078	ld	k0,120(k0)
8162306a36Sopenharmony_ci  2c:	041f0000	synci	0(zero)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci  30:	035bd02d	daddu	k0,k0,k1
8462306a36Sopenharmony_ci  34:	00000000	nop
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci  38:	df5a0000	ld	k0,0(k0)
8762306a36Sopenharmony_ci  3c:	403bf803	dmfc0	k1,c0_kscratch2
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci  40:	13400005	beqz	k0,58 <wait_loop>
9062306a36Sopenharmony_ci  44:	00000000	nop
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci  48:	03400008	jr	k0
9362306a36Sopenharmony_ci  4c:	00000000	nop
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci  50:	00000000	nop
9662306a36Sopenharmony_ci  54:	00000000	nop
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci0000000000000058 <wait_loop>:
9962306a36Sopenharmony_ci  58:	42000020	wait
10062306a36Sopenharmony_ci  5c:	00000000	nop
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci  60:	1000fffd	b	58 <wait_loop>
10362306a36Sopenharmony_ci  64:	00000000	nop
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci  68:	00000000	nop
10662306a36Sopenharmony_ci  6c:	00000000	nop
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#include <asm/octeon/cvmx-boot-vector.h>
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic unsigned long long _cvmx_bootvector_data[16] = {
11362306a36Sopenharmony_ci	0x40baf80040bbf803ull,  /* patch low order 8-bits if no KScratch*/
11462306a36Sopenharmony_ci	0x401a6000401b7801ull,
11562306a36Sopenharmony_ci	0x375a0084337b03ffull,
11662306a36Sopenharmony_ci	0x409a6000001bd940ull,
11762306a36Sopenharmony_ci	0x3c1abfc0bc110000ull,
11862306a36Sopenharmony_ci	0xdf5a0078041f0000ull,
11962306a36Sopenharmony_ci	0x035bd02d00000000ull,
12062306a36Sopenharmony_ci	0xdf5a0000403bf803ull,  /* patch low order 8-bits if no KScratch*/
12162306a36Sopenharmony_ci	0x1340000500000000ull,
12262306a36Sopenharmony_ci	0x0340000800000000ull,
12362306a36Sopenharmony_ci	0x0000000000000000ull,
12462306a36Sopenharmony_ci	0x4200002000000000ull,
12562306a36Sopenharmony_ci	0x1000fffd00000000ull,
12662306a36Sopenharmony_ci	0x0000000000000000ull,
12762306a36Sopenharmony_ci	OCTEON_BOOT_MOVEABLE_MAGIC1,
12862306a36Sopenharmony_ci	0 /* To be filled in with address of vector block*/
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/* 2^10 CPUs */
13262306a36Sopenharmony_ci#define VECTOR_TABLE_SIZE (1024 * sizeof(struct cvmx_boot_vector_element))
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic void cvmx_boot_vector_init(void *mem)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	uint64_t kseg0_mem;
13762306a36Sopenharmony_ci	int i;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	memset(mem, 0, VECTOR_TABLE_SIZE);
14062306a36Sopenharmony_ci	kseg0_mem = cvmx_ptr_to_phys(mem) | 0x8000000000000000ull;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	for (i = 0; i < 15; i++) {
14362306a36Sopenharmony_ci		uint64_t v = _cvmx_bootvector_data[i];
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci		if (OCTEON_IS_OCTEON1PLUS() && (i == 0 || i == 7))
14662306a36Sopenharmony_ci			v &= 0xffffffff00000000ull; /* KScratch not availble. */
14762306a36Sopenharmony_ci		cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
14862306a36Sopenharmony_ci		cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, v);
14962306a36Sopenharmony_ci	}
15062306a36Sopenharmony_ci	cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, 15 * 8);
15162306a36Sopenharmony_ci	cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, kseg0_mem);
15262306a36Sopenharmony_ci	cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/**
15662306a36Sopenharmony_ci * Get a pointer to the per-core table of reset vector pointers
15762306a36Sopenharmony_ci *
15862306a36Sopenharmony_ci */
15962306a36Sopenharmony_cistruct cvmx_boot_vector_element *cvmx_boot_vector_get(void)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	struct cvmx_boot_vector_element *ret;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	ret = cvmx_bootmem_alloc_named_range_once(VECTOR_TABLE_SIZE, 0,
16462306a36Sopenharmony_ci		(1ull << 32) - 1, 8, "__boot_vector1__", cvmx_boot_vector_init);
16562306a36Sopenharmony_ci	return ret;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ciEXPORT_SYMBOL(cvmx_boot_vector_get);
168