Linux Audio

Check our new training course

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