1#include <linux/export.h> 2#include <linux/types.h> 3#include <linux/io.h> 4#include <linux/spinlock.h> 5 6static 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 */ 14void 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} 25EXPORT_SYMBOL(atomic_io_modify_relaxed); 26 27void 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} 38EXPORT_SYMBOL(atomic_io_modify); 39 40/* 41 * Copy data from IO memory space to "real" memory space. 42 * This needs to be optimized. 43 */ 44void _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} 54EXPORT_SYMBOL(_memcpy_fromio); 55 56/* 57 * Copy data from "real" memory space to IO memory space. 58 * This needs to be optimized. 59 */ 60void _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} 70EXPORT_SYMBOL(_memcpy_toio); 71 72/* 73 * "memset" on IO memory space. 74 * This needs to be optimized. 75 */ 76void _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} 84EXPORT_SYMBOL(_memset_io); 85