1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * ioremap implementation. 4 * 5 * Copyright (C) 2015 Cadence Design Systems Inc. 6 */ 7 8 #include <linux/io.h> 9 #include <linux/vmalloc.h> 10 #include <asm/cacheflush.h> 11 #include <asm/io.h> 12 #include <asm/pgtable.h> 13 14 static void __iomem *xtensa_ioremap(unsigned long paddr, unsigned long size, 15 pgprot_t prot) 16 { 17 unsigned long offset = paddr & ~PAGE_MASK; 18 unsigned long pfn = __phys_to_pfn(paddr); 19 struct vm_struct *area; 20 unsigned long vaddr; 21 int err; 22 23 paddr &= PAGE_MASK; 24 25 WARN_ON(pfn_valid(pfn)); 26 27 size = PAGE_ALIGN(offset + size); 28 29 area = get_vm_area(size, VM_IOREMAP); 30 if (!area) 31 return NULL; 32 33 vaddr = (unsigned long)area->addr; 34 area->phys_addr = paddr; 35 36 err = ioremap_page_range(vaddr, vaddr + size, paddr, prot); 37 38 if (err) { 39 vunmap((void *)vaddr); 40 return NULL; 41 } 42 43 flush_cache_vmap(vaddr, vaddr + size); 44 return (void __iomem *)(offset + vaddr); 45 } 46 47 void __iomem *xtensa_ioremap_nocache(unsigned long addr, unsigned long size) 48 { 49 return xtensa_ioremap(addr, size, pgprot_noncached(PAGE_KERNEL)); 50 } 51 EXPORT_SYMBOL(xtensa_ioremap_nocache); 52 53 void __iomem *xtensa_ioremap_cache(unsigned long addr, unsigned long size) 54 { 55 return xtensa_ioremap(addr, size, PAGE_KERNEL); 56 } 57 EXPORT_SYMBOL(xtensa_ioremap_cache); 58 59 void xtensa_iounmap(volatile void __iomem *io_addr) 60 { 61 void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); 62 63 vunmap(addr); 64 } 65 EXPORT_SYMBOL(xtensa_iounmap); 66