summaryrefslogtreecommitdiffstats
path: root/lib/ioremap.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2019-08-13 11:24:04 +0200
committerChristoph Hellwig <hch@lst.de>2019-11-11 21:18:20 +0100
commit80b0ca98f91ddbc09828aff5a00af1c73837713e (patch)
tree9d88b3bd5945b7408861a6297b23164323bac713 /lib/ioremap.c
parentsh: remove __iounmap (diff)
downloadlinux-80b0ca98f91ddbc09828aff5a00af1c73837713e.tar.xz
linux-80b0ca98f91ddbc09828aff5a00af1c73837713e.zip
lib: provide a simple generic ioremap implementation
A lot of architectures reuse the same simple ioremap implementation, so start lifting the most simple variant to lib/ioremap.c. It provides ioremap_prot and iounmap, plus a default ioremap that uses prot_noncached, although that can be overridden by asm/io.h. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Palmer Dabbelt <palmer@dabbelt.com>
Diffstat (limited to 'lib/ioremap.c')
-rw-r--r--lib/ioremap.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 0a2ffadc6d71..3f0e18543de8 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -231,3 +231,42 @@ int ioremap_page_range(unsigned long addr,
return err;
}
+
+#ifdef CONFIG_GENERIC_IOREMAP
+void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot)
+{
+ unsigned long offset, vaddr;
+ phys_addr_t last_addr;
+ struct vm_struct *area;
+
+ /* Disallow wrap-around or zero size */
+ last_addr = addr + size - 1;
+ if (!size || last_addr < addr)
+ return NULL;
+
+ /* Page-align mappings */
+ offset = addr & (~PAGE_MASK);
+ addr -= offset;
+ size = PAGE_ALIGN(size + offset);
+
+ area = get_vm_area_caller(size, VM_IOREMAP,
+ __builtin_return_address(0));
+ if (!area)
+ return NULL;
+ vaddr = (unsigned long)area->addr;
+
+ if (ioremap_page_range(vaddr, vaddr + size, addr, __pgprot(prot))) {
+ free_vm_area(area);
+ return NULL;
+ }
+
+ return (void __iomem *)(vaddr + offset);
+}
+EXPORT_SYMBOL(ioremap_prot);
+
+void iounmap(volatile void __iomem *addr)
+{
+ vunmap((void *)((unsigned long)addr & PAGE_MASK));
+}
+EXPORT_SYMBOL(iounmap);
+#endif /* CONFIG_GENERIC_IOREMAP */