xref: /spdk/include/spdk/mmio.h (revision a6dbe3721eb3b5990707fc3e378c95e505dd8ab5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2015 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 /** \file
7  * Memory-mapped I/O utility functions
8  */
9 
10 #ifndef SPDK_MMIO_H
11 #define SPDK_MMIO_H
12 
13 #include "spdk/stdinc.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 #include "spdk/barrier.h"
20 
21 #ifdef __x86_64__
22 #define SPDK_MMIO_64BIT	1 /* Can do atomic 64-bit memory read/write (over PCIe) */
23 #else
24 #define SPDK_MMIO_64BIT	0
25 #endif
26 
27 static inline uint8_t
spdk_mmio_read_1(const volatile uint8_t * addr)28 spdk_mmio_read_1(const volatile uint8_t *addr)
29 {
30 	spdk_compiler_barrier();
31 	return *addr;
32 }
33 
34 static inline void
spdk_mmio_write_1(volatile uint8_t * addr,uint8_t val)35 spdk_mmio_write_1(volatile uint8_t *addr, uint8_t val)
36 {
37 	spdk_compiler_barrier();
38 	*addr = val;
39 }
40 
41 static inline uint16_t
spdk_mmio_read_2(const volatile uint16_t * addr)42 spdk_mmio_read_2(const volatile uint16_t *addr)
43 {
44 	spdk_compiler_barrier();
45 	return *addr;
46 }
47 
48 static inline void
spdk_mmio_write_2(volatile uint16_t * addr,uint16_t val)49 spdk_mmio_write_2(volatile uint16_t *addr, uint16_t val)
50 {
51 	spdk_compiler_barrier();
52 	*addr = val;
53 }
54 
55 static inline uint32_t
spdk_mmio_read_4(const volatile uint32_t * addr)56 spdk_mmio_read_4(const volatile uint32_t *addr)
57 {
58 	spdk_compiler_barrier();
59 	return *addr;
60 }
61 
62 static inline void
spdk_mmio_write_4(volatile uint32_t * addr,uint32_t val)63 spdk_mmio_write_4(volatile uint32_t *addr, uint32_t val)
64 {
65 	spdk_compiler_barrier();
66 	*addr = val;
67 }
68 
69 static inline uint64_t
spdk_mmio_read_8(volatile uint64_t * addr)70 spdk_mmio_read_8(volatile uint64_t *addr)
71 {
72 	uint64_t val;
73 	volatile uint32_t *addr32 = (volatile uint32_t *)addr;
74 
75 	spdk_compiler_barrier();
76 
77 	if (SPDK_MMIO_64BIT) {
78 		val = *addr;
79 	} else {
80 		/*
81 		 * Read lower 4 bytes before upper 4 bytes.
82 		 * This particular order is required by I/OAT.
83 		 * If the other order is required, use a pair of spdk_mmio_read_4() calls.
84 		 */
85 		val = addr32[0];
86 		val |= (uint64_t)addr32[1] << 32;
87 	}
88 
89 	return val;
90 }
91 
92 static inline void
spdk_mmio_write_8(volatile uint64_t * addr,uint64_t val)93 spdk_mmio_write_8(volatile uint64_t *addr, uint64_t val)
94 {
95 	volatile uint32_t *addr32 = (volatile uint32_t *)addr;
96 
97 	spdk_compiler_barrier();
98 
99 	if (SPDK_MMIO_64BIT) {
100 		*addr = val;
101 	} else {
102 		addr32[0] = (uint32_t)val;
103 		addr32[1] = (uint32_t)(val >> 32);
104 	}
105 }
106 
107 #ifdef __cplusplus
108 }
109 #endif
110 
111 #endif
112