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