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