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_civoid __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size, 862306a36Sopenharmony_ci pgprot_t prot, void *caller) 962306a36Sopenharmony_ci{ 1062306a36Sopenharmony_ci phys_addr_t paligned, offset; 1162306a36Sopenharmony_ci void __iomem *ret; 1262306a36Sopenharmony_ci int err; 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci /* We don't support the 4K PFN hack with ioremap */ 1562306a36Sopenharmony_ci if (pgprot_val(prot) & H_PAGE_4K_PFN) 1662306a36Sopenharmony_ci return NULL; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci /* 1962306a36Sopenharmony_ci * Choose an address to map it to. Once the vmalloc system is running, 2062306a36Sopenharmony_ci * we use it. Before that, we map using addresses going up from 2162306a36Sopenharmony_ci * ioremap_bot. vmalloc will use the addresses from IOREMAP_BASE 2262306a36Sopenharmony_ci * through ioremap_bot. 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci paligned = addr & PAGE_MASK; 2562306a36Sopenharmony_ci offset = addr & ~PAGE_MASK; 2662306a36Sopenharmony_ci size = PAGE_ALIGN(addr + size) - paligned; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (size == 0 || paligned == 0) 2962306a36Sopenharmony_ci return NULL; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (slab_is_available()) 3262306a36Sopenharmony_ci return generic_ioremap_prot(addr, size, prot); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci pr_warn("ioremap() called early from %pS. Use early_ioremap() instead\n", caller); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci err = early_ioremap_range(ioremap_bot, paligned, size, prot); 3762306a36Sopenharmony_ci if (err) 3862306a36Sopenharmony_ci return NULL; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci ret = (void __iomem *)ioremap_bot + offset; 4162306a36Sopenharmony_ci ioremap_bot += size + PAGE_SIZE; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci return ret; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * Unmap an IO region and remove it from vmalloc'd list. 4862306a36Sopenharmony_ci * Access to IO memory should be serialized by driver. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_civoid iounmap(volatile void __iomem *token) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci if (!slab_is_available()) 5362306a36Sopenharmony_ci return; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci generic_iounmap(PCI_FIX_ADDR(token)); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ciEXPORT_SYMBOL(iounmap); 58