1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/export.h> 3 #include <linux/types.h> 4 #include <linux/io.h> 5 #include <linux/spinlock.h> 6 7 static DEFINE_RAW_SPINLOCK(__io_lock); 8 9 /* 10 * Generic atomic MMIO modify. 11 * 12 * Allows thread-safe access to registers shared by unrelated subsystems. 13 * The access is protected by a single MMIO-wide lock. 14 */ 15 void atomic_io_modify_relaxed(void __iomem *reg, u32 mask, u32 set) 16 { 17 unsigned long flags; 18 u32 value; 19 20 raw_spin_lock_irqsave(&__io_lock, flags); 21 value = readl_relaxed(reg) & ~mask; 22 value |= (set & mask); 23 writel_relaxed(value, reg); 24 raw_spin_unlock_irqrestore(&__io_lock, flags); 25 } 26 EXPORT_SYMBOL(atomic_io_modify_relaxed); 27 28 void atomic_io_modify(void __iomem *reg, u32 mask, u32 set) 29 { 30 unsigned long flags; 31 u32 value; 32 33 raw_spin_lock_irqsave(&__io_lock, flags); 34 value = readl_relaxed(reg) & ~mask; 35 value |= (set & mask); 36 writel(value, reg); 37 raw_spin_unlock_irqrestore(&__io_lock, flags); 38 } 39 EXPORT_SYMBOL(atomic_io_modify); 40 41 /* 42 * Copy data from IO memory space to "real" memory space. 43 * This needs to be optimized. 44 */ 45 void _memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) 46 { 47 unsigned char *t = to; 48 while (count) { 49 count--; 50 *t = readb(from); 51 t++; 52 from++; 53 } 54 } 55 EXPORT_SYMBOL(_memcpy_fromio); 56 57 /* 58 * Copy data from "real" memory space to IO memory space. 59 * This needs to be optimized. 60 */ 61 void _memcpy_toio(volatile void __iomem *to, const void *from, size_t count) 62 { 63 const unsigned char *f = from; 64 while (count) { 65 count--; 66 writeb(*f, to); 67 f++; 68 to++; 69 } 70 } 71 EXPORT_SYMBOL(_memcpy_toio); 72 73 /* 74 * "memset" on IO memory space. 75 * This needs to be optimized. 76 */ 77 void _memset_io(volatile void __iomem *dst, int c, size_t count) 78 { 79 while (count) { 80 count--; 81 writeb(c, dst); 82 dst++; 83 } 84 } 85 EXPORT_SYMBOL(_memset_io); 86