1/* 2 * Based on arch/arm/kernel/io.c 3 * 4 * Copyright (C) 2012 ARM Ltd. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#include <linux/export.h> 20#include <linux/types.h> 21#include <linux/io.h> 22 23/* 24 * Copy data from IO memory space to "real" memory space. 25 */ 26void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) 27{ 28 while (count && (!IS_ALIGNED((unsigned long)from, 8) || 29 !IS_ALIGNED((unsigned long)to, 8))) { 30 *(u8 *)to = __raw_readb(from); 31 from++; 32 to++; 33 count--; 34 } 35 36 while (count >= 8) { 37 *(u64 *)to = __raw_readq(from); 38 from += 8; 39 to += 8; 40 count -= 8; 41 } 42 43 while (count) { 44 *(u8 *)to = __raw_readb(from); 45 from++; 46 to++; 47 count--; 48 } 49} 50EXPORT_SYMBOL(__memcpy_fromio); 51 52/* 53 * Copy data from "real" memory space to IO memory space. 54 */ 55void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) 56{ 57 while (count && (!IS_ALIGNED((unsigned long)to, 8) || 58 !IS_ALIGNED((unsigned long)from, 8))) { 59 __raw_writeb(*(volatile u8 *)from, to); 60 from++; 61 to++; 62 count--; 63 } 64 65 while (count >= 8) { 66 __raw_writeq(*(volatile u64 *)from, to); 67 from += 8; 68 to += 8; 69 count -= 8; 70 } 71 72 while (count) { 73 __raw_writeb(*(volatile u8 *)from, to); 74 from++; 75 to++; 76 count--; 77 } 78} 79EXPORT_SYMBOL(__memcpy_toio); 80 81/* 82 * "memset" on IO memory space. 83 */ 84void __memset_io(volatile void __iomem *dst, int c, size_t count) 85{ 86 u64 qc = (u8)c; 87 88 qc |= qc << 8; 89 qc |= qc << 16; 90 qc |= qc << 32; 91 92 while (count && !IS_ALIGNED((unsigned long)dst, 8)) { 93 __raw_writeb(c, dst); 94 dst++; 95 count--; 96 } 97 98 while (count >= 8) { 99 __raw_writeq(qc, dst); 100 dst += 8; 101 count -= 8; 102 } 103 104 while (count) { 105 __raw_writeb(c, dst); 106 dst++; 107 count--; 108 } 109} 110EXPORT_SYMBOL(__memset_io); 111