Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Re-map IO memory to kernel address space so that we can access it.
0004  * This is needed for high PCI addresses that aren't mapped in the
0005  * 640k-1MB IO memory area on PC's
0006  *
0007  * (C) Copyright 1995 1996 Linus Torvalds
0008  */
0009 #include <linux/vmalloc.h>
0010 #include <linux/mm.h>
0011 #include <linux/io.h>
0012 #include <linux/export.h>
0013 
0014 void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
0015                unsigned long prot)
0016 {
0017     unsigned long offset, vaddr;
0018     phys_addr_t last_addr;
0019     struct vm_struct *area;
0020 
0021     /* Disallow wrap-around or zero size */
0022     last_addr = phys_addr + size - 1;
0023     if (!size || last_addr < phys_addr)
0024         return NULL;
0025 
0026     /* Page-align mappings */
0027     offset = phys_addr & (~PAGE_MASK);
0028     phys_addr -= offset;
0029     size = PAGE_ALIGN(size + offset);
0030 
0031     if (!ioremap_allowed(phys_addr, size, prot))
0032         return NULL;
0033 
0034     area = get_vm_area_caller(size, VM_IOREMAP,
0035             __builtin_return_address(0));
0036     if (!area)
0037         return NULL;
0038     vaddr = (unsigned long)area->addr;
0039     area->phys_addr = phys_addr;
0040 
0041     if (ioremap_page_range(vaddr, vaddr + size, phys_addr,
0042                    __pgprot(prot))) {
0043         free_vm_area(area);
0044         return NULL;
0045     }
0046 
0047     return (void __iomem *)(vaddr + offset);
0048 }
0049 EXPORT_SYMBOL(ioremap_prot);
0050 
0051 void iounmap(volatile void __iomem *addr)
0052 {
0053     void *vaddr = (void *)((unsigned long)addr & PAGE_MASK);
0054 
0055     if (!iounmap_allowed(vaddr))
0056         return;
0057 
0058     if (is_vmalloc_addr(vaddr))
0059         vunmap(vaddr);
0060 }
0061 EXPORT_SYMBOL(iounmap);