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