xref: /kernel/linux/linux-5.10/arch/xtensa/mm/ioremap.c (revision 8c2ecf20)
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