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 area = get_vm_area_caller(size, VM_IOREMAP, 32 __builtin_return_address(0)); 33 if (!area) 34 return NULL; 35 vaddr = (unsigned long)area->addr; 36 area->phys_addr = phys_addr; 37 38 if (ioremap_page_range(vaddr, vaddr + size, phys_addr, 39 __pgprot(prot))) { 40 free_vm_area(area); 41 return NULL; 42 } 43 44 return (void __iomem *)(vaddr + offset); 45 } 46 EXPORT_SYMBOL(ioremap_prot); 47 48 void iounmap(volatile void __iomem *addr) 49 { 50 vunmap((void *)((unsigned long)addr & PAGE_MASK)); 51 } 52 EXPORT_SYMBOL(iounmap); 53