mirror of https://github.com/F-Stack/f-stack.git
627 lines
17 KiB
C
627 lines
17 KiB
C
|
/* SPDX-License-Identifier: BSD-3-Clause
|
||
|
* Copyright (c) 2022 Marvell.
|
||
|
*/
|
||
|
|
||
|
#include "roc_api.h"
|
||
|
#include "roc_priv.h"
|
||
|
|
||
|
#define TIME_SEC_IN_MS 1000
|
||
|
|
||
|
static int
|
||
|
roc_ml_reg_wait_to_clear(struct roc_ml *roc_ml, uint64_t offset, uint64_t mask)
|
||
|
{
|
||
|
uint64_t start_cycle;
|
||
|
uint64_t wait_cycles;
|
||
|
uint64_t reg_val;
|
||
|
|
||
|
wait_cycles = (ROC_ML_TIMEOUT_MS * plt_tsc_hz()) / TIME_SEC_IN_MS;
|
||
|
start_cycle = plt_tsc_cycles();
|
||
|
do {
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, offset);
|
||
|
|
||
|
if (!(reg_val & mask))
|
||
|
return 0;
|
||
|
} while (plt_tsc_cycles() - start_cycle < wait_cycles);
|
||
|
|
||
|
return -ETIME;
|
||
|
}
|
||
|
|
||
|
uint64_t
|
||
|
roc_ml_reg_read64(struct roc_ml *roc_ml, uint64_t offset)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
return plt_read64(PLT_PTR_ADD(ml->ml_reg_addr, offset));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_reg_write64(struct roc_ml *roc_ml, uint64_t val, uint64_t offset)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
plt_write64(val, PLT_PTR_ADD(ml->ml_reg_addr, offset));
|
||
|
}
|
||
|
|
||
|
uint32_t
|
||
|
roc_ml_reg_read32(struct roc_ml *roc_ml, uint64_t offset)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
return plt_read32(PLT_PTR_ADD(ml->ml_reg_addr, offset));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_reg_write32(struct roc_ml *roc_ml, uint32_t val, uint64_t offset)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
plt_write32(val, PLT_PTR_ADD(ml->ml_reg_addr, offset));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_reg_save(struct roc_ml *roc_ml, uint64_t offset)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
if (offset == ML_MLR_BASE) {
|
||
|
ml->ml_mlr_base =
|
||
|
FIELD_GET(ROC_ML_MLR_BASE_BASE, roc_ml_reg_read64(roc_ml, offset));
|
||
|
ml->ml_mlr_base_saved = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void *
|
||
|
roc_ml_addr_ap2mlip(struct roc_ml *roc_ml, void *addr)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
uint64_t ml_mlr_base;
|
||
|
|
||
|
ml_mlr_base = (ml->ml_mlr_base_saved) ? ml->ml_mlr_base :
|
||
|
FIELD_GET(ROC_ML_MLR_BASE_BASE,
|
||
|
roc_ml_reg_read64(roc_ml, ML_MLR_BASE));
|
||
|
return PLT_PTR_ADD(addr, ML_AXI_START_ADDR - ml_mlr_base);
|
||
|
}
|
||
|
|
||
|
void *
|
||
|
roc_ml_addr_mlip2ap(struct roc_ml *roc_ml, void *addr)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
uint64_t ml_mlr_base;
|
||
|
|
||
|
ml_mlr_base = (ml->ml_mlr_base_saved) ? ml->ml_mlr_base :
|
||
|
FIELD_GET(ROC_ML_MLR_BASE_BASE,
|
||
|
roc_ml_reg_read64(roc_ml, ML_MLR_BASE));
|
||
|
return PLT_PTR_ADD(addr, ml_mlr_base - ML_AXI_START_ADDR);
|
||
|
}
|
||
|
|
||
|
uint64_t
|
||
|
roc_ml_addr_pa_to_offset(struct roc_ml *roc_ml, uint64_t phys_addr)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
if (roc_model_is_cn10ka())
|
||
|
return phys_addr - ml->pci_dev->mem_resource[0].phys_addr;
|
||
|
else
|
||
|
return phys_addr - ml->pci_dev->mem_resource[0].phys_addr - ML_MLAB_BLK_OFFSET;
|
||
|
}
|
||
|
|
||
|
uint64_t
|
||
|
roc_ml_addr_offset_to_pa(struct roc_ml *roc_ml, uint64_t offset)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
if (roc_model_is_cn10ka())
|
||
|
return ml->pci_dev->mem_resource[0].phys_addr + offset;
|
||
|
else
|
||
|
return ml->pci_dev->mem_resource[0].phys_addr + ML_MLAB_BLK_OFFSET + offset;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_scratch_write_job(struct roc_ml *roc_ml, void *work_ptr)
|
||
|
{
|
||
|
union ml_scratch_work_ptr_s reg_work_ptr;
|
||
|
union ml_scratch_fw_ctrl_s reg_fw_ctrl;
|
||
|
|
||
|
reg_work_ptr.u64 = 0;
|
||
|
reg_work_ptr.s.work_ptr = PLT_U64_CAST(roc_ml_addr_ap2mlip(roc_ml, work_ptr));
|
||
|
|
||
|
reg_fw_ctrl.u64 = 0;
|
||
|
reg_fw_ctrl.s.valid = 1;
|
||
|
|
||
|
roc_ml_reg_write64(roc_ml, reg_work_ptr.u64, ML_SCRATCH_WORK_PTR);
|
||
|
roc_ml_reg_write64(roc_ml, reg_fw_ctrl.u64, ML_SCRATCH_FW_CTRL);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
roc_ml_scratch_is_valid_bit_set(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
union ml_scratch_fw_ctrl_s reg_fw_ctrl;
|
||
|
|
||
|
reg_fw_ctrl.u64 = roc_ml_reg_read64(roc_ml, ML_SCRATCH_FW_CTRL);
|
||
|
|
||
|
if (reg_fw_ctrl.s.valid == 1)
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
roc_ml_scratch_is_done_bit_set(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
union ml_scratch_fw_ctrl_s reg_fw_ctrl;
|
||
|
|
||
|
reg_fw_ctrl.u64 = roc_ml_reg_read64(roc_ml, ML_SCRATCH_FW_CTRL);
|
||
|
|
||
|
if (reg_fw_ctrl.s.done == 1)
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
roc_ml_scratch_enqueue(struct roc_ml *roc_ml, void *work_ptr)
|
||
|
{
|
||
|
union ml_scratch_work_ptr_s reg_work_ptr;
|
||
|
union ml_scratch_fw_ctrl_s reg_fw_ctrl;
|
||
|
bool ret = false;
|
||
|
|
||
|
reg_work_ptr.u64 = 0;
|
||
|
reg_work_ptr.s.work_ptr = PLT_U64_CAST(roc_ml_addr_ap2mlip(roc_ml, work_ptr));
|
||
|
|
||
|
reg_fw_ctrl.u64 = 0;
|
||
|
reg_fw_ctrl.s.valid = 1;
|
||
|
|
||
|
if (plt_spinlock_trylock(&roc_ml->sp_spinlock) != 0) {
|
||
|
bool valid = roc_ml_scratch_is_valid_bit_set(roc_ml);
|
||
|
bool done = roc_ml_scratch_is_done_bit_set(roc_ml);
|
||
|
|
||
|
if (valid == done) {
|
||
|
roc_ml_clk_force_on(roc_ml);
|
||
|
roc_ml_dma_stall_off(roc_ml);
|
||
|
|
||
|
roc_ml_reg_write64(roc_ml, reg_work_ptr.u64, ML_SCRATCH_WORK_PTR);
|
||
|
roc_ml_reg_write64(roc_ml, reg_fw_ctrl.u64, ML_SCRATCH_FW_CTRL);
|
||
|
|
||
|
ret = true;
|
||
|
}
|
||
|
plt_spinlock_unlock(&roc_ml->sp_spinlock);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
roc_ml_scratch_dequeue(struct roc_ml *roc_ml, void *work_ptr)
|
||
|
{
|
||
|
union ml_scratch_work_ptr_s reg_work_ptr;
|
||
|
bool ret = false;
|
||
|
|
||
|
if (plt_spinlock_trylock(&roc_ml->sp_spinlock) != 0) {
|
||
|
bool valid = roc_ml_scratch_is_valid_bit_set(roc_ml);
|
||
|
bool done = roc_ml_scratch_is_done_bit_set(roc_ml);
|
||
|
|
||
|
if (valid && done) {
|
||
|
reg_work_ptr.u64 = roc_ml_reg_read64(roc_ml, ML_SCRATCH_WORK_PTR);
|
||
|
if (work_ptr ==
|
||
|
roc_ml_addr_mlip2ap(roc_ml, PLT_PTR_CAST(reg_work_ptr.u64))) {
|
||
|
roc_ml_dma_stall_on(roc_ml);
|
||
|
roc_ml_clk_force_off(roc_ml);
|
||
|
|
||
|
roc_ml_reg_write64(roc_ml, 0, ML_SCRATCH_WORK_PTR);
|
||
|
roc_ml_reg_write64(roc_ml, 0, ML_SCRATCH_FW_CTRL);
|
||
|
ret = true;
|
||
|
}
|
||
|
}
|
||
|
plt_spinlock_unlock(&roc_ml->sp_spinlock);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_scratch_queue_reset(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
if (plt_spinlock_trylock(&roc_ml->sp_spinlock) != 0) {
|
||
|
roc_ml_dma_stall_on(roc_ml);
|
||
|
roc_ml_clk_force_off(roc_ml);
|
||
|
roc_ml_reg_write64(roc_ml, 0, ML_SCRATCH_WORK_PTR);
|
||
|
roc_ml_reg_write64(roc_ml, 0, ML_SCRATCH_FW_CTRL);
|
||
|
plt_spinlock_unlock(&roc_ml->sp_spinlock);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
roc_ml_jcmdq_enqueue_lf(struct roc_ml *roc_ml, struct ml_job_cmd_s *job_cmd)
|
||
|
{
|
||
|
bool ret = false;
|
||
|
|
||
|
if (FIELD_GET(ROC_ML_JCMDQ_STATUS_AVAIL_COUNT,
|
||
|
roc_ml_reg_read64(roc_ml, ML_JCMDQ_STATUS)) != 0) {
|
||
|
roc_ml_reg_write64(roc_ml, job_cmd->w0.u64, ML_JCMDQ_IN(0));
|
||
|
roc_ml_reg_write64(roc_ml, job_cmd->w1.u64, ML_JCMDQ_IN(1));
|
||
|
ret = true;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
roc_ml_jcmdq_enqueue_sl(struct roc_ml *roc_ml, struct ml_job_cmd_s *job_cmd)
|
||
|
{
|
||
|
bool ret = false;
|
||
|
|
||
|
if (plt_spinlock_trylock(&roc_ml->fp_spinlock) != 0) {
|
||
|
if (FIELD_GET(ROC_ML_JCMDQ_STATUS_AVAIL_COUNT,
|
||
|
roc_ml_reg_read64(roc_ml, ML_JCMDQ_STATUS)) != 0) {
|
||
|
roc_ml_reg_write64(roc_ml, job_cmd->w0.u64, ML_JCMDQ_IN(0));
|
||
|
roc_ml_reg_write64(roc_ml, job_cmd->w1.u64, ML_JCMDQ_IN(1));
|
||
|
ret = true;
|
||
|
}
|
||
|
plt_spinlock_unlock(&roc_ml->fp_spinlock);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_clk_force_on(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
uint64_t reg_val = 0;
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val |= ROC_ML_CFG_MLIP_CLK_FORCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_clk_force_off(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
uint64_t reg_val = 0;
|
||
|
|
||
|
roc_ml_reg_write64(roc_ml, 0, ML_SCRATCH_WORK_PTR);
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val &= ~ROC_ML_CFG_MLIP_CLK_FORCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_dma_stall_on(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
uint64_t reg_val = 0;
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_JOB_MGR_CTRL);
|
||
|
reg_val |= ROC_ML_JOB_MGR_CTRL_STALL_ON_IDLE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_JOB_MGR_CTRL);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
roc_ml_dma_stall_off(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
uint64_t reg_val = 0;
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_JOB_MGR_CTRL);
|
||
|
reg_val &= ~ROC_ML_JOB_MGR_CTRL_STALL_ON_IDLE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_JOB_MGR_CTRL);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
roc_ml_mlip_is_enabled(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
uint64_t reg_val;
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
|
||
|
if ((reg_val & ROC_ML_CFG_MLIP_ENA) != 0)
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
roc_ml_mlip_reset(struct roc_ml *roc_ml, bool force)
|
||
|
{
|
||
|
uint64_t reg_val;
|
||
|
|
||
|
/* Force reset */
|
||
|
if (force) {
|
||
|
/* Set ML(0)_CFG[ENA] = 0. */
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val &= ~ROC_ML_CFG_ENA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
|
||
|
/* Set ML(0)_CFG[MLIP_ENA] = 0. */
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val &= ~ROC_ML_CFG_MLIP_ENA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
|
||
|
/* Clear ML_MLR_BASE */
|
||
|
roc_ml_reg_write64(roc_ml, 0, ML_MLR_BASE);
|
||
|
}
|
||
|
|
||
|
if (roc_model_is_cn10ka()) {
|
||
|
/* Wait for all active jobs to finish.
|
||
|
* ML_CFG[ENA] : When set, MLW will accept job commands. This
|
||
|
* bit can be cleared at any time. If [BUSY] is set, software
|
||
|
* must wait until [BUSY] == 0 before setting this bit.
|
||
|
*/
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_CFG, ROC_ML_CFG_BUSY);
|
||
|
|
||
|
/* (1) Set ML(0)_AXI_BRIDGE_CTRL(0..1)[FENCE] = 1 to instruct
|
||
|
* the AXI bridge not to accept any new transactions from MLIP.
|
||
|
*/
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(0));
|
||
|
reg_val |= ROC_ML_AXI_BRIDGE_CTRL_FENCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(0));
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(1));
|
||
|
reg_val |= ROC_ML_AXI_BRIDGE_CTRL_FENCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(1));
|
||
|
|
||
|
/* (2) Wait until ML(0)_AXI_BRIDGE_CTRL(0..1)[BUSY] = 0 which
|
||
|
* indicates that there is no outstanding transactions on
|
||
|
* AXI-NCB paths.
|
||
|
*/
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_AXI_BRIDGE_CTRL(0),
|
||
|
ROC_ML_AXI_BRIDGE_CTRL_BUSY);
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_AXI_BRIDGE_CTRL(1),
|
||
|
ROC_ML_AXI_BRIDGE_CTRL_BUSY);
|
||
|
|
||
|
/* (3) Wait until ML(0)_JOB_MGR_CTRL[BUSY] = 0 which indicates
|
||
|
* that there are no pending jobs in the MLW's job manager.
|
||
|
*/
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_JOB_MGR_CTRL, ROC_ML_JOB_MGR_CTRL_BUSY);
|
||
|
|
||
|
/* (4) Set ML(0)_CFG[ENA] = 0. */
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val &= ~ROC_ML_CFG_ENA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
|
||
|
/* (5) Set ML(0)_CFG[MLIP_ENA] = 0. */
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val &= ~ROC_ML_CFG_MLIP_ENA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
|
||
|
/* (6) Set ML(0)_AXI_BRIDGE_CTRL(0..1)[FENCE] = 0.*/
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(0));
|
||
|
reg_val &= ~ROC_ML_AXI_BRIDGE_CTRL_FENCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(0));
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(1));
|
||
|
}
|
||
|
|
||
|
if (roc_model_is_cnf10kb()) {
|
||
|
/* (1) Clear MLAB(0)_CFG[ENA]. Any new jobs will bypass the job
|
||
|
* execution stages and their completions will be returned to
|
||
|
* PSM.
|
||
|
*/
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val &= ~ROC_ML_CFG_ENA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
|
||
|
/* (2) Quiesce the ACC and DMA AXI interfaces: For each of the
|
||
|
* two MLAB(0)_AXI_BRIDGE_CTRL(0..1) registers:
|
||
|
*
|
||
|
* (a) Set MLAB(0)_AXI_BRIDGE_CTRL(0..1)[FENCE] to block new AXI
|
||
|
* commands from MLIP.
|
||
|
*
|
||
|
* (b) Poll MLAB(0)_AXI_BRIDGE_CTRL(0..1)[BUSY] == 0.
|
||
|
*/
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(0));
|
||
|
reg_val |= ROC_ML_AXI_BRIDGE_CTRL_FENCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(0));
|
||
|
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_AXI_BRIDGE_CTRL(0),
|
||
|
ROC_ML_AXI_BRIDGE_CTRL_BUSY);
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(1));
|
||
|
reg_val |= ROC_ML_AXI_BRIDGE_CTRL_FENCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(1));
|
||
|
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_AXI_BRIDGE_CTRL(1),
|
||
|
ROC_ML_AXI_BRIDGE_CTRL_BUSY);
|
||
|
|
||
|
/* (3) Clear MLAB(0)_CFG[MLIP_ENA] to reset MLIP.
|
||
|
*/
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_CFG);
|
||
|
reg_val &= ~ROC_ML_CFG_MLIP_ENA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_CFG);
|
||
|
|
||
|
cnf10kb_mlip_reset_stage_4a:
|
||
|
/* (4) Flush any outstanding jobs in MLAB's job execution
|
||
|
* stages:
|
||
|
*
|
||
|
* (a) Wait for completion stage to clear:
|
||
|
* - Poll MLAB(0)_STG(0..2)_STATUS[VALID] == 0.
|
||
|
*/
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_STGX_STATUS(0), ROC_ML_STG_STATUS_VALID);
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_STGX_STATUS(1), ROC_ML_STG_STATUS_VALID);
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_STGX_STATUS(2), ROC_ML_STG_STATUS_VALID);
|
||
|
|
||
|
cnf10kb_mlip_reset_stage_4b:
|
||
|
/* (4b) Clear job run stage: Poll
|
||
|
* MLAB(0)_STG_CONTROL[RUN_TO_COMP] == 0.
|
||
|
*/
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_STG_CONTROL, ROC_ML_STG_CONTROL_RUN_TO_COMP);
|
||
|
|
||
|
/* (4b) Clear job run stage: If MLAB(0)_STG(1)_STATUS[VALID] ==
|
||
|
* 1:
|
||
|
* - Set MLAB(0)_STG_CONTROL[RUN_TO_COMP].
|
||
|
* - Poll MLAB(0)_STG_CONTROL[RUN_TO_COMP] == 0.
|
||
|
* - Repeat step (a) to clear job completion stage.
|
||
|
*/
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_STGX_STATUS(1));
|
||
|
if (reg_val & ROC_ML_STG_STATUS_VALID) {
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_STG_CONTROL);
|
||
|
reg_val |= ROC_ML_STG_CONTROL_RUN_TO_COMP;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_STG_CONTROL);
|
||
|
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_STG_CONTROL,
|
||
|
ROC_ML_STG_CONTROL_RUN_TO_COMP);
|
||
|
|
||
|
goto cnf10kb_mlip_reset_stage_4a;
|
||
|
}
|
||
|
|
||
|
/* (4c) Clear job fetch stage: Poll
|
||
|
* MLAB(0)_STG_CONTROL[FETCH_TO_RUN] == 0.
|
||
|
*/
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_STG_CONTROL, ROC_ML_STG_CONTROL_FETCH_TO_RUN);
|
||
|
|
||
|
/* (4c) Clear job fetch stage: If
|
||
|
* MLAB(0)_STG(0..2)_STATUS[VALID] == 1:
|
||
|
* - Set MLAB(0)_STG_CONTROL[FETCH_TO_RUN].
|
||
|
* - Poll MLAB(0)_STG_CONTROL[FETCH_TO_RUN] == 0.
|
||
|
* - Repeat step (b) to clear job run and completion stages.
|
||
|
*/
|
||
|
reg_val = (roc_ml_reg_read64(roc_ml, ML_STGX_STATUS(0)) |
|
||
|
roc_ml_reg_read64(roc_ml, ML_STGX_STATUS(1)) |
|
||
|
roc_ml_reg_read64(roc_ml, ML_STGX_STATUS(2)));
|
||
|
|
||
|
if (reg_val & ROC_ML_STG_STATUS_VALID) {
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_STG_CONTROL);
|
||
|
reg_val |= ROC_ML_STG_CONTROL_RUN_TO_COMP;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_STG_CONTROL);
|
||
|
|
||
|
roc_ml_reg_wait_to_clear(roc_ml, ML_STG_CONTROL,
|
||
|
ROC_ML_STG_CONTROL_RUN_TO_COMP);
|
||
|
|
||
|
goto cnf10kb_mlip_reset_stage_4b;
|
||
|
}
|
||
|
|
||
|
/* (5) Reset the ACC and DMA AXI interfaces: For each of the two
|
||
|
* MLAB(0)_AXI_BRIDGE_CTRL(0..1) registers:
|
||
|
*
|
||
|
* (5a) Set and then clear
|
||
|
* MLAB(0)_AXI_BRIDGE_CTRL(0..1)[FLUSH_WRITE_DATA].
|
||
|
*
|
||
|
* (5b) Clear MLAB(0)_AXI_BRIDGE_CTRL(0..1)[FENCE].
|
||
|
*/
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(0));
|
||
|
reg_val |= ROC_ML_AXI_BRIDGE_CTRL_FLUSH_WRITE_DATA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(0));
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(0));
|
||
|
reg_val &= ~ROC_ML_AXI_BRIDGE_CTRL_FLUSH_WRITE_DATA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(0));
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(0));
|
||
|
reg_val &= ~ROC_ML_AXI_BRIDGE_CTRL_FENCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(0));
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(1));
|
||
|
reg_val |= ROC_ML_AXI_BRIDGE_CTRL_FLUSH_WRITE_DATA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(1));
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(1));
|
||
|
reg_val &= ~ROC_ML_AXI_BRIDGE_CTRL_FLUSH_WRITE_DATA;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(1));
|
||
|
|
||
|
reg_val = roc_ml_reg_read64(roc_ml, ML_AXI_BRIDGE_CTRL(1));
|
||
|
reg_val &= ~ROC_ML_AXI_BRIDGE_CTRL_FENCE;
|
||
|
roc_ml_reg_write64(roc_ml, reg_val, ML_AXI_BRIDGE_CTRL(1));
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
roc_ml_dev_init(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
struct plt_pci_device *pci_dev;
|
||
|
struct dev *dev;
|
||
|
struct ml *ml;
|
||
|
|
||
|
if (roc_ml == NULL || roc_ml->pci_dev == NULL)
|
||
|
return -EINVAL;
|
||
|
|
||
|
PLT_STATIC_ASSERT(sizeof(struct ml) <= ROC_ML_MEM_SZ);
|
||
|
|
||
|
ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
memset(ml, 0, sizeof(*ml));
|
||
|
pci_dev = roc_ml->pci_dev;
|
||
|
dev = &ml->dev;
|
||
|
|
||
|
ml->pci_dev = pci_dev;
|
||
|
dev->roc_ml = roc_ml;
|
||
|
|
||
|
ml->ml_reg_addr = ml->pci_dev->mem_resource[0].addr;
|
||
|
ml->ml_mlr_base = 0;
|
||
|
ml->ml_mlr_base_saved = false;
|
||
|
|
||
|
plt_ml_dbg("ML: PCI Physical Address : 0x%016lx", ml->pci_dev->mem_resource[0].phys_addr);
|
||
|
plt_ml_dbg("ML: PCI Virtual Address : 0x%016lx",
|
||
|
PLT_U64_CAST(ml->pci_dev->mem_resource[0].addr));
|
||
|
|
||
|
plt_spinlock_init(&roc_ml->sp_spinlock);
|
||
|
plt_spinlock_init(&roc_ml->fp_spinlock);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
roc_ml_dev_fini(struct roc_ml *roc_ml)
|
||
|
{
|
||
|
struct ml *ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
if (ml == NULL)
|
||
|
return -EINVAL;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
roc_ml_blk_init(struct roc_bphy *roc_bphy, struct roc_ml *roc_ml)
|
||
|
{
|
||
|
struct dev *dev;
|
||
|
struct ml *ml;
|
||
|
|
||
|
if ((roc_ml == NULL) || (roc_bphy == NULL))
|
||
|
return -EINVAL;
|
||
|
|
||
|
PLT_STATIC_ASSERT(sizeof(struct ml) <= ROC_ML_MEM_SZ);
|
||
|
|
||
|
ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
memset(ml, 0, sizeof(*ml));
|
||
|
|
||
|
dev = &ml->dev;
|
||
|
|
||
|
ml->pci_dev = roc_bphy->pci_dev;
|
||
|
dev->roc_ml = roc_ml;
|
||
|
|
||
|
plt_ml_dbg(
|
||
|
"MLAB: Physical Address : 0x%016lx",
|
||
|
PLT_PTR_ADD_U64_CAST(ml->pci_dev->mem_resource[0].phys_addr, ML_MLAB_BLK_OFFSET));
|
||
|
plt_ml_dbg("MLAB: Virtual Address : 0x%016lx",
|
||
|
PLT_PTR_ADD_U64_CAST(ml->pci_dev->mem_resource[0].addr, ML_MLAB_BLK_OFFSET));
|
||
|
|
||
|
ml->ml_reg_addr = PLT_PTR_ADD(ml->pci_dev->mem_resource[0].addr, ML_MLAB_BLK_OFFSET);
|
||
|
ml->ml_mlr_base = 0;
|
||
|
ml->ml_mlr_base_saved = false;
|
||
|
|
||
|
plt_spinlock_init(&roc_ml->sp_spinlock);
|
||
|
plt_spinlock_init(&roc_ml->fp_spinlock);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
roc_ml_blk_fini(struct roc_bphy *roc_bphy, struct roc_ml *roc_ml)
|
||
|
{
|
||
|
struct ml *ml;
|
||
|
|
||
|
if ((roc_ml == NULL) || (roc_bphy == NULL))
|
||
|
return -EINVAL;
|
||
|
|
||
|
ml = roc_ml_to_ml_priv(roc_ml);
|
||
|
|
||
|
if (ml == NULL)
|
||
|
return -EINVAL;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint16_t
|
||
|
roc_ml_sso_pf_func_get(void)
|
||
|
{
|
||
|
return idev_sso_pffunc_get();
|
||
|
}
|