1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4  */
5 #include <linux/export.h>
6 #include <linux/types.h>
7 #include <linux/io.h>
8 
9 /*
10  * Copy data from IO memory space to "real" memory space.
11  */
__memcpy_fromio(void * to,const volatile void __iomem * from,size_t count)12 void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
13 {
14 	while (count && !IS_ALIGNED((unsigned long)from, 8)) {
15 		*(u8 *)to = __raw_readb(from);
16 		from++;
17 		to++;
18 		count--;
19 	}
20 
21 	while (count >= 8) {
22 		*(u64 *)to = __raw_readq(from);
23 		from += 8;
24 		to += 8;
25 		count -= 8;
26 	}
27 
28 	while (count) {
29 		*(u8 *)to = __raw_readb(from);
30 		from++;
31 		to++;
32 		count--;
33 	}
34 }
35 EXPORT_SYMBOL(__memcpy_fromio);
36 
37 /*
38  * Copy data from "real" memory space to IO memory space.
39  */
__memcpy_toio(volatile void __iomem * to,const void * from,size_t count)40 void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
41 {
42 	while (count && !IS_ALIGNED((unsigned long)to, 8)) {
43 		__raw_writeb(*(u8 *)from, to);
44 		from++;
45 		to++;
46 		count--;
47 	}
48 
49 	while (count >= 8) {
50 		__raw_writeq(*(u64 *)from, to);
51 		from += 8;
52 		to += 8;
53 		count -= 8;
54 	}
55 
56 	while (count) {
57 		__raw_writeb(*(u8 *)from, to);
58 		from++;
59 		to++;
60 		count--;
61 	}
62 }
63 EXPORT_SYMBOL(__memcpy_toio);
64 
65 /*
66  * "memset" on IO memory space.
67  */
__memset_io(volatile void __iomem * dst,int c,size_t count)68 void __memset_io(volatile void __iomem *dst, int c, size_t count)
69 {
70 	u64 qc = (u8)c;
71 
72 	qc |= qc << 8;
73 	qc |= qc << 16;
74 	qc |= qc << 32;
75 
76 	while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
77 		__raw_writeb(c, dst);
78 		dst++;
79 		count--;
80 	}
81 
82 	while (count >= 8) {
83 		__raw_writeq(qc, dst);
84 		dst += 8;
85 		count -= 8;
86 	}
87 
88 	while (count) {
89 		__raw_writeb(c, dst);
90 		dst++;
91 		count--;
92 	}
93 }
94 EXPORT_SYMBOL(__memset_io);
95