1f381d571SChristophe Leroy // SPDX-License-Identifier: GPL-2.0-or-later 2f381d571SChristophe Leroy 3f381d571SChristophe Leroy #include <linux/io.h> 4f381d571SChristophe Leroy #include <linux/slab.h> 5f381d571SChristophe Leroy #include <linux/vmalloc.h> 6f381d571SChristophe Leroy 7f381d571SChristophe Leroy void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size, 8f381d571SChristophe Leroy pgprot_t prot, void *caller) 9f381d571SChristophe Leroy { 104a45b746SChristophe Leroy phys_addr_t paligned, offset; 11f381d571SChristophe Leroy void __iomem *ret; 12163918fcSChristophe Leroy int err; 13f381d571SChristophe Leroy 144a45b746SChristophe Leroy /* We don't support the 4K PFN hack with ioremap */ 154a45b746SChristophe Leroy if (pgprot_val(prot) & H_PAGE_4K_PFN) 164a45b746SChristophe Leroy return NULL; 174a45b746SChristophe Leroy 18f381d571SChristophe Leroy /* 19f381d571SChristophe Leroy * Choose an address to map it to. Once the vmalloc system is running, 20f381d571SChristophe Leroy * we use it. Before that, we map using addresses going up from 21f381d571SChristophe Leroy * ioremap_bot. vmalloc will use the addresses from IOREMAP_BASE 22f381d571SChristophe Leroy * through ioremap_bot. 23f381d571SChristophe Leroy */ 24f381d571SChristophe Leroy paligned = addr & PAGE_MASK; 254a45b746SChristophe Leroy offset = addr & ~PAGE_MASK; 26f381d571SChristophe Leroy size = PAGE_ALIGN(addr + size) - paligned; 27f381d571SChristophe Leroy 28f381d571SChristophe Leroy if (size == 0 || paligned == 0) 29f381d571SChristophe Leroy return NULL; 30f381d571SChristophe Leroy 31163918fcSChristophe Leroy if (slab_is_available()) 324a45b746SChristophe Leroy return do_ioremap(paligned, offset, size, prot, caller); 33f381d571SChristophe Leroy 34d538aadcSChristophe Leroy pr_warn("ioremap() called early from %pS. Use early_ioremap() instead\n", caller); 35d538aadcSChristophe Leroy 36163918fcSChristophe Leroy err = early_ioremap_range(ioremap_bot, paligned, size, prot); 37163918fcSChristophe Leroy if (err) 38163918fcSChristophe Leroy return NULL; 39163918fcSChristophe Leroy 40163918fcSChristophe Leroy ret = (void __iomem *)ioremap_bot + offset; 41*57307f1bSChristophe Leroy ioremap_bot += size + PAGE_SIZE; 42163918fcSChristophe Leroy 43f381d571SChristophe Leroy return ret; 44f381d571SChristophe Leroy } 45f381d571SChristophe Leroy 46f381d571SChristophe Leroy /* 47f381d571SChristophe Leroy * Unmap an IO region and remove it from vmalloc'd list. 48f381d571SChristophe Leroy * Access to IO memory should be serialized by driver. 49f381d571SChristophe Leroy */ 50f381d571SChristophe Leroy void iounmap(volatile void __iomem *token) 51f381d571SChristophe Leroy { 52f381d571SChristophe Leroy void *addr; 53f381d571SChristophe Leroy 54f381d571SChristophe Leroy if (!slab_is_available()) 55f381d571SChristophe Leroy return; 56f381d571SChristophe Leroy 57f381d571SChristophe Leroy addr = (void *)((unsigned long __force)PCI_FIX_ADDR(token) & PAGE_MASK); 58f381d571SChristophe Leroy 59f381d571SChristophe Leroy if ((unsigned long)addr < ioremap_bot) { 60f381d571SChristophe Leroy pr_warn("Attempt to iounmap early bolted mapping at 0x%p\n", addr); 61f381d571SChristophe Leroy return; 62f381d571SChristophe Leroy } 63f381d571SChristophe Leroy vunmap(addr); 64f381d571SChristophe Leroy } 65f381d571SChristophe Leroy EXPORT_SYMBOL(iounmap); 66