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 55 /* 56 * Copy data from "real" memory space to IO memory space. 57 * This needs to be optimized. 58 */ 59 void _memcpy_toio(volatile void __iomem *to, const void *from, size_t count) 60 { 61 const unsigned char *f = from; 62 while (count) { 63 count--; 64 writeb(*f, to); 65 f++; 66 to++; 67 } 68 } 69 70 /* 71 * "memset" on IO memory space. 72 * This needs to be optimized. 73 */ 74 void _memset_io(volatile void __iomem *dst, int c, size_t count) 75 { 76 while (count) { 77 count--; 78 writeb(c, dst); 79 dst++; 80 } 81 } 82 83 EXPORT_SYMBOL(_memcpy_fromio); 84 EXPORT_SYMBOL(_memcpy_toio); 85 EXPORT_SYMBOL(_memset_io); 86