File: /usr/src/linux/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 u32 __isamem_convert_addr(void *addr)
31     {
32     	u32 ret, a = (u32) 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 ret;
57     
58     	BUG();
59     	return 0;
60     }
61     
62     /*
63      * read[bwl] and write[bwl]
64      */
65     u8 __readb(void *addr)
66     {
67     	u32 ret, a = __isamem_convert_addr(addr);
68     
69     	if ((int)addr & 1)
70     		ret = __arch_getl(a);
71     	else
72     		ret = __arch_getb(a);
73     	return ret;
74     }
75     
76     u16 __readw(void *addr)
77     {
78     	u32 a = __isamem_convert_addr(addr);
79     
80     	if ((int)addr & 1)
81     		BUG();
82     
83     	return __arch_getw(a);
84     }
85     
86     u32 __readl(void *addr)
87     {
88     	u32 ret, a = __isamem_convert_addr(addr);
89     
90     	if ((int)addr & 3)
91     		BUG();
92     
93     	ret = __arch_getw(a);
94     	ret |= __arch_getw(a + 4) << 16;
95     	return ret;
96     }
97     
98     EXPORT_SYMBOL(__readb);
99     EXPORT_SYMBOL(__readw);
100     EXPORT_SYMBOL(__readl);
101     
102     void __writeb(u8 val, void *addr)
103     {
104     	u32 a = __isamem_convert_addr(addr);
105     
106     	if ((int)addr & 1)
107     		__arch_putl(val, a);
108     	else
109     		__arch_putb(val, a);
110     }
111     
112     void __writew(u16 val, void *addr)
113     {
114     	u32 a = __isamem_convert_addr(addr);
115     
116     	if ((int)addr & 1)
117     		BUG();
118     
119     	__arch_putw(val, a);
120     }
121     
122     void __writel(u32 val, void *addr)
123     {
124     	u32 a = __isamem_convert_addr(addr);
125     
126     	if ((int)addr & 3)
127     		BUG();
128     
129     	__arch_putw(val, a);
130     	__arch_putw(val >> 16, a + 4);
131     }
132     
133     EXPORT_SYMBOL(__writeb);
134     EXPORT_SYMBOL(__writew);
135     EXPORT_SYMBOL(__writel);
136     
137     #define SUPERIO_PORT(p) \
138     	(((p) >> 3) == (0x3f8 >> 3) || \
139     	 ((p) >> 3) == (0x2f8 >> 3) || \
140     	 ((p) >> 3) == (0x378 >> 3))
141     
142     u8 __inb(int port)
143     {
144     	u32 ret;
145     
146     	/*
147     	 * The SuperIO registers use sane addressing techniques...
148     	 */
149     	if (SUPERIO_PORT(port))
150     		ret = __arch_getb(ISAIO_BASE + (port << 2));
151     	else {
152     		u32 a = ISAIO_BASE + ((port & ~1) << 1);
153     
154     		/*
155     		 * Shame nothing else does
156     		 */
157     		if (port & 1)
158     			ret = __arch_getl(a);
159     		else
160     			ret = __arch_getb(a);
161     	}
162     	return ret;
163     }
164     
165     u16 __inw(int port)
166     {
167     	u32 ret;
168     
169     	/*
170     	 * The SuperIO registers use sane addressing techniques...
171     	 */
172     	if (SUPERIO_PORT(port))
173     		ret = __arch_getw(ISAIO_BASE + (port << 2));
174     	else {
175     		u32 a = ISAIO_BASE + ((port & ~1) << 1);
176     
177     		/*
178     		 * Shame nothing else does
179     		 */
180     		if (port & 1)
181     			BUG();
182     
183     		ret = __arch_getw(a);
184     	}
185     	return ret;
186     }
187     
188     u32 __inl(int port)
189     {
190     	BUG();
191     	return 0;
192     }
193     
194     EXPORT_SYMBOL(__inb);
195     EXPORT_SYMBOL(__inw);
196     EXPORT_SYMBOL(__inl);
197     
198     void __outb(u8 val, int port)
199     {
200     	/*
201     	 * The SuperIO registers use sane addressing techniques...
202     	 */
203     	if (SUPERIO_PORT(port))
204     		__arch_putb(val, ISAIO_BASE + (port << 2));
205     	else {
206     		u32 a = ISAIO_BASE + ((port & ~1) << 1);
207     
208     		/*
209     		 * Shame nothing else does
210     		 */
211     		if (port & 1)
212     			__arch_putl(val, a);
213     		else
214     			__arch_putb(val, a);
215     	}
216     }
217     
218     void __outw(u16 val, int port)
219     {
220     	u32 off;
221     
222     	/*
223     	 * The SuperIO registers use sane addressing techniques...
224     	 */
225     	if (SUPERIO_PORT(port))
226     		off = port << 2;
227     	else {
228     		off = (port & ~1) << 1;
229     		if (port & 1)
230     			BUG();
231     
232     	}
233     	__arch_putw(val, ISAIO_BASE + off);
234     }
235     
236     void __outl(u32 val, int port)
237     {
238     	BUG();
239     }
240     
241     EXPORT_SYMBOL(__outb);
242     EXPORT_SYMBOL(__outw);
243     EXPORT_SYMBOL(__outl);
244     
245     extern void __arch_writesb(unsigned long virt, const void *from, int len);
246     extern void __arch_writesw(unsigned long virt, const void *from, int len);
247     extern void __arch_writesl(unsigned long virt, const void *from, int len);
248     extern void __arch_readsb(unsigned long virt, void *from, int len);
249     extern void __arch_readsw(unsigned long virt, void *from, int len);
250     extern void __arch_readsl(unsigned long virt, void *from, int len);
251     
252     void outsb(unsigned int port, const void *from, int len)
253     {
254     	u32 off;
255     
256     	if (SUPERIO_PORT(port))
257     		off = port << 2;
258     	else {
259     		off = (port & ~1) << 1;
260     		if (port & 1)
261     			BUG();
262     	}
263     
264     	__raw_writesb(ISAIO_BASE + off, from, len);
265     }
266     
267     void insb(unsigned int port, void *from, int len)
268     {
269     	u32 off;
270     
271     	if (SUPERIO_PORT(port))
272     		off = port << 2;
273     	else {
274     		off = (port & ~1) << 1;
275     		if (port & 1)
276     			BUG();
277     	}
278     
279     	__raw_readsb(ISAIO_BASE + off, from, len);
280     }
281     
282     void outsw(unsigned int port, const void *from, int len)
283     {
284     	u32 off;
285     
286     	if (SUPERIO_PORT(port))
287     		off = port << 2;
288     	else {
289     		off = (port & ~1) << 1;
290     		if (port & 1)
291     			BUG();
292     	}
293     
294     	__raw_writesw(ISAIO_BASE + off, from, len);
295     }
296     
297     void insw(unsigned int port, void *from, int len)
298     {
299     	u32 off;
300     
301     	if (SUPERIO_PORT(port))
302     		off = port << 2;
303     	else {
304     		off = (port & ~1) << 1;
305     		if (port & 1)
306     			BUG();
307     	}
308     
309     	__raw_readsw(ISAIO_BASE + off, from, len);
310     }
311     
312     void outsl(unsigned int port, const void *from, int len)
313     {
314     	panic("outsl not supported on this architecture");
315     }
316     
317     void insl(unsigned int port, void *from, int len)
318     {
319     	panic("insl not supported on this architecture");
320     }
321