1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016 Cavium, Inc
3 */
4
5 #ifndef _RTE_IO_H_
6 #define _RTE_IO_H_
7
8 /**
9 * @file
10 * I/O device memory operations
11 *
12 * This file defines the generic API for I/O device memory read/write operations
13 */
14
15 #include <stdint.h>
16 #include <rte_common.h>
17 #include <rte_compat.h>
18 #include <rte_atomic.h>
19
20 #ifdef __DOXYGEN__
21
22 /**
23 * Read a 8-bit value from I/O device memory address *addr*.
24 *
25 * The relaxed version does not have additional I/O memory barrier, useful in
26 * accessing the device registers of integrated controllers which implicitly
27 * strongly ordered with respect to memory access.
28 *
29 * @param addr
30 * I/O memory address to read the value from
31 * @return
32 * read value
33 */
34 static inline uint8_t
35 rte_read8_relaxed(const volatile void *addr);
36
37 /**
38 * Read a 16-bit value from I/O device memory address *addr*.
39 *
40 * The relaxed version does not have additional I/O memory barrier, useful in
41 * accessing the device registers of integrated controllers which implicitly
42 * strongly ordered with respect to memory access.
43 *
44 * @param addr
45 * I/O memory address to read the value from
46 * @return
47 * read value
48 */
49 static inline uint16_t
50 rte_read16_relaxed(const volatile void *addr);
51
52 /**
53 * Read a 32-bit value from I/O device memory address *addr*.
54 *
55 * The relaxed version does not have additional I/O memory barrier, useful in
56 * accessing the device registers of integrated controllers which implicitly
57 * strongly ordered with respect to memory access.
58 *
59 * @param addr
60 * I/O memory address to read the value from
61 * @return
62 * read value
63 */
64 static inline uint32_t
65 rte_read32_relaxed(const volatile void *addr);
66
67 /**
68 * Read a 64-bit value from I/O device memory address *addr*.
69 *
70 * The relaxed version does not have additional I/O memory barrier, useful in
71 * accessing the device registers of integrated controllers which implicitly
72 * strongly ordered with respect to memory access.
73 *
74 * @param addr
75 * I/O memory address to read the value from
76 * @return
77 * read value
78 */
79 static inline uint64_t
80 rte_read64_relaxed(const volatile void *addr);
81
82 /**
83 * Write a 8-bit value to I/O device memory address *addr*.
84 *
85 * The relaxed version does not have additional I/O memory barrier, useful in
86 * accessing the device registers of integrated controllers which implicitly
87 * strongly ordered with respect to memory access.
88 *
89 * @param value
90 * Value to write
91 * @param addr
92 * I/O memory address to write the value to
93 */
94
95 static inline void
96 rte_write8_relaxed(uint8_t value, volatile void *addr);
97
98 /**
99 * Write a 16-bit value to I/O device memory address *addr*.
100 *
101 * The relaxed version does not have additional I/O memory barrier, useful in
102 * accessing the device registers of integrated controllers which implicitly
103 * strongly ordered with respect to memory access.
104 *
105 * @param value
106 * Value to write
107 * @param addr
108 * I/O memory address to write the value to
109 */
110 static inline void
111 rte_write16_relaxed(uint16_t value, volatile void *addr);
112
113 /**
114 * Write a 32-bit value to I/O device memory address *addr*.
115 *
116 * The relaxed version does not have additional I/O memory barrier, useful in
117 * accessing the device registers of integrated controllers which implicitly
118 * strongly ordered with respect to memory access.
119 *
120 * @param value
121 * Value to write
122 * @param addr
123 * I/O memory address to write the value to
124 */
125 static inline void
126 rte_write32_relaxed(uint32_t value, volatile void *addr);
127
128 /**
129 * Write a 64-bit value to I/O device memory address *addr*.
130 *
131 * The relaxed version does not have additional I/O memory barrier, useful in
132 * accessing the device registers of integrated controllers which implicitly
133 * strongly ordered with respect to memory access.
134 *
135 * @param value
136 * Value to write
137 * @param addr
138 * I/O memory address to write the value to
139 */
140 static inline void
141 rte_write64_relaxed(uint64_t value, volatile void *addr);
142
143 /**
144 * Read a 8-bit value from I/O device memory address *addr*.
145 *
146 * @param addr
147 * I/O memory address to read the value from
148 * @return
149 * read value
150 */
151 static inline uint8_t
152 rte_read8(const volatile void *addr);
153
154 /**
155 * Read a 16-bit value from I/O device memory address *addr*.
156 *
157 *
158 * @param addr
159 * I/O memory address to read the value from
160 * @return
161 * read value
162 */
163 static inline uint16_t
164 rte_read16(const volatile void *addr);
165
166 /**
167 * Read a 32-bit value from I/O device memory address *addr*.
168 *
169 * @param addr
170 * I/O memory address to read the value from
171 * @return
172 * read value
173 */
174 static inline uint32_t
175 rte_read32(const volatile void *addr);
176
177 /**
178 * Read a 64-bit value from I/O device memory address *addr*.
179 *
180 * @param addr
181 * I/O memory address to read the value from
182 * @return
183 * read value
184 */
185 static inline uint64_t
186 rte_read64(const volatile void *addr);
187
188 /**
189 * Write a 8-bit value to I/O device memory address *addr*.
190 *
191 * @param value
192 * Value to write
193 * @param addr
194 * I/O memory address to write the value to
195 */
196
197 static inline void
198 rte_write8(uint8_t value, volatile void *addr);
199
200 /**
201 * Write a 16-bit value to I/O device memory address *addr*.
202 *
203 * @param value
204 * Value to write
205 * @param addr
206 * I/O memory address to write the value to
207 */
208 static inline void
209 rte_write16(uint16_t value, volatile void *addr);
210
211 /**
212 * Write a 32-bit value to I/O device memory address *addr*.
213 *
214 * @param value
215 * Value to write
216 * @param addr
217 * I/O memory address to write the value to
218 */
219 static inline void
220 rte_write32(uint32_t value, volatile void *addr);
221
222 /**
223 * Write a 64-bit value to I/O device memory address *addr*.
224 *
225 * @param value
226 * Value to write
227 * @param addr
228 * I/O memory address to write the value to
229 */
230 static inline void
231 rte_write64(uint64_t value, volatile void *addr);
232
233 /**
234 * Write a 32-bit value to I/O device memory address addr using write
235 * combining memory write protocol. Depending on the platform write combining
236 * may not be available and/or may be treated as a hint and the behavior may
237 * fallback to a regular store.
238 *
239 * @param value
240 * Value to write
241 * @param addr
242 * I/O memory address to write the value to
243 */
244 __rte_experimental
245 static inline void
246 rte_write32_wc(uint32_t value, volatile void *addr);
247
248 /**
249 * Write a 32-bit value to I/O device memory address addr using write
250 * combining memory write protocol. Depending on the platform write combining
251 * may not be available and/or may be treated as a hint and the behavior may
252 * fallback to a regular store.
253 *
254 * The relaxed version does not have additional I/O memory barrier, useful in
255 * accessing the device registers of integrated controllers which implicitly
256 * strongly ordered with respect to memory access.
257 *
258 * @param value
259 * Value to write
260 * @param addr
261 * I/O memory address to write the value to
262 */
263 __rte_experimental
264 static inline void
265 rte_write32_wc_relaxed(uint32_t value, volatile void *addr);
266
267 #endif /* __DOXYGEN__ */
268
269 #ifndef RTE_OVERRIDE_IO_H
270
271 static __rte_always_inline uint8_t
rte_read8_relaxed(const volatile void * addr)272 rte_read8_relaxed(const volatile void *addr)
273 {
274 return *(const volatile uint8_t *)addr;
275 }
276
277 static __rte_always_inline uint16_t
rte_read16_relaxed(const volatile void * addr)278 rte_read16_relaxed(const volatile void *addr)
279 {
280 return *(const volatile uint16_t *)addr;
281 }
282
283 static __rte_always_inline uint32_t
rte_read32_relaxed(const volatile void * addr)284 rte_read32_relaxed(const volatile void *addr)
285 {
286 return *(const volatile uint32_t *)addr;
287 }
288
289 static __rte_always_inline uint64_t
rte_read64_relaxed(const volatile void * addr)290 rte_read64_relaxed(const volatile void *addr)
291 {
292 return *(const volatile uint64_t *)addr;
293 }
294
295 static __rte_always_inline void
rte_write8_relaxed(uint8_t value,volatile void * addr)296 rte_write8_relaxed(uint8_t value, volatile void *addr)
297 {
298 *(volatile uint8_t *)addr = value;
299 }
300
301 static __rte_always_inline void
rte_write16_relaxed(uint16_t value,volatile void * addr)302 rte_write16_relaxed(uint16_t value, volatile void *addr)
303 {
304 *(volatile uint16_t *)addr = value;
305 }
306
307 static __rte_always_inline void
rte_write32_relaxed(uint32_t value,volatile void * addr)308 rte_write32_relaxed(uint32_t value, volatile void *addr)
309 {
310 *(volatile uint32_t *)addr = value;
311 }
312
313 static __rte_always_inline void
rte_write64_relaxed(uint64_t value,volatile void * addr)314 rte_write64_relaxed(uint64_t value, volatile void *addr)
315 {
316 *(volatile uint64_t *)addr = value;
317 }
318
319 static __rte_always_inline uint8_t
rte_read8(const volatile void * addr)320 rte_read8(const volatile void *addr)
321 {
322 uint8_t val;
323 val = rte_read8_relaxed(addr);
324 rte_io_rmb();
325 return val;
326 }
327
328 static __rte_always_inline uint16_t
rte_read16(const volatile void * addr)329 rte_read16(const volatile void *addr)
330 {
331 uint16_t val;
332 val = rte_read16_relaxed(addr);
333 rte_io_rmb();
334 return val;
335 }
336
337 static __rte_always_inline uint32_t
rte_read32(const volatile void * addr)338 rte_read32(const volatile void *addr)
339 {
340 uint32_t val;
341 val = rte_read32_relaxed(addr);
342 rte_io_rmb();
343 return val;
344 }
345
346 static __rte_always_inline uint64_t
rte_read64(const volatile void * addr)347 rte_read64(const volatile void *addr)
348 {
349 uint64_t val;
350 val = rte_read64_relaxed(addr);
351 rte_io_rmb();
352 return val;
353 }
354
355 static __rte_always_inline void
rte_write8(uint8_t value,volatile void * addr)356 rte_write8(uint8_t value, volatile void *addr)
357 {
358 rte_io_wmb();
359 rte_write8_relaxed(value, addr);
360 }
361
362 static __rte_always_inline void
rte_write16(uint16_t value,volatile void * addr)363 rte_write16(uint16_t value, volatile void *addr)
364 {
365 rte_io_wmb();
366 rte_write16_relaxed(value, addr);
367 }
368
369 static __rte_always_inline void
rte_write32(uint32_t value,volatile void * addr)370 rte_write32(uint32_t value, volatile void *addr)
371 {
372 rte_io_wmb();
373 rte_write32_relaxed(value, addr);
374 }
375
376 static __rte_always_inline void
rte_write64(uint64_t value,volatile void * addr)377 rte_write64(uint64_t value, volatile void *addr)
378 {
379 rte_io_wmb();
380 rte_write64_relaxed(value, addr);
381 }
382
383 #ifndef RTE_NATIVE_WRITE32_WC
384 static __rte_always_inline void
rte_write32_wc(uint32_t value,volatile void * addr)385 rte_write32_wc(uint32_t value, volatile void *addr)
386 {
387 rte_write32(value, addr);
388 }
389
390 static __rte_always_inline void
rte_write32_wc_relaxed(uint32_t value,volatile void * addr)391 rte_write32_wc_relaxed(uint32_t value, volatile void *addr)
392 {
393 rte_write32_relaxed(value, addr);
394 }
395 #endif /* RTE_NATIVE_WRITE32_WC */
396
397 #endif /* RTE_OVERRIDE_IO_H */
398
399 #endif /* _RTE_IO_H_ */
400