Linux-2.6.12-rc2
[linux-3.10.git] / arch / arm / mach-ebsa110 / io.c
1 /*
2  *  linux/arch/arm/mach-ebsa110/isamem.c
3  *
4  *  Copyright (C) 2001 Russell King
5  *
6  * Perform "ISA" memory and IO accesses.  The EBSA110 has some "peculiarities"
7  * in the way it handles accesses to odd IO ports on 16-bit devices.  These
8  * devices have their D0-D15 lines connected to the processors D0-D15 lines.
9  * Since they expect all byte IO operations to be performed on D0-D7, and the
10  * StrongARM expects to transfer the byte to these odd addresses on D8-D15,
11  * we must use a trick to get the required behaviour.
12  *
13  * The trick employed here is to use long word stores to odd address -1.  The
14  * glue logic picks this up as a "trick" access, and asserts the LSB of the
15  * peripherals address bus, thereby accessing the odd IO port.  Meanwhile, the
16  * StrongARM transfers its data on D0-D7 as expected.
17  *
18  * Things get more interesting on the pass-1 EBSA110 - the PCMCIA controller
19  * wiring was screwed in such a way that it had limited memory space access.
20  * Luckily, the work-around for this is not too horrible.  See
21  * __isamem_convert_addr for the details.
22  */
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/types.h>
26
27 #include <asm/io.h>
28 #include <asm/page.h>
29
30 static void __iomem *__isamem_convert_addr(void __iomem *addr)
31 {
32         u32 ret, a = (u32 __force) addr;
33
34         /*
35          * The PCMCIA controller is wired up as follows:
36          *        +---------+---------+---------+---------+---------+---------+
37          * PCMCIA | 2 2 2 2 | 1 1 1 1 | 1 1 1 1 | 1 1     |         |         |
38          *        | 3 2 1 0 | 9 8 7 6 | 5 4 3 2 | 1 0 9 8 | 7 6 5 4 | 3 2 1 0 |
39          *        +---------+---------+---------+---------+---------+---------+
40          *  CPU   | 2 2 2 2 | 2 1 1 1 | 1 1 1 1 | 1 1 1   |         |         |
41          *        | 4 3 2 1 | 0 9 9 8 | 7 6 5 4 | 3 2 0 9 | 8 7 6 5 | 4 3 2 x |
42          *        +---------+---------+---------+---------+---------+---------+
43          *
44          * This means that we can access PCMCIA regions as follows:
45          *      0x*10000 -> 0x*1ffff
46          *      0x*70000 -> 0x*7ffff
47          *      0x*90000 -> 0x*9ffff
48          *      0x*f0000 -> 0x*fffff
49          */
50         ret  = (a & 0xf803fe) << 1;
51         ret |= (a & 0x03fc00) << 2;
52
53         ret += 0xe8000000;
54
55         if ((a & 0x20000) == (a & 0x40000) >> 1)
56                 return (void __iomem *)ret;
57
58         BUG();
59         return NULL;
60 }
61
62 /*
63  * read[bwl] and write[bwl]
64  */
65 u8 __readb(void __iomem *addr)
66 {
67         void __iomem *a = __isamem_convert_addr(addr);
68         u32 ret;
69
70         if ((unsigned long)addr & 1)
71                 ret = __raw_readl(a);
72         else
73                 ret = __raw_readb(a);
74         return ret;
75 }
76
77 u16 __readw(void __iomem *addr)
78 {
79         void __iomem *a = __isamem_convert_addr(addr);
80
81         if ((unsigned long)addr & 1)
82                 BUG();
83
84         return __raw_readw(a);
85 }
86
87 u32 __readl(void __iomem *addr)
88 {
89         void __iomem *a = __isamem_convert_addr(addr);
90         u32 ret;
91
92         if ((unsigned long)addr & 3)
93                 BUG();
94
95         ret = __raw_readw(a);
96         ret |= __raw_readw(a + 4) << 16;
97         return ret;
98 }
99
100 EXPORT_SYMBOL(__readb);
101 EXPORT_SYMBOL(__readw);
102 EXPORT_SYMBOL(__readl);
103
104 void __writeb(u8 val, void __iomem *addr)
105 {
106         void __iomem *a = __isamem_convert_addr(addr);
107
108         if ((unsigned long)addr & 1)
109                 __raw_writel(val, a);
110         else
111                 __raw_writeb(val, a);
112 }
113
114 void __writew(u16 val, void __iomem *addr)
115 {
116         void __iomem *a = __isamem_convert_addr(addr);
117
118         if ((unsigned long)addr & 1)
119                 BUG();
120
121         __raw_writew(val, a);
122 }
123
124 void __writel(u32 val, void __iomem *addr)
125 {
126         void __iomem *a = __isamem_convert_addr(addr);
127
128         if ((unsigned long)addr & 3)
129                 BUG();
130
131         __raw_writew(val, a);
132         __raw_writew(val >> 16, a + 4);
133 }
134
135 EXPORT_SYMBOL(__writeb);
136 EXPORT_SYMBOL(__writew);
137 EXPORT_SYMBOL(__writel);
138
139 #define SUPERIO_PORT(p) \
140         (((p) >> 3) == (0x3f8 >> 3) || \
141          ((p) >> 3) == (0x2f8 >> 3) || \
142          ((p) >> 3) == (0x378 >> 3))
143
144 /*
145  * We're addressing an 8 or 16-bit peripheral which tranfers
146  * odd addresses on the low ISA byte lane.
147  */
148 u8 __inb8(unsigned int port)
149 {
150         u32 ret;
151
152         /*
153          * The SuperIO registers use sane addressing techniques...
154          */
155         if (SUPERIO_PORT(port))
156                 ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2));
157         else {
158                 void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
159
160                 /*
161                  * Shame nothing else does
162                  */
163                 if (port & 1)
164                         ret = __raw_readl(a);
165                 else
166                         ret = __raw_readb(a);
167         }
168         return ret;
169 }
170
171 /*
172  * We're addressing a 16-bit peripheral which transfers odd
173  * addresses on the high ISA byte lane.
174  */
175 u8 __inb16(unsigned int port)
176 {
177         unsigned int offset;
178
179         /*
180          * The SuperIO registers use sane addressing techniques...
181          */
182         if (SUPERIO_PORT(port))
183                 offset = port << 2;
184         else
185                 offset = (port & ~1) << 1 | (port & 1);
186
187         return __raw_readb((void __iomem *)ISAIO_BASE + offset);
188 }
189
190 u16 __inw(unsigned int port)
191 {
192         unsigned int offset;
193
194         /*
195          * The SuperIO registers use sane addressing techniques...
196          */
197         if (SUPERIO_PORT(port))
198                 offset = port << 2;
199         else {
200                 offset = port << 1;
201                 BUG_ON(port & 1);
202         }
203         return __raw_readw((void __iomem *)ISAIO_BASE + offset);
204 }
205
206 /*
207  * Fake a 32-bit read with two 16-bit reads.  Needed for 3c589.
208  */
209 u32 __inl(unsigned int port)
210 {
211         void __iomem *a;
212
213         if (SUPERIO_PORT(port) || port & 3)
214                 BUG();
215
216         a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
217
218         return __raw_readw(a) | __raw_readw(a + 4) << 16;
219 }
220
221 EXPORT_SYMBOL(__inb8);
222 EXPORT_SYMBOL(__inb16);
223 EXPORT_SYMBOL(__inw);
224 EXPORT_SYMBOL(__inl);
225
226 void __outb8(u8 val, unsigned int port)
227 {
228         /*
229          * The SuperIO registers use sane addressing techniques...
230          */
231         if (SUPERIO_PORT(port))
232                 __raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2));
233         else {
234                 void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
235
236                 /*
237                  * Shame nothing else does
238                  */
239                 if (port & 1)
240                         __raw_writel(val, a);
241                 else
242                         __raw_writeb(val, a);
243         }
244 }
245
246 void __outb16(u8 val, unsigned int port)
247 {
248         unsigned int offset;
249
250         /*
251          * The SuperIO registers use sane addressing techniques...
252          */
253         if (SUPERIO_PORT(port))
254                 offset = port << 2;
255         else
256                 offset = (port & ~1) << 1 | (port & 1);
257
258         __raw_writeb(val, (void __iomem *)ISAIO_BASE + offset);
259 }
260
261 void __outw(u16 val, unsigned int port)
262 {
263         unsigned int offset;
264
265         /*
266          * The SuperIO registers use sane addressing techniques...
267          */
268         if (SUPERIO_PORT(port))
269                 offset = port << 2;
270         else {
271                 offset = port << 1;
272                 BUG_ON(port & 1);
273         }
274         __raw_writew(val, (void __iomem *)ISAIO_BASE + offset);
275 }
276
277 void __outl(u32 val, unsigned int port)
278 {
279         BUG();
280 }
281
282 EXPORT_SYMBOL(__outb8);
283 EXPORT_SYMBOL(__outb16);
284 EXPORT_SYMBOL(__outw);
285 EXPORT_SYMBOL(__outl);
286
287 void outsb(unsigned int port, const void *from, int len)
288 {
289         u32 off;
290
291         if (SUPERIO_PORT(port))
292                 off = port << 2;
293         else {
294                 off = (port & ~1) << 1;
295                 if (port & 1)
296                         BUG();
297         }
298
299         __raw_writesb((void __iomem *)ISAIO_BASE + off, from, len);
300 }
301
302 void insb(unsigned int port, void *from, int len)
303 {
304         u32 off;
305
306         if (SUPERIO_PORT(port))
307                 off = port << 2;
308         else {
309                 off = (port & ~1) << 1;
310                 if (port & 1)
311                         BUG();
312         }
313
314         __raw_readsb((void __iomem *)ISAIO_BASE + off, from, len);
315 }
316
317 EXPORT_SYMBOL(outsb);
318 EXPORT_SYMBOL(insb);
319
320 void outsw(unsigned int port, const void *from, int len)
321 {
322         u32 off;
323
324         if (SUPERIO_PORT(port))
325                 off = port << 2;
326         else {
327                 off = (port & ~1) << 1;
328                 if (port & 1)
329                         BUG();
330         }
331
332         __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len);
333 }
334
335 void insw(unsigned int port, void *from, int len)
336 {
337         u32 off;
338
339         if (SUPERIO_PORT(port))
340                 off = port << 2;
341         else {
342                 off = (port & ~1) << 1;
343                 if (port & 1)
344                         BUG();
345         }
346
347         __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len);
348 }
349
350 EXPORT_SYMBOL(outsw);
351 EXPORT_SYMBOL(insw);
352
353 /*
354  * We implement these as 16-bit insw/outsw, mainly for
355  * 3c589 cards.
356  */
357 void outsl(unsigned int port, const void *from, int len)
358 {
359         u32 off = port << 1;
360
361         if (SUPERIO_PORT(port) || port & 3)
362                 BUG();
363
364         __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1);
365 }
366
367 void insl(unsigned int port, void *from, int len)
368 {
369         u32 off = port << 1;
370
371         if (SUPERIO_PORT(port) || port & 3)
372                 BUG();
373
374         __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1);
375 }
376
377 EXPORT_SYMBOL(outsl);
378 EXPORT_SYMBOL(insl);