1/*-
2 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``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
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * NETLOGIC_BSD
29 * $FreeBSD$
30 */
31
32#include <machine/asm.h>
33#include <machine/cpu.h>
34#include <machine/cpuregs.h>
35#include <mips/nlm/hal/iomap.h>
36#include <mips/nlm/hal/sys.h>
37#include <mips/nlm/hal/cpucontrol.h>
38
39#define SYS_REG_KSEG1(node, reg)	(0xa0000000 + XLP_DEFAULT_IO_BASE + \
40		XLP_IO_SYS_OFFSET(node)  + XLP_IO_PCI_HDRSZ + (reg) * 4)
41#include "assym.s"
42
43	.text
44	.set	noat
45	.set	noreorder
46	.set	mips64
47
48#define	MFCR(rt,rs)	.word	((0x1c<<26)|((rs)<<21)|((rt)<<16)|(0x18))
49#define	MTCR(rt,rs)	.word	((0x1c<<26)|((rs)<<21)|((rt)<<16)|(0x19))
50/*
51 * We need to do this to really flush the dcache before splitting it
52 */
53.macro flush_l1_dcache
54	.set	push
55	.set	noreorder
56	li	$8, LSU_DEBUG_DATA0 /* use register number to handle */
57	li	$9, LSU_DEBUG_ADDR  /* different ABIs */
58	li	t2, 0		/* index */
59	li	t3, 0x1000	/* loop count, 512 sets * 8 whatever? */
601:
61	sll	v0, t2, 5
62	MTCR(0, 8)
63	ori	v1, v0, 0x3	/* way0 | write_enable | write_active */
64	MTCR(3, 9)
652:
66	MFCR(3, 9)
67	andi	v1, 0x1		/* wait for write_active == 0 */
68	bnez	v1, 2b
69	nop
70	MTCR(0, 8)
71	ori	v1, v0, 0x7	/* way1 | write_enable | write_active */
72	MTCR(3, 9)
733:
74	MFCR(3, 9)
75	andi	v1, 0x1		/* wait for write_active == 0 */
76	bnez	v1, 3b
77	nop
78	addi	t2, 1
79	bne	t3, t2, 1b
80	nop
81	.set pop
82.endm
83
84VECTOR(XLPResetEntry, unknown)
85	mfc0	t0, MIPS_COP_0_STATUS
86	li	t1, 0x80000
87	and	t1, t0, t1
88	bnez	t1, nmi_handler
89	nop
90
91#ifdef SMP
92	/* Reset entry for secordary cores */
93	mfc0	t0, MIPS_COP_0_PRID, 1
94	srl	t0, t0, 2		/* discard thread id */
95	andi	t0, t0, 0x7		/* core id */
96	li	t1, 1
97	sll	t0, t1, t0
98	nor     t0, t0, zero		/* mask with core id bit clear */
99
100	/* clear CPU non-coherent bit */
101	li	t2, SYS_REG_KSEG1(0, SYS_CPU_NONCOHERENT_MODE)
102	lw	t1, 0(t2)
103	and	t1, t1, t0
104	sw	t1, 0(t2)
105	lw	t1, 0(t2)	/* read-back ensures operation complete */
106	sync
107
108	dla	t2, mpentry
109	jr	t2
110	nop
111#endif
112	nop
113	/* NOT REACHED */
114VECTOR_END(XLPResetEntry)
115
116
117	/* Not yet */
118nmi_handler:
119	nop
120	nop
121	j	nmi_handler
122
123#ifdef SMP
124	/*
125	 * Enable other threads in the core, called from thread 0
126	 * of the core
127 	 */
128LEAF(xlp_enable_threads)
129	/*
130	 * Save and restore callee saved registers of all ABIs
131	 * Enabling threads trashes the registers
132	 */
133	dmtc0	sp, $4, 2	/* SP saved in UserLocal */
134	ori	sp, sp, 0x7
135	xori	sp, sp, 0x7	/* align 64 bit */
136	addiu	sp, sp, -128
137	mfc0	t1, MIPS_COP_0_STATUS
138	sd	s0, 0(sp)
139	sd	s1, 8(sp)
140	sd	s2, 16(sp)
141	sd	s3, 24(sp)
142	sd	s4, 32(sp)
143	sd	s5, 40(sp)
144	sd	s6, 48(sp)
145	sd	s7, 56(sp)
146	sd	s8, 64(sp)
147	sd	t1, 72(sp)
148	sd	gp, 80(sp)
149	sd	ra, 88(sp)
150
151	flush_l1_dcache
152
153	/* Use register number to work in o32 and n32 */
154	li	$9, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE)
155	move	$8, a0
156	sync
157	MTCR(8, 9)
158	mfc0	t0, MIPS_COP_0_PRID, 1
159	andi	t0, 0x3
160	beqz	t0, 2f
161	nop
162	dla	t1, mpentry	/* child thread, go to hardware init */
163	jr	t1
164	nop
165
166
1672: 	/*
168	 * Parent hardware thread, restore registers, return
169	 */
170#if 1
171	/*
172	 * A0 Errata - Write MMU_SETUP after changing thread mode register.
173	 */
174	li	$9, 0x400
175	li	$8, 0
176	MTCR(8, 9)
177	sll	zero,3		/* ehb */
178#endif
179	dmfc0	t0, $4, 2	/* SP saved in UserLocal */
180	ori	sp, t0, 0x7
181	xori	sp, sp, 0x7	/* align 64 bit */
182	addiu	sp, sp, -128
183	ld	s0, 0(sp)
184	ld	s1, 8(sp)
185	ld	s2, 16(sp)
186	ld	s3, 24(sp)
187	ld	s4, 32(sp)
188	ld	s5, 40(sp)
189	ld	s6, 48(sp)
190	ld	s7, 56(sp)
191	ld	s8, 64(sp)
192	ld	t1, 72(sp)
193	ld	gp, 80(sp)
194	ld	ra, 88(sp)
195	mfc0	t1, MIPS_COP_0_STATUS
196
197	move	sp, t0		/* Restore the real SP */
198	jr.hb	ra
199	nop
200END(xlp_enable_threads)
201#endif
202