summaryrefslogtreecommitdiff
path: root/lib/iomem_copy.c
blob: dec7eaea60e02ba3514edaf713cdca9a8b6bf0f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2024 Kalray, Inc.  All Rights Reserved.
 */

#include <linux/align.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/types.h>
#include <linux/unaligned.h>

#ifndef memset_io
/**
 * memset_io() - Set a range of I/O memory to a constant value
 * @addr: The beginning of the I/O-memory range to set
 * @val: The value to set the memory to
 * @count: The number of bytes to set
 *
 * Set a range of I/O memory to a given value.
 */
void memset_io(volatile void __iomem *addr, int val, size_t count)
{
	long qc = (u8)val;

	qc *= ~0UL / 0xff;

	while (count && !IS_ALIGNED((long)addr, sizeof(long))) {
		__raw_writeb(val, addr);
		addr++;
		count--;
	}

	while (count >= sizeof(long)) {
#ifdef CONFIG_64BIT
		__raw_writeq(qc, addr);
#else
		__raw_writel(qc, addr);
#endif

		addr += sizeof(long);
		count -= sizeof(long);
	}

	while (count) {
		__raw_writeb(val, addr);
		addr++;
		count--;
	}
}
EXPORT_SYMBOL(memset_io);
#endif

#ifndef memcpy_fromio
/**
 * memcpy_fromio() - Copy a block of data from I/O memory
 * @dst: The (RAM) destination for the copy
 * @src: The (I/O memory) source for the data
 * @count: The number of bytes to copy
 *
 * Copy a block of data from I/O memory.
 */
void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count)
{
	while (count && !IS_ALIGNED((long)src, sizeof(long))) {
		*(u8 *)dst = __raw_readb(src);
		src++;
		dst++;
		count--;
	}

	while (count >= sizeof(long)) {
#ifdef CONFIG_64BIT
		long val = __raw_readq(src);
#else
		long val = __raw_readl(src);
#endif
		put_unaligned(val, (long *)dst);


		src += sizeof(long);
		dst += sizeof(long);
		count -= sizeof(long);
	}

	while (count) {
		*(u8 *)dst = __raw_readb(src);
		src++;
		dst++;
		count--;
	}
}
EXPORT_SYMBOL(memcpy_fromio);
#endif

#ifndef memcpy_toio
/**
 * memcpy_toio() -Copy a block of data into I/O memory
 * @dst: The (I/O memory) destination for the copy
 * @src: The (RAM) source for the data
 * @count: The number of bytes to copy
 *
 * Copy a block of data to I/O memory.
 */
void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count)
{
	while (count && !IS_ALIGNED((long)dst, sizeof(long))) {
		__raw_writeb(*(u8 *)src, dst);
		src++;
		dst++;
		count--;
	}

	while (count >= sizeof(long)) {
		long val = get_unaligned((long *)src);
#ifdef CONFIG_64BIT
		__raw_writeq(val, dst);
#else
		__raw_writel(val, dst);
#endif

		src += sizeof(long);
		dst += sizeof(long);
		count -= sizeof(long);
	}

	while (count) {
		__raw_writeb(*(u8 *)src, dst);
		src++;
		dst++;
		count--;
	}
}
EXPORT_SYMBOL(memcpy_toio);
#endif