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
ocxl_global_mmio_read32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 * val)7 int 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((char *)afu->global_mmio_ptr + offset);
25 break;
26 }
27
28 return 0;
29 }
30 EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32);
31
ocxl_global_mmio_read64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 * val)32 int 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((char *)afu->global_mmio_ptr + offset);
50 break;
51 }
52
53 return 0;
54 }
55 EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64);
56
ocxl_global_mmio_write32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 val)57 int 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, (char *)afu->global_mmio_ptr + offset);
75 break;
76 }
77
78
79 return 0;
80 }
81 EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32);
82
ocxl_global_mmio_write64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 val)83 int 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, (char *)afu->global_mmio_ptr + offset);
101 break;
102 }
103
104
105 return 0;
106 }
107 EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64);
108
ocxl_global_mmio_set32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 mask)109 int 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((char *)afu->global_mmio_ptr + offset);
131 tmp |= mask;
132 writel(tmp, (char *)afu->global_mmio_ptr + offset);
133 break;
134 }
135
136 return 0;
137 }
138 EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32);
139
ocxl_global_mmio_set64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 mask)140 int 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((char *)afu->global_mmio_ptr + offset);
162 tmp |= mask;
163 writeq(tmp, (char *)afu->global_mmio_ptr + offset);
164 break;
165 }
166
167 return 0;
168 }
169 EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64);
170
ocxl_global_mmio_clear32(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u32 mask)171 int 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((char *)afu->global_mmio_ptr + offset);
193 tmp &= ~mask;
194 writel(tmp, (char *)afu->global_mmio_ptr + offset);
195 break;
196 }
197
198
199 return 0;
200 }
201 EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32);
202
ocxl_global_mmio_clear64(struct ocxl_afu * afu,size_t offset,enum ocxl_endian endian,u64 mask)203 int 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((char *)afu->global_mmio_ptr + offset);
225 tmp &= ~mask;
226 writeq(tmp, (char *)afu->global_mmio_ptr + offset);
227 break;
228 }
229
230 writeq(tmp, (char *)afu->global_mmio_ptr + offset);
231
232 return 0;
233 }
234 EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);
235