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 void __iomem *ioremap(phys_addr_t addr, size_t size) 12 { 13 phys_addr_t last_addr; 14 unsigned long offset, vaddr; 15 struct vm_struct *area; 16 pgprot_t prot; 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_ALLOC, __builtin_return_address(0)); 27 if (!area) 28 return NULL; 29 30 vaddr = (unsigned long)area->addr; 31 32 prot = __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | 33 _PAGE_GLOBAL | _CACHE_UNCACHED | _PAGE_SO); 34 35 if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) { 36 free_vm_area(area); 37 return NULL; 38 } 39 40 return (void __iomem *)(vaddr + offset); 41 } 42 EXPORT_SYMBOL(ioremap); 43 44 void iounmap(void __iomem *addr) 45 { 46 vunmap((void *)((unsigned long)addr & PAGE_MASK)); 47 } 48 EXPORT_SYMBOL(iounmap); 49 50 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 51 unsigned long size, pgprot_t vma_prot) 52 { 53 if (!pfn_valid(pfn)) { 54 vma_prot.pgprot |= _PAGE_SO; 55 return pgprot_noncached(vma_prot); 56 } else if (file->f_flags & O_SYNC) { 57 return pgprot_noncached(vma_prot); 58 } 59 60 return vma_prot; 61 } 62 EXPORT_SYMBOL(phys_mem_access_prot); 63