1
2
3
4#include <linux/export.h>
5#include <linux/mm.h>
6#include <linux/vmalloc.h>
7#include <linux/io.h>
8
9#include <asm/pgtable.h>
10
11static void __iomem *__ioremap_caller(phys_addr_t addr, size_t size,
12 pgprot_t prot, void *caller)
13{
14 phys_addr_t last_addr;
15 unsigned long offset, vaddr;
16 struct vm_struct *area;
17
18 last_addr = addr + size - 1;
19 if (!size || last_addr < addr)
20 return NULL;
21
22 offset = addr & (~PAGE_MASK);
23 addr &= PAGE_MASK;
24 size = PAGE_ALIGN(size + offset);
25
26 area = get_vm_area_caller(size, VM_IOREMAP, caller);
27 if (!area)
28 return NULL;
29
30 vaddr = (unsigned long)area->addr;
31
32 if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
33 free_vm_area(area);
34 return NULL;
35 }
36
37 return (void __iomem *)(vaddr + offset);
38}
39
40void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot)
41{
42 return __ioremap_caller(phys_addr, size, prot,
43 __builtin_return_address(0));
44}
45EXPORT_SYMBOL(__ioremap);
46
47void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
48{
49 return __ioremap_caller(phys_addr, size, PAGE_KERNEL,
50 __builtin_return_address(0));
51}
52EXPORT_SYMBOL(ioremap_cache);
53
54void iounmap(void __iomem *addr)
55{
56 vunmap((void *)((unsigned long)addr & PAGE_MASK));
57}
58EXPORT_SYMBOL(iounmap);
59
60pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
61 unsigned long size, pgprot_t vma_prot)
62{
63 if (!pfn_valid(pfn)) {
64 return pgprot_noncached(vma_prot);
65 } else if (file->f_flags & O_SYNC) {
66 return pgprot_writecombine(vma_prot);
67 }
68
69 return vma_prot;
70}
71EXPORT_SYMBOL(phys_mem_access_prot);
72