Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / include / asm-arm / arch-rpc / io.h
1 /*
2  *  linux/include/asm-arm/arch-rpc/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.
72  */
73 static inline void __outb (unsigned int value, unsigned int port)
74 {
75         unsigned long temp;
76         __asm__ __volatile__(
77         "tst    %2, #0x80000000\n\t"
78         "mov    %0, %4\n\t"
79         "addeq  %0, %0, %3\n\t"
80         "strb   %1, [%0, %2, lsl #2]    @ outb"
81         : "=&r" (temp)
82         : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
83         : "cc");
84 }
85
86 static inline void __outw (unsigned int value, unsigned int port)
87 {
88         unsigned long temp;
89         __asm__ __volatile__(
90         "tst    %2, #0x80000000\n\t"
91         "mov    %0, %4\n\t"
92         "addeq  %0, %0, %3\n\t"
93         "str    %1, [%0, %2, lsl #2]    @ outw"
94         : "=&r" (temp)
95         : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
96         : "cc");
97 }
98
99 static inline void __outl (unsigned int value, unsigned int port)
100 {
101         unsigned long temp;
102         __asm__ __volatile__(
103         "tst    %2, #0x80000000\n\t"
104         "mov    %0, %4\n\t"
105         "addeq  %0, %0, %3\n\t"
106         "str    %1, [%0, %2, lsl #2]    @ outl"
107         : "=&r" (temp)
108         : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
109         : "cc");
110 }
111
112 #define DECLARE_DYN_IN(sz,fnsuffix,instr)                                       \
113 static inline unsigned sz __in##fnsuffix (unsigned int port)            \
114 {                                                                               \
115         unsigned long temp, value;                                              \
116         __asm__ __volatile__(                                                   \
117         "tst    %2, #0x80000000\n\t"                                            \
118         "mov    %0, %4\n\t"                                                     \
119         "addeq  %0, %0, %3\n\t"                                                 \
120         "ldr" instr "   %1, [%0, %2, lsl #2]    @ in" #fnsuffix                 \
121         : "=&r" (temp), "=r" (value)                                            \
122         : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)                \
123         : "cc");                                                                \
124         return (unsigned sz)value;                                              \
125 }
126
127 static inline void __iomem *__ioaddr(unsigned int port)
128 {
129         void __iomem *ret;
130         if (__PORT_PCIO(port))
131                 ret = PCIO_BASE;
132         else
133                 ret = IO_BASE;
134         return ret + (port << 2);
135 }
136
137 #define DECLARE_IO(sz,fnsuffix,instr)   \
138         DECLARE_DYN_IN(sz,fnsuffix,instr)
139
140 DECLARE_IO(char,b,"b")
141 DECLARE_IO(short,w,"")
142 DECLARE_IO(int,l,"")
143
144 #undef DECLARE_IO
145 #undef DECLARE_DYN_IN
146
147 /*
148  * Constant address IO functions
149  *
150  * These have to be macros for the 'J' constraint to work -
151  * +/-4096 immediate operand.
152  */
153 #define __outbc(value,port)                                                     \
154 ({                                                                              \
155         if (__PORT_PCIO((port)))                                                \
156                 __asm__ __volatile__(                                           \
157                 "strb   %0, [%1, %2]    @ outbc"                                \
158                 : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));          \
159         else                                                                    \
160                 __asm__ __volatile__(                                           \
161                 "strb   %0, [%1, %2]    @ outbc"                                \
162                 : : "r" (value), "r" (IO_BASE), "r" ((port) << 2));             \
163 })
164
165 #define __inbc(port)                                                            \
166 ({                                                                              \
167         unsigned char result;                                                   \
168         if (__PORT_PCIO((port)))                                                \
169                 __asm__ __volatile__(                                           \
170                 "ldrb   %0, [%1, %2]    @ inbc"                                 \
171                 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));         \
172         else                                                                    \
173                 __asm__ __volatile__(                                           \
174                 "ldrb   %0, [%1, %2]    @ inbc"                                 \
175                 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));            \
176         result;                                                                 \
177 })
178
179 #define __outwc(value,port)                                                     \
180 ({                                                                              \
181         unsigned long __v = value;                                              \
182         if (__PORT_PCIO((port)))                                                \
183                 __asm__ __volatile__(                                           \
184                 "str    %0, [%1, %2]    @ outwc"                                \
185                 : : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));    \
186         else                                                                    \
187                 __asm__ __volatile__(                                           \
188                 "str    %0, [%1, %2]    @ outwc"                                \
189                 : : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2));               \
190 })
191
192 #define __inwc(port)                                                            \
193 ({                                                                              \
194         unsigned short result;                                                  \
195         if (__PORT_PCIO((port)))                                                \
196                 __asm__ __volatile__(                                           \
197                 "ldr    %0, [%1, %2]    @ inwc"                                 \
198                 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));         \
199         else                                                                    \
200                 __asm__ __volatile__(                                           \
201                 "ldr    %0, [%1, %2]    @ inwc"                                 \
202                 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));            \
203         result & 0xffff;                                                        \
204 })
205
206 #define __outlc(value,port)                                                     \
207 ({                                                                              \
208         unsigned long __v = value;                                              \
209         if (__PORT_PCIO((port)))                                                \
210                 __asm__ __volatile__(                                           \
211                 "str    %0, [%1, %2]    @ outlc"                                \
212                 : : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2));            \
213         else                                                                    \
214                 __asm__ __volatile__(                                           \
215                 "str    %0, [%1, %2]    @ outlc"                                \
216                 : : "r" (__v), "r" (IO_BASE), "r" ((port) << 2));               \
217 })
218
219 #define __inlc(port)                                                            \
220 ({                                                                              \
221         unsigned long result;                                                   \
222         if (__PORT_PCIO((port)))                                                \
223                 __asm__ __volatile__(                                           \
224                 "ldr    %0, [%1, %2]    @ inlc"                                 \
225                 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));         \
226         else                                                                    \
227                 __asm__ __volatile__(                                           \
228                 "ldr    %0, [%1, %2]    @ inlc"                                 \
229                 : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));            \
230         result;                                                                 \
231 })
232
233 #define __ioaddrc(port)         \
234         ((__PORT_PCIO(port) ? PCIO_BASE : IO_BASE) + ((port) << 2))
235
236 #define inb(p)          (__builtin_constant_p((p)) ? __inbc(p)    : __inb(p))
237 #define inw(p)          (__builtin_constant_p((p)) ? __inwc(p)    : __inw(p))
238 #define inl(p)          (__builtin_constant_p((p)) ? __inlc(p)    : __inl(p))
239 #define outb(v,p)       (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
240 #define outw(v,p)       (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
241 #define outl(v,p)       (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
242 #define __ioaddr(p)     (__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
243 /* the following macro is deprecated */
244 #define ioaddr(port)    ((unsigned long)__ioaddr((port)))
245
246 #define insb(p,d,l)     __raw_readsb(__ioaddr(p),d,l)
247 #define insw(p,d,l)     __raw_readsw(__ioaddr(p),d,l)
248
249 #define outsb(p,d,l)    __raw_writesb(__ioaddr(p),d,l)
250 #define outsw(p,d,l)    __raw_writesw(__ioaddr(p),d,l)
251
252 /*
253  * 1:1 mapping for ioremapped regions.
254  */
255 #define __mem_pci(x)    (x)
256
257 #endif