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