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/mmzone.h>
662306a36Sopenharmony_ci#include <linux/vmalloc.h>
762306a36Sopenharmony_ci#include <asm/io-workarounds.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciunsigned long ioremap_bot;
1062306a36Sopenharmony_ciEXPORT_SYMBOL(ioremap_bot);
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_civoid __iomem *ioremap(phys_addr_t addr, unsigned long size)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	pgprot_t prot = pgprot_noncached(PAGE_KERNEL);
1562306a36Sopenharmony_ci	void *caller = __builtin_return_address(0);
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci	if (iowa_is_active())
1862306a36Sopenharmony_ci		return iowa_ioremap(addr, size, prot, caller);
1962306a36Sopenharmony_ci	return __ioremap_caller(addr, size, prot, caller);
2062306a36Sopenharmony_ci}
2162306a36Sopenharmony_ciEXPORT_SYMBOL(ioremap);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_civoid __iomem *ioremap_wc(phys_addr_t addr, unsigned long size)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	pgprot_t prot = pgprot_noncached_wc(PAGE_KERNEL);
2662306a36Sopenharmony_ci	void *caller = __builtin_return_address(0);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	if (iowa_is_active())
2962306a36Sopenharmony_ci		return iowa_ioremap(addr, size, prot, caller);
3062306a36Sopenharmony_ci	return __ioremap_caller(addr, size, prot, caller);
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ciEXPORT_SYMBOL(ioremap_wc);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_civoid __iomem *ioremap_coherent(phys_addr_t addr, unsigned long size)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	pgprot_t prot = pgprot_cached(PAGE_KERNEL);
3762306a36Sopenharmony_ci	void *caller = __builtin_return_address(0);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	if (iowa_is_active())
4062306a36Sopenharmony_ci		return iowa_ioremap(addr, size, prot, caller);
4162306a36Sopenharmony_ci	return __ioremap_caller(addr, size, prot, caller);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_civoid __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long flags)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	pte_t pte = __pte(flags);
4762306a36Sopenharmony_ci	void *caller = __builtin_return_address(0);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	/* writeable implies dirty for kernel addresses */
5062306a36Sopenharmony_ci	if (pte_write(pte))
5162306a36Sopenharmony_ci		pte = pte_mkdirty(pte);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
5462306a36Sopenharmony_ci	pte = pte_exprotect(pte);
5562306a36Sopenharmony_ci	pte = pte_mkprivileged(pte);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	if (iowa_is_active())
5862306a36Sopenharmony_ci		return iowa_ioremap(addr, size, pte_pgprot(pte), caller);
5962306a36Sopenharmony_ci	return __ioremap_caller(addr, size, pte_pgprot(pte), caller);
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ciEXPORT_SYMBOL(ioremap_prot);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ciint early_ioremap_range(unsigned long ea, phys_addr_t pa,
6462306a36Sopenharmony_ci			unsigned long size, pgprot_t prot)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	unsigned long i;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	for (i = 0; i < size; i += PAGE_SIZE) {
6962306a36Sopenharmony_ci		int err = map_kernel_page(ea + i, pa + i, prot);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		if (WARN_ON_ONCE(err))  /* Should clean up */
7262306a36Sopenharmony_ci			return err;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	return 0;
7662306a36Sopenharmony_ci}
77