/* * BSD LICENSE * * Copyright (C) Cavium Inc. 2017. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Cavium networks nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __OCTEONTX_IO_H__ #define __OCTEONTX_IO_H__ #include #include #include /* In Cavium OcteonTX SoC, all accesses to the device registers are * implicitly strongly ordered. So, The relaxed version of IO operation is * safe to use with out any IO memory barriers. */ #define octeontx_read64 rte_read64_relaxed #define octeontx_write64 rte_write64_relaxed /* ARM64 specific functions */ #if defined(RTE_ARCH_ARM64) #define octeontx_prefetch_store_keep(_ptr) ({\ asm volatile("prfm pstl1keep, %a0\n" : : "p" (_ptr)); }) #define octeontx_load_pair(val0, val1, addr) ({ \ asm volatile( \ "ldp %x[x0], %x[x1], [%x[p1]]" \ :[x0]"=r"(val0), [x1]"=r"(val1) \ :[p1]"r"(addr) \ ); }) #define octeontx_store_pair(val0, val1, addr) ({ \ asm volatile( \ "stp %x[x0], %x[x1], [%x[p1]]" \ ::[x0]"r"(val0), [x1]"r"(val1), [p1]"r"(addr) \ ); }) #else /* Un optimized functions for building on non arm64 arch */ #define octeontx_prefetch_store_keep(_ptr) do {} while (0) #define octeontx_load_pair(val0, val1, addr) \ do { \ val0 = rte_read64(addr); \ val1 = rte_read64(((uint8_t *)addr) + 8); \ } while (0) #define octeontx_store_pair(val0, val1, addr) \ do { \ rte_write64(val0, addr); \ rte_write64(val1, (((uint8_t *)addr) + 8)); \ } while (0) #endif #if defined(RTE_ARCH_ARM64) /** * Perform an atomic fetch-and-add operation. */ static inline uint64_t octeontx_reg_ldadd_u64(void *addr, int64_t off) { uint64_t old_val; __asm__ volatile( " .cpu generic+lse\n" " ldadd %1, %0, [%2]\n" : "=r" (old_val) : "r" (off), "r" (addr) : "memory"); return old_val; } /** * Perform a LMTST operation - an atomic write of up to 128 byte to * an I/O block that supports this operation type. * * @param lmtline_va is the address where LMTLINE is mapped * @param ioreg_va is the virtual address of the device register * @param cmdbuf is the array of peripheral commands to execute * @param cmdsize is the number of 64-bit words in 'cmdbuf' * * @return N/A */ static inline void octeontx_reg_lmtst(void *lmtline_va, void *ioreg_va, const uint64_t cmdbuf[], uint64_t cmdsize) { uint64_t result; uint64_t word_count; uint64_t *lmtline = lmtline_va; word_count = cmdsize; do { /* Copy commands to LMTLINE */ for (result = 0; result < word_count; result += 2) { lmtline[result + 0] = cmdbuf[result + 0]; lmtline[result + 1] = cmdbuf[result + 1]; } /* LDEOR initiates atomic transfer to I/O device */ __asm__ volatile( " .cpu generic+lse\n" " ldeor xzr, %0, [%1]\n" : "=r" (result) : "r" (ioreg_va) : "memory"); } while (!result); } #else static inline uint64_t octeontx_reg_ldadd_u64(void *addr, int64_t off) { RTE_SET_USED(addr); RTE_SET_USED(off); return 0; } static inline void octeontx_reg_lmtst(void *lmtline_va, void *ioreg_va, const uint64_t cmdbuf[], uint64_t cmdsize) { RTE_SET_USED(lmtline_va); RTE_SET_USED(ioreg_va); RTE_SET_USED(cmdbuf); RTE_SET_USED(cmdsize); } #endif #endif /* __OCTEONTX_IO_H__ */