xref: /linux/arch/arm64/kernel/io.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
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  * This generates a memcpy that works on a from/to address which is aligned to
14  * bits. Count is in terms of the number of bits sized quantities to copy. It
15  * optimizes to use the STR groupings when possible so that it is WC friendly.
16  */
17 #define memcpy_toio_aligned(to, from, count, bits)                        \
18 	({                                                                \
19 		volatile u##bits __iomem *_to = to;                       \
20 		const u##bits *_from = from;                              \
21 		size_t _count = count;                                    \
22 		const u##bits *_end_from = _from + ALIGN_DOWN(_count, 8); \
23                                                                           \
24 		for (; _from < _end_from; _from += 8, _to += 8)           \
25 			__const_memcpy_toio_aligned##bits(_to, _from, 8); \
26 		if ((_count % 8) >= 4) {                                  \
27 			__const_memcpy_toio_aligned##bits(_to, _from, 4); \
28 			_from += 4;                                       \
29 			_to += 4;                                         \
30 		}                                                         \
31 		if ((_count % 4) >= 2) {                                  \
32 			__const_memcpy_toio_aligned##bits(_to, _from, 2); \
33 			_from += 2;                                       \
34 			_to += 2;                                         \
35 		}                                                         \
36 		if (_count % 2)                                           \
37 			__const_memcpy_toio_aligned##bits(_to, _from, 1); \
38 	})
39 
40 void __iowrite64_copy_full(void __iomem *to, const void *from, size_t count)
41 {
42 	memcpy_toio_aligned(to, from, count, 64);
43 	dgh();
44 }
45 EXPORT_SYMBOL(__iowrite64_copy_full);
46 
47 void __iowrite32_copy_full(void __iomem *to, const void *from, size_t count)
48 {
49 	memcpy_toio_aligned(to, from, count, 32);
50 	dgh();
51 }
52 EXPORT_SYMBOL(__iowrite32_copy_full);
53