1// SPDX-License-Identifier: GPL-2.0+
2// Copyright 2019 IBM Corp.
3#include <linux/sched/mm.h>
4#include "trace.h"
5#include "ocxl_internal.h"
6
7int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset,
8 enum ocxl_endian endian, u32 *val)
9{
10 if (offset > afu->config.global_mmio_size - 4)
11 return -EINVAL;
12
13#ifdef __BIG_ENDIAN__
14 if (endian == OCXL_HOST_ENDIAN)
15 endian = OCXL_BIG_ENDIAN;
16#endif
17
18 switch (endian) {
19 case OCXL_BIG_ENDIAN:
20 *val = readl_be((char *)afu->global_mmio_ptr + offset);
21 break;
22
23 default:
24 *val = readl(addr: (char *)afu->global_mmio_ptr + offset);
25 break;
26 }
27
28 return 0;
29}
30EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32);
31
32int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset,
33 enum ocxl_endian endian, u64 *val)
34{
35 if (offset > afu->config.global_mmio_size - 8)
36 return -EINVAL;
37
38#ifdef __BIG_ENDIAN__
39 if (endian == OCXL_HOST_ENDIAN)
40 endian = OCXL_BIG_ENDIAN;
41#endif
42
43 switch (endian) {
44 case OCXL_BIG_ENDIAN:
45 *val = readq_be((char *)afu->global_mmio_ptr + offset);
46 break;
47
48 default:
49 *val = readq(addr: (char *)afu->global_mmio_ptr + offset);
50 break;
51 }
52
53 return 0;
54}
55EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64);
56
57int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset,
58 enum ocxl_endian endian, u32 val)
59{
60 if (offset > afu->config.global_mmio_size - 4)
61 return -EINVAL;
62
63#ifdef __BIG_ENDIAN__
64 if (endian == OCXL_HOST_ENDIAN)
65 endian = OCXL_BIG_ENDIAN;
66#endif
67
68 switch (endian) {
69 case OCXL_BIG_ENDIAN:
70 writel_be(val, (char *)afu->global_mmio_ptr + offset);
71 break;
72
73 default:
74 writel(val, addr: (char *)afu->global_mmio_ptr + offset);
75 break;
76 }
77
78
79 return 0;
80}
81EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32);
82
83int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset,
84 enum ocxl_endian endian, u64 val)
85{
86 if (offset > afu->config.global_mmio_size - 8)
87 return -EINVAL;
88
89#ifdef __BIG_ENDIAN__
90 if (endian == OCXL_HOST_ENDIAN)
91 endian = OCXL_BIG_ENDIAN;
92#endif
93
94 switch (endian) {
95 case OCXL_BIG_ENDIAN:
96 writeq_be(val, (char *)afu->global_mmio_ptr + offset);
97 break;
98
99 default:
100 writeq(val, addr: (char *)afu->global_mmio_ptr + offset);
101 break;
102 }
103
104
105 return 0;
106}
107EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64);
108
109int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset,
110 enum ocxl_endian endian, u32 mask)
111{
112 u32 tmp;
113
114 if (offset > afu->config.global_mmio_size - 4)
115 return -EINVAL;
116
117#ifdef __BIG_ENDIAN__
118 if (endian == OCXL_HOST_ENDIAN)
119 endian = OCXL_BIG_ENDIAN;
120#endif
121
122 switch (endian) {
123 case OCXL_BIG_ENDIAN:
124 tmp = readl_be((char *)afu->global_mmio_ptr + offset);
125 tmp |= mask;
126 writel_be(tmp, (char *)afu->global_mmio_ptr + offset);
127 break;
128
129 default:
130 tmp = readl(addr: (char *)afu->global_mmio_ptr + offset);
131 tmp |= mask;
132 writel(val: tmp, addr: (char *)afu->global_mmio_ptr + offset);
133 break;
134 }
135
136 return 0;
137}
138EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32);
139
140int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset,
141 enum ocxl_endian endian, u64 mask)
142{
143 u64 tmp;
144
145 if (offset > afu->config.global_mmio_size - 8)
146 return -EINVAL;
147
148#ifdef __BIG_ENDIAN__
149 if (endian == OCXL_HOST_ENDIAN)
150 endian = OCXL_BIG_ENDIAN;
151#endif
152
153 switch (endian) {
154 case OCXL_BIG_ENDIAN:
155 tmp = readq_be((char *)afu->global_mmio_ptr + offset);
156 tmp |= mask;
157 writeq_be(tmp, (char *)afu->global_mmio_ptr + offset);
158 break;
159
160 default:
161 tmp = readq(addr: (char *)afu->global_mmio_ptr + offset);
162 tmp |= mask;
163 writeq(val: tmp, addr: (char *)afu->global_mmio_ptr + offset);
164 break;
165 }
166
167 return 0;
168}
169EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64);
170
171int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset,
172 enum ocxl_endian endian, u32 mask)
173{
174 u32 tmp;
175
176 if (offset > afu->config.global_mmio_size - 4)
177 return -EINVAL;
178
179#ifdef __BIG_ENDIAN__
180 if (endian == OCXL_HOST_ENDIAN)
181 endian = OCXL_BIG_ENDIAN;
182#endif
183
184 switch (endian) {
185 case OCXL_BIG_ENDIAN:
186 tmp = readl_be((char *)afu->global_mmio_ptr + offset);
187 tmp &= ~mask;
188 writel_be(tmp, (char *)afu->global_mmio_ptr + offset);
189 break;
190
191 default:
192 tmp = readl(addr: (char *)afu->global_mmio_ptr + offset);
193 tmp &= ~mask;
194 writel(val: tmp, addr: (char *)afu->global_mmio_ptr + offset);
195 break;
196 }
197
198
199 return 0;
200}
201EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32);
202
203int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset,
204 enum ocxl_endian endian, u64 mask)
205{
206 u64 tmp;
207
208 if (offset > afu->config.global_mmio_size - 8)
209 return -EINVAL;
210
211#ifdef __BIG_ENDIAN__
212 if (endian == OCXL_HOST_ENDIAN)
213 endian = OCXL_BIG_ENDIAN;
214#endif
215
216 switch (endian) {
217 case OCXL_BIG_ENDIAN:
218 tmp = readq_be((char *)afu->global_mmio_ptr + offset);
219 tmp &= ~mask;
220 writeq_be(tmp, (char *)afu->global_mmio_ptr + offset);
221 break;
222
223 default:
224 tmp = readq(addr: (char *)afu->global_mmio_ptr + offset);
225 tmp &= ~mask;
226 writeq(val: tmp, addr: (char *)afu->global_mmio_ptr + offset);
227 break;
228 }
229
230 writeq(val: tmp, addr: (char *)afu->global_mmio_ptr + offset);
231
232 return 0;
233}
234EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);
235

source code of linux/drivers/misc/ocxl/mmio.c