summaryrefslogtreecommitdiff
path: root/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mach-octeon/include/mach/cvmx-fpa1.h')
-rw-r--r--arch/mips/mach-octeon/include/mach/cvmx-fpa1.h196
1 files changed, 196 insertions, 0 deletions
diff --git a/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h b/arch/mips/mach-octeon/include/mach/cvmx-fpa1.h
new file mode 100644
index 0000000000..6985083a5d
--- /dev/null
+++ b/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__ */