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 | |
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(addr: (char *)afu->global_mmio_ptr + offset); |
25 | break; |
26 | } |
27 | |
28 | return 0; |
29 | } |
30 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32); |
31 | |
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(addr: (char *)afu->global_mmio_ptr + offset); |
50 | break; |
51 | } |
52 | |
53 | return 0; |
54 | } |
55 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64); |
56 | |
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, addr: (char *)afu->global_mmio_ptr + offset); |
75 | break; |
76 | } |
77 | |
78 | |
79 | return 0; |
80 | } |
81 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32); |
82 | |
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, addr: (char *)afu->global_mmio_ptr + offset); |
101 | break; |
102 | } |
103 | |
104 | |
105 | return 0; |
106 | } |
107 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64); |
108 | |
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(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 | } |
138 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32); |
139 | |
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(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 | } |
169 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64); |
170 | |
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(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 | } |
201 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32); |
202 | |
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(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 | } |
234 | EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64); |
235 | |