1 /* 2 * arch/arm/mach-rpc/include/mach/io.h 3 * 4 * Copyright (C) 1997 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Modifications: 11 * 06-Dec-1997 RMK Created. 12 */ 13 #ifndef __ASM_ARM_ARCH_IO_H 14 #define __ASM_ARM_ARCH_IO_H 15 16 #include <mach/hardware.h> 17 18 #define IO_SPACE_LIMIT 0xffffffff 19 20 /* 21 * We use two different types of addressing - PC style addresses, and ARM 22 * addresses. PC style accesses the PC hardware with the normal PC IO 23 * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ 24 * and are translated to the start of IO. Note that all addresses are 25 * shifted left! 26 */ 27 #define __PORT_PCIO(x) (!((x) & 0x80000000)) 28 29 /* 30 * Dynamic IO functions. 31 */ 32 static inline void __outb (unsigned int value, unsigned int port) 33 { 34 unsigned long temp; 35 __asm__ __volatile__( 36 "tst %2, #0x80000000\n\t" 37 "mov %0, %4\n\t" 38 "addeq %0, %0, %3\n\t" 39 "strb %1, [%0, %2, lsl #2] @ outb" 40 : "=&r" (temp) 41 : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) 42 : "cc"); 43 } 44 45 static inline void __outw (unsigned int value, unsigned int port) 46 { 47 unsigned long temp; 48 __asm__ __volatile__( 49 "tst %2, #0x80000000\n\t" 50 "mov %0, %4\n\t" 51 "addeq %0, %0, %3\n\t" 52 "str %1, [%0, %2, lsl #2] @ outw" 53 : "=&r" (temp) 54 : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) 55 : "cc"); 56 } 57 58 static inline void __outl (unsigned int value, unsigned int port) 59 { 60 unsigned long temp; 61 __asm__ __volatile__( 62 "tst %2, #0x80000000\n\t" 63 "mov %0, %4\n\t" 64 "addeq %0, %0, %3\n\t" 65 "str %1, [%0, %2, lsl #2] @ outl" 66 : "=&r" (temp) 67 : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) 68 : "cc"); 69 } 70 71 #define DECLARE_DYN_IN(sz,fnsuffix,instr) \ 72 static inline unsigned sz __in##fnsuffix (unsigned int port) \ 73 { \ 74 unsigned long temp, value; \ 75 __asm__ __volatile__( \ 76 "tst %2, #0x80000000\n\t" \ 77 "mov %0, %4\n\t" \ 78 "addeq %0, %0, %3\n\t" \ 79 "ldr" instr " %1, [%0, %2, lsl #2] @ in" #fnsuffix \ 80 : "=&r" (temp), "=r" (value) \ 81 : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ 82 : "cc"); \ 83 return (unsigned sz)value; \ 84 } 85 86 static inline void __iomem *__deprecated __ioaddr(unsigned int port) 87 { 88 void __iomem *ret; 89 if (__PORT_PCIO(port)) 90 ret = PCIO_BASE; 91 else 92 ret = IO_BASE; 93 return ret + (port << 2); 94 } 95 96 #define DECLARE_IO(sz,fnsuffix,instr) \ 97 DECLARE_DYN_IN(sz,fnsuffix,instr) 98 99 DECLARE_IO(char,b,"b") 100 DECLARE_IO(short,w,"") 101 DECLARE_IO(int,l,"") 102 103 #undef DECLARE_IO 104 #undef DECLARE_DYN_IN 105 106 /* 107 * Constant address IO functions 108 * 109 * These have to be macros for the 'J' constraint to work - 110 * +/-4096 immediate operand. 111 */ 112 #define __outbc(value,port) \ 113 ({ \ 114 if (__PORT_PCIO((port))) \ 115 __asm__ __volatile__( \ 116 "strb %0, [%1, %2] @ outbc" \ 117 : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ 118 else \ 119 __asm__ __volatile__( \ 120 "strb %0, [%1, %2] @ outbc" \ 121 : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ 122 }) 123 124 #define __inbc(port) \ 125 ({ \ 126 unsigned char result; \ 127 if (__PORT_PCIO((port))) \ 128 __asm__ __volatile__( \ 129 "ldrb %0, [%1, %2] @ inbc" \ 130 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ 131 else \ 132 __asm__ __volatile__( \ 133 "ldrb %0, [%1, %2] @ inbc" \ 134 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ 135 result; \ 136 }) 137 138 #define __outwc(value,port) \ 139 ({ \ 140 unsigned long __v = value; \ 141 if (__PORT_PCIO((port))) \ 142 __asm__ __volatile__( \ 143 "str %0, [%1, %2] @ outwc" \ 144 : : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ 145 else \ 146 __asm__ __volatile__( \ 147 "str %0, [%1, %2] @ outwc" \ 148 : : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ 149 }) 150 151 #define __inwc(port) \ 152 ({ \ 153 unsigned short result; \ 154 if (__PORT_PCIO((port))) \ 155 __asm__ __volatile__( \ 156 "ldr %0, [%1, %2] @ inwc" \ 157 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ 158 else \ 159 __asm__ __volatile__( \ 160 "ldr %0, [%1, %2] @ inwc" \ 161 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ 162 result & 0xffff; \ 163 }) 164 165 #define __outlc(value,port) \ 166 ({ \ 167 unsigned long __v = value; \ 168 if (__PORT_PCIO((port))) \ 169 __asm__ __volatile__( \ 170 "str %0, [%1, %2] @ outlc" \ 171 : : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ 172 else \ 173 __asm__ __volatile__( \ 174 "str %0, [%1, %2] @ outlc" \ 175 : : "r" (__v), "r" (IO_BASE), "r" ((port) << 2)); \ 176 }) 177 178 #define __inlc(port) \ 179 ({ \ 180 unsigned long result; \ 181 if (__PORT_PCIO((port))) \ 182 __asm__ __volatile__( \ 183 "ldr %0, [%1, %2] @ inlc" \ 184 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ 185 else \ 186 __asm__ __volatile__( \ 187 "ldr %0, [%1, %2] @ inlc" \ 188 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ 189 result; \ 190 }) 191 192 #define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p)) 193 #define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p)) 194 #define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p)) 195 #define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p)) 196 #define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p)) 197 #define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p)) 198 199 /* the following macro is deprecated */ 200 #define ioaddr(port) ((unsigned long)__ioaddr((port))) 201 202 #define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l) 203 #define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l) 204 205 #define outsb(p,d,l) __raw_writesb(__ioaddr(p),d,l) 206 #define outsw(p,d,l) __raw_writesw(__ioaddr(p),d,l) 207 208 /* 209 * 1:1 mapping for ioremapped regions. 210 */ 211 #define __mem_pci(x) (x) 212 213 #endif 214