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)28spdk_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)35spdk_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)42spdk_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)49spdk_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)56spdk_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)63spdk_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)70spdk_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)93spdk_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