xref: /linux/lib/iomem_copy.c (revision 9cc8d0ecdd2aad42e377e971e3bb114339df609e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2024 Kalray, Inc.  All Rights Reserved.
4  */
5 
6 #include <linux/align.h>
7 #include <linux/export.h>
8 #include <linux/io.h>
9 #include <linux/types.h>
10 #include <linux/unaligned.h>
11 
12 #ifndef memset_io
13 /**
14  * memset_io() - Set a range of I/O memory to a constant value
15  * @addr: The beginning of the I/O-memory range to set
16  * @val: The value to set the memory to
17  * @count: The number of bytes to set
18  *
19  * Set a range of I/O memory to a given value.
20  */
21 void memset_io(volatile void __iomem *addr, int val, size_t count)
22 {
23 	long qc = (u8)val;
24 
25 	qc *= ~0UL / 0xff;
26 
27 	while (count && !IS_ALIGNED((long)addr, sizeof(long))) {
28 		__raw_writeb(val, addr);
29 		addr++;
30 		count--;
31 	}
32 
33 	while (count >= sizeof(long)) {
34 #ifdef CONFIG_64BIT
35 		__raw_writeq(qc, addr);
36 #else
37 		__raw_writel(qc, addr);
38 #endif
39 
40 		addr += sizeof(long);
41 		count -= sizeof(long);
42 	}
43 
44 	while (count) {
45 		__raw_writeb(val, addr);
46 		addr++;
47 		count--;
48 	}
49 }
50 EXPORT_SYMBOL(memset_io);
51 #endif
52 
53 #ifndef memcpy_fromio
54 /**
55  * memcpy_fromio() - Copy a block of data from I/O memory
56  * @dst: The (RAM) destination for the copy
57  * @src: The (I/O memory) source for the data
58  * @count: The number of bytes to copy
59  *
60  * Copy a block of data from I/O memory.
61  */
62 void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count)
63 {
64 	while (count && !IS_ALIGNED((long)src, sizeof(long))) {
65 		*(u8 *)dst = __raw_readb(src);
66 		src++;
67 		dst++;
68 		count--;
69 	}
70 
71 	while (count >= sizeof(long)) {
72 #ifdef CONFIG_64BIT
73 		long val = __raw_readq(src);
74 #else
75 		long val = __raw_readl(src);
76 #endif
77 		put_unaligned(val, (long *)dst);
78 
79 
80 		src += sizeof(long);
81 		dst += sizeof(long);
82 		count -= sizeof(long);
83 	}
84 
85 	while (count) {
86 		*(u8 *)dst = __raw_readb(src);
87 		src++;
88 		dst++;
89 		count--;
90 	}
91 }
92 EXPORT_SYMBOL(memcpy_fromio);
93 #endif
94 
95 #ifndef memcpy_toio
96 /**
97  * memcpy_toio() -Copy a block of data into I/O memory
98  * @dst: The (I/O memory) destination for the copy
99  * @src: The (RAM) source for the data
100  * @count: The number of bytes to copy
101  *
102  * Copy a block of data to I/O memory.
103  */
104 void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count)
105 {
106 	while (count && !IS_ALIGNED((long)dst, sizeof(long))) {
107 		__raw_writeb(*(u8 *)src, dst);
108 		src++;
109 		dst++;
110 		count--;
111 	}
112 
113 	while (count >= sizeof(long)) {
114 		long val = get_unaligned((long *)src);
115 #ifdef CONFIG_64BIT
116 		__raw_writeq(val, dst);
117 #else
118 		__raw_writel(val, dst);
119 #endif
120 
121 		src += sizeof(long);
122 		dst += sizeof(long);
123 		count -= sizeof(long);
124 	}
125 
126 	while (count) {
127 		__raw_writeb(*(u8 *)src, dst);
128 		src++;
129 		dst++;
130 		count--;
131 	}
132 }
133 EXPORT_SYMBOL(memcpy_toio);
134 #endif
135 
136 
137