0001
0002
0003
0004
0005
0006
0007
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
0022 last_addr = phys_addr + size - 1;
0023 if (!size || last_addr < phys_addr)
0024 return NULL;
0025
0026
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);