diff options
Diffstat (limited to 'arch/arm/kernel/io.c')
| -rw-r--r-- | arch/arm/kernel/io.c | 35 | 
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c index dcd5b4d8614..9203cf88333 100644 --- a/arch/arm/kernel/io.c +++ b/arch/arm/kernel/io.c @@ -1,6 +1,41 @@  #include <linux/export.h>  #include <linux/types.h>  #include <linux/io.h> +#include <linux/spinlock.h> + +static DEFINE_RAW_SPINLOCK(__io_lock); + +/* + * Generic atomic MMIO modify. + * + * Allows thread-safe access to registers shared by unrelated subsystems. + * The access is protected by a single MMIO-wide lock. + */ +void atomic_io_modify_relaxed(void __iomem *reg, u32 mask, u32 set) +{ +	unsigned long flags; +	u32 value; + +	raw_spin_lock_irqsave(&__io_lock, flags); +	value = readl_relaxed(reg) & ~mask; +	value |= (set & mask); +	writel_relaxed(value, reg); +	raw_spin_unlock_irqrestore(&__io_lock, flags); +} +EXPORT_SYMBOL(atomic_io_modify_relaxed); + +void atomic_io_modify(void __iomem *reg, u32 mask, u32 set) +{ +	unsigned long flags; +	u32 value; + +	raw_spin_lock_irqsave(&__io_lock, flags); +	value = readl_relaxed(reg) & ~mask; +	value |= (set & mask); +	writel(value, reg); +	raw_spin_unlock_irqrestore(&__io_lock, flags); +} +EXPORT_SYMBOL(atomic_io_modify);  /*   * Copy data from IO memory space to "real" memory space.  | 
