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 */
15void __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}
38EXPORT_SYMBOL(__memcpy_fromio);
39
40/*
41 * Copy data from "real" memory space to IO memory space.
42 */
43void __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}
66EXPORT_SYMBOL(__memcpy_toio);
67
68/*
69 * "memset" on IO memory space.
70 */
71void __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}
97EXPORT_SYMBOL(__memset_io);
98