diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-18 15:12:20 +0530 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-15 23:15:54 +0530 |
commit | 1162b0701b14ba112d4e3fe5c27c694caf983539 (patch) | |
tree | 4255ede27a8c75378ec6c2e5cccc64fac7e41c0a /arch/arc/mm/ioremap.c | |
parent | fbd7053a7854b12b0fdc415089c59baabf25c625 (diff) |
ARC: I/O and DMA Mappings
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/mm/ioremap.c')
-rw-r--r-- | arch/arc/mm/ioremap.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c new file mode 100644 index 000000000000..52518b6d0f28 --- /dev/null +++ b/arch/arc/mm/ioremap.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/vmalloc.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <asm/cache.h> + +void __iomem *ioremap(unsigned long paddr, unsigned long size) +{ + unsigned long vaddr; + struct vm_struct *area; + unsigned long off, end; + const pgprot_t prot = PAGE_KERNEL_NO_CACHE; + + /* Don't allow wraparound or zero size */ + end = paddr + size - 1; + if (!size || (end < paddr)) + return NULL; + + /* If the region is h/w uncached, nothing special needed */ + if (paddr >= ARC_UNCACHED_ADDR_SPACE) + return (void __iomem *)paddr; + + /* An early platform driver might end up here */ + if (!slab_is_available()) + return NULL; + + /* Mappings have to be page-aligned, page-sized */ + off = paddr & ~PAGE_MASK; + paddr &= PAGE_MASK; + size = PAGE_ALIGN(end + 1) - paddr; + + /* + * Ok, go for it.. + */ + area = get_vm_area(size, VM_IOREMAP); + if (!area) + return NULL; + + area->phys_addr = paddr; + vaddr = (unsigned long)area->addr; + if (ioremap_page_range(vaddr, vaddr + size, paddr, prot)) { + vfree(area->addr); + return NULL; + } + + return (void __iomem *)(off + (char __iomem *)vaddr); +} +EXPORT_SYMBOL(ioremap); + +void iounmap(const void __iomem *addr) +{ + if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE) + return; + + vfree((void *)(PAGE_MASK & (unsigned long __force)addr)); +} +EXPORT_SYMBOL(iounmap); |