1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Re-map IO memory to kernel address space so that we can access it. 4 * This is needed for high PCI addresses that aren't mapped in the 5 * 640k-1MB IO memory area on PC's 6 * 7 * (C) Copyright 1995 1996 Linus Torvalds 8 */ 9 #include <linux/vmalloc.h> 10 #include <linux/mm.h> 11 #include <linux/io.h> 12 #include <linux/export.h> 13 14 /* 15 * Ioremap often, but not always uses the generic vmalloc area. E.g on 16 * Power ARCH, it could have different ioremap space. 17 */ 18 #ifndef IOREMAP_START 19 #define IOREMAP_START VMALLOC_START 20 #define IOREMAP_END VMALLOC_END 21 #endif 22 23 void __iomem *generic_ioremap_prot(phys_addr_t phys_addr, size_t size, 24 pgprot_t prot) 25 { 26 unsigned long offset, vaddr; 27 phys_addr_t last_addr; 28 struct vm_struct *area; 29 30 /* An early platform driver might end up here */ 31 if (WARN_ON_ONCE(!slab_is_available())) 32 return NULL; 33 34 /* Disallow wrap-around or zero size */ 35 last_addr = phys_addr + size - 1; 36 if (!size || last_addr < phys_addr) 37 return NULL; 38 39 /* Page-align mappings */ 40 offset = phys_addr & (~PAGE_MASK); 41 phys_addr -= offset; 42 size = PAGE_ALIGN(size + offset); 43 44 if (!ioremap_allowed(phys_addr, size, pgprot_val(prot))) 45 return NULL; 46 47 area = __get_vm_area_caller(size, VM_IOREMAP, IOREMAP_START, 48 IOREMAP_END, __builtin_return_address(0)); 49 if (!area) 50 return NULL; 51 vaddr = (unsigned long)area->addr; 52 area->phys_addr = phys_addr; 53 54 if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) { 55 free_vm_area(area); 56 return NULL; 57 } 58 59 return (void __iomem *)(vaddr + offset); 60 } 61 62 #ifndef ioremap_prot 63 void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, 64 unsigned long prot) 65 { 66 return generic_ioremap_prot(phys_addr, size, __pgprot(prot)); 67 } 68 EXPORT_SYMBOL(ioremap_prot); 69 #endif 70 71 void generic_iounmap(volatile void __iomem *addr) 72 { 73 void *vaddr = (void *)((unsigned long)addr & PAGE_MASK); 74 75 if (!iounmap_allowed(vaddr)) 76 return; 77 78 if (is_ioremap_addr(vaddr)) 79 vunmap(vaddr); 80 } 81 82 #ifndef iounmap 83 void iounmap(volatile void __iomem *addr) 84 { 85 generic_iounmap(addr); 86 } 87 EXPORT_SYMBOL(iounmap); 88 #endif 89