io.c (1814B)
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 7static 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 */ 15void 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} 26EXPORT_SYMBOL(atomic_io_modify_relaxed); 27 28void 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} 39EXPORT_SYMBOL(atomic_io_modify); 40 41/* 42 * Copy data from IO memory space to "real" memory space. 43 * This needs to be optimized. 44 */ 45void _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} 55EXPORT_SYMBOL(_memcpy_fromio); 56 57/* 58 * Copy data from "real" memory space to IO memory space. 59 * This needs to be optimized. 60 */ 61void _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} 71EXPORT_SYMBOL(_memcpy_toio); 72 73/* 74 * "memset" on IO memory space. 75 * This needs to be optimized. 76 */ 77void _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} 85EXPORT_SYMBOL(_memset_io);