linux/arch/parisc/lib/iomap.c
<<
>>
Prefs
   1/*
   2 * iomap.c - Implement iomap interface for PA-RISC
   3 * Copyright (c) 2004 Matthew Wilcox
   4 */
   5
   6#include <linux/ioport.h>
   7#include <linux/pci.h>
   8#include <linux/export.h>
   9#include <asm/io.h>
  10
  11/*
  12 * The iomap space on 32-bit PA-RISC is intended to look like this:
  13 * 00000000-7fffffff virtual mapped IO
  14 * 80000000-8fffffff ISA/EISA port space that can't be virtually mapped
  15 * 90000000-9fffffff Dino port space
  16 * a0000000-afffffff Astro port space
  17 * b0000000-bfffffff PAT port space
  18 * c0000000-cfffffff non-swapped memory IO
  19 * f0000000-ffffffff legacy IO memory pointers
  20 *
  21 * For the moment, here's what it looks like:
  22 * 80000000-8fffffff All ISA/EISA port space
  23 * f0000000-ffffffff legacy IO memory pointers
  24 *
  25 * On 64-bit, everything is extended, so:
  26 * 8000000000000000-8fffffffffffffff All ISA/EISA port space
  27 * f000000000000000-ffffffffffffffff legacy IO memory pointers
  28 */
  29
  30/*
  31 * Technically, this should be 'if (VMALLOC_START < addr < VMALLOC_END),
  32 * but that's slow and we know it'll be within the first 2GB.
  33 */
  34#ifdef CONFIG_64BIT
  35#define INDIRECT_ADDR(addr)     (((unsigned long)(addr) & 1UL<<63) != 0)
  36#define ADDR_TO_REGION(addr)    (((unsigned long)addr >> 60) & 7)
  37#define IOPORT_MAP_BASE         (8UL << 60)
  38#else
  39#define INDIRECT_ADDR(addr)     (((unsigned long)(addr) & 1UL<<31) != 0)
  40#define ADDR_TO_REGION(addr)    (((unsigned long)addr >> 28) & 7)
  41#define IOPORT_MAP_BASE         (8UL << 28)
  42#endif
  43
  44struct iomap_ops {
  45        unsigned int (*read8)(void __iomem *);
  46        unsigned int (*read16)(void __iomem *);
  47        unsigned int (*read16be)(void __iomem *);
  48        unsigned int (*read32)(void __iomem *);
  49        unsigned int (*read32be)(void __iomem *);
  50        void (*write8)(u8, void __iomem *);
  51        void (*write16)(u16, void __iomem *);
  52        void (*write16be)(u16, void __iomem *);
  53        void (*write32)(u32, void __iomem *);
  54        void (*write32be)(u32, void __iomem *);
  55        void (*read8r)(void __iomem *, void *, unsigned long);
  56        void (*read16r)(void __iomem *, void *, unsigned long);
  57        void (*read32r)(void __iomem *, void *, unsigned long);
  58        void (*write8r)(void __iomem *, const void *, unsigned long);
  59        void (*write16r)(void __iomem *, const void *, unsigned long);
  60        void (*write32r)(void __iomem *, const void *, unsigned long);
  61};
  62
  63/* Generic ioport ops.  To be replaced later by specific dino/elroy/wax code */
  64
  65#define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff)
  66
  67static unsigned int ioport_read8(void __iomem *addr)
  68{
  69        return inb(ADDR2PORT(addr));
  70}
  71
  72static unsigned int ioport_read16(void __iomem *addr)
  73{
  74        return inw(ADDR2PORT(addr));
  75}
  76
  77static unsigned int ioport_read32(void __iomem *addr)
  78{
  79        return inl(ADDR2PORT(addr));
  80}
  81
  82static void ioport_write8(u8 datum, void __iomem *addr)
  83{
  84        outb(datum, ADDR2PORT(addr));
  85}
  86
  87static void ioport_write16(u16 datum, void __iomem *addr)
  88{
  89        outw(datum, ADDR2PORT(addr));
  90}
  91
  92static void ioport_write32(u32 datum, void __iomem *addr)
  93{
  94        outl(datum, ADDR2PORT(addr));
  95}
  96
  97static void ioport_read8r(void __iomem *addr, void *dst, unsigned long count)
  98{
  99        insb(ADDR2PORT(addr), dst, count);
 100}
 101
 102static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
 103{
 104        insw(ADDR2PORT(addr), dst, count);
 105}
 106
 107static void ioport_read32r(void __iomem *addr, void *dst, unsigned long count)
 108{
 109        insl(ADDR2PORT(addr), dst, count);
 110}
 111
 112static void ioport_write8r(void __iomem *addr, const void *s, unsigned long n)
 113{
 114        outsb(ADDR2PORT(addr), s, n);
 115}
 116
 117static void ioport_write16r(void __iomem *addr, const void *s, unsigned long n)
 118{
 119        outsw(ADDR2PORT(addr), s, n);
 120}
 121
 122static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n)
 123{
 124        outsl(ADDR2PORT(addr), s, n);
 125}
 126
 127static const struct iomap_ops ioport_ops = {
 128        .read8 = ioport_read8,
 129        .read16 = ioport_read16,
 130        .read16be = ioport_read16,
 131        .read32 = ioport_read32,
 132        .read32be = ioport_read32,
 133        .write8 = ioport_write8,
 134        .write16 = ioport_write16,
 135        .write16be = ioport_write16,
 136        .write32 = ioport_write32,
 137        .write32be = ioport_write32,
 138        .read8r = ioport_read8r,
 139        .read16r = ioport_read16r,
 140        .read32r = ioport_read32r,
 141        .write8r = ioport_write8r,
 142        .write16r = ioport_write16r,
 143        .write32r = ioport_write32r,
 144};
 145
 146/* Legacy I/O memory ops */
 147
 148static unsigned int iomem_read8(void __iomem *addr)
 149{
 150        return readb(addr);
 151}
 152
 153static unsigned int iomem_read16(void __iomem *addr)
 154{
 155        return readw(addr);
 156}
 157
 158static unsigned int iomem_read16be(void __iomem *addr)
 159{
 160        return __raw_readw(addr);
 161}
 162
 163static unsigned int iomem_read32(void __iomem *addr)
 164{
 165        return readl(addr);
 166}
 167
 168static unsigned int iomem_read32be(void __iomem *addr)
 169{
 170        return __raw_readl(addr);
 171}
 172
 173static void iomem_write8(u8 datum, void __iomem *addr)
 174{
 175        writeb(datum, addr);
 176}
 177
 178static void iomem_write16(u16 datum, void __iomem *addr)
 179{
 180        writew(datum, addr);
 181}
 182
 183static void iomem_write16be(u16 datum, void __iomem *addr)
 184{
 185        __raw_writew(datum, addr);
 186}
 187
 188static void iomem_write32(u32 datum, void __iomem *addr)
 189{
 190        writel(datum, addr);
 191}
 192
 193static void iomem_write32be(u32 datum, void __iomem *addr)
 194{
 195        __raw_writel(datum, addr);
 196}
 197
 198static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
 199{
 200        while (count--) {
 201                *(u8 *)dst = __raw_readb(addr);
 202                dst++;
 203        }
 204}
 205
 206static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
 207{
 208        while (count--) {
 209                *(u16 *)dst = __raw_readw(addr);
 210                dst += 2;
 211        }
 212}
 213
 214static void iomem_read32r(void __iomem *addr, void *dst, unsigned long count)
 215{
 216        while (count--) {
 217                *(u32 *)dst = __raw_readl(addr);
 218                dst += 4;
 219        }
 220}
 221
 222static void iomem_write8r(void __iomem *addr, const void *s, unsigned long n)
 223{
 224        while (n--) {
 225                __raw_writeb(*(u8 *)s, addr);
 226                s++;
 227        }
 228}
 229
 230static void iomem_write16r(void __iomem *addr, const void *s, unsigned long n)
 231{
 232        while (n--) {
 233                __raw_writew(*(u16 *)s, addr);
 234                s += 2;
 235        }
 236}
 237
 238static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n)
 239{
 240        while (n--) {
 241                __raw_writel(*(u32 *)s, addr);
 242                s += 4;
 243        }
 244}
 245
 246static const struct iomap_ops iomem_ops = {
 247        .read8 = iomem_read8,
 248        .read16 = iomem_read16,
 249        .read16be = iomem_read16be,
 250        .read32 = iomem_read32,
 251        .read32be = iomem_read32be,
 252        .write8 = iomem_write8,
 253        .write16 = iomem_write16,
 254        .write16be = iomem_write16be,
 255        .write32 = iomem_write32,
 256        .write32be = iomem_write32be,
 257        .read8r = iomem_read8r,
 258        .read16r = iomem_read16r,
 259        .read32r = iomem_read32r,
 260        .write8r = iomem_write8r,
 261        .write16r = iomem_write16r,
 262        .write32r = iomem_write32r,
 263};
 264
 265static const struct iomap_ops *iomap_ops[8] = {
 266        [0] = &ioport_ops,
 267        [7] = &iomem_ops
 268};
 269
 270
 271unsigned int ioread8(void __iomem *addr)
 272{
 273        if (unlikely(INDIRECT_ADDR(addr)))
 274                return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr);
 275        return *((u8 *)addr);
 276}
 277
 278unsigned int ioread16(void __iomem *addr)
 279{
 280        if (unlikely(INDIRECT_ADDR(addr)))
 281                return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr);
 282        return le16_to_cpup((u16 *)addr);
 283}
 284
 285unsigned int ioread16be(void __iomem *addr)
 286{
 287        if (unlikely(INDIRECT_ADDR(addr)))
 288                return iomap_ops[ADDR_TO_REGION(addr)]->read16be(addr);
 289        return *((u16 *)addr);
 290}
 291
 292unsigned int ioread32(void __iomem *addr)
 293{
 294        if (unlikely(INDIRECT_ADDR(addr)))
 295                return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr);
 296        return le32_to_cpup((u32 *)addr);
 297}
 298
 299unsigned int ioread32be(void __iomem *addr)
 300{
 301        if (unlikely(INDIRECT_ADDR(addr)))
 302                return iomap_ops[ADDR_TO_REGION(addr)]->read32be(addr);
 303        return *((u32 *)addr);
 304}
 305
 306void iowrite8(u8 datum, void __iomem *addr)
 307{
 308        if (unlikely(INDIRECT_ADDR(addr))) {
 309                iomap_ops[ADDR_TO_REGION(addr)]->write8(datum, addr);
 310        } else {
 311                *((u8 *)addr) = datum;
 312        }
 313}
 314
 315void iowrite16(u16 datum, void __iomem *addr)
 316{
 317        if (unlikely(INDIRECT_ADDR(addr))) {
 318                iomap_ops[ADDR_TO_REGION(addr)]->write16(datum, addr);
 319        } else {
 320                *((u16 *)addr) = cpu_to_le16(datum);
 321        }
 322}
 323
 324void iowrite16be(u16 datum, void __iomem *addr)
 325{
 326        if (unlikely(INDIRECT_ADDR(addr))) {
 327                iomap_ops[ADDR_TO_REGION(addr)]->write16be(datum, addr);
 328        } else {
 329                *((u16 *)addr) = datum;
 330        }
 331}
 332
 333void iowrite32(u32 datum, void __iomem *addr)
 334{
 335        if (unlikely(INDIRECT_ADDR(addr))) {
 336                iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr);
 337        } else {
 338                *((u32 *)addr) = cpu_to_le32(datum);
 339        }
 340}
 341
 342void iowrite32be(u32 datum, void __iomem *addr)
 343{
 344        if (unlikely(INDIRECT_ADDR(addr))) {
 345                iomap_ops[ADDR_TO_REGION(addr)]->write32be(datum, addr);
 346        } else {
 347                *((u32 *)addr) = datum;
 348        }
 349}
 350
 351/* Repeating interfaces */
 352
 353void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
 354{
 355        if (unlikely(INDIRECT_ADDR(addr))) {
 356                iomap_ops[ADDR_TO_REGION(addr)]->read8r(addr, dst, count);
 357        } else {
 358                while (count--) {
 359                        *(u8 *)dst = *(u8 *)addr;
 360                        dst++;
 361                }
 362        }
 363}
 364
 365void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
 366{
 367        if (unlikely(INDIRECT_ADDR(addr))) {
 368                iomap_ops[ADDR_TO_REGION(addr)]->read16r(addr, dst, count);
 369        } else {
 370                while (count--) {
 371                        *(u16 *)dst = *(u16 *)addr;
 372                        dst += 2;
 373                }
 374        }
 375}
 376
 377void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
 378{
 379        if (unlikely(INDIRECT_ADDR(addr))) {
 380                iomap_ops[ADDR_TO_REGION(addr)]->read32r(addr, dst, count);
 381        } else {
 382                while (count--) {
 383                        *(u32 *)dst = *(u32 *)addr;
 384                        dst += 4;
 385                }
 386        }
 387}
 388
 389void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
 390{
 391        if (unlikely(INDIRECT_ADDR(addr))) {
 392                iomap_ops[ADDR_TO_REGION(addr)]->write8r(addr, src, count);
 393        } else {
 394                while (count--) {
 395                        *(u8 *)addr = *(u8 *)src;
 396                        src++;
 397                }
 398        }
 399}
 400
 401void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
 402{
 403        if (unlikely(INDIRECT_ADDR(addr))) {
 404                iomap_ops[ADDR_TO_REGION(addr)]->write16r(addr, src, count);
 405        } else {
 406                while (count--) {
 407                        *(u16 *)addr = *(u16 *)src;
 408                        src += 2;
 409                }
 410        }
 411}
 412
 413void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
 414{
 415        if (unlikely(INDIRECT_ADDR(addr))) {
 416                iomap_ops[ADDR_TO_REGION(addr)]->write32r(addr, src, count);
 417        } else {
 418                while (count--) {
 419                        *(u32 *)addr = *(u32 *)src;
 420                        src += 4;
 421                }
 422        }
 423}
 424
 425/* Mapping interfaces */
 426
 427void __iomem *ioport_map(unsigned long port, unsigned int nr)
 428{
 429        return (void __iomem *)(IOPORT_MAP_BASE | port);
 430}
 431
 432void ioport_unmap(void __iomem *addr)
 433{
 434        if (!INDIRECT_ADDR(addr)) {
 435                iounmap(addr);
 436        }
 437}
 438
 439void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
 440{
 441        if (!INDIRECT_ADDR(addr)) {
 442                iounmap(addr);
 443        }
 444}
 445
 446EXPORT_SYMBOL(ioread8);
 447EXPORT_SYMBOL(ioread16);
 448EXPORT_SYMBOL(ioread16be);
 449EXPORT_SYMBOL(ioread32);
 450EXPORT_SYMBOL(ioread32be);
 451EXPORT_SYMBOL(iowrite8);
 452EXPORT_SYMBOL(iowrite16);
 453EXPORT_SYMBOL(iowrite16be);
 454EXPORT_SYMBOL(iowrite32);
 455EXPORT_SYMBOL(iowrite32be);
 456EXPORT_SYMBOL(ioread8_rep);
 457EXPORT_SYMBOL(ioread16_rep);
 458EXPORT_SYMBOL(ioread32_rep);
 459EXPORT_SYMBOL(iowrite8_rep);
 460EXPORT_SYMBOL(iowrite16_rep);
 461EXPORT_SYMBOL(iowrite32_rep);
 462EXPORT_SYMBOL(ioport_map);
 463EXPORT_SYMBOL(ioport_unmap);
 464EXPORT_SYMBOL(pci_iounmap);
 465