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