blob: a36dc6bdec8a663d20740d68d0dafe66c51d06f2 [file] [log] [blame]
Nicholas Flintham9fafe902014-03-31 13:51:31 +01001/*
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#include <linux/io.h>
27
28#include <mach/hardware.h>
29#include <asm/page.h>
30
31static void __iomem *__isamem_convert_addr(const volatile void __iomem *addr)
32{
33 u32 ret, a = (u32 __force) addr;
34
35 ret = (a & 0xf803fe) << 1;
36 ret |= (a & 0x03fc00) << 2;
37
38 ret += 0xe8000000;
39
40 if ((a & 0x20000) == (a & 0x40000) >> 1)
41 return (void __iomem *)ret;
42
43 BUG();
44 return NULL;
45}
46
47u8 __readb(const volatile void __iomem *addr)
48{
49 void __iomem *a = __isamem_convert_addr(addr);
50 u32 ret;
51
52 if ((unsigned long)addr & 1)
53 ret = __raw_readl(a);
54 else
55 ret = __raw_readb(a);
56 return ret;
57}
58
59u16 __readw(const volatile void __iomem *addr)
60{
61 void __iomem *a = __isamem_convert_addr(addr);
62
63 if ((unsigned long)addr & 1)
64 BUG();
65
66 return __raw_readw(a);
67}
68
69u32 __readl(const volatile void __iomem *addr)
70{
71 void __iomem *a = __isamem_convert_addr(addr);
72 u32 ret;
73
74 if ((unsigned long)addr & 3)
75 BUG();
76
77 ret = __raw_readw(a);
78 ret |= __raw_readw(a + 4) << 16;
79 return ret;
80}
81
82EXPORT_SYMBOL(__readb);
83EXPORT_SYMBOL(__readw);
84EXPORT_SYMBOL(__readl);
85
86void readsw(const void __iomem *addr, void *data, int len)
87{
88 void __iomem *a = __isamem_convert_addr(addr);
89
90 BUG_ON((unsigned long)addr & 1);
91
92 __raw_readsw(a, data, len);
93}
94EXPORT_SYMBOL(readsw);
95
96void readsl(const void __iomem *addr, void *data, int len)
97{
98 void __iomem *a = __isamem_convert_addr(addr);
99
100 BUG_ON((unsigned long)addr & 3);
101
102 __raw_readsl(a, data, len);
103}
104EXPORT_SYMBOL(readsl);
105
106void __writeb(u8 val, void __iomem *addr)
107{
108 void __iomem *a = __isamem_convert_addr(addr);
109
110 if ((unsigned long)addr & 1)
111 __raw_writel(val, a);
112 else
113 __raw_writeb(val, a);
114}
115
116void __writew(u16 val, void __iomem *addr)
117{
118 void __iomem *a = __isamem_convert_addr(addr);
119
120 if ((unsigned long)addr & 1)
121 BUG();
122
123 __raw_writew(val, a);
124}
125
126void __writel(u32 val, void __iomem *addr)
127{
128 void __iomem *a = __isamem_convert_addr(addr);
129
130 if ((unsigned long)addr & 3)
131 BUG();
132
133 __raw_writew(val, a);
134 __raw_writew(val >> 16, a + 4);
135}
136
137EXPORT_SYMBOL(__writeb);
138EXPORT_SYMBOL(__writew);
139EXPORT_SYMBOL(__writel);
140
141void writesw(void __iomem *addr, const void *data, int len)
142{
143 void __iomem *a = __isamem_convert_addr(addr);
144
145 BUG_ON((unsigned long)addr & 1);
146
147 __raw_writesw(a, data, len);
148}
149EXPORT_SYMBOL(writesw);
150
151void writesl(void __iomem *addr, const void *data, int len)
152{
153 void __iomem *a = __isamem_convert_addr(addr);
154
155 BUG_ON((unsigned long)addr & 3);
156
157 __raw_writesl(a, data, len);
158}
159EXPORT_SYMBOL(writesl);
160
161#define SUPERIO_PORT(p) \
162 (((p) >> 3) == (0x3f8 >> 3) || \
163 ((p) >> 3) == (0x2f8 >> 3) || \
164 ((p) >> 3) == (0x378 >> 3))
165
166u8 __inb8(unsigned int port)
167{
168 u32 ret;
169
170 if (SUPERIO_PORT(port))
171 ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2));
172 else {
173 void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
174
175 if (port & 1)
176 ret = __raw_readl(a);
177 else
178 ret = __raw_readb(a);
179 }
180 return ret;
181}
182
183u8 __inb16(unsigned int port)
184{
185 unsigned int offset;
186
187 if (SUPERIO_PORT(port))
188 offset = port << 2;
189 else
190 offset = (port & ~1) << 1 | (port & 1);
191
192 return __raw_readb((void __iomem *)ISAIO_BASE + offset);
193}
194
195u16 __inw(unsigned int port)
196{
197 unsigned int offset;
198
199 if (SUPERIO_PORT(port))
200 offset = port << 2;
201 else {
202 offset = port << 1;
203 BUG_ON(port & 1);
204 }
205 return __raw_readw((void __iomem *)ISAIO_BASE + offset);
206}
207
208u32 __inl(unsigned int port)
209{
210 void __iomem *a;
211
212 if (SUPERIO_PORT(port) || port & 3)
213 BUG();
214
215 a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
216
217 return __raw_readw(a) | __raw_readw(a + 4) << 16;
218}
219
220EXPORT_SYMBOL(__inb8);
221EXPORT_SYMBOL(__inb16);
222EXPORT_SYMBOL(__inw);
223EXPORT_SYMBOL(__inl);
224
225void __outb8(u8 val, unsigned int port)
226{
227 if (SUPERIO_PORT(port))
228 __raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2));
229 else {
230 void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
231
232 if (port & 1)
233 __raw_writel(val, a);
234 else
235 __raw_writeb(val, a);
236 }
237}
238
239void __outb16(u8 val, unsigned int port)
240{
241 unsigned int offset;
242
243 if (SUPERIO_PORT(port))
244 offset = port << 2;
245 else
246 offset = (port & ~1) << 1 | (port & 1);
247
248 __raw_writeb(val, (void __iomem *)ISAIO_BASE + offset);
249}
250
251void __outw(u16 val, unsigned int port)
252{
253 unsigned int offset;
254
255 if (SUPERIO_PORT(port))
256 offset = port << 2;
257 else {
258 offset = port << 1;
259 BUG_ON(port & 1);
260 }
261 __raw_writew(val, (void __iomem *)ISAIO_BASE + offset);
262}
263
264void __outl(u32 val, unsigned int port)
265{
266 BUG();
267}
268
269EXPORT_SYMBOL(__outb8);
270EXPORT_SYMBOL(__outb16);
271EXPORT_SYMBOL(__outw);
272EXPORT_SYMBOL(__outl);
273
274void outsb(unsigned int port, const void *from, int len)
275{
276 u32 off;
277
278 if (SUPERIO_PORT(port))
279 off = port << 2;
280 else {
281 off = (port & ~1) << 1;
282 if (port & 1)
283 BUG();
284 }
285
286 __raw_writesb((void __iomem *)ISAIO_BASE + off, from, len);
287}
288
289void insb(unsigned int port, void *from, int len)
290{
291 u32 off;
292
293 if (SUPERIO_PORT(port))
294 off = port << 2;
295 else {
296 off = (port & ~1) << 1;
297 if (port & 1)
298 BUG();
299 }
300
301 __raw_readsb((void __iomem *)ISAIO_BASE + off, from, len);
302}
303
304EXPORT_SYMBOL(outsb);
305EXPORT_SYMBOL(insb);
306
307void outsw(unsigned int port, const void *from, int len)
308{
309 u32 off;
310
311 if (SUPERIO_PORT(port))
312 off = port << 2;
313 else {
314 off = (port & ~1) << 1;
315 if (port & 1)
316 BUG();
317 }
318
319 __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len);
320}
321
322void insw(unsigned int port, void *from, int len)
323{
324 u32 off;
325
326 if (SUPERIO_PORT(port))
327 off = port << 2;
328 else {
329 off = (port & ~1) << 1;
330 if (port & 1)
331 BUG();
332 }
333
334 __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len);
335}
336
337EXPORT_SYMBOL(outsw);
338EXPORT_SYMBOL(insw);
339
340void outsl(unsigned int port, const void *from, int len)
341{
342 u32 off = port << 1;
343
344 if (SUPERIO_PORT(port) || port & 3)
345 BUG();
346
347 __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1);
348}
349
350void insl(unsigned int port, void *from, int len)
351{
352 u32 off = port << 1;
353
354 if (SUPERIO_PORT(port) || port & 3)
355 BUG();
356
357 __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1);
358}
359
360EXPORT_SYMBOL(outsl);
361EXPORT_SYMBOL(insl);