Merge tag 'armsoc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-block.git] / arch / nds32 / mm / ioremap.c
CommitLineData
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
9void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
10
11static 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
49void __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
55EXPORT_SYMBOL(ioremap);
56
57void iounmap(volatile void __iomem * addr)
58{
59 vunmap((void *)(PAGE_MASK & (unsigned long)addr));
60}
61
62EXPORT_SYMBOL(iounmap);