cpufunc.h revision 204635
1178172Simp/*	$OpenBSD: pio.h,v 1.2 1998/09/15 10:50:12 pefo Exp $	*/
2178172Simp
3178172Simp/*
4178172Simp * Copyright (c) 1995-1999 Per Fogelstrom.  All rights reserved.
5178172Simp *
6178172Simp * Redistribution and use in source and binary forms, with or without
7178172Simp * modification, are permitted provided that the following conditions
8178172Simp * are met:
9178172Simp * 1. Redistributions of source code must retain the above copyright
10178172Simp *    notice, this list of conditions and the following disclaimer.
11178172Simp * 2. Redistributions in binary form must reproduce the above copyright
12178172Simp *    notice, this list of conditions and the following disclaimer in the
13178172Simp *    documentation and/or other materials provided with the distribution.
14178172Simp * 3. All advertising materials mentioning features or use of this software
15178172Simp *    must display the following acknowledgement:
16178172Simp *      This product includes software developed by Per Fogelstrom.
17178172Simp * 4. The name of the author may not be used to endorse or promote products
18178172Simp *    derived from this software without specific prior written permission
19178172Simp *
20178172Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21178172Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22178172Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23178172Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24178172Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25178172Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26178172Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27178172Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28178172Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29178172Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30178172Simp *
31178172Simp *	JNPR: cpufunc.h,v 1.5 2007/08/09 11:23:32 katta
32178172Simp * $FreeBSD: head/sys/mips/include/cpufunc.h 204635 2010-03-03 15:05:58Z gnn $
33178172Simp */
34178172Simp
35178172Simp#ifndef _MACHINE_CPUFUNC_H_
36178172Simp#define	_MACHINE_CPUFUNC_H_
37178172Simp
38178172Simp#include <sys/types.h>
39178172Simp#include <machine/cpuregs.h>
40178172Simp
41178172Simp/*
42178172Simp * These functions are required by user-land atomi ops
43178172Simp */
44178172Simp
45178172Simpstatic __inline void
46178172Simpmips_barrier(void)
47178172Simp{
48178172Simp	__asm __volatile (".set noreorder\n\t"
49178172Simp			  "nop\n\t"
50178172Simp			  "nop\n\t"
51178172Simp			  "nop\n\t"
52178172Simp			  "nop\n\t"
53178172Simp			  "nop\n\t"
54178172Simp			  "nop\n\t"
55178172Simp			  "nop\n\t"
56178172Simp			  "nop\n\t"
57178172Simp			  ".set reorder\n\t"
58178172Simp			  : : : "memory");
59178172Simp}
60178172Simp
61178172Simpstatic __inline void
62178172Simpmips_wbflush(void)
63178172Simp{
64178172Simp	__asm __volatile ("sync" : : : "memory");
65178172Simp	mips_barrier();
66178172Simp#if 0
67178172Simp	__asm __volatile("mtc0 %0, $12\n" /* MIPS_COP_0_STATUS */
68178172Simp	   : : "r" (flag));
69178172Simp#endif
70178172Simp}
71178172Simp
72178172Simpstatic __inline void
73178172Simpmips_read_membar(void)
74178172Simp{
75178172Simp	/* Nil */
76178172Simp}
77178172Simp
78178172Simpstatic __inline void
79178172Simpmips_write_membar(void)
80178172Simp{
81178172Simp	mips_wbflush();
82178172Simp}
83178172Simp
84178172Simp#ifdef _KERNEL
85178172Simp
86178172Simpstatic __inline void
87178172Simpmips_tlbp(void)
88178172Simp{
89178172Simp	__asm __volatile ("tlbp");
90178172Simp	mips_barrier();
91178172Simp#if 0
92178172Simp	register_t ret;
93178172Simp	register_t tmp;
94178172Simp
95178172Simp	__asm __volatile("mfc0	%0, $12\n" /* MIPS_COP_0_STATUS */
96178172Simp	 		 "and	%1, %0, $~1\n" /* MIPS_SR_INT_IE */
97178172Simp			 "mtc0	%1, $12\n" /* MIPS_COP_0_STATUS */
98178172Simp			 : "=r" (ret), "=r" (tmp));
99178172Simp	return (ret);
100178172Simp#endif
101178172Simp}
102178172Simp
103178172Simpstatic __inline void
104178172Simpmips_tlbr(void)
105178172Simp{
106178172Simp	__asm __volatile ("tlbr");
107178172Simp	mips_barrier();
108178172Simp}
109178172Simp
110178172Simpstatic __inline void
111178172Simpmips_tlbwi(void)
112178172Simp{
113178172Simp	__asm __volatile ("tlbwi");
114178172Simp	mips_barrier();
115178172Simp#if 0
116178172Simp	__asm __volatile("mfc %0, $12\n" /* MIPS_COP_0_STATUS */
117178172Simp	    		 "or  %0, %0, $1\n" /* MIPS_SR_INT_IE */
118178172Simp			 "mtc0 %0, $12\n" /* MIPS_COP_0_STATUS */
119178172Simp			 : "=r" (tmp));
120178172Simp#endif
121178172Simp}
122178172Simp
123178172Simpstatic __inline void
124178172Simpmips_tlbwr(void)
125178172Simp{
126178172Simp	__asm __volatile ("tlbwr");
127178172Simp	mips_barrier();
128178172Simp}
129178172Simp
130178172Simp
131178172Simp#if 0	/* XXX mips64 */
132178172Simp
133178172Simp#define	MIPS_RDRW64_COP0(n,r)					\
134178172Simpstatic __inline uint64_t					\
135178172Simpmips_rd_ ## n (void)						\
136178172Simp{								\
137178172Simp	int v0;							\
138178172Simp	__asm __volatile ("dmfc0 %[v0], $"__XSTRING(r)";"	\
139178172Simp			  : [v0] "=&r"(v0));			\
140178172Simp	mips_barrier();						\
141178172Simp	return (v0);						\
142178172Simp}								\
143178172Simpstatic __inline void						\
144178172Simpmips_wr_ ## n (uint64_t a0)					\
145178172Simp{								\
146178172Simp	__asm __volatile ("dmtc0 %[a0], $"__XSTRING(r)";"	\
147178172Simp			 __XSTRING(COP0_SYNC)";"		\
148178172Simp			 "nop;"					\
149178172Simp			 "nop;"					\
150178172Simp			 :					\
151178172Simp			 : [a0] "r"(a0));			\
152178172Simp	mips_barrier();						\
153178172Simp} struct __hack
154178172Simp
155178172SimpMIPS_RDRW64_COP0(entrylo0, MIPS_COP_0_TLB_LO0);
156178172SimpMIPS_RDRW64_COP0(entrylo1, MIPS_COP_0_TLB_LO1);
157178172SimpMIPS_RDRW64_COP0(entryhi, MIPS_COP_0_TLB_HI);
158178172SimpMIPS_RDRW64_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK);
159178172SimpMIPS_RDRW64_COP0(xcontext, MIPS_COP_0_TLB_XCONTEXT);
160178172Simp
161178172Simp#undef	MIPS_RDRW64_COP0
162178172Simp#endif
163178172Simp
164178172Simp#define	MIPS_RDRW32_COP0(n,r)					\
165178172Simpstatic __inline uint32_t					\
166178172Simpmips_rd_ ## n (void)						\
167178172Simp{								\
168178172Simp	int v0;							\
169178172Simp	__asm __volatile ("mfc0 %[v0], $"__XSTRING(r)";"	\
170178172Simp			  : [v0] "=&r"(v0));			\
171178172Simp	mips_barrier();						\
172178172Simp	return (v0);						\
173178172Simp}								\
174178172Simpstatic __inline void						\
175178172Simpmips_wr_ ## n (uint32_t a0)					\
176178172Simp{								\
177178172Simp	__asm __volatile ("mtc0 %[a0], $"__XSTRING(r)";"	\
178178172Simp			 __XSTRING(COP0_SYNC)";"		\
179178172Simp			 "nop;"					\
180178172Simp			 "nop;"					\
181178172Simp			 :					\
182178172Simp			 : [a0] "r"(a0));			\
183178172Simp	mips_barrier();						\
184178172Simp} struct __hack
185178172Simp
186202031Simp#define	MIPS_RDRW32_COP0_SEL(n,r,s)					\
187202031Simpstatic __inline uint32_t					\
188202031Simpmips_rd_ ## n ## s(void)						\
189202031Simp{								\
190202031Simp	int v0;							\
191202031Simp	__asm __volatile ("mfc0 %[v0], $"__XSTRING(r)", "__XSTRING(s)";"	\
192202031Simp			  : [v0] "=&r"(v0));			\
193202031Simp	mips_barrier();						\
194202031Simp	return (v0);						\
195202031Simp}								\
196202031Simpstatic __inline void						\
197202031Simpmips_wr_ ## n ## s(uint32_t a0)					\
198202031Simp{								\
199202031Simp	__asm __volatile ("mtc0 %[a0], $"__XSTRING(r)", "__XSTRING(s)";"	\
200202031Simp			 __XSTRING(COP0_SYNC)";"		\
201202031Simp			 "nop;"					\
202202031Simp			 "nop;"					\
203202031Simp			 :					\
204202031Simp			 : [a0] "r"(a0));			\
205202031Simp	mips_barrier();						\
206202031Simp} struct __hack
207202031Simp
208178172Simp#ifdef TARGET_OCTEON
209178172Simpstatic __inline void mips_sync_icache (void)
210178172Simp{
211202031Simp	__asm __volatile (
212202031Simp		".set push\n"
213202031Simp		".set mips64\n"
214202031Simp		".word 0x041f0000\n"		/* xxx ICACHE */
215202031Simp		"nop\n"
216202031Simp		".set pop\n"
217202031Simp		: : );
218178172Simp}
219178172Simp#endif
220178172Simp
221178172SimpMIPS_RDRW32_COP0(compare, MIPS_COP_0_COMPARE);
222178172SimpMIPS_RDRW32_COP0(config, MIPS_COP_0_CONFIG);
223202031SimpMIPS_RDRW32_COP0_SEL(config, MIPS_COP_0_CONFIG, 1);
224202031SimpMIPS_RDRW32_COP0_SEL(config, MIPS_COP_0_CONFIG, 2);
225202031SimpMIPS_RDRW32_COP0_SEL(config, MIPS_COP_0_CONFIG, 3);
226178172SimpMIPS_RDRW32_COP0(count, MIPS_COP_0_COUNT);
227178172SimpMIPS_RDRW32_COP0(index, MIPS_COP_0_TLB_INDEX);
228178172SimpMIPS_RDRW32_COP0(wired, MIPS_COP_0_TLB_WIRED);
229178172SimpMIPS_RDRW32_COP0(cause, MIPS_COP_0_CAUSE);
230178172SimpMIPS_RDRW32_COP0(status, MIPS_COP_0_STATUS);
231178172Simp
232178172Simp/* XXX: Some of these registers are specific to MIPS32. */
233178172SimpMIPS_RDRW32_COP0(entrylo0, MIPS_COP_0_TLB_LO0);
234178172SimpMIPS_RDRW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1);
235178172SimpMIPS_RDRW32_COP0(entrylow, MIPS_COP_0_TLB_LOW);
236178172SimpMIPS_RDRW32_COP0(entryhi, MIPS_COP_0_TLB_HI);
237178172SimpMIPS_RDRW32_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK);
238178172SimpMIPS_RDRW32_COP0(prid, MIPS_COP_0_PRID);
239178172SimpMIPS_RDRW32_COP0(watchlo, MIPS_COP_0_WATCH_LO);
240202031SimpMIPS_RDRW32_COP0_SEL(watchlo, MIPS_COP_0_WATCH_LO, 1);
241202031SimpMIPS_RDRW32_COP0_SEL(watchlo, MIPS_COP_0_WATCH_LO, 2);
242202031SimpMIPS_RDRW32_COP0_SEL(watchlo, MIPS_COP_0_WATCH_LO, 3);
243178172SimpMIPS_RDRW32_COP0(watchhi, MIPS_COP_0_WATCH_HI);
244202031SimpMIPS_RDRW32_COP0_SEL(watchhi, MIPS_COP_0_WATCH_HI, 1);
245202031SimpMIPS_RDRW32_COP0_SEL(watchhi, MIPS_COP_0_WATCH_HI, 2);
246202031SimpMIPS_RDRW32_COP0_SEL(watchhi, MIPS_COP_0_WATCH_HI, 3);
247204635Sgnn
248204635SgnnMIPS_RDRW32_COP0_SEL(perfcnt, MIPS_COP_0_PERFCNT, 0);
249204635SgnnMIPS_RDRW32_COP0_SEL(perfcnt, MIPS_COP_0_PERFCNT, 1);
250204635SgnnMIPS_RDRW32_COP0_SEL(perfcnt, MIPS_COP_0_PERFCNT, 2);
251204635SgnnMIPS_RDRW32_COP0_SEL(perfcnt, MIPS_COP_0_PERFCNT, 3);
252204635Sgnn
253204635Sgnn
254178172Simp#undef	MIPS_RDRW32_COP0
255178172Simp
256178172Simpstatic __inline register_t
257178172Simpintr_disable(void)
258178172Simp{
259178172Simp	register_t s;
260178172Simp
261178172Simp	s = mips_rd_status();
262178172Simp	mips_wr_status(s & ~MIPS_SR_INT_IE);
263178172Simp
264178172Simp	return (s);
265178172Simp}
266178172Simp
267178172Simpstatic __inline register_t
268178172Simpintr_enable(void)
269178172Simp{
270178172Simp	register_t s;
271178172Simp
272178172Simp	s = mips_rd_status();
273178172Simp	mips_wr_status(s | MIPS_SR_INT_IE);
274178172Simp
275178172Simp	return (s);
276178172Simp}
277178172Simp
278178172Simp#define	intr_restore(s)	mips_wr_status((s))
279178172Simp
280178172Simpstatic __inline void
281178172Simpbreakpoint(void)
282178172Simp{
283178172Simp	__asm __volatile ("break");
284178172Simp}
285178172Simp
286178172Simp#endif /* _KERNEL */
287178172Simp
288178172Simp#define	readb(va)	(*(volatile uint8_t *) (va))
289178172Simp#define	readw(va)	(*(volatile uint16_t *) (va))
290178172Simp#define	readl(va)	(*(volatile uint32_t *) (va))
291178172Simp
292178172Simp#define	writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
293178172Simp#define	writew(va, d)	(*(volatile uint16_t *) (va) = (d))
294178172Simp#define	writel(va, d)	(*(volatile uint32_t *) (va) = (d))
295178172Simp
296178172Simp/*
297178172Simp * I/O macros.
298178172Simp */
299178172Simp
300178172Simp#define	outb(a,v)	(*(volatile unsigned char*)(a) = (v))
301178172Simp#define	out8(a,v)	(*(volatile unsigned char*)(a) = (v))
302178172Simp#define	outw(a,v)	(*(volatile unsigned short*)(a) = (v))
303178172Simp#define	out16(a,v)	outw(a,v)
304178172Simp#define	outl(a,v)	(*(volatile unsigned int*)(a) = (v))
305178172Simp#define	out32(a,v)	outl(a,v)
306178172Simp#define	inb(a)		(*(volatile unsigned char*)(a))
307178172Simp#define	in8(a)		(*(volatile unsigned char*)(a))
308178172Simp#define	inw(a)		(*(volatile unsigned short*)(a))
309178172Simp#define	in16(a)		inw(a)
310178172Simp#define	inl(a)		(*(volatile unsigned int*)(a))
311178172Simp#define	in32(a)		inl(a)
312178172Simp
313178172Simp#define	out8rb(a,v)	(*(volatile unsigned char*)(a) = (v))
314178172Simp#define	out16rb(a,v)	(__out16rb((volatile uint16_t *)(a), v))
315178172Simp#define	out32rb(a,v)	(__out32rb((volatile uint32_t *)(a), v))
316178172Simp#define	in8rb(a)	(*(volatile unsigned char*)(a))
317178172Simp#define	in16rb(a)	(__in16rb((volatile uint16_t *)(a)))
318178172Simp#define	in32rb(a)	(__in32rb((volatile uint32_t *)(a)))
319178172Simp
320178172Simp#define	_swap_(x)	(((x) >> 24) | ((x) << 24) | \
321178172Simp	    (((x) >> 8) & 0xff00) | (((x) & 0xff00) << 8))
322178172Simp
323178172Simpstatic __inline void __out32rb(volatile uint32_t *, uint32_t);
324178172Simpstatic __inline void __out16rb(volatile uint16_t *, uint16_t);
325178172Simpstatic __inline uint32_t __in32rb(volatile uint32_t *);
326178172Simpstatic __inline uint16_t __in16rb(volatile uint16_t *);
327178172Simp
328178172Simpstatic __inline void
329178172Simp__out32rb(volatile uint32_t *a, uint32_t v)
330178172Simp{
331178172Simp	uint32_t _v_ = v;
332178172Simp
333178172Simp	_v_ = _swap_(_v_);
334178172Simp	out32(a, _v_);
335178172Simp}
336178172Simp
337178172Simpstatic __inline void
338178172Simp__out16rb(volatile uint16_t *a, uint16_t v)
339178172Simp{
340178172Simp	uint16_t _v_;
341178172Simp
342178172Simp	_v_ = ((v >> 8) & 0xff) | (v << 8);
343178172Simp	out16(a, _v_);
344178172Simp}
345178172Simp
346178172Simpstatic __inline uint32_t
347178172Simp__in32rb(volatile uint32_t *a)
348178172Simp{
349178172Simp	uint32_t _v_;
350178172Simp
351178172Simp	_v_ = in32(a);
352178172Simp	_v_ = _swap_(_v_);
353178172Simp	return _v_;
354178172Simp}
355178172Simp
356178172Simpstatic __inline uint16_t
357178172Simp__in16rb(volatile uint16_t *a)
358178172Simp{
359178172Simp	uint16_t _v_;
360178172Simp
361178172Simp	_v_ = in16(a);
362178172Simp	_v_ = ((_v_ >> 8) & 0xff) | (_v_ << 8);
363178172Simp	return _v_;
364178172Simp}
365178172Simp
366178172Simpvoid insb(uint8_t *, uint8_t *,int);
367178172Simpvoid insw(uint16_t *, uint16_t *,int);
368178172Simpvoid insl(uint32_t *, uint32_t *,int);
369178172Simpvoid outsb(uint8_t *, const uint8_t *,int);
370178172Simpvoid outsw(uint16_t *, const uint16_t *,int);
371178172Simpvoid outsl(uint32_t *, const uint32_t *,int);
372178172Simpu_int loadandclear(volatile u_int *addr);
373178172Simp
374178172Simp#endif /* !_MACHINE_CPUFUNC_H_ */
375