diff options
Diffstat (limited to 'roms/u-boot/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h')
-rw-r--r-- | roms/u-boot/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/roms/u-boot/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h b/roms/u-boot/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h new file mode 100644 index 000000000..6985083a5 --- /dev/null +++ b/roms/u-boot/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Marvell International Ltd. + * + * Interface to the hardware Free Pool Allocator on Octeon chips. + * These are the legacy models, i.e. prior to CN78XX/CN76XX. + */ + +#ifndef __CVMX_FPA1_HW_H__ +#define __CVMX_FPA1_HW_H__ + +#include "cvmx-scratch.h" +#include "cvmx-fpa-defs.h" +#include "cvmx-fpa3.h" + +/* Legacy pool range is 0..7 and 8 on CN68XX */ +typedef int cvmx_fpa1_pool_t; + +#define CVMX_FPA1_NUM_POOLS 8 +#define CVMX_FPA1_INVALID_POOL ((cvmx_fpa1_pool_t)-1) +#define CVMX_FPA1_NAME_SIZE 16 + +/** + * Structure describing the data format used for stores to the FPA. + */ +typedef union { + u64 u64; + struct { + u64 scraddr : 8; + u64 len : 8; + u64 did : 8; + u64 addr : 40; + } s; +} cvmx_fpa1_iobdma_data_t; + +/* + * Allocate or reserve the specified fpa pool. + * + * @param pool FPA pool to allocate/reserve. If -1 it + * finds an empty pool to allocate. + * @return Alloctaed pool number or CVMX_FPA1_POOL_INVALID + * if fails to allocate the pool + */ +cvmx_fpa1_pool_t cvmx_fpa1_reserve_pool(cvmx_fpa1_pool_t pool); + +/** + * Free the specified fpa pool. + * @param pool Pool to free + * @return 0 for success -1 failure + */ +int cvmx_fpa1_release_pool(cvmx_fpa1_pool_t pool); + +static inline void cvmx_fpa1_free(void *ptr, cvmx_fpa1_pool_t pool, u64 num_cache_lines) +{ + cvmx_addr_t newptr; + + newptr.u64 = cvmx_ptr_to_phys(ptr); + newptr.sfilldidspace.didspace = CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)); + /* Make sure that any previous writes to memory go out before we free + * this buffer. This also serves as a barrier to prevent GCC from + * reordering operations to after the free. + */ + CVMX_SYNCWS; + /* value written is number of cache lines not written back */ + cvmx_write_io(newptr.u64, num_cache_lines); +} + +static inline void cvmx_fpa1_free_nosync(void *ptr, cvmx_fpa1_pool_t pool, + unsigned int num_cache_lines) +{ + cvmx_addr_t newptr; + + newptr.u64 = cvmx_ptr_to_phys(ptr); + newptr.sfilldidspace.didspace = CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)); + /* Prevent GCC from reordering around free */ + asm volatile("" : : : "memory"); + /* value written is number of cache lines not written back */ + cvmx_write_io(newptr.u64, num_cache_lines); +} + +/** + * Enable the FPA for use. Must be performed after any CSR + * configuration but before any other FPA functions. + */ +static inline void cvmx_fpa1_enable(void) +{ + cvmx_fpa_ctl_status_t status; + + status.u64 = csr_rd(CVMX_FPA_CTL_STATUS); + if (status.s.enb) { + /* + * CN68XXP1 should not reset the FPA (doing so may break + * the SSO, so we may end up enabling it more than once. + * Just return and don't spew messages. + */ + return; + } + + status.u64 = 0; + status.s.enb = 1; + csr_wr(CVMX_FPA_CTL_STATUS, status.u64); +} + +/** + * Reset FPA to disable. Make sure buffers from all FPA pools are freed + * before disabling FPA. + */ +static inline void cvmx_fpa1_disable(void) +{ + cvmx_fpa_ctl_status_t status; + + if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1)) + return; + + status.u64 = csr_rd(CVMX_FPA_CTL_STATUS); + status.s.reset = 1; + csr_wr(CVMX_FPA_CTL_STATUS, status.u64); +} + +static inline void *cvmx_fpa1_alloc(cvmx_fpa1_pool_t pool) +{ + u64 address; + + for (;;) { + address = csr_rd(CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool))); + if (cvmx_likely(address)) { + return cvmx_phys_to_ptr(address); + } else { + if (csr_rd(CVMX_FPA_QUEX_AVAILABLE(pool)) > 0) + udelay(50); + else + return NULL; + } + } +} + +/** + * Asynchronously get a new block from the FPA + * @INTERNAL + * + * The result of cvmx_fpa_async_alloc() may be retrieved using + * cvmx_fpa_async_alloc_finish(). + * + * @param scr_addr Local scratch address to put response in. This is a byte + * address but must be 8 byte aligned. + * @param pool Pool to get the block from + */ +static inline void cvmx_fpa1_async_alloc(u64 scr_addr, cvmx_fpa1_pool_t pool) +{ + cvmx_fpa1_iobdma_data_t data; + + /* Hardware only uses 64 bit aligned locations, so convert from byte + * address to 64-bit index + */ + data.u64 = 0ull; + data.s.scraddr = scr_addr >> 3; + data.s.len = 1; + data.s.did = CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool); + data.s.addr = 0; + + cvmx_scratch_write64(scr_addr, 0ull); + CVMX_SYNCW; + cvmx_send_single(data.u64); +} + +/** + * Retrieve the result of cvmx_fpa_async_alloc + * @INTERNAL + * + * @param scr_addr The Local scratch address. Must be the same value + * passed to cvmx_fpa_async_alloc(). + * + * @param pool Pool the block came from. Must be the same value + * passed to cvmx_fpa_async_alloc. + * + * @return Pointer to the block or NULL on failure + */ +static inline void *cvmx_fpa1_async_alloc_finish(u64 scr_addr, cvmx_fpa1_pool_t pool) +{ + u64 address; + + CVMX_SYNCIOBDMA; + + address = cvmx_scratch_read64(scr_addr); + if (cvmx_likely(address)) + return cvmx_phys_to_ptr(address); + else + return cvmx_fpa1_alloc(pool); +} + +static inline u64 cvmx_fpa1_get_available(cvmx_fpa1_pool_t pool) +{ + return csr_rd(CVMX_FPA_QUEX_AVAILABLE(pool)); +} + +#endif /* __CVMX_FPA1_HW_H__ */ |