1198629Srrs/*-
2198629Srrs * Copyright (c) 2003-2009 RMI Corporation
3198629Srrs * All rights reserved.
4198629Srrs *
5198629Srrs * Redistribution and use in source and binary forms, with or without
6198629Srrs * modification, are permitted provided that the following conditions
7198629Srrs * are met:
8198629Srrs * 1. Redistributions of source code must retain the above copyright
9198629Srrs *    notice, this list of conditions and the following disclaimer.
10198629Srrs * 2. Redistributions in binary form must reproduce the above copyright
11198629Srrs *    notice, this list of conditions and the following disclaimer in the
12198629Srrs *    documentation and/or other materials provided with the distribution.
13198629Srrs * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14198629Srrs *    may be used to endorse or promote products derived from this software
15198629Srrs *    without specific prior written permission.
16198629Srrs *
17198629Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18198629Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19198629Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20198629Srrs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21198629Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22198629Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23198629Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24198629Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25198629Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26198629Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27198629Srrs * SUCH DAMAGE.
28198629Srrs *
29211994Sjchandra * RMI_BSD
30211994Sjchandra * $FreeBSD$
31211994Sjchandra */
32198629Srrs#ifndef __MIPS_EXTS_H__
33212366Sjchandra#define	__MIPS_EXTS_H__
34198629Srrs
35212366Sjchandra#define	CPU_BLOCKID_IFU		0
36212366Sjchandra#define	CPU_BLOCKID_ICU		1
37212366Sjchandra#define	CPU_BLOCKID_IEU		2
38212366Sjchandra#define	CPU_BLOCKID_LSU		3
39212366Sjchandra#define	CPU_BLOCKID_MMU		4
40212366Sjchandra#define	CPU_BLOCKID_PRF		5
41198629Srrs
42213441Sjchandra#define	LSU_CERRLOG_REGID	9
43198629Srrs
44212366Sjchandra#if defined(__mips_n64) || defined(__mips_n32)
45212366Sjchandrastatic __inline uint64_t
46212366Sjchandraread_xlr_ctrl_register(int block, int reg)
47198629Srrs{
48212366Sjchandra	uint64_t res;
49198629Srrs
50212366Sjchandra	__asm__ __volatile__(
51212366Sjchandra	    ".set	push\n\t"
52212366Sjchandra	    ".set	noreorder\n\t"
53212366Sjchandra	    "move	$9, %1\n\t"
54212366Sjchandra	    ".word	0x71280018\n\t"  /* mfcr $8, $9 */
55212366Sjchandra	    "move	%0, $8\n\t"
56212366Sjchandra	    ".set	pop\n"
57212366Sjchandra	    : "=r" (res) : "r"((block << 8) | reg)
58212366Sjchandra	    : "$8", "$9"
59212366Sjchandra	);
60212366Sjchandra	return (res);
61198629Srrs}
62198629Srrs
63212366Sjchandrastatic __inline void
64212366Sjchandrawrite_xlr_ctrl_register(int block, int reg, uint64_t value)
65198629Srrs{
66212366Sjchandra	__asm__ __volatile__(
67212366Sjchandra	    ".set	push\n\t"
68212366Sjchandra	    ".set	noreorder\n\t"
69212366Sjchandra	    "move	$8, %0\n"
70212366Sjchandra	    "move	$9, %1\n"
71212366Sjchandra	    ".word	0x71280019\n"    /* mtcr $8, $9  */
72212366Sjchandra	    ".set	pop\n"
73212366Sjchandra	    :
74212366Sjchandra	    : "r" (value), "r" ((block << 8) | reg)
75212366Sjchandra	    : "$8", "$9"
76212366Sjchandra	);
77198629Srrs}
78198629Srrs
79212366Sjchandra#else /* !(defined(__mips_n64) || defined(__mips_n32)) */
80212366Sjchandra
81212366Sjchandrastatic __inline uint64_t
82212366Sjchandraread_xlr_ctrl_register(int block, int reg)
83198629Srrs{
84212366Sjchandra	uint32_t high, low;
85212366Sjchandra
86212366Sjchandra	__asm__ __volatile__(
87212366Sjchandra	    ".set	push\n\t"
88212366Sjchandra	    ".set	noreorder\n\t"
89212366Sjchandra	    ".set	mips64\n\t"
90212366Sjchandra	    "move	$9, %2\n"
91212366Sjchandra	    ".word 	0x71280018\n"  /* "mfcr    $8, $9\n" */
92212366Sjchandra	    "dsra32	%0, $8, 0\n\t"
93212366Sjchandra	    "sll	%1, $8, 0\n\t"
94212366Sjchandra	    ".set	pop"
95212366Sjchandra	    : "=r" (high), "=r"(low)
96212366Sjchandra	    : "r" ((block << 8) | reg)
97212366Sjchandra	    : "$8", "$9");
98212366Sjchandra
99212366Sjchandra	return ( (((uint64_t)high) << 32) | low);
100198629Srrs}
101198629Srrs
102212366Sjchandrastatic __inline void
103212366Sjchandrawrite_xlr_ctrl_register(int block, int reg, uint64_t value)
104198629Srrs{
105212366Sjchandra	uint32_t low, high;
106198629Srrs	high = value >> 32;
107198629Srrs	low = value & 0xffffffff;
108198629Srrs
109198629Srrs	__asm__ __volatile__(
110212366Sjchandra	   ".set	push\n\t"
111212366Sjchandra	   ".set	noreorder\n\t"
112212366Sjchandra	   ".set	mips64\n\t"
113212366Sjchandra	   "dsll32	$9, %0, 0\n\t"
114212366Sjchandra	   "dsll32	$8, %1, 0\n\t"
115212366Sjchandra	   "dsrl32	$8, $8, 0\n\t"
116212366Sjchandra	   "or		$8, $9, $8\n\t"
117212366Sjchandra	   "move	$9, %2\n\t"
118212366Sjchandra	   ".word	0x71280019\n\t" /* mtcr $8, $9 */
119212366Sjchandra	   ".set	pop\n"
120212366Sjchandra	   :  /* No outputs */
121212366Sjchandra	   : "r" (high), "r" (low), "r"((block << 8) | reg)
122212366Sjchandra	   : "$8", "$9");
123212366Sjchandra}
124212366Sjchandra#endif /* defined(__mips_n64) || defined(__mips_n32) */
125198629Srrs
126212366Sjchandra/*
127212366Sjchandra * 32 bit read write for c0
128212366Sjchandra */
129212366Sjchandra#define read_c0_register32(reg, sel)				\
130212366Sjchandra({								\
131212366Sjchandra	 uint32_t __rv;						\
132212366Sjchandra	__asm__ __volatile__(					\
133212366Sjchandra	    ".set	push\n\t"				\
134212366Sjchandra	    ".set	mips32\n\t"				\
135212366Sjchandra	    "mfc0	%0, $%1, %2\n\t"			\
136212366Sjchandra	    ".set	pop\n"					\
137212366Sjchandra	    : "=r" (__rv) : "i" (reg), "i" (sel) );		\
138212366Sjchandra	__rv;							\
139212366Sjchandra })
140198629Srrs
141212366Sjchandra#define write_c0_register32(reg,  sel, value)			\
142212366Sjchandra	__asm__ __volatile__(					\
143212366Sjchandra	    ".set	push\n\t"				\
144212366Sjchandra	    ".set	mips32\n\t"				\
145212366Sjchandra	    "mtc0	%0, $%1, %2\n\t"			\
146212366Sjchandra	    ".set	pop\n"					\
147212366Sjchandra	: : "r" (value), "i" (reg), "i" (sel) );
148198629Srrs
149212366Sjchandra#define read_c2_register32(reg, sel)				\
150212366Sjchandra({								\
151212366Sjchandra	uint32_t __rv;						\
152212366Sjchandra	__asm__ __volatile__(					\
153212366Sjchandra	    ".set	push\n\t"				\
154212366Sjchandra	    ".set	mips32\n\t"				\
155212366Sjchandra	    "mfc2	%0, $%1, %2\n\t"			\
156212366Sjchandra	    ".set	pop\n"					\
157212366Sjchandra	    : "=r" (__rv) : "i" (reg), "i" (sel) );		\
158212366Sjchandra	__rv;							\
159212366Sjchandra })
160198629Srrs
161212366Sjchandra#define write_c2_register32(reg,  sel, value)			\
162212366Sjchandra	__asm__ __volatile__(					\
163212366Sjchandra	    ".set	push\n\t"				\
164212366Sjchandra	    ".set	mips32\n\t"				\
165212366Sjchandra	    "mtc2	%0, $%1, %2\n\t"			\
166212366Sjchandra	    ".set	pop\n"					\
167212366Sjchandra	: : "r" (value), "i" (reg), "i" (sel) );
168198629Srrs
169212366Sjchandra#if defined(__mips_n64) || defined(__mips_n32)
170212366Sjchandra/*
171212366Sjchandra * On 64 bit compilation, the operations are simple
172212366Sjchandra */
173212366Sjchandra#define read_c0_register64(reg, sel)				\
174212366Sjchandra({								\
175212366Sjchandra	uint64_t __rv;						\
176212366Sjchandra	__asm__ __volatile__(					\
177212366Sjchandra	    ".set	push\n\t"				\
178212366Sjchandra	    ".set	mips64\n\t"				\
179212366Sjchandra	    "dmfc0	%0, $%1, %2\n\t"			\
180212366Sjchandra	    ".set	pop\n"					\
181212366Sjchandra	    : "=r" (__rv) : "i" (reg), "i" (sel) );		\
182212366Sjchandra	__rv;							\
183212366Sjchandra })
184198629Srrs
185212366Sjchandra#define write_c0_register64(reg,  sel, value)			\
186212366Sjchandra	__asm__ __volatile__(					\
187212366Sjchandra	    ".set	push\n\t"				\
188212366Sjchandra	    ".set	mips64\n\t"				\
189212366Sjchandra	    "dmtc0	%0, $%1, %2\n\t"			\
190212366Sjchandra	    ".set	pop\n"					\
191212366Sjchandra	: : "r" (value), "i" (reg), "i" (sel) );
192211994Sjchandra
193212366Sjchandra#define read_c2_register64(reg, sel)				\
194212366Sjchandra({								\
195212366Sjchandra	uint64_t __rv;						\
196212366Sjchandra	__asm__ __volatile__(					\
197212366Sjchandra	    ".set	push\n\t"				\
198212366Sjchandra	    ".set	mips64\n\t"				\
199212366Sjchandra	    "dmfc2	%0, $%1, %2\n\t"			\
200212366Sjchandra	    ".set	pop\n"					\
201212366Sjchandra	    : "=r" (__rv) : "i" (reg), "i" (sel) );		\
202212366Sjchandra	__rv;							\
203212366Sjchandra })
204211994Sjchandra
205212366Sjchandra#define write_c2_register64(reg,  sel, value)			\
206212366Sjchandra	__asm__ __volatile__(					\
207212366Sjchandra	    ".set	push\n\t"				\
208212366Sjchandra	    ".set	mips64\n\t"				\
209212366Sjchandra	    "dmtc2	%0, $%1, %2\n\t"			\
210212366Sjchandra	    ".set	pop\n"					\
211212366Sjchandra	: : "r" (value), "i" (reg), "i" (sel) );
212211994Sjchandra
213212366Sjchandra#else /* ! (defined(__mips_n64) || defined(__mips_n32)) */
214211994Sjchandra
215212366Sjchandra/*
216212366Sjchandra * 32 bit compilation, 64 bit values has to split
217212366Sjchandra */
218212366Sjchandra#define read_c0_register64(reg, sel)				\
219212366Sjchandra({								\
220212366Sjchandra	uint32_t __high, __low;					\
221212366Sjchandra	__asm__ __volatile__(					\
222212366Sjchandra	    ".set	push\n\t"				\
223212366Sjchandra	    ".set	noreorder\n\t"				\
224212366Sjchandra	    ".set	mips64\n\t"				\
225212366Sjchandra	    "dmfc0	$8, $%2, %3\n\t"			\
226212366Sjchandra	    "dsra32	%0, $8, 0\n\t"				\
227212366Sjchandra	    "sll	%1, $8, 0\n\t"				\
228212366Sjchandra	    ".set	pop\n"					\
229212366Sjchandra	    : "=r"(__high), "=r"(__low): "i"(reg), "i"(sel)	\
230212366Sjchandra	    : "$8");						\
231212366Sjchandra	((uint64_t)__high << 32) | __low;			\
232212366Sjchandra})
233211994Sjchandra
234212366Sjchandra#define write_c0_register64(reg, sel, value)			\
235212366Sjchandrado {								\
236212366Sjchandra       uint32_t __high = value >> 32;				\
237212366Sjchandra       uint32_t __low = value & 0xffffffff;			\
238212366Sjchandra	__asm__ __volatile__(					\
239212366Sjchandra	    ".set	push\n\t"				\
240212366Sjchandra	    ".set	noreorder\n\t"				\
241212366Sjchandra	    ".set	mips64\n\t"				\
242212366Sjchandra	    "dsll32	$8, %1, 0\n\t"				\
243212366Sjchandra	    "dsll32	$9, %0, 0\n\t"				\
244212366Sjchandra	    "dsrl32	$8, $8, 0\n\t"				\
245212366Sjchandra	    "or		$8, $8, $9\n\t"				\
246212366Sjchandra	    "dmtc0	$8, $%2, %3\n\t"			\
247212366Sjchandra	    ".set	pop"					\
248212366Sjchandra	    :: "r"(__high), "r"(__low),	 "i"(reg), "i"(sel)	\
249212366Sjchandra	    :"$8", "$9");					\
250212366Sjchandra} while(0)
251211994Sjchandra
252212366Sjchandra#define read_c2_register64(reg, sel)				\
253212366Sjchandra({								\
254212366Sjchandra	uint32_t __high, __low;					\
255212366Sjchandra	__asm__ __volatile__(					\
256212366Sjchandra	    ".set	push\n\t"				\
257212366Sjchandra	    ".set	noreorder\n\t"				\
258212366Sjchandra	    ".set	mips64\n\t"				\
259212366Sjchandra	    "dmfc2	$8, $%2, %3\n\t"			\
260212366Sjchandra	    "dsra32	%0, $8, 0\n\t"				\
261212366Sjchandra	    "sll	%1, $8, 0\n\t"				\
262212366Sjchandra	    ".set	pop\n"					\
263212366Sjchandra	    : "=r"(__high), "=r"(__low): "i"(reg), "i"(sel)	\
264212366Sjchandra	    : "$8");						\
265212366Sjchandra	((uint64_t)__high << 32) | __low;			\
266212366Sjchandra})
267211994Sjchandra
268212366Sjchandra#define write_c2_register64(reg, sel, value)			\
269212366Sjchandrado {								\
270212366Sjchandra       uint32_t __high = value >> 32;				\
271212366Sjchandra       uint32_t __low = value & 0xffffffff;			\
272212366Sjchandra	__asm__ __volatile__(					\
273212366Sjchandra	    ".set	push\n\t"				\
274212366Sjchandra	    ".set	noreorder\n\t"				\
275212366Sjchandra	    ".set	mips64\n\t"				\
276212366Sjchandra	    "dsll32	$8, %1, 0\n\t"				\
277212366Sjchandra	    "dsll32	$9, %0, 0\n\t"				\
278212366Sjchandra	    "dsrl32	$8, $8, 0\n\t"				\
279212366Sjchandra	    "or		$8, $8, $9\n\t"				\
280212366Sjchandra	    "dmtc2	$8, $%2, %3\n\t"			\
281212366Sjchandra	    ".set	pop"					\
282212366Sjchandra	    :: "r"(__high), "r"(__low),	 "i"(reg), "i"(sel)	\
283212366Sjchandra	    :"$8", "$9");					\
284212366Sjchandra} while(0)
285211994Sjchandra
286212366Sjchandra#endif /* defined(__mips_n64) || defined(__mips_n32) */
287211994Sjchandra
288212366Sjchandrastatic __inline int
289212366Sjchandraxlr_cpu_id(void)
290212366Sjchandra{
291211994Sjchandra
292212366Sjchandra	return (read_c0_register32(15, 1) & 0x1f);
293212366Sjchandra}
294211994Sjchandra
295212366Sjchandrastatic __inline int
296212366Sjchandraxlr_core_id(void)
297212366Sjchandra{
298211994Sjchandra
299212366Sjchandra	return (xlr_cpu_id() / 4);
300212366Sjchandra}
301211994Sjchandra
302212366Sjchandrastatic __inline int
303212366Sjchandraxlr_thr_id(void)
304212366Sjchandra{
305211994Sjchandra
306212366Sjchandra	return (read_c0_register32(15, 1) & 0x3);
307212366Sjchandra}
308212366Sjchandra
309212366Sjchandra/* Additional registers on the XLR */
310212366Sjchandra#define	MIPS_COP_0_OSSCRATCH	22
311212366Sjchandra#define	XLR_CACHELINE_SIZE	32
312212366Sjchandra
313211994Sjchandra/* functions to write to and read from the extended
314211994Sjchandra * cp0 registers.
315211994Sjchandra * EIRR : Extended Interrupt Request Register
316211994Sjchandra *        cp0 register 9 sel 6
317211994Sjchandra *        bits 0...7 are same as cause register 8...15
318211994Sjchandra * EIMR : Extended Interrupt Mask Register
319211994Sjchandra *        cp0 register 9 sel 7
320211994Sjchandra *        bits 0...7 are same as status register 8...15
321211994Sjchandra */
322212366Sjchandrastatic __inline uint64_t
323211994Sjchandraread_c0_eirr64(void)
324211994Sjchandra{
325211994Sjchandra
326212366Sjchandra	return (read_c0_register64(9, 6));
327211994Sjchandra}
328211994Sjchandra
329212366Sjchandrastatic __inline void
330212366Sjchandrawrite_c0_eirr64(uint64_t val)
331211994Sjchandra{
332211994Sjchandra
333212366Sjchandra	write_c0_register64(9, 6, val);
334211994Sjchandra}
335211994Sjchandra
336212366Sjchandrastatic __inline uint64_t
337212366Sjchandraread_c0_eimr64(void)
338211994Sjchandra{
339211994Sjchandra
340212366Sjchandra	return (read_c0_register64(9, 7));
341211994Sjchandra}
342211994Sjchandra
343212366Sjchandrastatic __inline void
344212366Sjchandrawrite_c0_eimr64(uint64_t val)
345211994Sjchandra{
346211994Sjchandra
347212366Sjchandra	write_c0_register64(9, 7, val);
348211994Sjchandra}
349211994Sjchandra
350212758Sjchandrastatic __inline int
351211994Sjchandraxlr_test_and_set(int *lock)
352211994Sjchandra{
353211994Sjchandra	int oldval = 0;
354211994Sjchandra
355212366Sjchandra	__asm__ __volatile__(
356212366Sjchandra	    ".set push\n"
357212366Sjchandra	    ".set noreorder\n"
358212366Sjchandra	    "move $9, %2\n"
359212366Sjchandra	    "li $8, 1\n"
360211994Sjchandra	    //      "swapw $8, $9\n"
361212366Sjchandra	    ".word 0x71280014\n"
362212366Sjchandra	    "move %1, $8\n"
363212366Sjchandra	    ".set pop\n"
364212366Sjchandra	    : "+m"(*lock), "=r"(oldval)
365212366Sjchandra	    : "r"((unsigned long)lock)
366212366Sjchandra	    : "$8", "$9"
367211994Sjchandra	);
368211994Sjchandra
369212758Sjchandra	return (oldval == 0 ? 1 /* success */ : 0 /* failure */);
370211994Sjchandra}
371211994Sjchandra
372212758Sjchandrastatic __inline uint32_t
373211994Sjchandraxlr_mfcr(uint32_t reg)
374211994Sjchandra{
375211994Sjchandra	uint32_t val;
376211994Sjchandra
377211994Sjchandra	__asm__ __volatile__(
378212366Sjchandra	    "move   $8, %1\n"
379212366Sjchandra	    ".word  0x71090018\n"
380212366Sjchandra	    "move   %0, $9\n"
381212366Sjchandra	    : "=r"(val)
382212366Sjchandra	    : "r"(reg):"$8", "$9");
383211994Sjchandra
384211994Sjchandra	return val;
385211994Sjchandra}
386211994Sjchandra
387212758Sjchandrastatic __inline void
388211994Sjchandraxlr_mtcr(uint32_t reg, uint32_t val)
389211994Sjchandra{
390211994Sjchandra	__asm__ __volatile__(
391212366Sjchandra	    "move   $8, %1\n"
392212366Sjchandra	    "move   $9, %0\n"
393212366Sjchandra	    ".word  0x71090019\n"
394212366Sjchandra	    :: "r"(val), "r"(reg)
395212366Sjchandra	    : "$8", "$9");
396211994Sjchandra}
397211994Sjchandra
398212758Sjchandra/*
399212758Sjchandra * Atomic increment a unsigned  int
400212758Sjchandra */
401212758Sjchandrastatic __inline unsigned int
402212758Sjchandraxlr_ldaddwu(unsigned int value, unsigned int *addr)
403212758Sjchandra{
404212758Sjchandra	__asm__	 __volatile__(
405212758Sjchandra	    ".set	push\n"
406212758Sjchandra	    ".set	noreorder\n"
407212758Sjchandra	    "move	$8, %2\n"
408212758Sjchandra	    "move	$9, %3\n"
409212758Sjchandra	    ".word	0x71280011\n"  /* ldaddwu $8, $9 */
410212758Sjchandra	    "move	%0, $8\n"
411212758Sjchandra	    ".set	pop\n"
412212758Sjchandra	    : "=&r"(value), "+m"(*addr)
413212758Sjchandra	    : "0"(value), "r" ((unsigned long)addr)
414212758Sjchandra	    :  "$8", "$9");
415212758Sjchandra
416212758Sjchandra	return (value);
417212758Sjchandra}
418212758Sjchandra
419212366Sjchandra#if defined(__mips_n64)
420212896Sjchandrastatic __inline uint32_t
421212896Sjchandraxlr_paddr_lw(uint64_t paddr)
422212896Sjchandra{
423212896Sjchandra
424212896Sjchandra	paddr |= 0x9800000000000000ULL;
425212896Sjchandra	return (*(uint32_t *)(uintptr_t)paddr);
426212896Sjchandra}
427212896Sjchandra
428212758Sjchandrastatic __inline uint64_t
429212758Sjchandraxlr_paddr_ld(uint64_t paddr)
430211994Sjchandra{
431212366Sjchandra
432212366Sjchandra	paddr |= 0x9800000000000000ULL;
433212758Sjchandra	return (*(uint64_t *)(uintptr_t)paddr);
434212366Sjchandra}
435211994Sjchandra
436212366Sjchandra#elif defined(__mips_n32)
437212896Sjchandrastatic __inline uint32_t
438212957Sjchandraxlr_paddr_lw(uint64_t paddr)
439212896Sjchandra{
440212896Sjchandra	uint32_t val;
441212896Sjchandra
442212896Sjchandra	paddr |= 0x9800000000000000ULL;
443212896Sjchandra	__asm__ __volatile__(
444212896Sjchandra	    ".set	push		\n\t"
445212896Sjchandra	    ".set	mips64		\n\t"
446212896Sjchandra	    "lw		%0, 0(%1)	\n\t"
447212896Sjchandra	    ".set	pop		\n"
448212896Sjchandra	    : "=r"(val)
449212896Sjchandra	    : "r"(paddr));
450212896Sjchandra
451212896Sjchandra	return (val);
452212896Sjchandra}
453212896Sjchandra
454212758Sjchandrastatic __inline uint64_t
455212758Sjchandraxlr_paddr_ld(uint64_t paddr)
456212366Sjchandra{
457212758Sjchandra	uint64_t val;
458211994Sjchandra
459212366Sjchandra	paddr |= 0x9800000000000000ULL;
460212366Sjchandra	__asm__ __volatile__(
461212366Sjchandra	    ".set	push		\n\t"
462212366Sjchandra	    ".set	mips64		\n\t"
463212758Sjchandra	    "ld		%0, 0(%1)	\n\t"
464212366Sjchandra	    ".set	pop		\n"
465212366Sjchandra	    : "=r"(val)
466212366Sjchandra	    : "r"(paddr));
467211994Sjchandra
468212366Sjchandra	return (val);
469212366Sjchandra}
470212896Sjchandra
471212896Sjchandra#else   /* o32 compilation */
472212758Sjchandrastatic __inline uint32_t
473212896Sjchandraxlr_paddr_lw(uint64_t paddr)
474212896Sjchandra{
475212896Sjchandra	uint32_t addrh, addrl;
476212896Sjchandra       	uint32_t val;
477212896Sjchandra
478212896Sjchandra	addrh = 0x98000000 | (paddr >> 32);
479212896Sjchandra	addrl = paddr & 0xffffffff;
480212896Sjchandra
481212896Sjchandra	__asm__ __volatile__(
482212896Sjchandra	    ".set	push		\n\t"
483212896Sjchandra	    ".set	mips64		\n\t"
484213441Sjchandra	    "dsll32	$8, %1, 0	\n\t"
485213441Sjchandra	    "dsll32	$9, %2, 0	\n\t"  /* get rid of the */
486213441Sjchandra	    "dsrl32	$9, $9, 0	\n\t"  /* sign extend */
487213441Sjchandra	    "or		$9, $8, $8	\n\t"
488213441Sjchandra	    "lw		%0, 0($9)	\n\t"
489212896Sjchandra	    ".set	pop		\n"
490213441Sjchandra	    :	"=r"(val)
491213441Sjchandra	    :	"r"(addrh), "r"(addrl)
492213441Sjchandra	    :	"$8", "$9");
493212896Sjchandra
494212896Sjchandra	return (val);
495212896Sjchandra}
496212896Sjchandra
497212896Sjchandrastatic __inline uint64_t
498212758Sjchandraxlr_paddr_ld(uint64_t paddr)
499212366Sjchandra{
500212758Sjchandra	uint32_t addrh, addrl;
501212758Sjchandra       	uint32_t valh, vall;
502212366Sjchandra
503212758Sjchandra	addrh = 0x98000000 | (paddr >> 32);
504212758Sjchandra	addrl = paddr & 0xffffffff;
505212366Sjchandra
506212366Sjchandra	__asm__ __volatile__(
507212896Sjchandra	    ".set	push		\n\t"
508212896Sjchandra	    ".set	mips64		\n\t"
509213441Sjchandra	    "dsll32	%0, %2, 0	\n\t"
510213441Sjchandra	    "dsll32	%1, %3, 0	\n\t"  /* get rid of the */
511213441Sjchandra	    "dsrl32	%1, %1, 0	\n\t"  /* sign extend */
512213441Sjchandra	    "or		%0, %0, %1	\n\t"
513212896Sjchandra	    "lw		%1, 4(%0)	\n\t"
514212896Sjchandra	    "lw		%0, 0(%0)	\n\t"
515212896Sjchandra	    ".set	pop		\n"
516213441Sjchandra	    :       "=&r"(valh), "=&r"(vall)
517212758Sjchandra	    :       "r"(addrh), "r"(addrl));
518212366Sjchandra
519212758Sjchandra	return (((uint64_t)valh << 32) | vall);
520211994Sjchandra}
521212366Sjchandra#endif
522211994Sjchandra
523212758Sjchandra/*
524212758Sjchandra * XXX: Not really needed in n32 or n64, retain for now
525212758Sjchandra */
526212758Sjchandra#if defined(__mips_n64) || defined(__mips_n32)
527212758Sjchandrastatic __inline uint32_t
528212758Sjchandraxlr_enable_kx(void)
529212758Sjchandra{
530212758Sjchandra
531212758Sjchandra	return (0);
532212758Sjchandra}
533212758Sjchandra
534212758Sjchandrastatic __inline void
535212758Sjchandraxlr_restore_kx(uint32_t sr)
536212758Sjchandra{
537212758Sjchandra}
538212896Sjchandra
539212896Sjchandra#else /* !defined(__mips_n64) && !defined(__mips_n32) */
540212896Sjchandra/*
541212896Sjchandra * o32 compilation, we will disable interrupts and enable
542212896Sjchandra * the KX bit so that we can use XKPHYS to access any 40bit
543212896Sjchandra * physical address
544212896Sjchandra */
545212758Sjchandrastatic __inline uint32_t
546212758Sjchandraxlr_enable_kx(void)
547212758Sjchandra{
548212758Sjchandra	uint32_t sr = mips_rd_status();
549212758Sjchandra
550212758Sjchandra	mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
551212758Sjchandra	return (sr);
552212758Sjchandra}
553212758Sjchandra
554212758Sjchandrastatic __inline void
555212758Sjchandraxlr_restore_kx(uint32_t sr)
556212758Sjchandra{
557212758Sjchandra
558212758Sjchandra	mips_wr_status(sr);
559212758Sjchandra}
560212896Sjchandra#endif /* defined(__mips_n64) || defined(__mips_n32) */
561212758Sjchandra
562213377Sjchandra/*
563213377Sjchandra * XLR/XLS processors have maximum 8 cores, and maximum 4 threads
564213377Sjchandra * per core
565213377Sjchandra */
566213377Sjchandra#define	XLR_MAX_CORES		8
567213377Sjchandra#define	XLR_NTHREADS		4
568213377Sjchandra
569213377Sjchandra/*
570213377Sjchandra * FreeBSD can be started with few threads and cores turned off,
571213377Sjchandra * so have a hardware thread id to FreeBSD cpuid mapping.
572213377Sjchandra */
573213377Sjchandraextern int xlr_ncores;
574213377Sjchandraextern int xlr_threads_per_core;
575211994Sjchandraextern uint32_t xlr_hw_thread_mask;
576211994Sjchandraextern int xlr_cpuid_to_hwtid[];
577211994Sjchandraextern int xlr_hwtid_to_cpuid[];
578211994Sjchandra
579198629Srrs#endif
580