1fea25720SGraeme Russ #ifndef _ASM_IO_H 2fea25720SGraeme Russ #define _ASM_IO_H 3fea25720SGraeme Russ 4ec516c48SGabe Black #include <compiler.h> 5ec516c48SGabe Black 6fea25720SGraeme Russ /* 7fea25720SGraeme Russ * This file contains the definitions for the x86 IO instructions 8fea25720SGraeme Russ * inb/inw/inl/outb/outw/outl and the "string versions" of the same 9fea25720SGraeme Russ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" 10fea25720SGraeme Russ * versions of the single-IO instructions (inb_p/inw_p/..). 11fea25720SGraeme Russ * 12fea25720SGraeme Russ * This file is not meant to be obfuscating: it's just complicated 13fea25720SGraeme Russ * to (a) handle it all in a way that makes gcc able to optimize it 14fea25720SGraeme Russ * as well as possible and (b) trying to avoid writing the same thing 15fea25720SGraeme Russ * over and over again with slight variations and possibly making a 16fea25720SGraeme Russ * mistake somewhere. 17fea25720SGraeme Russ */ 18fea25720SGraeme Russ 19fea25720SGraeme Russ /* 20fea25720SGraeme Russ * Thanks to James van Artsdalen for a better timing-fix than 21fea25720SGraeme Russ * the two short jumps: using outb's to a nonexistent port seems 22fea25720SGraeme Russ * to guarantee better timings even on fast machines. 23fea25720SGraeme Russ * 24fea25720SGraeme Russ * On the other hand, I'd like to be sure of a non-existent port: 25fea25720SGraeme Russ * I feel a bit unsafe about using 0x80 (should be safe, though) 26fea25720SGraeme Russ * 27fea25720SGraeme Russ * Linus 28fea25720SGraeme Russ */ 29fea25720SGraeme Russ 30fea25720SGraeme Russ /* 31fea25720SGraeme Russ * Bit simplified and optimized by Jan Hubicka 32fea25720SGraeme Russ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999. 33fea25720SGraeme Russ * 34fea25720SGraeme Russ * isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added, 35fea25720SGraeme Russ * isa_read[wl] and isa_write[wl] fixed 36fea25720SGraeme Russ * - Arnaldo Carvalho de Melo <acme@conectiva.com.br> 37fea25720SGraeme Russ */ 38fea25720SGraeme Russ 39fea25720SGraeme Russ #define IO_SPACE_LIMIT 0xffff 40fea25720SGraeme Russ 41687c108bSGabe Black #include <asm/types.h> 42687c108bSGabe Black 43fea25720SGraeme Russ 44fea25720SGraeme Russ #ifdef __KERNEL__ 45fea25720SGraeme Russ 46fea25720SGraeme Russ 47fea25720SGraeme Russ /* 48fea25720SGraeme Russ * readX/writeX() are used to access memory mapped devices. On some 49fea25720SGraeme Russ * architectures the memory mapped IO stuff needs to be accessed 50fea25720SGraeme Russ * differently. On the x86 architecture, we just read/write the 51fea25720SGraeme Russ * memory location directly. 52fea25720SGraeme Russ */ 53fea25720SGraeme Russ 54fea25720SGraeme Russ #define readb(addr) (*(volatile unsigned char *) (addr)) 55fea25720SGraeme Russ #define readw(addr) (*(volatile unsigned short *) (addr)) 56fea25720SGraeme Russ #define readl(addr) (*(volatile unsigned int *) (addr)) 57fea25720SGraeme Russ #define __raw_readb readb 58fea25720SGraeme Russ #define __raw_readw readw 59fea25720SGraeme Russ #define __raw_readl readl 60fea25720SGraeme Russ 61fea25720SGraeme Russ #define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b)) 62fea25720SGraeme Russ #define writew(b,addr) (*(volatile unsigned short *) (addr) = (b)) 63fea25720SGraeme Russ #define writel(b,addr) (*(volatile unsigned int *) (addr) = (b)) 64fea25720SGraeme Russ #define __raw_writeb writeb 65fea25720SGraeme Russ #define __raw_writew writew 66fea25720SGraeme Russ #define __raw_writel writel 67fea25720SGraeme Russ 68fea25720SGraeme Russ #define memset_io(a,b,c) memset((a),(b),(c)) 69fea25720SGraeme Russ #define memcpy_fromio(a,b,c) memcpy((a),(b),(c)) 70fea25720SGraeme Russ #define memcpy_toio(a,b,c) memcpy((a),(b),(c)) 71fea25720SGraeme Russ 72*3f70a6f5SSimon Glass #define write_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v), a) 73*3f70a6f5SSimon Glass #define read_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a)) 74*3f70a6f5SSimon Glass 75*3f70a6f5SSimon Glass #define write_le64(a, v) write_arch(q, le64, a, v) 76*3f70a6f5SSimon Glass #define write_le32(a, v) write_arch(l, le32, a, v) 77*3f70a6f5SSimon Glass #define write_le16(a, v) write_arch(w, le16, a, v) 78*3f70a6f5SSimon Glass 79*3f70a6f5SSimon Glass #define read_le64(a) read_arch(q, le64, a) 80*3f70a6f5SSimon Glass #define read_le32(a) read_arch(l, le32, a) 81*3f70a6f5SSimon Glass #define read_le16(a) read_arch(w, le16, a) 82*3f70a6f5SSimon Glass 83*3f70a6f5SSimon Glass #define write_be32(a, v) write_arch(l, be32, a, v) 84*3f70a6f5SSimon Glass #define write_be16(a, v) write_arch(w, be16, a, v) 85*3f70a6f5SSimon Glass 86*3f70a6f5SSimon Glass #define read_be32(a) read_arch(l, be32, a) 87*3f70a6f5SSimon Glass #define read_be16(a) read_arch(w, be16, a) 88*3f70a6f5SSimon Glass 89*3f70a6f5SSimon Glass #define write_8(a, v) __raw_writeb(v, a) 90*3f70a6f5SSimon Glass #define read_8(a) __raw_readb(a) 91*3f70a6f5SSimon Glass 92*3f70a6f5SSimon Glass #define clrbits(type, addr, clear) \ 93*3f70a6f5SSimon Glass write_##type((addr), read_##type(addr) & ~(clear)) 94*3f70a6f5SSimon Glass 95*3f70a6f5SSimon Glass #define setbits(type, addr, set) \ 96*3f70a6f5SSimon Glass write_##type((addr), read_##type(addr) | (set)) 97*3f70a6f5SSimon Glass 98*3f70a6f5SSimon Glass #define clrsetbits(type, addr, clear, set) \ 99*3f70a6f5SSimon Glass write_##type((addr), (read_##type(addr) & ~(clear)) | (set)) 100*3f70a6f5SSimon Glass 101*3f70a6f5SSimon Glass #define clrbits_be32(addr, clear) clrbits(be32, addr, clear) 102*3f70a6f5SSimon Glass #define setbits_be32(addr, set) setbits(be32, addr, set) 103*3f70a6f5SSimon Glass #define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) 104*3f70a6f5SSimon Glass 105*3f70a6f5SSimon Glass #define clrbits_le32(addr, clear) clrbits(le32, addr, clear) 106*3f70a6f5SSimon Glass #define setbits_le32(addr, set) setbits(le32, addr, set) 107*3f70a6f5SSimon Glass #define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) 108*3f70a6f5SSimon Glass 109*3f70a6f5SSimon Glass #define clrbits_be16(addr, clear) clrbits(be16, addr, clear) 110*3f70a6f5SSimon Glass #define setbits_be16(addr, set) setbits(be16, addr, set) 111*3f70a6f5SSimon Glass #define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) 112*3f70a6f5SSimon Glass 113*3f70a6f5SSimon Glass #define clrbits_le16(addr, clear) clrbits(le16, addr, clear) 114*3f70a6f5SSimon Glass #define setbits_le16(addr, set) setbits(le16, addr, set) 115*3f70a6f5SSimon Glass #define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) 116*3f70a6f5SSimon Glass 117*3f70a6f5SSimon Glass #define clrbits_8(addr, clear) clrbits(8, addr, clear) 118*3f70a6f5SSimon Glass #define setbits_8(addr, set) setbits(8, addr, set) 119*3f70a6f5SSimon Glass #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) 120*3f70a6f5SSimon Glass 121fea25720SGraeme Russ /* 122fea25720SGraeme Russ * ISA space is 'always mapped' on a typical x86 system, no need to 123fea25720SGraeme Russ * explicitly ioremap() it. The fact that the ISA IO space is mapped 124fea25720SGraeme Russ * to PAGE_OFFSET is pure coincidence - it does not mean ISA values 125fea25720SGraeme Russ * are physical addresses. The following constant pointer can be 126fea25720SGraeme Russ * used as the IO-area pointer (it can be iounmapped as well, so the 127fea25720SGraeme Russ * analogy with PCI is quite large): 128fea25720SGraeme Russ */ 129fea25720SGraeme Russ #define isa_readb(a) readb((a)) 130fea25720SGraeme Russ #define isa_readw(a) readw((a)) 131fea25720SGraeme Russ #define isa_readl(a) readl((a)) 132fea25720SGraeme Russ #define isa_writeb(b,a) writeb(b,(a)) 133fea25720SGraeme Russ #define isa_writew(w,a) writew(w,(a)) 134fea25720SGraeme Russ #define isa_writel(l,a) writel(l,(a)) 135fea25720SGraeme Russ #define isa_memset_io(a,b,c) memset_io((a),(b),(c)) 136fea25720SGraeme Russ #define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),(b),(c)) 137fea25720SGraeme Russ #define isa_memcpy_toio(a,b,c) memcpy_toio((a),(b),(c)) 138fea25720SGraeme Russ 139fea25720SGraeme Russ 140fea25720SGraeme Russ static inline int check_signature(unsigned long io_addr, 141fea25720SGraeme Russ const unsigned char *signature, int length) 142fea25720SGraeme Russ { 143fea25720SGraeme Russ int retval = 0; 144fea25720SGraeme Russ do { 145fea25720SGraeme Russ if (readb(io_addr) != *signature) 146fea25720SGraeme Russ goto out; 147fea25720SGraeme Russ io_addr++; 148fea25720SGraeme Russ signature++; 149fea25720SGraeme Russ length--; 150fea25720SGraeme Russ } while (length); 151fea25720SGraeme Russ retval = 1; 152fea25720SGraeme Russ out: 153fea25720SGraeme Russ return retval; 154fea25720SGraeme Russ } 155fea25720SGraeme Russ 156fea25720SGraeme Russ /** 157fea25720SGraeme Russ * isa_check_signature - find BIOS signatures 158fea25720SGraeme Russ * @io_addr: mmio address to check 159fea25720SGraeme Russ * @signature: signature block 160fea25720SGraeme Russ * @length: length of signature 161fea25720SGraeme Russ * 162fea25720SGraeme Russ * Perform a signature comparison with the ISA mmio address io_addr. 163fea25720SGraeme Russ * Returns 1 on a match. 164fea25720SGraeme Russ * 165fea25720SGraeme Russ * This function is deprecated. New drivers should use ioremap and 166fea25720SGraeme Russ * check_signature. 167fea25720SGraeme Russ */ 168fea25720SGraeme Russ 169fea25720SGraeme Russ 170fea25720SGraeme Russ static inline int isa_check_signature(unsigned long io_addr, 171fea25720SGraeme Russ const unsigned char *signature, int length) 172fea25720SGraeme Russ { 173fea25720SGraeme Russ int retval = 0; 174fea25720SGraeme Russ do { 175fea25720SGraeme Russ if (isa_readb(io_addr) != *signature) 176fea25720SGraeme Russ goto out; 177fea25720SGraeme Russ io_addr++; 178fea25720SGraeme Russ signature++; 179fea25720SGraeme Russ length--; 180fea25720SGraeme Russ } while (length); 181fea25720SGraeme Russ retval = 1; 182fea25720SGraeme Russ out: 183fea25720SGraeme Russ return retval; 184fea25720SGraeme Russ } 185fea25720SGraeme Russ 186fea25720SGraeme Russ #endif /* __KERNEL__ */ 187fea25720SGraeme Russ 188fea25720SGraeme Russ #ifdef SLOW_IO_BY_JUMPING 189fea25720SGraeme Russ #define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:" 190fea25720SGraeme Russ #else 191339c5111SStefan Reinauer #define __SLOW_DOWN_IO "\noutb %%al,$0xed" 192fea25720SGraeme Russ #endif 193fea25720SGraeme Russ 194fea25720SGraeme Russ #ifdef REALLY_SLOW_IO 195fea25720SGraeme Russ #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO 196fea25720SGraeme Russ #else 197fea25720SGraeme Russ #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO 198fea25720SGraeme Russ #endif 199fea25720SGraeme Russ 200fea25720SGraeme Russ 201fea25720SGraeme Russ /* 202fea25720SGraeme Russ * Talk about misusing macros.. 203fea25720SGraeme Russ */ 204fea25720SGraeme Russ #define __OUT1(s,x) \ 205fea25720SGraeme Russ static inline void out##s(unsigned x value, unsigned short port) { 206fea25720SGraeme Russ 207fea25720SGraeme Russ #define __OUT2(s,s1,s2) \ 208fea25720SGraeme Russ __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" 209fea25720SGraeme Russ 210fea25720SGraeme Russ 211fea25720SGraeme Russ #define __OUT(s,s1,x) \ 212fea25720SGraeme Russ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \ 213fea25720SGraeme Russ __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} 214fea25720SGraeme Russ 215fea25720SGraeme Russ #define __IN1(s) \ 216fea25720SGraeme Russ static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; 217fea25720SGraeme Russ 218fea25720SGraeme Russ #define __IN2(s,s1,s2) \ 219fea25720SGraeme Russ __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" 220fea25720SGraeme Russ 221fea25720SGraeme Russ #define __IN(s,s1,i...) \ 222fea25720SGraeme Russ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ 223fea25720SGraeme Russ __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 224fea25720SGraeme Russ 225fea25720SGraeme Russ #define __INS(s) \ 226fea25720SGraeme Russ static inline void ins##s(unsigned short port, void * addr, unsigned long count) \ 227fea25720SGraeme Russ { __asm__ __volatile__ ("rep ; ins" #s \ 228fea25720SGraeme Russ : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 229fea25720SGraeme Russ 230fea25720SGraeme Russ #define __OUTS(s) \ 231fea25720SGraeme Russ static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ 232fea25720SGraeme Russ { __asm__ __volatile__ ("rep ; outs" #s \ 233fea25720SGraeme Russ : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 234fea25720SGraeme Russ 235fea25720SGraeme Russ #define RETURN_TYPE unsigned char 236fea25720SGraeme Russ __IN(b,"") 237fea25720SGraeme Russ #undef RETURN_TYPE 238fea25720SGraeme Russ #define RETURN_TYPE unsigned short 239fea25720SGraeme Russ __IN(w,"") 240fea25720SGraeme Russ #undef RETURN_TYPE 241fea25720SGraeme Russ #define RETURN_TYPE unsigned int 242fea25720SGraeme Russ __IN(l,"") 243fea25720SGraeme Russ #undef RETURN_TYPE 244fea25720SGraeme Russ 245fea25720SGraeme Russ __OUT(b,"b",char) 246fea25720SGraeme Russ __OUT(w,"w",short) 247fea25720SGraeme Russ __OUT(l,,int) 248fea25720SGraeme Russ 249fea25720SGraeme Russ __INS(b) 250fea25720SGraeme Russ __INS(w) 251fea25720SGraeme Russ __INS(l) 252fea25720SGraeme Russ 253fea25720SGraeme Russ __OUTS(b) 254fea25720SGraeme Russ __OUTS(w) 255fea25720SGraeme Russ __OUTS(l) 256fea25720SGraeme Russ 257fea25720SGraeme Russ static inline void sync(void) 258fea25720SGraeme Russ { 259fea25720SGraeme Russ } 260fea25720SGraeme Russ 261fea25720SGraeme Russ /* 262fea25720SGraeme Russ * Given a physical address and a length, return a virtual address 263fea25720SGraeme Russ * that can be used to access the memory range with the caching 264fea25720SGraeme Russ * properties specified by "flags". 265fea25720SGraeme Russ */ 266fea25720SGraeme Russ #define MAP_NOCACHE (0) 267fea25720SGraeme Russ #define MAP_WRCOMBINE (0) 268fea25720SGraeme Russ #define MAP_WRBACK (0) 269fea25720SGraeme Russ #define MAP_WRTHROUGH (0) 270fea25720SGraeme Russ 271fea25720SGraeme Russ static inline void * 272fea25720SGraeme Russ map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) 273fea25720SGraeme Russ { 274ec516c48SGabe Black return (void *)(uintptr_t)paddr; 275fea25720SGraeme Russ } 276fea25720SGraeme Russ 277fea25720SGraeme Russ /* 278fea25720SGraeme Russ * Take down a mapping set up by map_physmem(). 279fea25720SGraeme Russ */ 280fea25720SGraeme Russ static inline void unmap_physmem(void *vaddr, unsigned long flags) 281fea25720SGraeme Russ { 282fea25720SGraeme Russ 283fea25720SGraeme Russ } 284fea25720SGraeme Russ 285fea25720SGraeme Russ static inline phys_addr_t virt_to_phys(void * vaddr) 286fea25720SGraeme Russ { 287ec516c48SGabe Black return (phys_addr_t)(uintptr_t)(vaddr); 288fea25720SGraeme Russ } 289fea25720SGraeme Russ 2908a487a44SSimon Glass /* 2918a487a44SSimon Glass * TODO: The kernel offers some more advanced versions of barriers, it might 2928a487a44SSimon Glass * have some advantages to use them instead of the simple one here. 2938a487a44SSimon Glass */ 2948a487a44SSimon Glass #define dmb() __asm__ __volatile__ ("" : : : "memory") 2958a487a44SSimon Glass #define __iormb() dmb() 2968a487a44SSimon Glass #define __iowmb() dmb() 2978a487a44SSimon Glass 298fea25720SGraeme Russ #endif 299