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