Commit | Line | Data |
---|---|---|
1162b070 VG |
1 | /* |
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License version 2 as | |
6 | * published by the Free Software Foundation. | |
7 | */ | |
8 | ||
9 | #include <linux/vmalloc.h> | |
10 | #include <linux/init.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/io.h> | |
13 | #include <linux/mm.h> | |
14 | #include <linux/slab.h> | |
15 | #include <asm/cache.h> | |
16 | ||
17 | void __iomem *ioremap(unsigned long paddr, unsigned long size) | |
18 | { | |
19 | unsigned long vaddr; | |
20 | struct vm_struct *area; | |
21 | unsigned long off, end; | |
22 | const pgprot_t prot = PAGE_KERNEL_NO_CACHE; | |
23 | ||
24 | /* Don't allow wraparound or zero size */ | |
25 | end = paddr + size - 1; | |
26 | if (!size || (end < paddr)) | |
27 | return NULL; | |
28 | ||
29 | /* If the region is h/w uncached, nothing special needed */ | |
30 | if (paddr >= ARC_UNCACHED_ADDR_SPACE) | |
31 | return (void __iomem *)paddr; | |
32 | ||
33 | /* An early platform driver might end up here */ | |
34 | if (!slab_is_available()) | |
35 | return NULL; | |
36 | ||
37 | /* Mappings have to be page-aligned, page-sized */ | |
38 | off = paddr & ~PAGE_MASK; | |
39 | paddr &= PAGE_MASK; | |
40 | size = PAGE_ALIGN(end + 1) - paddr; | |
41 | ||
42 | /* | |
43 | * Ok, go for it.. | |
44 | */ | |
45 | area = get_vm_area(size, VM_IOREMAP); | |
46 | if (!area) | |
47 | return NULL; | |
48 | ||
49 | area->phys_addr = paddr; | |
50 | vaddr = (unsigned long)area->addr; | |
51 | if (ioremap_page_range(vaddr, vaddr + size, paddr, prot)) { | |
52 | vfree(area->addr); | |
53 | return NULL; | |
54 | } | |
55 | ||
56 | return (void __iomem *)(off + (char __iomem *)vaddr); | |
57 | } | |
58 | EXPORT_SYMBOL(ioremap); | |
59 | ||
60 | void iounmap(const void __iomem *addr) | |
61 | { | |
62 | if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE) | |
63 | return; | |
64 | ||
65 | vfree((void *)(PAGE_MASK & (unsigned long __force)addr)); | |
66 | } | |
67 | EXPORT_SYMBOL(iounmap); |