linux/arch/arm/mach-ebsa110/io.c
<<
>>
Prefs
   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);
 441