cpufunc.h revision 178172
1/*	$OpenBSD: pio.h,v 1.2 1998/09/15 10:50:12 pefo Exp $	*/
2
3/*
4 * Copyright (c) 1995-1999 Per Fogelstrom.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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 the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *      This product includes software developed by Per Fogelstrom.
17 * 4. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 *	JNPR: cpufunc.h,v 1.5 2007/08/09 11:23:32 katta
32 * $FreeBSD: head/sys/mips/include/cpufunc.h 178172 2008-04-13 07:27:37Z imp $
33 */
34
35#ifndef _MACHINE_CPUFUNC_H_
36#define	_MACHINE_CPUFUNC_H_
37
38#include <sys/types.h>
39#include <machine/cpuregs.h>
40
41/*
42 * These functions are required by user-land atomi ops
43 */
44
45static __inline void
46mips_barrier(void)
47{
48	__asm __volatile (".set noreorder\n\t"
49			  "nop\n\t"
50			  "nop\n\t"
51			  "nop\n\t"
52			  "nop\n\t"
53			  "nop\n\t"
54			  "nop\n\t"
55			  "nop\n\t"
56			  "nop\n\t"
57			  ".set reorder\n\t"
58			  : : : "memory");
59}
60
61static __inline void
62mips_wbflush(void)
63{
64	__asm __volatile ("sync" : : : "memory");
65	mips_barrier();
66#if 0
67	__asm __volatile("mtc0 %0, $12\n" /* MIPS_COP_0_STATUS */
68	   : : "r" (flag));
69#endif
70}
71
72static __inline void
73mips_read_membar(void)
74{
75	/* Nil */
76}
77
78static __inline void
79mips_write_membar(void)
80{
81	mips_wbflush();
82}
83
84#ifdef _KERNEL
85
86static __inline void
87mips_tlbp(void)
88{
89	__asm __volatile ("tlbp");
90	mips_barrier();
91#if 0
92	register_t ret;
93	register_t tmp;
94
95	__asm __volatile("mfc0	%0, $12\n" /* MIPS_COP_0_STATUS */
96	 		 "and	%1, %0, $~1\n" /* MIPS_SR_INT_IE */
97			 "mtc0	%1, $12\n" /* MIPS_COP_0_STATUS */
98			 : "=r" (ret), "=r" (tmp));
99	return (ret);
100#endif
101}
102
103static __inline void
104mips_tlbr(void)
105{
106	__asm __volatile ("tlbr");
107	mips_barrier();
108}
109
110static __inline void
111mips_tlbwi(void)
112{
113	__asm __volatile ("tlbwi");
114	mips_barrier();
115#if 0
116	__asm __volatile("mfc %0, $12\n" /* MIPS_COP_0_STATUS */
117	    		 "or  %0, %0, $1\n" /* MIPS_SR_INT_IE */
118			 "mtc0 %0, $12\n" /* MIPS_COP_0_STATUS */
119			 : "=r" (tmp));
120#endif
121}
122
123static __inline void
124mips_tlbwr(void)
125{
126	__asm __volatile ("tlbwr");
127	mips_barrier();
128}
129
130
131#if 0	/* XXX mips64 */
132
133#define	MIPS_RDRW64_COP0(n,r)					\
134static __inline uint64_t					\
135mips_rd_ ## n (void)						\
136{								\
137	int v0;							\
138	__asm __volatile ("dmfc0 %[v0], $"__XSTRING(r)";"	\
139			  : [v0] "=&r"(v0));			\
140	mips_barrier();						\
141	return (v0);						\
142}								\
143static __inline void						\
144mips_wr_ ## n (uint64_t a0)					\
145{								\
146	__asm __volatile ("dmtc0 %[a0], $"__XSTRING(r)";"	\
147			 __XSTRING(COP0_SYNC)";"		\
148			 "nop;"					\
149			 "nop;"					\
150			 :					\
151			 : [a0] "r"(a0));			\
152	mips_barrier();						\
153} struct __hack
154
155MIPS_RDRW64_COP0(entrylo0, MIPS_COP_0_TLB_LO0);
156MIPS_RDRW64_COP0(entrylo1, MIPS_COP_0_TLB_LO1);
157MIPS_RDRW64_COP0(entryhi, MIPS_COP_0_TLB_HI);
158MIPS_RDRW64_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK);
159MIPS_RDRW64_COP0(xcontext, MIPS_COP_0_TLB_XCONTEXT);
160
161#undef	MIPS_RDRW64_COP0
162#endif
163
164#define	MIPS_RDRW32_COP0(n,r)					\
165static __inline uint32_t					\
166mips_rd_ ## n (void)						\
167{								\
168	int v0;							\
169	__asm __volatile ("mfc0 %[v0], $"__XSTRING(r)";"	\
170			  : [v0] "=&r"(v0));			\
171	mips_barrier();						\
172	return (v0);						\
173}								\
174static __inline void						\
175mips_wr_ ## n (uint32_t a0)					\
176{								\
177	__asm __volatile ("mtc0 %[a0], $"__XSTRING(r)";"	\
178			 __XSTRING(COP0_SYNC)";"		\
179			 "nop;"					\
180			 "nop;"					\
181			 :					\
182			 : [a0] "r"(a0));			\
183	mips_barrier();						\
184} struct __hack
185
186#ifdef TARGET_OCTEON
187static __inline void mips_sync_icache (void)
188{
189    __asm __volatile (
190        ".set mips64\n"
191        ".word 0x041f0000\n"
192        "nop\n"
193        ".set mips0\n"
194        : : );
195}
196#endif
197
198MIPS_RDRW32_COP0(compare, MIPS_COP_0_COMPARE);
199MIPS_RDRW32_COP0(config, MIPS_COP_0_CONFIG);
200MIPS_RDRW32_COP0(count, MIPS_COP_0_COUNT);
201MIPS_RDRW32_COP0(index, MIPS_COP_0_TLB_INDEX);
202MIPS_RDRW32_COP0(wired, MIPS_COP_0_TLB_WIRED);
203MIPS_RDRW32_COP0(cause, MIPS_COP_0_CAUSE);
204MIPS_RDRW32_COP0(status, MIPS_COP_0_STATUS);
205
206/* XXX: Some of these registers are specific to MIPS32. */
207MIPS_RDRW32_COP0(entrylo0, MIPS_COP_0_TLB_LO0);
208MIPS_RDRW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1);
209MIPS_RDRW32_COP0(entrylow, MIPS_COP_0_TLB_LOW);
210MIPS_RDRW32_COP0(entryhi, MIPS_COP_0_TLB_HI);
211MIPS_RDRW32_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK);
212MIPS_RDRW32_COP0(prid, MIPS_COP_0_PRID);
213MIPS_RDRW32_COP0(watchlo, MIPS_COP_0_WATCH_LO);
214MIPS_RDRW32_COP0(watchhi, MIPS_COP_0_WATCH_HI);
215
216static __inline uint32_t
217mips_rd_config_sel1(void)
218{
219	int v0;
220	__asm __volatile("mfc0 %[v0], $16, 1 ;"
221			 : [v0] "=&r" (v0));
222	mips_barrier();
223	return (v0);
224}
225
226#undef	MIPS_RDRW32_COP0
227
228static __inline register_t
229intr_disable(void)
230{
231	register_t s;
232
233	s = mips_rd_status();
234	mips_wr_status(s & ~MIPS_SR_INT_IE);
235
236	return (s);
237}
238
239static __inline register_t
240intr_enable(void)
241{
242	register_t s;
243
244	s = mips_rd_status();
245	mips_wr_status(s | MIPS_SR_INT_IE);
246
247	return (s);
248}
249
250#define	intr_restore(s)	mips_wr_status((s))
251
252static __inline void
253breakpoint(void)
254{
255	__asm __volatile ("break");
256}
257
258#endif /* _KERNEL */
259
260#define	readb(va)	(*(volatile uint8_t *) (va))
261#define	readw(va)	(*(volatile uint16_t *) (va))
262#define	readl(va)	(*(volatile uint32_t *) (va))
263
264#define	writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
265#define	writew(va, d)	(*(volatile uint16_t *) (va) = (d))
266#define	writel(va, d)	(*(volatile uint32_t *) (va) = (d))
267
268/*
269 * I/O macros.
270 */
271
272#define	outb(a,v)	(*(volatile unsigned char*)(a) = (v))
273#define	out8(a,v)	(*(volatile unsigned char*)(a) = (v))
274#define	outw(a,v)	(*(volatile unsigned short*)(a) = (v))
275#define	out16(a,v)	outw(a,v)
276#define	outl(a,v)	(*(volatile unsigned int*)(a) = (v))
277#define	out32(a,v)	outl(a,v)
278#define	inb(a)		(*(volatile unsigned char*)(a))
279#define	in8(a)		(*(volatile unsigned char*)(a))
280#define	inw(a)		(*(volatile unsigned short*)(a))
281#define	in16(a)		inw(a)
282#define	inl(a)		(*(volatile unsigned int*)(a))
283#define	in32(a)		inl(a)
284
285#define	out8rb(a,v)	(*(volatile unsigned char*)(a) = (v))
286#define	out16rb(a,v)	(__out16rb((volatile uint16_t *)(a), v))
287#define	out32rb(a,v)	(__out32rb((volatile uint32_t *)(a), v))
288#define	in8rb(a)	(*(volatile unsigned char*)(a))
289#define	in16rb(a)	(__in16rb((volatile uint16_t *)(a)))
290#define	in32rb(a)	(__in32rb((volatile uint32_t *)(a)))
291
292#define	_swap_(x)	(((x) >> 24) | ((x) << 24) | \
293	    (((x) >> 8) & 0xff00) | (((x) & 0xff00) << 8))
294
295static __inline void __out32rb(volatile uint32_t *, uint32_t);
296static __inline void __out16rb(volatile uint16_t *, uint16_t);
297static __inline uint32_t __in32rb(volatile uint32_t *);
298static __inline uint16_t __in16rb(volatile uint16_t *);
299
300static __inline void
301__out32rb(volatile uint32_t *a, uint32_t v)
302{
303	uint32_t _v_ = v;
304
305	_v_ = _swap_(_v_);
306	out32(a, _v_);
307}
308
309static __inline void
310__out16rb(volatile uint16_t *a, uint16_t v)
311{
312	uint16_t _v_;
313
314	_v_ = ((v >> 8) & 0xff) | (v << 8);
315	out16(a, _v_);
316}
317
318static __inline uint32_t
319__in32rb(volatile uint32_t *a)
320{
321	uint32_t _v_;
322
323	_v_ = in32(a);
324	_v_ = _swap_(_v_);
325	return _v_;
326}
327
328static __inline uint16_t
329__in16rb(volatile uint16_t *a)
330{
331	uint16_t _v_;
332
333	_v_ = in16(a);
334	_v_ = ((_v_ >> 8) & 0xff) | (_v_ << 8);
335	return _v_;
336}
337
338void insb(uint8_t *, uint8_t *,int);
339void insw(uint16_t *, uint16_t *,int);
340void insl(uint32_t *, uint32_t *,int);
341void outsb(uint8_t *, const uint8_t *,int);
342void outsw(uint16_t *, const uint16_t *,int);
343void outsl(uint32_t *, const uint32_t *,int);
344u_int loadandclear(volatile u_int *addr);
345
346#endif /* !_MACHINE_CPUFUNC_H_ */
347