mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-23 19:43:33 +00:00
197 lines
4.9 KiB
C
197 lines
4.9 KiB
C
|
/* 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__ */
|