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