cvmx-boot-vector.c 3.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 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);