Commit | Line | Data |
---|---|---|
4a64f68d GH |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (C) 2005-2017 Andes Technology Corporation | |
3 | ||
4 | #include <linux/vmalloc.h> | |
5 | #include <linux/io.h> | |
6 | #include <linux/mm.h> | |
7 | #include <asm/pgtable.h> | |
8 | ||
9 | void __iomem *ioremap(phys_addr_t phys_addr, size_t size); | |
10 | ||
11 | static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, | |
12 | void *caller) | |
13 | { | |
14 | struct vm_struct *area; | |
15 | unsigned long addr, offset, last_addr; | |
16 | pgprot_t prot; | |
17 | ||
18 | /* Don't allow wraparound or zero size */ | |
19 | last_addr = phys_addr + size - 1; | |
20 | if (!size || last_addr < phys_addr) | |
21 | return NULL; | |
22 | ||
23 | /* | |
24 | * Mappings have to be page-aligned | |
25 | */ | |
26 | offset = phys_addr & ~PAGE_MASK; | |
27 | phys_addr &= PAGE_MASK; | |
28 | size = PAGE_ALIGN(last_addr + 1) - phys_addr; | |
29 | ||
30 | /* | |
31 | * Ok, go for it.. | |
32 | */ | |
33 | area = get_vm_area_caller(size, VM_IOREMAP, caller); | |
34 | if (!area) | |
35 | return NULL; | |
36 | ||
37 | area->phys_addr = phys_addr; | |
38 | addr = (unsigned long)area->addr; | |
39 | prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | | |
40 | _PAGE_G | _PAGE_C_DEV); | |
41 | if (ioremap_page_range(addr, addr + size, phys_addr, prot)) { | |
42 | vunmap((void *)addr); | |
43 | return NULL; | |
44 | } | |
45 | return (__force void __iomem *)(offset + (char *)addr); | |
46 | ||
47 | } | |
48 | ||
49 | void __iomem *ioremap(phys_addr_t phys_addr, size_t size) | |
50 | { | |
51 | return __ioremap_caller(phys_addr, size, | |
52 | __builtin_return_address(0)); | |
53 | } | |
54 | ||
55 | EXPORT_SYMBOL(ioremap); | |
56 | ||
57 | void iounmap(volatile void __iomem * addr) | |
58 | { | |
59 | vunmap((void *)(PAGE_MASK & (unsigned long)addr)); | |
60 | } | |
61 | ||
62 | EXPORT_SYMBOL(iounmap); |