• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
10 
__ioremap_caller(phys_addr_t phys_addr,size_t size,void * caller)11 static 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 
ioremap(phys_addr_t phys_addr,size_t size)49 void __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 
55 EXPORT_SYMBOL(ioremap);
56 
iounmap(volatile void __iomem * addr)57 void iounmap(volatile void __iomem * addr)
58 {
59 	vunmap((void *)(PAGE_MASK & (unsigned long)addr));
60 }
61 
62 EXPORT_SYMBOL(iounmap);
63