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>
This commit is contained in:
@@ -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 */
|
||||
|
Reference in New Issue
Block a user