1/*	$NetBSD: locore_octeon.S,v 1.10 2016/07/27 09:32:35 skrll Exp $	*/
2
3/*
4 * Copyright (c) 2007 Internet Initiative Japan, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <mips/asm.h>
30RCSID("$NetBSD: locore_octeon.S,v 1.10 2016/07/27 09:32:35 skrll Exp $")
31
32#include "cpunode.h"			/* for NWDOG */
33#include "opt_cputype.h"
34#include "opt_ddb.h"
35#include "opt_multiprocessor.h"
36
37#include <mips/cpuregs.h>
38#include <arch/mips/cavium/dev/octeon_corereg.h>
39
40RCSID("$NetBSD: locore_octeon.S,v 1.10 2016/07/27 09:32:35 skrll Exp $")
41
42#include "assym.h"
43
44#define	_CP0_READ64(_cp0)				\
45	dmfc0	v0, _cp0;				\
46	j	ra;					\
47	 nop
48
49#define	_CP0_WRITE64(_cp0)				\
50	dmtc0	a0, _cp0;				\
51	j	ra;					\
52	 nop
53
54	.set	noreorder
55	.set	noat
56	.set	arch=octeon
57
58	.text
59
60LEAF(mips_cp0_cvmctl_read)
61	_CP0_READ64(CP0_CVMCTL)
62END(mips_cp0_cvmctl_read)
63
64LEAF(mips_cp0_cvmctl_write)
65	_CP0_WRITE64(CP0_CVMCTL)
66END(mips_cp0_cvmctl_write)
67
68LEAF(mips_cp0_cvmmemctl_read)
69	_CP0_READ64(CP0_CVMMEMCTL)
70END(mips_cp0_cvmmemctl_read)
71
72LEAF(mips_cp0_cvmmemctl_write)
73	_CP0_WRITE64(CP0_CVMMEMCTL)
74END(mips_cp0_cvmmemctl_write)
75
76LEAF(mips_cp0_cvmcnt_read)
77	_CP0_READ64(CP0_CVMCNT)
78END(mips_cp0_cvmcnt_read)
79
80LEAF(mips_cp0_cvmcnt_write)
81	_CP0_WRITE64(CP0_CVMCNT)
82END(mips_cp0_cvmcnt_write)
83
84LEAF(mips_cp0_performance_counter_control0_read)
85	_CP0_READ64(CP0_PCCTL)
86END(mips_cp0_performance_counter_control0_read)
87
88LEAF(mips_cp0_performance_counter_control0_write)
89	_CP0_WRITE64(CP0_PCCTL)
90END(mips_cp0_performance_counter_control0_write)
91
92LEAF(mips_cp0_performance_counter_control1_read)
93	_CP0_READ64(CP0_PCCTL1)
94END(mips_cp0_performance_counter_control1_read)
95
96LEAF(mips_cp0_performance_counter_control1_write)
97	_CP0_WRITE64(CP0_PCCTL1)
98END(mips_cp0_performance_counter_control1_write)
99
100LEAF(mips_cp0_performance_counter_counter0_read)
101	_CP0_READ64(CP0_PCCNT)
102END(mips_cp0_performance_counter_counter0_read)
103
104LEAF(mips_cp0_performance_counter_counter0_write)
105	_CP0_WRITE64(CP0_PCCNT)
106END(mips_cp0_performance_counter_counter0_write)
107
108LEAF(mips_cp0_performance_counter_counter1_read)
109	_CP0_READ64(CP0_PCCNT1)
110END(mips_cp0_performance_counter_counter1_read)
111
112LEAF(mips_cp0_performance_counter_counter1_write)
113	_CP0_WRITE64(CP0_PCCNT1)
114END(mips_cp0_performance_counter_counter1_write)
115
116#ifdef MULTIPROCESSOR
117
118NESTED_NOPROFILE(octeon_cpu_spinup, 0, ra)
119	//
120	// Since the OCTEON cpus doesn't a COP0 OSCONTEXT register, each core
121	// must has its own exception vector page.  The exceptions will be
122	// modified to refer to that CPU's cpu_info structure.
123	//
124	mfc0	s1, MIPS_COP_0_EBASE	# get EBASE
125	ext	s0, s1, 0, 10		# fetch cpunum (MIPSNNR2)
126	ins	s1, zero, 0, 10		# clear it (MIPSNNR2)
127	ins	s1, s0, 12, 10		# insert cpunum as exception address
128	ehb
129	mtc0	s1, MIPS_COP_0_EBASE	# set EBASE
130	COP0_SYNC
131
132	// we only can deal with 2 cores
133	li	v0, 1
134	beq	s0, v0, 2f
135	 nop
136	// spin if this isn't cpu 1
1371:	wait
138	b	1b
139	 nop
140
141	// Indicate this CPU was started by u-boot
1422:	PTR_LA	t0, _C_LABEL(cpus_booted) # get addr for kcpuset
1433:	sync
144	PTR_L	a0, (t0)		# get kcpuset
145	beqz	a0, 3b			# loop until not NULL
146	 nop
147	jal	_C_LABEL(kcpuset_atomic_set)
148	 move	a1, s0			# pass it our cpu number
149
150	// Wait until cpuid_infos[cpunum] is not NULL.
151	PTR_LA	a1, _C_LABEL(cpuid_infos)
152	dsll	v0, s0, PTR_SCALESHIFT	# cpunum -> array index
153	PTR_ADD	t0, a1, v0		# add to array start
1544:	sync
155	PTR_L	a1, (t0)		# get cpu_info pointer
156	beqz	a1, 4b			# loop until non-NULL
157	 nop
158
159	j	_C_LABEL(cpu_trampoline)
160	 nop
161END(octeon_cpu_spinup)
162#endif /* MULTIPROCESSOR */
163
164#if NWDOG > 0 || defined(DDB)
165
166#define	UINT64_C(x)	(x)
167
168#include <mips/cavium/dev/octeon_ciureg.h>
169
170NESTED_NOPROFILE(octeon_reset_vector, 0, ra)
171	mfc0	k0, MIPS_COP_0_STATUS	# get cp0 status
172	bbit1	k0, V_MIPS3_SR_SR, 1f	# MIPS3_SR_SR
173	 ins	k0, zero, V_MIPS_SR_BEV, 1 # clear boot exception vectors
174	mtc0	k0, MIPS_COP_0_STATUS	# write cp0 status
175	ehb				# hazard barrier
176#ifdef MULTIPROCESSOR
177	mfc0	k0, MIPS_COP_0_EBASE	# get EBASE
178	ext	k0, k0, 0, 10		# select cpunum
179	dsll	k0, k0, PTR_SCALESHIFT	# cpunum -> array index
180	PTR_LA	k1, _C_LABEL(cpuid_infos)
181	PTR_ADDU k1, k1, k0		# add to array start
182	PTR_L	k0, (k1)		# get cpu_info
183#else
184	PTR_LA	k0, _C_LABEL(cpu_info_store) # get cpu_info
185#endif
186	j	_C_LABEL(mips64r2_kern_nonmaskable_intr)
187	 sd	zero, CIU_NMI_OFFSET(k1)# clear NMI
1881:
189	li	k1, ((MIPS_XKPHYS_START|CIU_BASE) >> 32)	# CIU base (MSW)
190	dsll	k1, 32			# shift it place
191	ld	k0, CIU_FUSE_OFFSET(k1)	# get mask of CPUs
192	sd	k0, CIU_SOFT_RST_OFFSET(k1)	# reset them
193	ld	v0, CIU_SOFT_RST_OFFSET(k1)	# force a load
194	sd	k0, CIU_SOFT_RST_OFFSET(k1)	# do it again.
1952:
196	wait				# wait forever
197	b	2b			# and loop until reset
198	 nop
199END(octeon_reset_vector)
200#endif
201