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 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 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, 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, 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, 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(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(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#define SUPERIO_PORT(p) \
 181        (((p) >> 3) == (0x3f8 >> 3) || \
 182         ((p) >> 3) == (0x2f8 >> 3) || \
 183         ((p) >> 3) == (0x378 >> 3))
 184
 185/*
 186 * We're addressing an 8 or 16-bit peripheral which tranfers
 187 * odd addresses on the low ISA byte lane.
 188 */
 189u8 __inb8(unsigned int port)
 190{
 191        u32 ret;
 192
 193        /*
 194         * The SuperIO registers use sane addressing techniques...
 195         */
 196        if (SUPERIO_PORT(port))
 197                ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2));
 198        else {
 199                void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
 200
 201                /*
 202                 * Shame nothing else does
 203                 */
 204                if (port & 1)
 205                        ret = __raw_readl(a);
 206                else
 207                        ret = __raw_readb(a);
 208        }
 209        return ret;
 210}
 211
 212/*
 213 * We're addressing a 16-bit peripheral which transfers odd
 214 * addresses on the high ISA byte lane.
 215 */
 216u8 __inb16(unsigned int port)
 217{
 218        unsigned int offset;
 219
 220        /*
 221         * The SuperIO registers use sane addressing techniques...
 222         */
 223        if (SUPERIO_PORT(port))
 224                offset = port << 2;
 225        else
 226                offset = (port & ~1) << 1 | (port & 1);
 227
 228        return __raw_readb((void __iomem *)ISAIO_BASE + offset);
 229}
 230
 231u16 __inw(unsigned int port)
 232{
 233        unsigned int offset;
 234
 235        /*
 236         * The SuperIO registers use sane addressing techniques...
 237         */
 238        if (SUPERIO_PORT(port))
 239                offset = port << 2;
 240        else {
 241                offset = port << 1;
 242                BUG_ON(port & 1);
 243        }
 244        return __raw_readw((void __iomem *)ISAIO_BASE + offset);
 245}
 246
 247/*
 248 * Fake a 32-bit read with two 16-bit reads.  Needed for 3c589.
 249 */
 250u32 __inl(unsigned int port)
 251{
 252        void __iomem *a;
 253
 254        if (SUPERIO_PORT(port) || port & 3)
 255                BUG();
 256
 257        a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
 258
 259        return __raw_readw(a) | __raw_readw(a + 4) << 16;
 260}
 261
 262EXPORT_SYMBOL(__inb8);
 263EXPORT_SYMBOL(__inb16);
 264EXPORT_SYMBOL(__inw);
 265EXPORT_SYMBOL(__inl);
 266
 267void __outb8(u8 val, unsigned int port)
 268{
 269        /*
 270         * The SuperIO registers use sane addressing techniques...
 271         */
 272        if (SUPERIO_PORT(port))
 273                __raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2));
 274        else {
 275                void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
 276
 277                /*
 278                 * Shame nothing else does
 279                 */
 280                if (port & 1)
 281                        __raw_writel(val, a);
 282                else
 283                        __raw_writeb(val, a);
 284        }
 285}
 286
 287void __outb16(u8 val, unsigned int port)
 288{
 289        unsigned int offset;
 290
 291        /*
 292         * The SuperIO registers use sane addressing techniques...
 293         */
 294        if (SUPERIO_PORT(port))
 295                offset = port << 2;
 296        else
 297                offset = (port & ~1) << 1 | (port & 1);
 298
 299        __raw_writeb(val, (void __iomem *)ISAIO_BASE + offset);
 300}
 301
 302void __outw(u16 val, unsigned int port)
 303{
 304        unsigned int offset;
 305
 306        /*
 307         * The SuperIO registers use sane addressing techniques...
 308         */
 309        if (SUPERIO_PORT(port))
 310                offset = port << 2;
 311        else {
 312                offset = port << 1;
 313                BUG_ON(port & 1);
 314        }
 315        __raw_writew(val, (void __iomem *)ISAIO_BASE + offset);
 316}
 317
 318void __outl(u32 val, unsigned int port)
 319{
 320        BUG();
 321}
 322
 323EXPORT_SYMBOL(__outb8);
 324EXPORT_SYMBOL(__outb16);
 325EXPORT_SYMBOL(__outw);
 326EXPORT_SYMBOL(__outl);
 327
 328void outsb(unsigned int port, const void *from, int len)
 329{
 330        u32 off;
 331
 332        if (SUPERIO_PORT(port))
 333                off = port << 2;
 334        else {
 335                off = (port & ~1) << 1;
 336                if (port & 1)
 337                        BUG();
 338        }
 339
 340        __raw_writesb((void __iomem *)ISAIO_BASE + off, from, len);
 341}
 342
 343void insb(unsigned int port, void *from, int len)
 344{
 345        u32 off;
 346
 347        if (SUPERIO_PORT(port))
 348                off = port << 2;
 349        else {
 350                off = (port & ~1) << 1;
 351                if (port & 1)
 352                        BUG();
 353        }
 354
 355        __raw_readsb((void __iomem *)ISAIO_BASE + off, from, len);
 356}
 357
 358EXPORT_SYMBOL(outsb);
 359EXPORT_SYMBOL(insb);
 360
 361void outsw(unsigned int port, const void *from, int len)
 362{
 363        u32 off;
 364
 365        if (SUPERIO_PORT(port))
 366                off = port << 2;
 367        else {
 368                off = (port & ~1) << 1;
 369                if (port & 1)
 370                        BUG();
 371        }
 372
 373        __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len);
 374}
 375
 376void insw(unsigned int port, void *from, int len)
 377{
 378        u32 off;
 379
 380        if (SUPERIO_PORT(port))
 381                off = port << 2;
 382        else {
 383                off = (port & ~1) << 1;
 384                if (port & 1)
 385                        BUG();
 386        }
 387
 388        __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len);
 389}
 390
 391EXPORT_SYMBOL(outsw);
 392EXPORT_SYMBOL(insw);
 393
 394/*
 395 * We implement these as 16-bit insw/outsw, mainly for
 396 * 3c589 cards.
 397 */
 398void outsl(unsigned int port, const void *from, int len)
 399{
 400        u32 off = port << 1;
 401
 402        if (SUPERIO_PORT(port) || port & 3)
 403                BUG();
 404
 405        __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1);
 406}
 407
 408void insl(unsigned int port, void *from, int len)
 409{
 410        u32 off = port << 1;
 411
 412        if (SUPERIO_PORT(port) || port & 3)
 413                BUG();
 414
 415        __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1);
 416}
 417
 418EXPORT_SYMBOL(outsl);
 419EXPORT_SYMBOL(insl);
 420