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