1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3 4 #include <linux/export.h> 5 #include <linux/mm.h> 6 #include <linux/vmalloc.h> 7 #include <linux/io.h> 8 9 #include <asm/pgtable.h> 10 11 static void __iomem *__ioremap_caller(phys_addr_t addr, size_t size, 12 pgprot_t prot, void *caller) 13 { 14 phys_addr_t last_addr; 15 unsigned long offset, vaddr; 16 struct vm_struct *area; 17 18 last_addr = addr + size - 1; 19 if (!size || last_addr < addr) 20 return NULL; 21 22 offset = addr & (~PAGE_MASK); 23 addr &= PAGE_MASK; 24 size = PAGE_ALIGN(size + offset); 25 26 area = get_vm_area_caller(size, VM_IOREMAP, caller); 27 if (!area) 28 return NULL; 29 30 vaddr = (unsigned long)area->addr; 31 32 if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) { 33 free_vm_area(area); 34 return NULL; 35 } 36 37 return (void __iomem *)(vaddr + offset); 38 } 39 40 void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot) 41 { 42 return __ioremap_caller(phys_addr, size, prot, 43 __builtin_return_address(0)); 44 } 45 EXPORT_SYMBOL(__ioremap); 46 47 void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size) 48 { 49 return __ioremap_caller(phys_addr, size, PAGE_KERNEL, 50 __builtin_return_address(0)); 51 } 52 EXPORT_SYMBOL(ioremap_cache); 53 54 void iounmap(void __iomem *addr) 55 { 56 vunmap((void *)((unsigned long)addr & PAGE_MASK)); 57 } 58 EXPORT_SYMBOL(iounmap); 59 60 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 61 unsigned long size, pgprot_t vma_prot) 62 { 63 if (!pfn_valid(pfn)) { 64 return pgprot_noncached(vma_prot); 65 } else if (file->f_flags & O_SYNC) { 66 return pgprot_writecombine(vma_prot); 67 } 68 69 return vma_prot; 70 } 71 EXPORT_SYMBOL(phys_mem_access_prot); 72