Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.14-rc1 547 lines 13 kB view raw
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 45struct 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 u64 (*read64)(const void __iomem *); 52 u64 (*read64be)(const void __iomem *); 53 void (*write8)(u8, void __iomem *); 54 void (*write16)(u16, void __iomem *); 55 void (*write16be)(u16, void __iomem *); 56 void (*write32)(u32, void __iomem *); 57 void (*write32be)(u32, void __iomem *); 58 void (*write64)(u64, void __iomem *); 59 void (*write64be)(u64, void __iomem *); 60 void (*read8r)(const void __iomem *, void *, unsigned long); 61 void (*read16r)(const void __iomem *, void *, unsigned long); 62 void (*read32r)(const void __iomem *, void *, unsigned long); 63 void (*write8r)(void __iomem *, const void *, unsigned long); 64 void (*write16r)(void __iomem *, const void *, unsigned long); 65 void (*write32r)(void __iomem *, const void *, unsigned long); 66}; 67 68/* Generic ioport ops. To be replaced later by specific dino/elroy/wax code */ 69 70#define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff) 71 72static unsigned int ioport_read8(const void __iomem *addr) 73{ 74 return inb(ADDR2PORT(addr)); 75} 76 77static unsigned int ioport_read16(const void __iomem *addr) 78{ 79 return inw(ADDR2PORT(addr)); 80} 81 82static unsigned int ioport_read32(const void __iomem *addr) 83{ 84 return inl(ADDR2PORT(addr)); 85} 86 87static void ioport_write8(u8 datum, void __iomem *addr) 88{ 89 outb(datum, ADDR2PORT(addr)); 90} 91 92static void ioport_write16(u16 datum, void __iomem *addr) 93{ 94 outw(datum, ADDR2PORT(addr)); 95} 96 97static void ioport_write32(u32 datum, void __iomem *addr) 98{ 99 outl(datum, ADDR2PORT(addr)); 100} 101 102static void ioport_read8r(const void __iomem *addr, void *dst, unsigned long count) 103{ 104 insb(ADDR2PORT(addr), dst, count); 105} 106 107static void ioport_read16r(const void __iomem *addr, void *dst, unsigned long count) 108{ 109 insw(ADDR2PORT(addr), dst, count); 110} 111 112static void ioport_read32r(const void __iomem *addr, void *dst, unsigned long count) 113{ 114 insl(ADDR2PORT(addr), dst, count); 115} 116 117static void ioport_write8r(void __iomem *addr, const void *s, unsigned long n) 118{ 119 outsb(ADDR2PORT(addr), s, n); 120} 121 122static void ioport_write16r(void __iomem *addr, const void *s, unsigned long n) 123{ 124 outsw(ADDR2PORT(addr), s, n); 125} 126 127static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n) 128{ 129 outsl(ADDR2PORT(addr), s, n); 130} 131 132static const struct iomap_ops ioport_ops = { 133 .read8 = ioport_read8, 134 .read16 = ioport_read16, 135 .read16be = ioport_read16, 136 .read32 = ioport_read32, 137 .read32be = ioport_read32, 138 .write8 = ioport_write8, 139 .write16 = ioport_write16, 140 .write16be = ioport_write16, 141 .write32 = ioport_write32, 142 .write32be = ioport_write32, 143 .read8r = ioport_read8r, 144 .read16r = ioport_read16r, 145 .read32r = ioport_read32r, 146 .write8r = ioport_write8r, 147 .write16r = ioport_write16r, 148 .write32r = ioport_write32r, 149}; 150 151/* Legacy I/O memory ops */ 152 153static unsigned int iomem_read8(const void __iomem *addr) 154{ 155 return readb(addr); 156} 157 158static unsigned int iomem_read16(const void __iomem *addr) 159{ 160 return readw(addr); 161} 162 163static unsigned int iomem_read16be(const void __iomem *addr) 164{ 165 return __raw_readw(addr); 166} 167 168static unsigned int iomem_read32(const void __iomem *addr) 169{ 170 return readl(addr); 171} 172 173static unsigned int iomem_read32be(const void __iomem *addr) 174{ 175 return __raw_readl(addr); 176} 177 178static u64 iomem_read64(const void __iomem *addr) 179{ 180 return readq(addr); 181} 182 183static u64 iomem_read64be(const void __iomem *addr) 184{ 185 return __raw_readq(addr); 186} 187 188static void iomem_write8(u8 datum, void __iomem *addr) 189{ 190 writeb(datum, addr); 191} 192 193static void iomem_write16(u16 datum, void __iomem *addr) 194{ 195 writew(datum, addr); 196} 197 198static void iomem_write16be(u16 datum, void __iomem *addr) 199{ 200 __raw_writew(datum, addr); 201} 202 203static void iomem_write32(u32 datum, void __iomem *addr) 204{ 205 writel(datum, addr); 206} 207 208static void iomem_write32be(u32 datum, void __iomem *addr) 209{ 210 __raw_writel(datum, addr); 211} 212 213static void iomem_write64(u64 datum, void __iomem *addr) 214{ 215 writel(datum, addr); 216} 217 218static void iomem_write64be(u64 datum, void __iomem *addr) 219{ 220 __raw_writel(datum, addr); 221} 222 223static void iomem_read8r(const void __iomem *addr, void *dst, unsigned long count) 224{ 225 while (count--) { 226 *(u8 *)dst = __raw_readb(addr); 227 dst++; 228 } 229} 230 231static void iomem_read16r(const void __iomem *addr, void *dst, unsigned long count) 232{ 233 while (count--) { 234 *(u16 *)dst = __raw_readw(addr); 235 dst += 2; 236 } 237} 238 239static void iomem_read32r(const void __iomem *addr, void *dst, unsigned long count) 240{ 241 while (count--) { 242 *(u32 *)dst = __raw_readl(addr); 243 dst += 4; 244 } 245} 246 247static void iomem_write8r(void __iomem *addr, const void *s, unsigned long n) 248{ 249 while (n--) { 250 __raw_writeb(*(u8 *)s, addr); 251 s++; 252 } 253} 254 255static void iomem_write16r(void __iomem *addr, const void *s, unsigned long n) 256{ 257 while (n--) { 258 __raw_writew(*(u16 *)s, addr); 259 s += 2; 260 } 261} 262 263static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n) 264{ 265 while (n--) { 266 __raw_writel(*(u32 *)s, addr); 267 s += 4; 268 } 269} 270 271static const struct iomap_ops iomem_ops = { 272 .read8 = iomem_read8, 273 .read16 = iomem_read16, 274 .read16be = iomem_read16be, 275 .read32 = iomem_read32, 276 .read32be = iomem_read32be, 277 .read64 = iomem_read64, 278 .read64be = iomem_read64be, 279 .write8 = iomem_write8, 280 .write16 = iomem_write16, 281 .write16be = iomem_write16be, 282 .write32 = iomem_write32, 283 .write32be = iomem_write32be, 284 .write64 = iomem_write64, 285 .write64be = iomem_write64be, 286 .read8r = iomem_read8r, 287 .read16r = iomem_read16r, 288 .read32r = iomem_read32r, 289 .write8r = iomem_write8r, 290 .write16r = iomem_write16r, 291 .write32r = iomem_write32r, 292}; 293 294static const struct iomap_ops *iomap_ops[8] = { 295 [0] = &ioport_ops, 296 [7] = &iomem_ops 297}; 298 299 300unsigned int ioread8(const void __iomem *addr) 301{ 302 if (unlikely(INDIRECT_ADDR(addr))) 303 return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr); 304 return *((u8 *)addr); 305} 306 307unsigned int ioread16(const void __iomem *addr) 308{ 309 if (unlikely(INDIRECT_ADDR(addr))) 310 return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr); 311 return le16_to_cpup((u16 *)addr); 312} 313 314unsigned int ioread16be(const void __iomem *addr) 315{ 316 if (unlikely(INDIRECT_ADDR(addr))) 317 return iomap_ops[ADDR_TO_REGION(addr)]->read16be(addr); 318 return *((u16 *)addr); 319} 320 321unsigned int ioread32(const void __iomem *addr) 322{ 323 if (unlikely(INDIRECT_ADDR(addr))) 324 return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr); 325 return le32_to_cpup((u32 *)addr); 326} 327 328unsigned int ioread32be(const void __iomem *addr) 329{ 330 if (unlikely(INDIRECT_ADDR(addr))) 331 return iomap_ops[ADDR_TO_REGION(addr)]->read32be(addr); 332 return *((u32 *)addr); 333} 334 335u64 ioread64(const void __iomem *addr) 336{ 337 if (unlikely(INDIRECT_ADDR(addr))) 338 return iomap_ops[ADDR_TO_REGION(addr)]->read64(addr); 339 return le64_to_cpup((u64 *)addr); 340} 341 342u64 ioread64be(const void __iomem *addr) 343{ 344 if (unlikely(INDIRECT_ADDR(addr))) 345 return iomap_ops[ADDR_TO_REGION(addr)]->read64be(addr); 346 return *((u64 *)addr); 347} 348 349u64 ioread64_hi_lo(const void __iomem *addr) 350{ 351 u32 low, high; 352 353 high = ioread32(addr + sizeof(u32)); 354 low = ioread32(addr); 355 356 return low + ((u64)high << 32); 357} 358 359void iowrite8(u8 datum, void __iomem *addr) 360{ 361 if (unlikely(INDIRECT_ADDR(addr))) { 362 iomap_ops[ADDR_TO_REGION(addr)]->write8(datum, addr); 363 } else { 364 *((u8 *)addr) = datum; 365 } 366} 367 368void iowrite16(u16 datum, void __iomem *addr) 369{ 370 if (unlikely(INDIRECT_ADDR(addr))) { 371 iomap_ops[ADDR_TO_REGION(addr)]->write16(datum, addr); 372 } else { 373 *((u16 *)addr) = cpu_to_le16(datum); 374 } 375} 376 377void iowrite16be(u16 datum, void __iomem *addr) 378{ 379 if (unlikely(INDIRECT_ADDR(addr))) { 380 iomap_ops[ADDR_TO_REGION(addr)]->write16be(datum, addr); 381 } else { 382 *((u16 *)addr) = datum; 383 } 384} 385 386void iowrite32(u32 datum, void __iomem *addr) 387{ 388 if (unlikely(INDIRECT_ADDR(addr))) { 389 iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr); 390 } else { 391 *((u32 *)addr) = cpu_to_le32(datum); 392 } 393} 394 395void iowrite32be(u32 datum, void __iomem *addr) 396{ 397 if (unlikely(INDIRECT_ADDR(addr))) { 398 iomap_ops[ADDR_TO_REGION(addr)]->write32be(datum, addr); 399 } else { 400 *((u32 *)addr) = datum; 401 } 402} 403 404void iowrite64(u64 datum, void __iomem *addr) 405{ 406 if (unlikely(INDIRECT_ADDR(addr))) { 407 iomap_ops[ADDR_TO_REGION(addr)]->write64(datum, addr); 408 } else { 409 *((u64 *)addr) = cpu_to_le64(datum); 410 } 411} 412 413void iowrite64be(u64 datum, void __iomem *addr) 414{ 415 if (unlikely(INDIRECT_ADDR(addr))) { 416 iomap_ops[ADDR_TO_REGION(addr)]->write64be(datum, addr); 417 } else { 418 *((u64 *)addr) = datum; 419 } 420} 421 422void iowrite64_hi_lo(u64 val, void __iomem *addr) 423{ 424 iowrite32(val >> 32, addr + sizeof(u32)); 425 iowrite32(val, addr); 426} 427 428/* Repeating interfaces */ 429 430void 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 442void 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 454void 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 466void 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 478void 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 490void 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 504void __iomem *ioport_map(unsigned long port, unsigned int nr) 505{ 506 return (void __iomem *)(IOPORT_MAP_BASE | port); 507} 508 509void ioport_unmap(void __iomem *addr) 510{ 511 if (!INDIRECT_ADDR(addr)) { 512 iounmap(addr); 513 } 514} 515 516void pci_iounmap(struct pci_dev *dev, void __iomem * addr) 517{ 518 if (!INDIRECT_ADDR(addr)) { 519 iounmap(addr); 520 } 521} 522 523EXPORT_SYMBOL(ioread8); 524EXPORT_SYMBOL(ioread16); 525EXPORT_SYMBOL(ioread16be); 526EXPORT_SYMBOL(ioread32); 527EXPORT_SYMBOL(ioread32be); 528EXPORT_SYMBOL(ioread64); 529EXPORT_SYMBOL(ioread64be); 530EXPORT_SYMBOL(ioread64_hi_lo); 531EXPORT_SYMBOL(iowrite8); 532EXPORT_SYMBOL(iowrite16); 533EXPORT_SYMBOL(iowrite16be); 534EXPORT_SYMBOL(iowrite32); 535EXPORT_SYMBOL(iowrite32be); 536EXPORT_SYMBOL(iowrite64); 537EXPORT_SYMBOL(iowrite64be); 538EXPORT_SYMBOL(iowrite64_hi_lo); 539EXPORT_SYMBOL(ioread8_rep); 540EXPORT_SYMBOL(ioread16_rep); 541EXPORT_SYMBOL(ioread32_rep); 542EXPORT_SYMBOL(iowrite8_rep); 543EXPORT_SYMBOL(iowrite16_rep); 544EXPORT_SYMBOL(iowrite32_rep); 545EXPORT_SYMBOL(ioport_map); 546EXPORT_SYMBOL(ioport_unmap); 547EXPORT_SYMBOL(pci_iounmap);