1*091e51d2SBin Meng /* 2*091e51d2SBin Meng * (C) Copyright 2000-2002 3*091e51d2SBin Meng * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*091e51d2SBin Meng * 5*091e51d2SBin Meng * SPDX-License-Identifier: GPL-2.0+ 6*091e51d2SBin Meng */ 7*091e51d2SBin Meng 8fea25720SGraeme Russ #ifndef _ASM_IO_H 9fea25720SGraeme Russ #define _ASM_IO_H 10fea25720SGraeme Russ 11afc366f0SMasahiro Yamada #include <linux/compiler.h> 12ec516c48SGabe Black 13fea25720SGraeme Russ /* 14fea25720SGraeme Russ * This file contains the definitions for the x86 IO instructions 15fea25720SGraeme Russ * inb/inw/inl/outb/outw/outl and the "string versions" of the same 16fea25720SGraeme Russ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" 17fea25720SGraeme Russ * versions of the single-IO instructions (inb_p/inw_p/..). 18fea25720SGraeme Russ * 19fea25720SGraeme Russ * This file is not meant to be obfuscating: it's just complicated 20fea25720SGraeme Russ * to (a) handle it all in a way that makes gcc able to optimize it 21fea25720SGraeme Russ * as well as possible and (b) trying to avoid writing the same thing 22fea25720SGraeme Russ * over and over again with slight variations and possibly making a 23fea25720SGraeme Russ * mistake somewhere. 24fea25720SGraeme Russ */ 25fea25720SGraeme Russ 26fea25720SGraeme Russ /* 27fea25720SGraeme Russ * Thanks to James van Artsdalen for a better timing-fix than 28fea25720SGraeme Russ * the two short jumps: using outb's to a nonexistent port seems 29fea25720SGraeme Russ * to guarantee better timings even on fast machines. 30fea25720SGraeme Russ * 31fea25720SGraeme Russ * On the other hand, I'd like to be sure of a non-existent port: 32fea25720SGraeme Russ * I feel a bit unsafe about using 0x80 (should be safe, though) 33fea25720SGraeme Russ * 34fea25720SGraeme Russ * Linus 35fea25720SGraeme Russ */ 36fea25720SGraeme Russ 37fea25720SGraeme Russ /* 38fea25720SGraeme Russ * Bit simplified and optimized by Jan Hubicka 39fea25720SGraeme Russ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999. 40fea25720SGraeme Russ * 41fea25720SGraeme Russ * isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added, 42fea25720SGraeme Russ * isa_read[wl] and isa_write[wl] fixed 43fea25720SGraeme Russ * - Arnaldo Carvalho de Melo <acme@conectiva.com.br> 44fea25720SGraeme Russ */ 45fea25720SGraeme Russ 46fea25720SGraeme Russ #define IO_SPACE_LIMIT 0xffff 47fea25720SGraeme Russ 48687c108bSGabe Black #include <asm/types.h> 49687c108bSGabe Black 50fea25720SGraeme Russ 51fea25720SGraeme Russ #ifdef __KERNEL__ 52fea25720SGraeme Russ 53fea25720SGraeme Russ 54fea25720SGraeme Russ /* 55fea25720SGraeme Russ * readX/writeX() are used to access memory mapped devices. On some 56fea25720SGraeme Russ * architectures the memory mapped IO stuff needs to be accessed 57fea25720SGraeme Russ * differently. On the x86 architecture, we just read/write the 58fea25720SGraeme Russ * memory location directly. 59fea25720SGraeme Russ */ 60fea25720SGraeme Russ 61fea25720SGraeme Russ #define readb(addr) (*(volatile unsigned char *) (addr)) 62fea25720SGraeme Russ #define readw(addr) (*(volatile unsigned short *) (addr)) 63fea25720SGraeme Russ #define readl(addr) (*(volatile unsigned int *) (addr)) 64fea25720SGraeme Russ #define __raw_readb readb 65fea25720SGraeme Russ #define __raw_readw readw 66fea25720SGraeme Russ #define __raw_readl readl 67fea25720SGraeme Russ 68fea25720SGraeme Russ #define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b)) 69fea25720SGraeme Russ #define writew(b,addr) (*(volatile unsigned short *) (addr) = (b)) 70fea25720SGraeme Russ #define writel(b,addr) (*(volatile unsigned int *) (addr) = (b)) 71fea25720SGraeme Russ #define __raw_writeb writeb 72fea25720SGraeme Russ #define __raw_writew writew 73fea25720SGraeme Russ #define __raw_writel writel 74fea25720SGraeme Russ 75fea25720SGraeme Russ #define memset_io(a,b,c) memset((a),(b),(c)) 76fea25720SGraeme Russ #define memcpy_fromio(a,b,c) memcpy((a),(b),(c)) 77fea25720SGraeme Russ #define memcpy_toio(a,b,c) memcpy((a),(b),(c)) 78fea25720SGraeme Russ 793f70a6f5SSimon Glass #define write_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v), a) 803f70a6f5SSimon Glass #define read_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a)) 813f70a6f5SSimon Glass 823f70a6f5SSimon Glass #define write_le64(a, v) write_arch(q, le64, a, v) 833f70a6f5SSimon Glass #define write_le32(a, v) write_arch(l, le32, a, v) 843f70a6f5SSimon Glass #define write_le16(a, v) write_arch(w, le16, a, v) 853f70a6f5SSimon Glass 863f70a6f5SSimon Glass #define read_le64(a) read_arch(q, le64, a) 873f70a6f5SSimon Glass #define read_le32(a) read_arch(l, le32, a) 883f70a6f5SSimon Glass #define read_le16(a) read_arch(w, le16, a) 893f70a6f5SSimon Glass 903f70a6f5SSimon Glass #define write_be32(a, v) write_arch(l, be32, a, v) 913f70a6f5SSimon Glass #define write_be16(a, v) write_arch(w, be16, a, v) 923f70a6f5SSimon Glass 933f70a6f5SSimon Glass #define read_be32(a) read_arch(l, be32, a) 943f70a6f5SSimon Glass #define read_be16(a) read_arch(w, be16, a) 953f70a6f5SSimon Glass 963f70a6f5SSimon Glass #define write_8(a, v) __raw_writeb(v, a) 973f70a6f5SSimon Glass #define read_8(a) __raw_readb(a) 983f70a6f5SSimon Glass 993f70a6f5SSimon Glass #define clrbits(type, addr, clear) \ 1003f70a6f5SSimon Glass write_##type((addr), read_##type(addr) & ~(clear)) 1013f70a6f5SSimon Glass 1023f70a6f5SSimon Glass #define setbits(type, addr, set) \ 1033f70a6f5SSimon Glass write_##type((addr), read_##type(addr) | (set)) 1043f70a6f5SSimon Glass 1053f70a6f5SSimon Glass #define clrsetbits(type, addr, clear, set) \ 1063f70a6f5SSimon Glass write_##type((addr), (read_##type(addr) & ~(clear)) | (set)) 1073f70a6f5SSimon Glass 1083f70a6f5SSimon Glass #define clrbits_be32(addr, clear) clrbits(be32, addr, clear) 1093f70a6f5SSimon Glass #define setbits_be32(addr, set) setbits(be32, addr, set) 1103f70a6f5SSimon Glass #define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) 1113f70a6f5SSimon Glass 1123f70a6f5SSimon Glass #define clrbits_le32(addr, clear) clrbits(le32, addr, clear) 1133f70a6f5SSimon Glass #define setbits_le32(addr, set) setbits(le32, addr, set) 1143f70a6f5SSimon Glass #define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) 1153f70a6f5SSimon Glass 1163f70a6f5SSimon Glass #define clrbits_be16(addr, clear) clrbits(be16, addr, clear) 1173f70a6f5SSimon Glass #define setbits_be16(addr, set) setbits(be16, addr, set) 1183f70a6f5SSimon Glass #define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) 1193f70a6f5SSimon Glass 1203f70a6f5SSimon Glass #define clrbits_le16(addr, clear) clrbits(le16, addr, clear) 1213f70a6f5SSimon Glass #define setbits_le16(addr, set) setbits(le16, addr, set) 1223f70a6f5SSimon Glass #define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) 1233f70a6f5SSimon Glass 1243f70a6f5SSimon Glass #define clrbits_8(addr, clear) clrbits(8, addr, clear) 1253f70a6f5SSimon Glass #define setbits_8(addr, set) setbits(8, addr, set) 1263f70a6f5SSimon Glass #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) 1273f70a6f5SSimon Glass 128fea25720SGraeme Russ #endif /* __KERNEL__ */ 129fea25720SGraeme Russ 130fea25720SGraeme Russ #ifdef SLOW_IO_BY_JUMPING 131fea25720SGraeme Russ #define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:" 132fea25720SGraeme Russ #else 133339c5111SStefan Reinauer #define __SLOW_DOWN_IO "\noutb %%al,$0xed" 134fea25720SGraeme Russ #endif 135fea25720SGraeme Russ 136fea25720SGraeme Russ #ifdef REALLY_SLOW_IO 137fea25720SGraeme Russ #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO 138fea25720SGraeme Russ #else 139fea25720SGraeme Russ #define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO 140fea25720SGraeme Russ #endif 141fea25720SGraeme Russ 142fea25720SGraeme Russ 143fea25720SGraeme Russ /* 144fea25720SGraeme Russ * Talk about misusing macros.. 145fea25720SGraeme Russ */ 146fea25720SGraeme Russ #define __OUT1(s,x) \ 147005174d6SSimon Glass static inline void _out##s(unsigned x value, unsigned short port) { 148fea25720SGraeme Russ 149fea25720SGraeme Russ #define __OUT2(s,s1,s2) \ 150fea25720SGraeme Russ __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" 151fea25720SGraeme Russ 152fea25720SGraeme Russ 153fea25720SGraeme Russ #define __OUT(s,s1,x) \ 154fea25720SGraeme Russ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \ 155fea25720SGraeme Russ __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} 156fea25720SGraeme Russ 157fea25720SGraeme Russ #define __IN1(s) \ 158005174d6SSimon Glass static inline RETURN_TYPE _in##s(unsigned short port) { RETURN_TYPE _v; 159fea25720SGraeme Russ 160fea25720SGraeme Russ #define __IN2(s,s1,s2) \ 161fea25720SGraeme Russ __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" 162fea25720SGraeme Russ 163fea25720SGraeme Russ #define __IN(s,s1,i...) \ 164fea25720SGraeme Russ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ 165fea25720SGraeme Russ __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 166fea25720SGraeme Russ 167fea25720SGraeme Russ #define __INS(s) \ 168fea25720SGraeme Russ static inline void ins##s(unsigned short port, void * addr, unsigned long count) \ 169fea25720SGraeme Russ { __asm__ __volatile__ ("rep ; ins" #s \ 170fea25720SGraeme Russ : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 171fea25720SGraeme Russ 172fea25720SGraeme Russ #define __OUTS(s) \ 173fea25720SGraeme Russ static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ 174fea25720SGraeme Russ { __asm__ __volatile__ ("rep ; outs" #s \ 175fea25720SGraeme Russ : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } 176fea25720SGraeme Russ 177fea25720SGraeme Russ #define RETURN_TYPE unsigned char 178fea25720SGraeme Russ __IN(b,"") 179fea25720SGraeme Russ #undef RETURN_TYPE 180fea25720SGraeme Russ #define RETURN_TYPE unsigned short 181fea25720SGraeme Russ __IN(w,"") 182fea25720SGraeme Russ #undef RETURN_TYPE 183fea25720SGraeme Russ #define RETURN_TYPE unsigned int 184fea25720SGraeme Russ __IN(l,"") 185fea25720SGraeme Russ #undef RETURN_TYPE 186fea25720SGraeme Russ 187005174d6SSimon Glass #define inb(port) _inb((uintptr_t)(port)) 188005174d6SSimon Glass #define inw(port) _inw((uintptr_t)(port)) 189005174d6SSimon Glass #define inl(port) _inl((uintptr_t)(port)) 190005174d6SSimon Glass 191fea25720SGraeme Russ __OUT(b,"b",char) 192fea25720SGraeme Russ __OUT(w,"w",short) 193fea25720SGraeme Russ __OUT(l,,int) 194fea25720SGraeme Russ 195005174d6SSimon Glass #define outb(val, port) _outb(val, (uintptr_t)(port)) 196005174d6SSimon Glass #define outw(val, port) _outw(val, (uintptr_t)(port)) 197005174d6SSimon Glass #define outl(val, port) _outl(val, (uintptr_t)(port)) 198005174d6SSimon Glass 199fea25720SGraeme Russ __INS(b) 200fea25720SGraeme Russ __INS(w) 201fea25720SGraeme Russ __INS(l) 202fea25720SGraeme Russ 203fea25720SGraeme Russ __OUTS(b) 204fea25720SGraeme Russ __OUTS(w) 205fea25720SGraeme Russ __OUTS(l) 206fea25720SGraeme Russ 20730928c11SSimon Glass /* IO space accessors */ 20830928c11SSimon Glass #define clrio(type, addr, clear) \ 20930928c11SSimon Glass out##type(in##type(addr) & ~(clear), (addr)) 21030928c11SSimon Glass 21130928c11SSimon Glass #define setio(type, addr, set) \ 21230928c11SSimon Glass out##type(in##type(addr) | (set), (addr)) 21330928c11SSimon Glass 21430928c11SSimon Glass #define clrsetio(type, addr, clear, set) \ 21530928c11SSimon Glass out##type((in##type(addr) & ~(clear)) | (set), (addr)) 21630928c11SSimon Glass 21730928c11SSimon Glass #define clrio_32(addr, clear) clrio(l, addr, clear) 21830928c11SSimon Glass #define clrio_16(addr, clear) clrio(w, addr, clear) 21930928c11SSimon Glass #define clrio_8(addr, clear) clrio(b, addr, clear) 22030928c11SSimon Glass 22130928c11SSimon Glass #define setio_32(addr, set) setio(l, addr, set) 22230928c11SSimon Glass #define setio_16(addr, set) setio(w, addr, set) 22330928c11SSimon Glass #define setio_8(addr, set) setio(b, addr, set) 22430928c11SSimon Glass 22530928c11SSimon Glass #define clrsetio_32(addr, clear, set) clrsetio(l, addr, clear, set) 22630928c11SSimon Glass #define clrsetio_16(addr, clear, set) clrsetio(w, addr, clear, set) 22730928c11SSimon Glass #define clrsetio_8(addr, clear, set) clrsetio(b, addr, clear, set) 22830928c11SSimon Glass 229fea25720SGraeme Russ static inline void sync(void) 230fea25720SGraeme Russ { 231fea25720SGraeme Russ } 232fea25720SGraeme Russ 233fea25720SGraeme Russ /* 234fea25720SGraeme Russ * Given a physical address and a length, return a virtual address 235fea25720SGraeme Russ * that can be used to access the memory range with the caching 236fea25720SGraeme Russ * properties specified by "flags". 237fea25720SGraeme Russ */ 238fea25720SGraeme Russ #define MAP_NOCACHE (0) 239fea25720SGraeme Russ #define MAP_WRCOMBINE (0) 240fea25720SGraeme Russ #define MAP_WRBACK (0) 241fea25720SGraeme Russ #define MAP_WRTHROUGH (0) 242fea25720SGraeme Russ 243fea25720SGraeme Russ static inline void * 244fea25720SGraeme Russ map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) 245fea25720SGraeme Russ { 246ec516c48SGabe Black return (void *)(uintptr_t)paddr; 247fea25720SGraeme Russ } 248fea25720SGraeme Russ 249fea25720SGraeme Russ /* 250fea25720SGraeme Russ * Take down a mapping set up by map_physmem(). 251fea25720SGraeme Russ */ 252fea25720SGraeme Russ static inline void unmap_physmem(void *vaddr, unsigned long flags) 253fea25720SGraeme Russ { 254fea25720SGraeme Russ 255fea25720SGraeme Russ } 256fea25720SGraeme Russ 257fea25720SGraeme Russ static inline phys_addr_t virt_to_phys(void * vaddr) 258fea25720SGraeme Russ { 259ec516c48SGabe Black return (phys_addr_t)(uintptr_t)(vaddr); 260fea25720SGraeme Russ } 261fea25720SGraeme Russ 2628a487a44SSimon Glass /* 2638a487a44SSimon Glass * TODO: The kernel offers some more advanced versions of barriers, it might 2648a487a44SSimon Glass * have some advantages to use them instead of the simple one here. 2658a487a44SSimon Glass */ 2668a487a44SSimon Glass #define dmb() __asm__ __volatile__ ("" : : : "memory") 2678a487a44SSimon Glass #define __iormb() dmb() 2688a487a44SSimon Glass #define __iowmb() dmb() 2698a487a44SSimon Glass 270*091e51d2SBin Meng #endif /* _ASM_IO_H */ 271