1 /*
2 * linux/include/asm-arm/arch-arc/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 #define IO_SPACE_LIMIT 0xffffffff
17
18 /*
19 * GCC is totally crap at loading/storing data. We try to persuade it
20 * to do the right thing by using these whereever possible instead of
21 * the above.
22 */
23 #define __arch_base_getb(b,o) \
24 ({ \
25 unsigned int v, r = (b); \
26 __asm__ __volatile__( \
27 "ldrb %0, [%1, %2]" \
28 : "=r" (v) \
29 : "r" (r), "Ir" (o)); \
30 v; \
31 })
32
33 #define __arch_base_getl(b,o) \
34 ({ \
35 unsigned int v, r = (b); \
36 __asm__ __volatile__( \
37 "ldr %0, [%1, %2]" \
38 : "=r" (v) \
39 : "r" (r), "Ir" (o)); \
40 v; \
41 })
42
43 #define __arch_base_putb(v,b,o) \
44 ({ \
45 unsigned int r = (b); \
46 __asm__ __volatile__( \
47 "strb %0, [%1, %2]" \
48 : \
49 : "r" (v), "r" (r), "Ir" (o)); \
50 })
51
52 #define __arch_base_putl(v,b,o) \
53 ({ \
54 unsigned int r = (b); \
55 __asm__ __volatile__( \
56 "str %0, [%1, %2]" \
57 : \
58 : "r" (v), "r" (r), "Ir" (o)); \
59 })
60
61 /*
62 * We use two different types of addressing - PC style addresses, and ARM
63 * addresses. PC style accesses the PC hardware with the normal PC IO
64 * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+
65 * and are translated to the start of IO. Note that all addresses are
66 * shifted left!
67 */
68 #define __PORT_PCIO(x) (!((x) & 0x80000000))
69
70 /*
71 * Dynamic IO functions - let the compiler
72 * optimize the expressions
73 */
__outb(unsigned int value,unsigned int port)74 static inline void __outb (unsigned int value, unsigned int port)
75 {
76 unsigned long temp;
77 __asm__ __volatile__(
78 "tst %2, #0x80000000\n\t"
79 "mov %0, %4\n\t"
80 "addeq %0, %0, %3\n\t"
81 "strb %1, [%0, %2, lsl #2] @ outb"
82 : "=&r" (temp)
83 : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
84 : "cc");
85 }
86
__outw(unsigned int value,unsigned int port)87 static inline void __outw (unsigned int value, unsigned int port)
88 {
89 unsigned long temp;
90 __asm__ __volatile__(
91 "tst %2, #0x80000000\n\t"
92 "mov %0, %4\n\t"
93 "addeq %0, %0, %3\n\t"
94 "str %1, [%0, %2, lsl #2] @ outw"
95 : "=&r" (temp)
96 : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
97 : "cc");
98 }
99
__outl(unsigned int value,unsigned int port)100 static inline void __outl (unsigned int value, unsigned int port)
101 {
102 unsigned long temp;
103 __asm__ __volatile__(
104 "tst %2, #0x80000000\n\t"
105 "mov %0, %4\n\t"
106 "addeq %0, %0, %3\n\t"
107 "str %1, [%0, %2, lsl #2] @ outl"
108 : "=&r" (temp)
109 : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
110 : "cc");
111 }
112
113 #define DECLARE_DYN_IN(sz,fnsuffix,instr) \
114 static inline unsigned sz __in##fnsuffix (unsigned int port) \
115 { \
116 unsigned long temp, value; \
117 __asm__ __volatile__( \
118 "tst %2, #0x80000000\n\t" \
119 "mov %0, %4\n\t" \
120 "addeq %0, %0, %3\n\t" \
121 "ldr" instr " %1, [%0, %2, lsl #2] @ in" #fnsuffix \
122 : "=&r" (temp), "=r" (value) \
123 : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
124 : "cc"); \
125 return (unsigned sz)value; \
126 }
127
__ioaddr(unsigned int port)128 static inline unsigned int __ioaddr (unsigned int port) \
129 { \
130 if (__PORT_PCIO(port)) \
131 return (unsigned int)(PCIO_BASE + (port << 2)); \
132 else \
133 return (unsigned int)(IO_BASE + (port << 2)); \
134 }
135
136 #define DECLARE_IO(sz,fnsuffix,instr) \
137 DECLARE_DYN_IN(sz,fnsuffix,instr)
138
139 DECLARE_IO(char,b,"b")
140 DECLARE_IO(short,w,"")
141 DECLARE_IO(int,l,"")
142
143 #undef DECLARE_IO
144 #undef DECLARE_DYN_IN
145
146 /*
147 * Constant address IO functions
148 *
149 * These have to be macros for the 'J' constraint to work -
150 * +/-4096 immediate operand.
151 */
152 #define __outbc(value,port) \
153 ({ \
154 if (__PORT_PCIO((port))) \
155 __asm__ __volatile__( \
156 "strb %0, [%1, %2] @ outbc" \
157 : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
158 else \
159 __asm__ __volatile__( \
160 "strb %0, [%1, %2] @ outbc" \
161 : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \
162 })
163
164 #define __inbc(port) \
165 ({ \
166 unsigned char result; \
167 if (__PORT_PCIO((port))) \
168 __asm__ __volatile__( \
169 "ldrb %0, [%1, %2] @ inbc" \
170 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
171 else \
172 __asm__ __volatile__( \
173 "ldrb %0, [%1, %2] @ inbc" \
174 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
175 result; \
176 })
177
178 #define __outwc(value,port) \
179 ({ \
180 unsigned long v = value; \
181 if (__PORT_PCIO((port))) \
182 __asm__ __volatile__( \
183 "str %0, [%1, %2] @ outwc" \
184 : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
185 else \
186 __asm__ __volatile__( \
187 "str %0, [%1, %2] @ outwc" \
188 : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \
189 })
190
191 #define __inwc(port) \
192 ({ \
193 unsigned short result; \
194 if (__PORT_PCIO((port))) \
195 __asm__ __volatile__( \
196 "ldr %0, [%1, %2] @ inwc" \
197 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
198 else \
199 __asm__ __volatile__( \
200 "ldr %0, [%1, %2] @ inwc" \
201 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
202 result & 0xffff; \
203 })
204
205 #define __outlc(value,port) \
206 ({ \
207 unsigned long v = value; \
208 if (__PORT_PCIO((port))) \
209 __asm__ __volatile__( \
210 "str %0, [%1, %2] @ outlc" \
211 : : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
212 else \
213 __asm__ __volatile__( \
214 "str %0, [%1, %2] @ outlc" \
215 : : "r" (v), "r" (IO_BASE), "r" ((port) << 2)); \
216 })
217
218 #define __inlc(port) \
219 ({ \
220 unsigned long result; \
221 if (__PORT_PCIO((port))) \
222 __asm__ __volatile__( \
223 "ldr %0, [%1, %2] @ inlc" \
224 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
225 else \
226 __asm__ __volatile__( \
227 "ldr %0, [%1, %2] @ inlc" \
228 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
229 result; \
230 })
231
232 #define __ioaddrc(port) \
233 ({ \
234 unsigned long addr; \
235 if (__PORT_PCIO((port))) \
236 addr = PCIO_BASE + ((port) << 2); \
237 else \
238 addr = IO_BASE + ((port) << 2); \
239 addr; \
240 })
241
242 #define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p))
243 #define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p))
244 #define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p))
245 #define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
246 #define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
247 #define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
248 #define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
249 /* the following macro is depreciated */
250 #define ioaddr(port) __ioaddr((port))
251
252 #endif
253