~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-ebsa110/io.c

Version: ~ [ linux-6.3-rc3 ] ~ [ linux-6.2.7 ] ~ [ linux-6.1.20 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.103 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.175 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.237 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.278 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.310 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 32 static 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  */
 67 u8 __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 
 79 u16 __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 
 89 u32 __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 
102 EXPORT_SYMBOL(__readb);
103 EXPORT_SYMBOL(__readw);
104 EXPORT_SYMBOL(__readl);
105 
106 void 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 }
114 EXPORT_SYMBOL(readsw);
115 
116 void 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 }
124 EXPORT_SYMBOL(readsl);
125 
126 void __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 
136 void __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 
146 void __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 
157 EXPORT_SYMBOL(__writeb);
158 EXPORT_SYMBOL(__writew);
159 EXPORT_SYMBOL(__writel);
160 
161 void 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 }
169 EXPORT_SYMBOL(writesw);
170 
171 void 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 }
179 EXPORT_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  */
210 u8 __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  */
237 u8 __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 
252 u16 __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  */
271 u32 __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 
283 EXPORT_SYMBOL(__inb8);
284 EXPORT_SYMBOL(__inb16);
285 EXPORT_SYMBOL(__inw);
286 EXPORT_SYMBOL(__inl);
287 
288 void __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 
308 void __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 
323 void __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 
339 void __outl(u32 val, unsigned int port)
340 {
341         BUG();
342 }
343 
344 EXPORT_SYMBOL(__outb8);
345 EXPORT_SYMBOL(__outb16);
346 EXPORT_SYMBOL(__outw);
347 EXPORT_SYMBOL(__outl);
348 
349 void 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 
364 void 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 
379 EXPORT_SYMBOL(outsb);
380 EXPORT_SYMBOL(insb);
381 
382 void 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 
397 void 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 
412 EXPORT_SYMBOL(outsw);
413 EXPORT_SYMBOL(insw);
414 
415 /*
416  * We implement these as 16-bit insw/outsw, mainly for
417  * 3c589 cards.
418  */
419 void 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 
429 void 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 
439 EXPORT_SYMBOL(outsl);
440 EXPORT_SYMBOL(insl);
441 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp