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