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 */ 26 void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) 27 { 28 while (count && !IS_ALIGNED((unsigned long)from, 8)) { 29 *(u8 *)to = __raw_readb(from); 30 from++; 31 to++; 32 count--; 33 } 34 35 while (count >= 8) { 36 *(u64 *)to = __raw_readq(from); 37 from += 8; 38 to += 8; 39 count -= 8; 40 } 41 42 while (count) { 43 *(u8 *)to = __raw_readb(from); 44 from++; 45 to++; 46 count--; 47 } 48 } 49 EXPORT_SYMBOL(__memcpy_fromio); 50 51 /* 52 * Copy data from "real" memory space to IO memory space. 53 */ 54 void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) 55 { 56 while (count && !IS_ALIGNED((unsigned long)to, 8)) { 57 __raw_writeb(*(u8 *)from, to); 58 from++; 59 to++; 60 count--; 61 } 62 63 while (count >= 8) { 64 __raw_writeq(*(u64 *)from, to); 65 from += 8; 66 to += 8; 67 count -= 8; 68 } 69 70 while (count) { 71 __raw_writeb(*(u8 *)from, to); 72 from++; 73 to++; 74 count--; 75 } 76 } 77 EXPORT_SYMBOL(__memcpy_toio); 78 79 /* 80 * "memset" on IO memory space. 81 */ 82 void __memset_io(volatile void __iomem *dst, int c, size_t count) 83 { 84 u64 qc = (u8)c; 85 86 qc |= qc << 8; 87 qc |= qc << 16; 88 qc |= qc << 32; 89 90 while (count && !IS_ALIGNED((unsigned long)dst, 8)) { 91 __raw_writeb(c, dst); 92 dst++; 93 count--; 94 } 95 96 while (count >= 8) { 97 __raw_writeq(qc, dst); 98 dst += 8; 99 count -= 8; 100 } 101 102 while (count) { 103 __raw_writeb(c, dst); 104 dst++; 105 count--; 106 } 107 } 108 EXPORT_SYMBOL(__memset_io); 109