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 
__isamem_convert_addr(void * addr)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  */
__readb(void * addr)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 
__readw(void * addr)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 
__readl(void * addr)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 
__writeb(u8 val,void * addr)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 
__writew(u16 val,void * addr)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 
__writel(u32 val,void * addr)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 /*
143  * We're addressing an 8 or 16-bit peripheral which tranfers
144  * odd addresses on the low ISA byte lane.
145  */
__inb8(unsigned int port)146 u8 __inb8(unsigned int port)
147 {
148 	u32 ret;
149 
150 	/*
151 	 * The SuperIO registers use sane addressing techniques...
152 	 */
153 	if (SUPERIO_PORT(port))
154 		ret = __arch_getb(ISAIO_BASE + (port << 2));
155 	else {
156 		u32 a = ISAIO_BASE + ((port & ~1) << 1);
157 
158 		/*
159 		 * Shame nothing else does
160 		 */
161 		if (port & 1)
162 			ret = __arch_getl(a);
163 		else
164 			ret = __arch_getb(a);
165 	}
166 	return ret;
167 }
168 
169 /*
170  * We're addressing a 16-bit peripheral which transfers odd
171  * addresses on the high ISA byte lane.
172  */
__inb16(unsigned int port)173 u8 __inb16(unsigned int port)
174 {
175 	u32 ret;
176 
177 	/*
178 	 * The SuperIO registers use sane addressing techniques...
179 	 */
180 	if (SUPERIO_PORT(port))
181 		ret = __arch_getb(ISAIO_BASE + (port << 2));
182 	else {
183 		u32 a = ISAIO_BASE + ((port & ~1) << 1);
184 
185 		/*
186 		 * Shame nothing else does
187 		 */
188 		ret = __arch_getb(a + (port & 1));
189 	}
190 	return ret;
191 }
192 
__inw(unsigned int port)193 u16 __inw(unsigned int port)
194 {
195 	u32 ret;
196 
197 	/*
198 	 * The SuperIO registers use sane addressing techniques...
199 	 */
200 	if (SUPERIO_PORT(port) || port & 1)
201 		ret = __arch_getw(ISAIO_BASE + (port << 2));
202 	else {
203 		u32 a = ISAIO_BASE + (port << 1);
204 
205 		/*
206 		 * Shame nothing else does
207 		 */
208 		if (port & 1)
209 			BUG();
210 
211 		ret = __arch_getw(a);
212 	}
213 	return ret;
214 }
215 
216 /*
217  * Fake a 32-bit read with two 16-bit reads.  Needed for 3c589.
218  */
__inl(unsigned int port)219 u32 __inl(unsigned int port)
220 {
221 	u32 a;
222 
223 	if (SUPERIO_PORT(port) || port & 3)
224 		BUG();
225 
226 	a = ISAIO_BASE + (port << 1);
227 
228 	return __arch_getw(a) | __arch_getw(a + 4) << 16;
229 }
230 
231 EXPORT_SYMBOL(__inb8);
232 EXPORT_SYMBOL(__inb16);
233 EXPORT_SYMBOL(__inw);
234 EXPORT_SYMBOL(__inl);
235 
__outb8(u8 val,unsigned int port)236 void __outb8(u8 val, unsigned int port)
237 {
238 	/*
239 	 * The SuperIO registers use sane addressing techniques...
240 	 */
241 	if (SUPERIO_PORT(port))
242 		__arch_putb(val, ISAIO_BASE + (port << 2));
243 	else {
244 		u32 a = ISAIO_BASE + ((port & ~1) << 1);
245 
246 		/*
247 		 * Shame nothing else does
248 		 */
249 		if (port & 1)
250 			__arch_putl(val, a);
251 		else
252 			__arch_putb(val, a);
253 	}
254 }
255 
__outb16(u8 val,unsigned int port)256 void __outb16(u8 val, unsigned int port)
257 {
258 	/*
259 	 * The SuperIO registers use sane addressing techniques...
260 	 */
261 	if (SUPERIO_PORT(port))
262 		__arch_putb(val, ISAIO_BASE + (port << 2));
263 	else {
264 		u32 a = ISAIO_BASE + ((port & ~1) << 1);
265 
266 		/*
267 		 * Shame nothing else does
268 		 */
269 		__arch_putb(val, a + (port & 1));
270 	}
271 }
272 
__outw(u16 val,unsigned int port)273 void __outw(u16 val, unsigned int port)
274 {
275 	u32 off;
276 
277 	/*
278 	 * The SuperIO registers use sane addressing techniques...
279 	 */
280 	if (SUPERIO_PORT(port))
281 		off = port << 2;
282 	else {
283 		off = port << 1;
284 		if (port & 1)
285 			BUG();
286 
287 	}
288 	__arch_putw(val, ISAIO_BASE + off);
289 }
290 
__outl(u32 val,unsigned int port)291 void __outl(u32 val, unsigned int port)
292 {
293 	BUG();
294 }
295 
296 EXPORT_SYMBOL(__outb8);
297 EXPORT_SYMBOL(__outb16);
298 EXPORT_SYMBOL(__outw);
299 EXPORT_SYMBOL(__outl);
300 
301 extern void __arch_writesb(unsigned long virt, const void *from, int len);
302 extern void __arch_writesw(unsigned long virt, const void *from, int len);
303 extern void __arch_writesl(unsigned long virt, const void *from, int len);
304 extern void __arch_readsb(unsigned long virt, void *from, int len);
305 extern void __arch_readsw(unsigned long virt, void *from, int len);
306 extern void __arch_readsl(unsigned long virt, void *from, int len);
307 
outsb(unsigned int port,const void * from,int len)308 void outsb(unsigned int port, const void *from, int len)
309 {
310 	u32 off;
311 
312 	if (SUPERIO_PORT(port))
313 		off = port << 2;
314 	else {
315 		off = (port & ~1) << 1;
316 		if (port & 1)
317 			BUG();
318 	}
319 
320 	__raw_writesb(ISAIO_BASE + off, from, len);
321 }
322 
insb(unsigned int port,void * from,int len)323 void insb(unsigned int port, void *from, int len)
324 {
325 	u32 off;
326 
327 	if (SUPERIO_PORT(port))
328 		off = port << 2;
329 	else {
330 		off = (port & ~1) << 1;
331 		if (port & 1)
332 			BUG();
333 	}
334 
335 	__raw_readsb(ISAIO_BASE + off, from, len);
336 }
337 
338 EXPORT_SYMBOL(outsb);
339 EXPORT_SYMBOL(insb);
340 
outsw(unsigned int port,const void * from,int len)341 void outsw(unsigned int port, const void *from, int len)
342 {
343 	u32 off;
344 
345 	if (SUPERIO_PORT(port))
346 		off = port << 2;
347 	else {
348 		off = (port & ~1) << 1;
349 		if (port & 1)
350 			BUG();
351 	}
352 
353 	__raw_writesw(ISAIO_BASE + off, from, len);
354 }
355 
insw(unsigned int port,void * from,int len)356 void insw(unsigned int port, void *from, int len)
357 {
358 	u32 off;
359 
360 	if (SUPERIO_PORT(port))
361 		off = port << 2;
362 	else {
363 		off = (port & ~1) << 1;
364 		if (port & 1)
365 			BUG();
366 	}
367 
368 	__raw_readsw(ISAIO_BASE + off, from, len);
369 }
370 
371 EXPORT_SYMBOL(outsw);
372 EXPORT_SYMBOL(insw);
373 
374 /*
375  * We implement these as 16-bit insw/outsw, mainly for
376  * 3c589 cards.
377  */
outsl(unsigned int port,const void * from,int len)378 void outsl(unsigned int port, const void *from, int len)
379 {
380 	u32 off = port << 1;
381 
382 	if (SUPERIO_PORT(port) || port & 3)
383 		BUG();
384 
385 	__raw_writesw(ISAIO_BASE + off, from, len << 1);
386 }
387 
insl(unsigned int port,void * from,int len)388 void insl(unsigned int port, void *from, int len)
389 {
390 	u32 off = port << 1;
391 
392 	if (SUPERIO_PORT(port) || port & 3)
393 		BUG();
394 
395 	__raw_readsw(ISAIO_BASE + off, from, len << 1);
396 }
397 
398 EXPORT_SYMBOL(outsl);
399 EXPORT_SYMBOL(insl);
400