1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2*a6dbe372Spaul luse * Copyright (C) 2015 Intel Corporation. 3460327eaSDaniel Verkamp * All rights reserved. 4460327eaSDaniel Verkamp */ 5460327eaSDaniel Verkamp 68eafb654SDaniel Verkamp /** \file 78eafb654SDaniel Verkamp * Memory-mapped I/O utility functions 88eafb654SDaniel Verkamp */ 98eafb654SDaniel Verkamp 10460327eaSDaniel Verkamp #ifndef SPDK_MMIO_H 11460327eaSDaniel Verkamp #define SPDK_MMIO_H 12460327eaSDaniel Verkamp 1345cab335SDaniel Verkamp #include "spdk/stdinc.h" 1445cab335SDaniel Verkamp 1504adec22SDaniel Verkamp #ifdef __cplusplus 1604adec22SDaniel Verkamp extern "C" { 1704adec22SDaniel Verkamp #endif 1804adec22SDaniel Verkamp 194a1d47ebSDaniel Verkamp #include "spdk/barrier.h" 204a1d47ebSDaniel Verkamp 21460327eaSDaniel Verkamp #ifdef __x86_64__ 22460327eaSDaniel Verkamp #define SPDK_MMIO_64BIT 1 /* Can do atomic 64-bit memory read/write (over PCIe) */ 23460327eaSDaniel Verkamp #else 24460327eaSDaniel Verkamp #define SPDK_MMIO_64BIT 0 25460327eaSDaniel Verkamp #endif 26460327eaSDaniel Verkamp 2715e97834SDaniel Verkamp static inline uint8_t spdk_mmio_read_1(const volatile uint8_t * addr)2815e97834SDaniel Verkampspdk_mmio_read_1(const volatile uint8_t *addr) 2915e97834SDaniel Verkamp { 3015e97834SDaniel Verkamp spdk_compiler_barrier(); 3115e97834SDaniel Verkamp return *addr; 3215e97834SDaniel Verkamp } 3315e97834SDaniel Verkamp 3415e97834SDaniel Verkamp static inline void spdk_mmio_write_1(volatile uint8_t * addr,uint8_t val)3515e97834SDaniel Verkampspdk_mmio_write_1(volatile uint8_t *addr, uint8_t val) 3615e97834SDaniel Verkamp { 3715e97834SDaniel Verkamp spdk_compiler_barrier(); 3815e97834SDaniel Verkamp *addr = val; 3915e97834SDaniel Verkamp } 4015e97834SDaniel Verkamp 4115e97834SDaniel Verkamp static inline uint16_t spdk_mmio_read_2(const volatile uint16_t * addr)4215e97834SDaniel Verkampspdk_mmio_read_2(const volatile uint16_t *addr) 4315e97834SDaniel Verkamp { 4415e97834SDaniel Verkamp spdk_compiler_barrier(); 4515e97834SDaniel Verkamp return *addr; 4615e97834SDaniel Verkamp } 4715e97834SDaniel Verkamp 4815e97834SDaniel Verkamp static inline void spdk_mmio_write_2(volatile uint16_t * addr,uint16_t val)4915e97834SDaniel Verkampspdk_mmio_write_2(volatile uint16_t *addr, uint16_t val) 5015e97834SDaniel Verkamp { 5115e97834SDaniel Verkamp spdk_compiler_barrier(); 5215e97834SDaniel Verkamp *addr = val; 5315e97834SDaniel Verkamp } 5415e97834SDaniel Verkamp 55460327eaSDaniel Verkamp static inline uint32_t spdk_mmio_read_4(const volatile uint32_t * addr)56460327eaSDaniel Verkampspdk_mmio_read_4(const volatile uint32_t *addr) 57460327eaSDaniel Verkamp { 584a1d47ebSDaniel Verkamp spdk_compiler_barrier(); 59460327eaSDaniel Verkamp return *addr; 60460327eaSDaniel Verkamp } 61460327eaSDaniel Verkamp 62460327eaSDaniel Verkamp static inline void spdk_mmio_write_4(volatile uint32_t * addr,uint32_t val)63460327eaSDaniel Verkampspdk_mmio_write_4(volatile uint32_t *addr, uint32_t val) 64460327eaSDaniel Verkamp { 654a1d47ebSDaniel Verkamp spdk_compiler_barrier(); 66460327eaSDaniel Verkamp *addr = val; 67460327eaSDaniel Verkamp } 68460327eaSDaniel Verkamp 69460327eaSDaniel Verkamp static inline uint64_t spdk_mmio_read_8(volatile uint64_t * addr)70460327eaSDaniel Verkampspdk_mmio_read_8(volatile uint64_t *addr) 71460327eaSDaniel Verkamp { 72460327eaSDaniel Verkamp uint64_t val; 73460327eaSDaniel Verkamp volatile uint32_t *addr32 = (volatile uint32_t *)addr; 74460327eaSDaniel Verkamp 754a1d47ebSDaniel Verkamp spdk_compiler_barrier(); 764a1d47ebSDaniel Verkamp 77460327eaSDaniel Verkamp if (SPDK_MMIO_64BIT) { 78460327eaSDaniel Verkamp val = *addr; 79460327eaSDaniel Verkamp } else { 80460327eaSDaniel Verkamp /* 81460327eaSDaniel Verkamp * Read lower 4 bytes before upper 4 bytes. 82460327eaSDaniel Verkamp * This particular order is required by I/OAT. 83460327eaSDaniel Verkamp * If the other order is required, use a pair of spdk_mmio_read_4() calls. 84460327eaSDaniel Verkamp */ 85460327eaSDaniel Verkamp val = addr32[0]; 86460327eaSDaniel Verkamp val |= (uint64_t)addr32[1] << 32; 87460327eaSDaniel Verkamp } 88460327eaSDaniel Verkamp 89460327eaSDaniel Verkamp return val; 90460327eaSDaniel Verkamp } 91460327eaSDaniel Verkamp 92460327eaSDaniel Verkamp static inline void spdk_mmio_write_8(volatile uint64_t * addr,uint64_t val)93460327eaSDaniel Verkampspdk_mmio_write_8(volatile uint64_t *addr, uint64_t val) 94460327eaSDaniel Verkamp { 95460327eaSDaniel Verkamp volatile uint32_t *addr32 = (volatile uint32_t *)addr; 96460327eaSDaniel Verkamp 974a1d47ebSDaniel Verkamp spdk_compiler_barrier(); 984a1d47ebSDaniel Verkamp 99460327eaSDaniel Verkamp if (SPDK_MMIO_64BIT) { 100460327eaSDaniel Verkamp *addr = val; 101460327eaSDaniel Verkamp } else { 102460327eaSDaniel Verkamp addr32[0] = (uint32_t)val; 103460327eaSDaniel Verkamp addr32[1] = (uint32_t)(val >> 32); 104460327eaSDaniel Verkamp } 105460327eaSDaniel Verkamp } 106460327eaSDaniel Verkamp 10704adec22SDaniel Verkamp #ifdef __cplusplus 10804adec22SDaniel Verkamp } 10904adec22SDaniel Verkamp #endif 11004adec22SDaniel Verkamp 111460327eaSDaniel Verkamp #endif 112