18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ioremap implementation. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Cadence Design Systems Inc. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/io.h> 98c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 108c2ecf20Sopenharmony_ci#include <linux/pgtable.h> 118c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 128c2ecf20Sopenharmony_ci#include <asm/io.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic void __iomem *xtensa_ioremap(unsigned long paddr, unsigned long size, 158c2ecf20Sopenharmony_ci pgprot_t prot) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci unsigned long offset = paddr & ~PAGE_MASK; 188c2ecf20Sopenharmony_ci unsigned long pfn = __phys_to_pfn(paddr); 198c2ecf20Sopenharmony_ci struct vm_struct *area; 208c2ecf20Sopenharmony_ci unsigned long vaddr; 218c2ecf20Sopenharmony_ci int err; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci paddr &= PAGE_MASK; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci WARN_ON(pfn_valid(pfn)); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci size = PAGE_ALIGN(offset + size); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci area = get_vm_area(size, VM_IOREMAP); 308c2ecf20Sopenharmony_ci if (!area) 318c2ecf20Sopenharmony_ci return NULL; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci vaddr = (unsigned long)area->addr; 348c2ecf20Sopenharmony_ci area->phys_addr = paddr; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci err = ioremap_page_range(vaddr, vaddr + size, paddr, prot); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (err) { 398c2ecf20Sopenharmony_ci vunmap((void *)vaddr); 408c2ecf20Sopenharmony_ci return NULL; 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci flush_cache_vmap(vaddr, vaddr + size); 448c2ecf20Sopenharmony_ci return (void __iomem *)(offset + vaddr); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_civoid __iomem *xtensa_ioremap_nocache(unsigned long addr, unsigned long size) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci return xtensa_ioremap(addr, size, pgprot_noncached(PAGE_KERNEL)); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(xtensa_ioremap_nocache); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_civoid __iomem *xtensa_ioremap_cache(unsigned long addr, unsigned long size) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci return xtensa_ioremap(addr, size, PAGE_KERNEL); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(xtensa_ioremap_cache); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_civoid xtensa_iounmap(volatile void __iomem *io_addr) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci vunmap(addr); 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(xtensa_iounmap); 66