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 void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, 15 unsigned long prot) 16 { 17 unsigned long offset, vaddr; 18 phys_addr_t last_addr; 19 struct vm_struct *area; 20 21 /* Disallow wrap-around or zero size */ 22 last_addr = phys_addr + size - 1; 23 if (!size || last_addr < phys_addr) 24 return NULL; 25 26 /* Page-align mappings */ 27 offset = phys_addr & (~PAGE_MASK); 28 phys_addr -= offset; 29 size = PAGE_ALIGN(size + offset); 30 31 if (!ioremap_allowed(phys_addr, size, prot)) 32 return NULL; 33 34 area = get_vm_area_caller(size, VM_IOREMAP, 35 __builtin_return_address(0)); 36 if (!area) 37 return NULL; 38 vaddr = (unsigned long)area->addr; 39 area->phys_addr = phys_addr; 40 41 if (ioremap_page_range(vaddr, vaddr + size, phys_addr, 42 __pgprot(prot))) { 43 free_vm_area(area); 44 return NULL; 45 } 46 47 return (void __iomem *)(vaddr + offset); 48 } 49 EXPORT_SYMBOL(ioremap_prot); 50 51 void iounmap(volatile void __iomem *addr) 52 { 53 void *vaddr = (void *)((unsigned long)addr & PAGE_MASK); 54 55 if (!iounmap_allowed(vaddr)) 56 return; 57 58 if (is_vmalloc_addr(vaddr)) 59 vunmap(vaddr); 60 } 61 EXPORT_SYMBOL(iounmap); 62