[ARM] 3009/1: S3C2410 - io.h offsets too large for LDRH/STRH
[linux-3.10.git] / include / asm-arm / arch-s3c2410 / io.h
1 /*
2  * linux/include/asm-arm/arch-s3c2410/io.h
3  *  from linux/include/asm-arm/arch-rpc/io.h
4  *
5  * Copyright (C) 1997 Russell King
6  *           (C) 2003 Simtec Electronics
7  *
8  * Modifications:
9  *  06-Dec-1997 RMK     Created.
10  *  02-Sep-2003 BJD     Modified for S3C2410
11  *  10-Mar-2005 LCVR    Changed S3C2410_VA to S3C24XX_VA
12  *  13-Oct-2005 BJD     Fixed problems with LDRH/STRH offset range
13  */
14
15 #ifndef __ASM_ARM_ARCH_IO_H
16 #define __ASM_ARM_ARCH_IO_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 above A28
24  * and are translated to the start of IO.  Note that all addresses are
25  * not shifted left!
26  */
27
28 #define __PORT_PCIO(x)  ((x) < (1<<28))
29
30 #define PCIO_BASE        (S3C24XX_VA_ISA_WORD)
31 #define PCIO_BASE_b      (S3C24XX_VA_ISA_BYTE)
32 #define PCIO_BASE_w      (S3C24XX_VA_ISA_WORD)
33 #define PCIO_BASE_l      (S3C24XX_VA_ISA_WORD)
34 /*
35  * Dynamic IO functions - let the compiler
36  * optimize the expressions
37  */
38
39 #define DECLARE_DYN_OUT(sz,fnsuffix,instr) \
40 static inline void __out##fnsuffix (unsigned int val, unsigned int port) \
41 { \
42         unsigned long temp;                                   \
43         __asm__ __volatile__(                                 \
44         "cmp    %2, #(1<<28)\n\t"                             \
45         "mov    %0, %2\n\t"                                   \
46         "addcc  %0, %0, %3\n\t"                               \
47         "str" instr " %1, [%0, #0 ]     @ out" #fnsuffix      \
48         : "=&r" (temp)                                        \
49         : "r" (val), "r" (port), "Ir" (PCIO_BASE_##fnsuffix)  \
50         : "cc");                                              \
51 }
52
53
54 #define DECLARE_DYN_IN(sz,fnsuffix,instr)                               \
55 static inline unsigned sz __in##fnsuffix (unsigned int port)            \
56 {                                                                       \
57         unsigned long temp, value;                                      \
58         __asm__ __volatile__(                                           \
59         "cmp    %2, #(1<<28)\n\t"                                       \
60         "mov    %0, %2\n\t"                                             \
61         "addcc  %0, %0, %3\n\t"                                         \
62         "ldr" instr "   %1, [%0, #0 ]   @ in" #fnsuffix         \
63         : "=&r" (temp), "=r" (value)                                    \
64         : "r" (port), "Ir" (PCIO_BASE_##fnsuffix)       \
65         : "cc");                                                        \
66         return (unsigned sz)value;                                      \
67 }
68
69 static inline void __iomem *__ioaddr (unsigned long port)
70 {
71         return __PORT_PCIO(port) ? (PCIO_BASE + port) : (void __iomem *)port;
72 }
73
74 #define DECLARE_IO(sz,fnsuffix,instr)   \
75         DECLARE_DYN_IN(sz,fnsuffix,instr) \
76         DECLARE_DYN_OUT(sz,fnsuffix,instr)
77
78 DECLARE_IO(char,b,"b")
79 DECLARE_IO(short,w,"h")
80 DECLARE_IO(int,l,"")
81
82 #undef DECLARE_IO
83 #undef DECLARE_DYN_IN
84
85 /*
86  * Constant address IO functions
87  *
88  * These have to be macros for the 'J' constraint to work -
89  * +/-4096 immediate operand.
90  */
91 #define __outbc(value,port)                                             \
92 ({                                                                      \
93         if (__PORT_PCIO((port)))                                        \
94                 __asm__ __volatile__(                                   \
95                 "strb   %0, [%1, %2]    @ outbc"                        \
96                 : : "r" (value), "r" (PCIO_BASE), "Jr" ((port)));       \
97         else                                                            \
98                 __asm__ __volatile__(                                   \
99                 "strb   %0, [%1, #0]    @ outbc"                        \
100                 : : "r" (value), "r" ((port)));                         \
101 })
102
103 #define __inbc(port)                                                    \
104 ({                                                                      \
105         unsigned char result;                                           \
106         if (__PORT_PCIO((port)))                                        \
107                 __asm__ __volatile__(                                   \
108                 "ldrb   %0, [%1, %2]    @ inbc"                         \
109                 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port)));      \
110         else                                                            \
111                 __asm__ __volatile__(                                   \
112                 "ldrb   %0, [%1, #0]    @ inbc"                         \
113                 : "=r" (result) : "r" ((port)));                        \
114         result;                                                         \
115 })
116
117 #define __outwc(value,port)                                             \
118 ({                                                                      \
119         unsigned long v = value;                                        \
120         if (__PORT_PCIO((port))) {                                      \
121                 if ((port) < 256 && (port) > -256)                      \
122                         __asm__ __volatile__(                           \
123                         "strh   %0, [%1, %2]    @ outwc"                \
124                         : : "r" (v), "r" (PCIO_BASE), "Jr" ((port)));   \
125                 else if ((port) > 0)                                    \
126                         __asm__ __volatile__(                           \
127                         "strh   %0, [%1, %2]    @ outwc"                \
128                         : : "r" (v),                                    \
129                             "r" (PCIO_BASE + ((port) & ~0xff)),         \
130                              "Jr" (((port) & 0xff)));                   \
131                 else                                                    \
132                         __asm__ __volatile__(                           \
133                         "strh   %0, [%1, #0]    @ outwc"                \
134                         : : "r" (v),                                    \
135                             "r" (PCIO_BASE + (port)));                  \
136         } else                                                          \
137                 __asm__ __volatile__(                                   \
138                 "strh   %0, [%1, #0]    @ outwc"                        \
139                 : : "r" (v), "r" ((port)));                             \
140 })
141
142 #define __inwc(port)                                                    \
143 ({                                                                      \
144         unsigned short result;                                          \
145         if (__PORT_PCIO((port))) {                                      \
146                 if ((port) < 256 && (port) > -256 )                     \
147                         __asm__ __volatile__(                           \
148                         "ldrh   %0, [%1, %2]    @ inwc"                 \
149                         : "=r" (result)                                 \
150                         : "r" (PCIO_BASE),                              \
151                           "Jr" ((port)));                               \
152                 else if ((port) > 0)                                    \
153                         __asm__ __volatile__(                           \
154                         "ldrh   %0, [%1, %2]    @ inwc"                 \
155                         : "=r" (result)                                 \
156                         : "r" (PCIO_BASE + ((port) & ~0xff)),           \
157                           "Jr" (((port) & 0xff)));                      \
158                 else                                                    \
159                         __asm__ __volatile__(                           \
160                         "ldrh   %0, [%1, #0]    @ inwc"                 \
161                         : "=r" (result)                                 \
162                         : "r" (PCIO_BASE + ((port))));                  \
163         } else                                                          \
164                 __asm__ __volatile__(                                   \
165                 "ldrh   %0, [%1, #0]    @ inwc"                         \
166                 : "=r" (result) : "r" ((port)));                        \
167         result;                                                         \
168 })
169
170 #define __outlc(value,port)                                             \
171 ({                                                                      \
172         unsigned long v = value;                                        \
173         if (__PORT_PCIO((port)))                                        \
174                 __asm__ __volatile__(                                   \
175                 "str    %0, [%1, %2]    @ outlc"                        \
176                 : : "r" (v), "r" (PCIO_BASE), "Jr" ((port)));   \
177         else                                                            \
178                 __asm__ __volatile__(                                   \
179                 "str    %0, [%1, #0]    @ outlc"                        \
180                 : : "r" (v), "r" ((port)));             \
181 })
182
183 #define __inlc(port)                                                    \
184 ({                                                                      \
185         unsigned long result;                                           \
186         if (__PORT_PCIO((port)))                                        \
187                 __asm__ __volatile__(                                   \
188                 "ldr    %0, [%1, %2]    @ inlc"                         \
189                 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port)));      \
190         else                                                            \
191                 __asm__ __volatile__(                                   \
192                 "ldr    %0, [%1, #0]    @ inlc"                         \
193                 : "=r" (result) : "r" ((port)));                \
194         result;                                                         \
195 })
196
197 #define __ioaddrc(port) ((__PORT_PCIO(port) ? PCIO_BASE + (port) : (void __iomem *)(port)))
198
199 #define inb(p)          (__builtin_constant_p((p)) ? __inbc(p)     : __inb(p))
200 #define inw(p)          (__builtin_constant_p((p)) ? __inwc(p)     : __inw(p))
201 #define inl(p)          (__builtin_constant_p((p)) ? __inlc(p)     : __inl(p))
202 #define outb(v,p)       (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
203 #define outw(v,p)       (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
204 #define outl(v,p)       (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
205 #define __ioaddr(p)     (__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
206 /* the following macro is deprecated */
207 #define ioaddr(port)    __ioaddr((port))
208
209 #define insb(p,d,l)     __raw_readsb(__ioaddr(p),d,l)
210 #define insw(p,d,l)     __raw_readsw(__ioaddr(p),d,l)
211 #define insl(p,d,l)     __raw_readsl(__ioaddr(p),d,l)
212
213 #define outsb(p,d,l)    __raw_writesb(__ioaddr(p),d,l)
214 #define outsw(p,d,l)    __raw_writesw(__ioaddr(p),d,l)
215 #define outsl(p,d,l)    __raw_writesl(__ioaddr(p),d,l)
216
217 /*
218  * 1:1 mapping for ioremapped regions.
219  */
220 #define __mem_pci(x)    (x)
221
222 #endif