dm writecache: add cond_resched to loop in persistent_memory_claim()
[linux/fpc-iii.git] / drivers / misc / ocxl / mmio.c
blobaae713db4ebe80a4d5c1bab429275eeccf633735
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"
7 int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset,
8 enum ocxl_endian endian, u32 *val)
10 if (offset > afu->config.global_mmio_size - 4)
11 return -EINVAL;
13 #ifdef __BIG_ENDIAN__
14 if (endian == OCXL_HOST_ENDIAN)
15 endian = OCXL_BIG_ENDIAN;
16 #endif
18 switch (endian) {
19 case OCXL_BIG_ENDIAN:
20 *val = readl_be((char *)afu->global_mmio_ptr + offset);
21 break;
23 default:
24 *val = readl((char *)afu->global_mmio_ptr + offset);
25 break;
28 return 0;
30 EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32);
32 int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset,
33 enum ocxl_endian endian, u64 *val)
35 if (offset > afu->config.global_mmio_size - 8)
36 return -EINVAL;
38 #ifdef __BIG_ENDIAN__
39 if (endian == OCXL_HOST_ENDIAN)
40 endian = OCXL_BIG_ENDIAN;
41 #endif
43 switch (endian) {
44 case OCXL_BIG_ENDIAN:
45 *val = readq_be((char *)afu->global_mmio_ptr + offset);
46 break;
48 default:
49 *val = readq((char *)afu->global_mmio_ptr + offset);
50 break;
53 return 0;
55 EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64);
57 int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset,
58 enum ocxl_endian endian, u32 val)
60 if (offset > afu->config.global_mmio_size - 4)
61 return -EINVAL;
63 #ifdef __BIG_ENDIAN__
64 if (endian == OCXL_HOST_ENDIAN)
65 endian = OCXL_BIG_ENDIAN;
66 #endif
68 switch (endian) {
69 case OCXL_BIG_ENDIAN:
70 writel_be(val, (char *)afu->global_mmio_ptr + offset);
71 break;
73 default:
74 writel(val, (char *)afu->global_mmio_ptr + offset);
75 break;
79 return 0;
81 EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32);
83 int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset,
84 enum ocxl_endian endian, u64 val)
86 if (offset > afu->config.global_mmio_size - 8)
87 return -EINVAL;
89 #ifdef __BIG_ENDIAN__
90 if (endian == OCXL_HOST_ENDIAN)
91 endian = OCXL_BIG_ENDIAN;
92 #endif
94 switch (endian) {
95 case OCXL_BIG_ENDIAN:
96 writeq_be(val, (char *)afu->global_mmio_ptr + offset);
97 break;
99 default:
100 writeq(val, (char *)afu->global_mmio_ptr + offset);
101 break;
105 return 0;
107 EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64);
109 int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset,
110 enum ocxl_endian endian, u32 mask)
112 u32 tmp;
114 if (offset > afu->config.global_mmio_size - 4)
115 return -EINVAL;
117 #ifdef __BIG_ENDIAN__
118 if (endian == OCXL_HOST_ENDIAN)
119 endian = OCXL_BIG_ENDIAN;
120 #endif
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;
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;
136 return 0;
138 EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32);
140 int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset,
141 enum ocxl_endian endian, u64 mask)
143 u64 tmp;
145 if (offset > afu->config.global_mmio_size - 8)
146 return -EINVAL;
148 #ifdef __BIG_ENDIAN__
149 if (endian == OCXL_HOST_ENDIAN)
150 endian = OCXL_BIG_ENDIAN;
151 #endif
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;
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;
167 return 0;
169 EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64);
171 int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset,
172 enum ocxl_endian endian, u32 mask)
174 u32 tmp;
176 if (offset > afu->config.global_mmio_size - 4)
177 return -EINVAL;
179 #ifdef __BIG_ENDIAN__
180 if (endian == OCXL_HOST_ENDIAN)
181 endian = OCXL_BIG_ENDIAN;
182 #endif
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;
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;
199 return 0;
201 EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32);
203 int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset,
204 enum ocxl_endian endian, u64 mask)
206 u64 tmp;
208 if (offset > afu->config.global_mmio_size - 8)
209 return -EINVAL;
211 #ifdef __BIG_ENDIAN__
212 if (endian == OCXL_HOST_ENDIAN)
213 endian = OCXL_BIG_ENDIAN;
214 #endif
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;
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;
230 writeq(tmp, (char *)afu->global_mmio_ptr + offset);
232 return 0;
234 EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);