162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/io.h>
462306a36Sopenharmony_ci#include <linux/slab.h>
562306a36Sopenharmony_ci#include <linux/vmalloc.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <mm/mmu_decl.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_civoid __iomem *ioremap_wt(phys_addr_t addr, unsigned long size)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	pgprot_t prot = pgprot_cached_wthru(PAGE_KERNEL);
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	return __ioremap_caller(addr, size, prot, __builtin_return_address(0));
1462306a36Sopenharmony_ci}
1562306a36Sopenharmony_ciEXPORT_SYMBOL(ioremap_wt);
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_civoid __iomem *
1862306a36Sopenharmony_ci__ioremap_caller(phys_addr_t addr, unsigned long size, pgprot_t prot, void *caller)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	unsigned long v;
2162306a36Sopenharmony_ci	phys_addr_t p, offset;
2262306a36Sopenharmony_ci	int err;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	/*
2562306a36Sopenharmony_ci	 * If the address lies within the first 16 MB, assume it's in ISA
2662306a36Sopenharmony_ci	 * memory space
2762306a36Sopenharmony_ci	 */
2862306a36Sopenharmony_ci	if (addr < SZ_16M)
2962306a36Sopenharmony_ci		addr += _ISA_MEM_BASE;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	/*
3262306a36Sopenharmony_ci	 * Choose an address to map it to.
3362306a36Sopenharmony_ci	 * Once the vmalloc system is running, we use it.
3462306a36Sopenharmony_ci	 * Before then, we use space going down from IOREMAP_TOP
3562306a36Sopenharmony_ci	 * (ioremap_bot records where we're up to).
3662306a36Sopenharmony_ci	 */
3762306a36Sopenharmony_ci	p = addr & PAGE_MASK;
3862306a36Sopenharmony_ci	offset = addr & ~PAGE_MASK;
3962306a36Sopenharmony_ci	size = PAGE_ALIGN(addr + size) - p;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#ifndef CONFIG_CRASH_DUMP
4262306a36Sopenharmony_ci	/*
4362306a36Sopenharmony_ci	 * Don't allow anybody to remap normal RAM that we're using.
4462306a36Sopenharmony_ci	 * mem_init() sets high_memory so only do the check after that.
4562306a36Sopenharmony_ci	 */
4662306a36Sopenharmony_ci	if (slab_is_available() && p <= virt_to_phys(high_memory - 1) &&
4762306a36Sopenharmony_ci	    page_is_ram(__phys_to_pfn(p))) {
4862306a36Sopenharmony_ci		pr_warn("%s(): phys addr 0x%llx is RAM lr %ps\n", __func__,
4962306a36Sopenharmony_ci			(unsigned long long)p, __builtin_return_address(0));
5062306a36Sopenharmony_ci		return NULL;
5162306a36Sopenharmony_ci	}
5262306a36Sopenharmony_ci#endif
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	if (size == 0)
5562306a36Sopenharmony_ci		return NULL;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/*
5862306a36Sopenharmony_ci	 * Is it already mapped?  Perhaps overlapped by a previous
5962306a36Sopenharmony_ci	 * mapping.
6062306a36Sopenharmony_ci	 */
6162306a36Sopenharmony_ci	v = p_block_mapped(p);
6262306a36Sopenharmony_ci	if (v)
6362306a36Sopenharmony_ci		return (void __iomem *)v + offset;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (slab_is_available())
6662306a36Sopenharmony_ci		return generic_ioremap_prot(addr, size, prot);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	/*
6962306a36Sopenharmony_ci	 * Should check if it is a candidate for a BAT mapping
7062306a36Sopenharmony_ci	 */
7162306a36Sopenharmony_ci	pr_warn("ioremap() called early from %pS. Use early_ioremap() instead\n", caller);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	err = early_ioremap_range(ioremap_bot - size - PAGE_SIZE, p, size, prot);
7462306a36Sopenharmony_ci	if (err)
7562306a36Sopenharmony_ci		return NULL;
7662306a36Sopenharmony_ci	ioremap_bot -= size + PAGE_SIZE;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	return (void __iomem *)ioremap_bot + offset;
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_civoid iounmap(volatile void __iomem *addr)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	/*
8462306a36Sopenharmony_ci	 * If mapped by BATs then there is nothing to do.
8562306a36Sopenharmony_ci	 * Calling vfree() generates a benign warning.
8662306a36Sopenharmony_ci	 */
8762306a36Sopenharmony_ci	if (v_block_mapped((unsigned long)addr))
8862306a36Sopenharmony_ci		return;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	generic_iounmap(addr);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ciEXPORT_SYMBOL(iounmap);
93