Merge branches 'for-4.16/upstream' and 'for-4.15/upstream-fixes' into for-linus
[sfrench/cifs-2.6.git] / arch / arm64 / kernel / io.c
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);