1/*	$NetBSD: rmixl_subr.S,v 1.4 2011/04/14 05:20:08 cliff Exp $	*/
2
3/*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Cliff Neighbors.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "opt_cputype.h"
33#include "opt_multiprocessor.h"
34
35#include <sys/cdefs.h>
36
37#include <mips/asm.h>
38#include <mips/cpuregs.h>
39
40RCSID("$NetBSD: rmixl_subr.S,v 1.4 2011/04/14 05:20:08 cliff Exp $");
41
42#include "assym.h"
43
44#define RMIXL_COP_0_EIRR	_(9), 6
45#define RMIXL_COP_0_EIMR	_(9), 7
46
47	.set    noreorder
48	.set	arch=xlr
49	.text
50
51/*
52 * read XLS Processor Control register
53 *
54 * uint64_t rmixl_mfcr(u_int cr);
55 */
56LEAF(rmixl_mfcr)
57#if defined(__mips_o32)
58#error O32 not supported
59#endif
60	j	ra
61	 mfcr	v0, a0
62END(rmixl_mfcr)
63
64/*
65 * write XLS Processor Control register
66 *
67 * void rmixl_mtcr(u_int cr, uint64_t val);
68 */
69LEAF(rmixl_mtcr)
70#if defined(__mips_o32)
71#error O32 not supported
72#endif
73	j	ra
74	 mtcr	a1, a0
75END(rmixl_mtcr)
76
77/*
78 * void rmixl_eirr_ack(uint64_t eimr, uint64_t vecbit, uint64_t preserve)
79 *
80 *	ack in EIRR the irq we are about to handle
81 *	disable all interrupts to prevent a race that would allow
82 *	e.g. softints set from a higher interrupt getting
83 *	clobbered by the EIRR read-modify-write
84 */
85LEAF(rmixl_eirr_ack)
86	dmtc0	zero, RMIXL_COP_0_EIMR	/* EIMR = 0 */
87	COP0_SYNC
88	dmfc0	a3, RMIXL_COP_0_EIRR	/* a3 = EIRR */
89	and	a3, a2			/* a3 &= preserve */
90	or	a3, a1			/* a3 |= vecbit */
91	dmtc0	a3, RMIXL_COP_0_EIRR	/* EIRR = a3 */
92	COP0_SYNC
93	dmtc0	a0, RMIXL_COP_0_EIMR	/* EIMR = eimr */
94	JR_HB_RA
95END(rmixl_eirr_ack)
96
97#ifdef MULTIPROCESSOR
98/*
99 * rmixlfw_wakeup_cpu(func, args, mask, callback)
100 */
101NESTED(rmixlfw_wakeup_cpu, CALLFRAME_SIZ+4*SZREG, ra)
102	PTR_ADDU	sp, sp, -(CALLFRAME_SIZ+4*SZREG)
103	REG_S		ra, CALLFRAME_RA(sp)
104	REG_S		s0, CALLFRAME_S0(sp)
105	REG_S		gp, CALLFRAME_SIZ+0*SZREG(sp)
106	REG_S		t8, CALLFRAME_SIZ+1*SZREG(sp)
107	mfc0		t0, MIPS_COP_0_STATUS
108	REG_S		t0, CALLFRAME_SIZ+2*SZREG(sp)
109
110	move		s0, sp			/* save sp */
111#ifdef _LP64
112	dsll32		t0, sp, 0		/* nuke upper half */
113	dsrl32		t0, t0, 0		/*  "    "     "   */
114	li		t1, MIPS_KSEG0_START
115	or		sp, t0, t1		/* set MIPS_KSEG0_START */
116#endif
117	jalr		a3			/* callback to firmware */
118	 nop
119	move		sp, s0			/* restore sp */
120
121	REG_L		t0, CALLFRAME_SIZ+2*SZREG(sp)
122	mtc0		t0, MIPS_COP_0_STATUS
123	REG_L		t8, CALLFRAME_SIZ+1*SZREG(sp)
124	REG_L		gp, CALLFRAME_SIZ+0*SZREG(sp)
125	REG_L		s0, CALLFRAME_S0(sp)
126	REG_L		ra, CALLFRAME_RA(sp)
127	jr		ra
128	 PTR_ADDU	sp, sp, (CALLFRAME_SIZ+4*SZREG)
129END(rmixlfw_wakeup_cpu)
130
131/*
132 * rmixl_cpu_trampoline - entry point for subordinate (non-#0) CPU wakeup
133 */
134NESTED(rmixl_cpu_trampoline, CALLFRAME_SIZ, ra)
135#ifdef _LP64
136	/*
137	 * reconstruct trampoline args addr:
138	 * sign-extend 32 bit KSEG0 address in a0
139	 * to make proper 64 bit KSEG0 addr
140	 */
141	sll		s0, a0, 0
142	li		t0, MIPS_SR_KX
143#else
144	li		t0, 0
145#endif
146
147	mtc0		zero, $9, 7	/* disable all in MIPS_COP_0_EIMR */
148
149	mtc0		t0, MIPS_COP_0_STATUS
150
151	/* ensure COP_0_EBASE field 'EBASE' is 0 */
152	mfc0		t0, $15, 1	/* MIPS_COP_0_EBASE */
153	and		t0, t0, 0x3ff
154	mtc0		t0, $15, 1	/* MIPS_COP_0_EBASE */
155
156	/*
157	 * load our stack pointer from trampoline args
158	 */
159	REG_L		sp, 0*SZREG(s0)		/* XXX ta_sp */
160
161	/*
162	 * load our (idle) lwp from trampoline args
163	 * save in t8 reg dedicated as 'mips_curlwp'
164	 */
165	REG_L		t8, 1*SZREG(s0)		/* XXX ta_lwp */
166
167	/*
168	 * load our ta_cpuinfo from trampoline args and pass in a1
169	 * jump to common mips cpu_trampoline
170	 */
171	REG_L		a1, 2*SZREG(s0)		/* XXX ta_cpuinfo */
172	dmtc0		a1, $22, 0		/* MIPS_COP_0_OSSCRATCH */
173	j		cpu_trampoline
174	 nop
175
176	/* NOTREACHED */
177
178END(rmixl_cpu_trampoline)
179
180#endif	/* MULTIPROCESSOR */
181