Files
open-gpu-kernel-modules/src/common/nvswitch/kernel/ls10/soe_ls10.c
Bernhard Stoeckner 337e28efda 535.86.05
2023-07-18 16:00:22 +02:00

1343 lines
42 KiB
C

/*
* SPDX-FileCopyrightText: Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "soe/soe_nvswitch.h"
#include "soe/soe_priv_nvswitch.h"
#include "rmlsfm.h"
#include "nvlink_export.h"
#include "common_nvswitch.h"
#include "ls10/ls10.h"
#include "ls10/soe_ls10.h"
#include "nvswitch/ls10/dev_soe_ip.h"
#include "nvswitch/ls10/dev_soe_ip_addendum.h"
#include "nvswitch/ls10/dev_falcon_v4.h"
#include "nvswitch/ls10/dev_nvlsaw_ip.h"
#include "nvswitch/ls10/dev_nvlsaw_ip_addendum.h"
#include "nvswitch/ls10/dev_riscv_pri.h"
#include "flcn/flcnable_nvswitch.h"
#include "flcn/flcn_nvswitch.h"
#include "rmflcncmdif_nvswitch.h"
#include "soe/soeifcmn.h"
/**
* @brief Sets pEngDescUc and pEngDescBc to the discovered
* engine that matches this flcnable instance
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE pointer
* @param[out] pEngDescUc pointer to the UniCast Engine
* Descriptor
* @param[out] pEngDescBc pointer to the BroadCast Engine
* Descriptor
*/
static void
_soeFetchEngines_LS10
(
nvswitch_device *device,
FLCNABLE *pSoe,
ENGINE_DESCRIPTOR_TYPE *pEngDescUc,
ENGINE_DESCRIPTOR_TYPE *pEngDescBc
)
{
pEngDescUc->initialized = NV_FALSE;
if (NVSWITCH_ENG_IS_VALID(device, SOE, 0))
{
pEngDescUc->base = NVSWITCH_GET_ENG(device, SOE, , 0);
}
else
{
pEngDescUc->base = 0;
}
pEngDescBc->initialized = NV_FALSE;
pEngDescBc->base = 0;
}
/*
* @Brief : Send a test command to SOE
*
* @param device The nvswitch device
*/
static NV_STATUS
_nvswitch_soe_send_test_cmd
(
nvswitch_device *device
)
{
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
NvU32 cmdSeqDesc;
NV_STATUS status;
FLCN *pFlcn = device->pSoe->pFlcn;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_NULL;
// sending nothing but a header for UNIT_NULL
cmd.hdr.size = RM_FLCN_QUEUE_HDR_SIZE;
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS * 5, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg - not used for now
NULL, // pPayload - not used for now
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
NVSWITCH_ASSERT(status == NVL_SUCCESS);
return status;
}
#if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
/*!
* Helper function to dump some registers for debug.
*
* @param[in] device nvswitch_device pointer
*/
static void
dumpDebugRegisters
(
nvswitch_device *device
)
{
FLCN *pFlcn = device->pSoe->pFlcn;
NvU32 regOS = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_OS);
NvU32 regPC = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_RPC);
NvU32 regCPUCTL = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_CPUCTL);
NvU32 regIDLESTATE = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_IDLESTATE);
NvU32 regMAILBOX0 = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_MAILBOX0);
NvU32 regMAILBOX1 = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_MAILBOX1);
NvU32 regIRQSTAT = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSTAT);
NvU32 regIRQMODE = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQMODE);
NvU32 regIRQMASK = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_IRQMASK);
NvU32 regIRQDEST = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_IRQDEST);
NvU32 regIRQDELEG = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_IRQDELEG);
NvU32 regDMACTL = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMACTL);
NvU32 regDMATRFCMD = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFCMD);
NvU32 regDMATRFBASE = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFBASE);
NvU32 regDMATRFMOFFS = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFMOFFS);
NvU32 regDMATRFFBOFFS = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFFBOFFS);
NvU32 regPRIVERR_STAT = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_STAT);
NvU32 regPRIVERR_INFO = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_INFO);
NvU32 regPRIVERR_ADDR_HI = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_ADDR_HI);
NvU32 regPRIVERR_ADDR_LO = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_ADDR);
NvU32 regHUBERR_STAT = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_HUB_ERR_STAT);
NvU32 regBCR_CTRL = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_BCR_CTRL);
NvU32 regRESET_PLM = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_RESET_PRIV_LEVEL_MASK);
NvU32 regEXE_PLM = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_EXE_PRIV_LEVEL_MASK);
NVSWITCH_PRINT(device, ERROR, "Peregrine Registers:\n");
NVSWITCH_PRINT(device, ERROR, "OS : 0x%08x\n", regOS);
NVSWITCH_PRINT(device, ERROR, "PC (lo32) : 0x%08x\n", regPC);
NVSWITCH_PRINT(device, ERROR, "CPUCTL : 0x%08x\n", regCPUCTL);
NVSWITCH_PRINT(device, ERROR, "IDLESTATE : 0x%08x\n", regIDLESTATE);
NVSWITCH_PRINT(device, ERROR, "MAILBOX0 : 0x%08x\n", regMAILBOX0);
NVSWITCH_PRINT(device, ERROR, "MAILBOX1 : 0x%08x\n", regMAILBOX1);
NVSWITCH_PRINT(device, ERROR, "IRQSTAT : 0x%08x\n", regIRQSTAT);
NVSWITCH_PRINT(device, ERROR, "IRQMODE : 0x%08x\n", regIRQMODE);
NVSWITCH_PRINT(device, ERROR, "IRQMASK : 0x%08x\n", regIRQMASK);
NVSWITCH_PRINT(device, ERROR, "IRQDEST : 0x%08x\n", regIRQDEST);
NVSWITCH_PRINT(device, ERROR, "IRQDELEG : 0x%08x\n", regIRQDELEG);
NVSWITCH_PRINT(device, ERROR, "DMACTL : 0x%08x\n", regDMACTL);
NVSWITCH_PRINT(device, ERROR, "DMATRFCMD : 0x%08x\n", regDMATRFCMD);
NVSWITCH_PRINT(device, ERROR, "DMATRFBASE : 0x%08x\n", regDMATRFBASE);
NVSWITCH_PRINT(device, ERROR, "DMATRFMOFFS : 0x%08x\n", regDMATRFMOFFS);
NVSWITCH_PRINT(device, ERROR, "DMATRFFBOFFS : 0x%08x\n", regDMATRFFBOFFS);
NVSWITCH_PRINT(device, ERROR, "PRIVERR_STAT : 0x%08x\n", regPRIVERR_STAT);
NVSWITCH_PRINT(device, ERROR, "PRIVERR_INFO : 0x%08x\n", regPRIVERR_INFO);
NVSWITCH_PRINT(device, ERROR, "PRIVERR_ADDR : 0x%08x%08x\n", regPRIVERR_ADDR_HI, regPRIVERR_ADDR_LO);
NVSWITCH_PRINT(device, ERROR, "HUBERR_STAT : 0x%08x\n", regHUBERR_STAT);
NVSWITCH_PRINT(device, ERROR, "BCR_CTRL : 0x%08x\n", regBCR_CTRL);
NVSWITCH_PRINT(device, ERROR, "RESET_PLM : 0x%08x\n", regRESET_PLM);
NVSWITCH_PRINT(device, ERROR, "EXE_PLM : 0x%08x\n", regEXE_PLM);
}
#endif // defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
/*
* @Brief : Attach or Detach driver to SOE Queues
*
* @param[in] device
*/
static void
_nvswitch_soe_attach_detach_driver_ls10
(
nvswitch_device *device,
NvBool bAttach
)
{
NvU32 val;
val = NVSWITCH_SAW_RD32_LS10(device, _NVLSAW, _DRIVER_ATTACH_DETACH);
if (bAttach)
{
val = FLD_SET_DRF(_NVLSAW, _DRIVER_ATTACH_DETACH, _STATUS,
_ATTACHED, val);
}
else
{
val = FLD_SET_DRF(_NVLSAW, _DRIVER_ATTACH_DETACH, _STATUS,
_DETACHED, val);
}
NVSWITCH_SAW_WR32_LS10(device, _NVLSAW, _DRIVER_ATTACH_DETACH, val);
}
/*
* @Brief : Returns if SOE is attached to the Queues
*
* @param[in] device
*/
static NvBool
_nvswitch_is_soe_attached_ls10
(
nvswitch_device *device
)
{
NvU32 val;
NvBool bSoeAttached;
val = NVSWITCH_SAW_RD32_LS10(device, _NVLSAW, _SOE_ATTACH_DETACH);
bSoeAttached = FLD_TEST_DRF(_NVLSAW, _SOE_ATTACH_DETACH, _STATUS, _ATTACHED, val);
return bSoeAttached;
}
/*
* @Brief : Backup NPORT state and issue NPORT reset
*
* @param[in] device
* @param[in] nport
*/
NvlStatus
nvswitch_soe_issue_nport_reset_ls10
(
nvswitch_device *device,
NvU32 nport
)
{
FLCN *pFlcn = device->pSoe->pFlcn;
NvU32 cmdSeqDesc = 0;
NV_STATUS status;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
RM_SOE_CORE_CMD_NPORT_RESET *pNportReset;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_CORE;
cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, NPORT_RESET);
pNportReset = &cmd.cmd.core.nportReset;
pNportReset->nport = nport;
pNportReset->cmdType = RM_SOE_CORE_CMD_ISSUE_NPORT_RESET;
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg
NULL, // pPayload
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: Failed to send NPORT RESET command to SOE status 0x%x\n",
__FUNCTION__, status);
return -NVL_ERR_INVALID_STATE;
}
return NVL_SUCCESS;
}
/*
* @Brief : De-Assert NPORT reset and restore NPORT state
*
* @param[in] device
* @param[in] nport
*/
NvlStatus
nvswitch_soe_restore_nport_state_ls10
(
nvswitch_device *device,
NvU32 nport
)
{
FLCN *pFlcn = device->pSoe->pFlcn;
NvU32 cmdSeqDesc = 0;
NV_STATUS status;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
RM_SOE_CORE_CMD_NPORT_STATE *pNportState;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_CORE;
cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, NPORT_STATE);
pNportState = &cmd.cmd.core.nportState;
pNportState->nport = nport;
pNportState->cmdType = RM_SOE_CORE_CMD_RESTORE_NPORT_STATE;
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg
NULL, // pPayload
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: Failed to send NPORT BACKUP command to SOE status 0x%x\n",
__FUNCTION__, status);
return -NVL_ERR_INVALID_STATE;
}
return NVL_SUCCESS;
}
/*
* @Brief : Set NPORT TPROD state in SOE
*
* @param[in] device
* @param[in] nport
*/
NvlStatus
nvswitch_set_nport_tprod_state_ls10
(
nvswitch_device *device,
NvU32 nport
)
{
FLCN *pFlcn = device->pSoe->pFlcn;
NvU32 cmdSeqDesc = 0;
NV_STATUS status;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
RM_SOE_CORE_CMD_NPORT_TPROD_STATE *nportTprodState;
if (!NVSWITCH_ENG_IS_VALID(device, NPORT, nport))
{
NVSWITCH_PRINT(device, ERROR, "%s: NPORT #%d invalid\n",
__FUNCTION__, nport);
return -NVL_BAD_ARGS;
}
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_CORE;
cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, NPORT_TPROD_STATE);
nportTprodState = &cmd.cmd.core.nportTprodState;
nportTprodState->nport = nport;
nportTprodState->cmdType = RM_SOE_CORE_CMD_SET_NPORT_TPROD_STATE;
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg
NULL, // pPayload
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: Failed to send NPORT SET_TPROD_STATE command to SOE, status 0x%x\n",
__FUNCTION__, status);
return -NVL_ERR_INVALID_STATE;
}
return NVL_SUCCESS;
}
/*
* @Brief : INIT L2 register state in SOE
*
* @param[in] device
* @param[in] nport
*/
void
nvswitch_soe_init_l2_state_ls10
(
nvswitch_device *device
)
{
FLCN *pFlcn;
NvU32 cmdSeqDesc = 0;
NV_STATUS status;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
RM_SOE_CORE_CMD_L2_STATE *pL2State;
if (!nvswitch_is_soe_supported(device))
{
NVSWITCH_PRINT(device, INFO, "%s: SOE is not supported\n",
__FUNCTION__);
return;
}
pFlcn = device->pSoe->pFlcn;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_CORE;
cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, L2_STATE);
pL2State = &cmd.cmd.core.l2State;
pL2State->cmdType = RM_SOE_CORE_CMD_INIT_L2_STATE;
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg
NULL, // pPayload
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: Failed to send INIT_L2_STATE command to SOE, status 0x%x\n",
__FUNCTION__, status);
}
}
/*
* @Brief : Enable/Disable NPORT interrupts
*
* @param[in] device
* @param[in] nport
*/
NvlStatus
nvswitch_soe_set_nport_interrupts_ls10
(
nvswitch_device *device,
NvU32 nport,
NvBool bEnable
)
{
FLCN *pFlcn;
NvU32 cmdSeqDesc = 0;
NV_STATUS status;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
RM_SOE_CORE_CMD_NPORT_INTRS *pNportIntrs;
if (!nvswitch_is_soe_supported(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s: SOE is not supported\n",
__FUNCTION__);
return -NVL_ERR_INVALID_STATE;
}
pFlcn = device->pSoe->pFlcn;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_CORE;
cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, NPORT_INTRS);
pNportIntrs = &cmd.cmd.core.nportIntrs;
pNportIntrs->cmdType = RM_SOE_CORE_CMD_SET_NPORT_INTRS;
pNportIntrs->nport = nport;
pNportIntrs->bEnable = bEnable;
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg
NULL, // pPayload
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to send SET_NPORT_INTRS command to SOE, status 0x%x\n",
__FUNCTION__, status);
return -NVL_ERR_GENERIC;
}
return NVL_SUCCESS;
}
/*
* @Brief : Disable NPORT Fatal Interrupt in SOE
*
* @param[in] device
* @param[in] nport
* @param[in] nportIntrEnable
* @param[in] nportIntrType
*/
void
nvswitch_soe_disable_nport_fatal_interrupts_ls10
(
nvswitch_device *device,
NvU32 nport,
NvU32 nportIntrEnable,
NvU8 nportIntrType
)
{
FLCN *pFlcn;
NvU32 cmdSeqDesc = 0;
NV_STATUS status;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
RM_SOE_CORE_CMD_NPORT_FATAL_INTR *pNportIntrDisable;
NVSWITCH_GET_BIOS_INFO_PARAMS p = { 0 };
NvlStatus stat;
stat = device->hal.nvswitch_ctrl_get_bios_info(device, &p);
if ((stat != NVL_SUCCESS) || ((p.version & SOE_VBIOS_VERSION_MASK) <
SOE_VBIOS_REVLOCK_DISABLE_NPORT_FATAL_INTR))
{
NVSWITCH_PRINT(device, ERROR,
"%s: Skipping DISABLE_NPORT_FATAL_INTR command to SOE. Update firmware "
"from .%02X to .%02X\n",
__FUNCTION__, (NvU32)((p.version & SOE_VBIOS_VERSION_MASK) >> 16),
SOE_VBIOS_REVLOCK_DISABLE_NPORT_FATAL_INTR);
return;
}
if (!nvswitch_is_soe_supported(device))
{
NVSWITCH_PRINT(device, INFO, "%s: SOE is not supported\n",
__FUNCTION__);
return;
}
pFlcn = device->pSoe->pFlcn;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_CORE;
cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, NPORT_FATAL_INTR);
pNportIntrDisable = &cmd.cmd.core.nportDisableIntr;
pNportIntrDisable->cmdType = RM_SOE_CORE_CMD_DISABLE_NPORT_FATAL_INTR;
pNportIntrDisable->nport = nport;
pNportIntrDisable->nportIntrEnable = nportIntrEnable;
pNportIntrDisable->nportIntrType = nportIntrType;
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg
NULL, // pPayload
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: Failed to send DISABLE_NPORT_FATAL_INTR command to SOE, status 0x%x\n",
__FUNCTION__, status);
}
}
/*
* @Brief : Init sequence for SOE FSP RISCV image
*
* The driver assumes SOE is already booted by FSP.
* Driver checks for SOE state and handshakes with a test command.
* If FSP or SOE fails to boot, driver fails and quits.
*
* @param[in] nvswitch device
*/
NvlStatus
nvswitch_init_soe_ls10
(
nvswitch_device *device
)
{
NvlStatus status;
NvU32 data;
FLCN *pFlcn = device->pSoe->pFlcn;
//
// Check if SOE has halted unexpectedly.
//
// The explicit check is required because the interrupts
// are not yet enabled as the device is still initializing.
//
if (soeIsCpuHalted_HAL(device, ((PSOE)pFlcn->pFlcnable)))
{
NVSWITCH_PRINT(device, ERROR,
"%s: SOE halted\n",
__FUNCTION__);
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP,
"SOE init Failed(0)\n");
status = -NVL_ERR_INVALID_STATE;
goto nvswitch_init_soe_fail;
}
// Check for SOE BOOT SUCCESS
data = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_MAILBOX1);
if (data != SOE_BOOTSTRAP_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: SOE boot failed\n",
__FUNCTION__);
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP,
"SOE init failed(1)\n");
status = -NVL_ERR_INVALID_STATE;
goto nvswitch_init_soe_fail;
}
// Register SOE callbacks
status = nvswitch_soe_register_event_callbacks(device);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_COMMAND_QUEUE,
"Failed to register SOE events\n");
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP,
"SOE init failed(2)\n");
return status;
}
// Sanity the command and message queues as a final check
if (_nvswitch_soe_send_test_cmd(device) != NV_OK)
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP,
"SOE init failed(4)\n");
status = -NVL_ERR_INVALID_STATE;
goto nvswitch_init_soe_fail;
}
NVSWITCH_PRINT(device, SETUP,
"%s: SOE successfully bootstrapped.\n",
__FUNCTION__);
return NVL_SUCCESS;
nvswitch_init_soe_fail :
// Log any failures SOE may have had during bootstrap
(void)soeService_HAL(device, ((PSOE)pFlcn->pFlcnable));
#if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
dumpDebugRegisters(device);
#endif // defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
flcnDbgInfoCapturePcTrace_HAL(device, pFlcn);
NVSWITCH_ASSERT(0);
return status;
}
/*
* @Brief : Shutdown SOE during driver unload
*
* @param[in] device Bootstrap SOE on this device
*/
NvlStatus
nvswitch_unload_soe_ls10
(
nvswitch_device *device
)
{
// Detach driver from SOE Queues
_nvswitch_soe_attach_detach_driver_ls10(device, NV_FALSE);
return NVL_SUCCESS;
}
/*!
* @brief : Register callback functions for events and messages from SOE
*
* @param[in] device nvswitch_device pointer
*/
NvlStatus
nvswitch_soe_register_event_callbacks_ls10
(
nvswitch_device *device
)
{
NV_STATUS status;
PFLCN pFlcn = device->pSoe->pFlcn;
PSOE pSoe = (PSOE)device->pSoe;
// Register Thermal callback funcion
status = flcnQueueEventRegister(
device, pFlcn,
RM_SOE_UNIT_THERM,
NULL,
nvswitch_therm_soe_callback_ls10,
NULL,
&pSoe->thermEvtDesc);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to register thermal event handler.\n",
__FUNCTION__);
return -NVL_ERR_INVALID_STATE;
}
return NVL_SUCCESS;
}
void
nvswitch_soe_unregister_events_ls10
(
nvswitch_device *device
)
{
PFLCN pFlcn = device->pSoe->pFlcn;
PSOE pSoe = (PSOE)device->pSoe;
NV_STATUS status;
// un-register thermal callback funcion
status = flcnQueueEventUnregister(device, pFlcn,
pSoe->thermEvtDesc);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to un-register thermal event handler.\n",
__FUNCTION__);
}
}
/*!
* @brief Determine if the SOE RISCV CPU is halted
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE pointer
*
* @return NvBool reflecting the SOE Riscv CPU halted state
*/
static NvBool
_soeIsCpuHalted_LS10
(
nvswitch_device *device,
PSOE pSoe
)
{
NvU32 data;
data = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_RISCV, _CPUCTL);
return FLD_TEST_DRF(_PFALCON, _FALCON_CPUCTL, _HALTED, _TRUE, data);
}
static NvU32
_soeIntrStatus_LS10
(
nvswitch_device *device
)
{
NvU32 irq, mask, dest;
irq = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_FALCON, _IRQSTAT);
mask = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_RISCV, _IRQMASK);
dest = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_RISCV, _IRQDEST);
return (irq & mask & dest);
}
/*!
* @brief Top level service routine
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE pointer
*
* @return 32-bit interrupt status AFTER all known interrupt-sources were
* serviced.
*/
static NvU32
_soeService_LS10
(
nvswitch_device *device,
PSOE pSoe
)
{
NvBool bRecheckMsgQ = NV_FALSE;
NvBool bRecheckPrintQ = NV_FALSE;
NvU32 clearBits = 0;
NvU32 intrStatus;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
if (pFlcn == NULL)
{
NVSWITCH_ASSERT(0);
return NV_ERR_INVALID_ARGUMENT;
}
// Get the IRQ status and mask the sources not directed to host.
intrStatus = _soeIntrStatus_LS10(device);
// Exit if there is nothing to do
if (intrStatus == 0)
{
return 0;
}
// Service pending interrupts
if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _WDTMR, _TRUE))
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_WATCHDOG,
"SOE Watchdog error\n");
NVSWITCH_PRINT(device, INFO,
"%s: Watchdog timer fired. We do not support this "
"yet.\n", __FUNCTION__);
NVSWITCH_ASSERT(0);
clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _WDTMR, _SET);
}
if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _EXTERR, _TRUE))
{
clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _EXTERR, _SET);
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_EXTERR, "SOE EXTERR\n");
}
if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _HALT, _TRUE))
{
clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _HALT, _SET);
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_HALT, "SOE HALTED\n");
soeServiceHalt_HAL(device, pSoe);
}
if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _SWGEN0, _TRUE))
{
clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _SWGEN0, _SET);
NVSWITCH_PRINT(device, MMIO,
"%s: Received a message from SOE via SWGEN0\n",
__FUNCTION__);
soeProcessMessages_HAL(device, pSoe);
bRecheckMsgQ = NV_TRUE;
}
if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _SWGEN1, _TRUE))
{
clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _SWGEN1, _SET);
NVSWITCH_PRINT(device, INFO,
"%s: Received a SWGEN1 interrupt\n",
__FUNCTION__);
flcnDebugBufferDisplay_HAL(device, pFlcn);
bRecheckPrintQ = NV_TRUE;
}
// Clear any sources that were serviced and get the new status.
flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSCLR, clearBits);
// Re-read interrupt status before retriggering to return correct value
intrStatus = _soeIntrStatus_LS10(device);
//
// If we just processed a SWGEN0 message queue interrupt, peek
// into the message queue and see if any messages were missed the last time
// the queue was purged (above). If it is not empty, re-generate SWGEN0
// (since it is now cleared) and exit. As long as an interrupt is pending,
// this function will be re-entered and the message(s) will be processed.
//
if (bRecheckMsgQ)
{
PFALCON_QUEUE_INFO pQueueInfo;
FLCNQUEUE *pMsgQ;
pQueueInfo = pFlcn->pQueueInfo;
NVSWITCH_ASSERT(pQueueInfo != NULL);
NVSWITCH_ASSERT(pQueueInfo->pQueues != NULL);
pMsgQ = &pQueueInfo->pQueues[SOE_RM_MSGQ_LOG_ID];
if (!pMsgQ->isEmpty(device, pFlcn, pMsgQ))
{
// It is not necessary to RMW IRQSSET (zeros are ignored)
flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSSET,
DRF_DEF(_PFALCON, _FALCON_IRQSSET, _SWGEN0, _SET));
}
}
//
// If we just processed a SWGEN1 interrupt (Debug Buffer interrupt), peek
// into the Debug Buffer and see if any text was missed the last time
// the buffer was displayed (above). If it is not empty, re-generate SWGEN1
// (since it is now cleared) and exit. As long as an interrupt is pending,
// this function will be re-entered and the message(s) will be processed.
//
if (bRecheckPrintQ)
{
if (!flcnDebugBufferIsEmpty_HAL(device, pFlcn))
{
flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSSET,
DRF_DEF(_PFALCON, _FALCON_IRQSSET, _SWGEN1, _SET));
}
}
flcnIntrRetrigger_HAL(device, pFlcn);
return intrStatus;
}
/*!
* Called by soeService to handle a SOE halt. This function will dump the
* current status of SOE and then trap the CPU for further inspection for a
* debug build.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
*/
static void
_soeServiceHalt_LS10
(
nvswitch_device *device,
PSOE pSoe
)
{
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
NVSWITCH_PRINT(device, ERROR,
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
"!! ** SOE HALTED ** !!\n"
"!! Please file a bug with the following information. !!\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n");
#if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
dumpDebugRegisters(device);
#endif // defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
flcnDbgInfoCaptureRiscvPcTrace_HAL(device, pFlcn);
NVSWITCH_ASSERT(0);
}
/*!
* Use the SOE INIT Message to construct, initialize or update SOE Queues.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
*
* @return 'NV_OK' upon successful creation of all SOE Queues
*/
static NV_STATUS
_soeUpdateInitMsgQueuesInfo
(
nvswitch_device *device,
PSOE pSoe
)
{
FLCNQUEUE *pQueue;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
PFALCON_QUEUE_INFO pQueueInfo;
NvU32 queueOffset;
NvU16 queueSize;
NvU8 queuePhyId;
NvU8 queueLogId;
NV_STATUS status;
//
// No command should be longer than half the queue size.
// See _soeQueueCmdValidate_IMPL().
//
ct_assert(sizeof(RM_FLCN_CMD_SOE) <= (SOE_CMD_QUEUE_LENGTH / 2));
NVSWITCH_ASSERT(pFlcn != NULL);
pQueueInfo = pFlcn->pQueueInfo;
NVSWITCH_ASSERT(pQueueInfo != NULL);
// Construct DMEM for CMDQ
queueOffset = SOE_EMEM_CHANNEL_CMDQ_OFFSET;
queueSize = SOE_CMD_QUEUE_LENGTH;
queuePhyId = 0;
queueLogId = SOE_RM_CMDQ_LOG_ID;
pQueue = &pQueueInfo->pQueues[queueLogId];
status = flcnQueueConstruct_dmem_nvswitch(
device,
pFlcn,
&pQueue, // ppQueue
queueLogId, // Logical ID of the queue
queuePhyId, // Physical ID of the queue
queueOffset, // offset
queueSize, // size
RM_FLCN_QUEUE_HDR_SIZE); // cmdHdrSize
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Error constructing SOE CmdQueue (status="
"0x%08x).\n", __FUNCTION__, status);
NVSWITCH_ASSERT(0);
return status;
}
// Construct DMEM for MSGQ
queueOffset = SOE_EMEM_CHANNEL_MSGQ_OFFSET;
queueSize = SOE_MSG_QUEUE_LENGTH;
queuePhyId = 0;
queueLogId = SOE_RM_MSGQ_LOG_ID;
pQueue = &pQueueInfo->pQueues[queueLogId];
status = flcnQueueConstruct_dmem_nvswitch(
device,
pFlcn,
&pQueue, // ppQueue
queueLogId, // Logical ID of the queue
queuePhyId, // Physical ID of the queue
queueOffset, // offset
queueSize, // size
RM_FLCN_QUEUE_HDR_SIZE); // cmdHdrSize
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Error constructing SOE MsgQueue (status="
"0x%08x).\n", __FUNCTION__, status);
NVSWITCH_ASSERT(0);
return status;
}
pFlcn->bOSReady = NV_TRUE;
return NV_OK;
}
static NV_STATUS
_soeWaitForInitAck_LS10
(
nvswitch_device *device,
PSOE pSoe
)
{
NV_STATUS status;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
if (!_nvswitch_is_soe_attached_ls10(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s SOE is not to attached!\n",
__FUNCTION__);
NVSWITCH_ASSERT(0);
return NV_ERR_NOT_READY;
}
// Update InitMsg Queue info before sending any commands
if (!pFlcn->bOSReady)
{
status = _soeUpdateInitMsgQueuesInfo(device, pSoe);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s Failed to attach driver!\n",
__FUNCTION__);
NVSWITCH_ASSERT(0);
return status;
}
// Attach driver to SOE Queues
_nvswitch_soe_attach_detach_driver_ls10(device, NV_TRUE);
}
return NV_OK;
}
/*!
* Purges all the messages from the SOE's message queue. Each message will
* be analyzed, clients will be notified of status, and events will be routed
* to all registered event listeners.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
*
* @return 'NV_OK' if the message queue was successfully purged.
*/
static NV_STATUS
_soeProcessMessages_LS10
(
nvswitch_device *device,
PSOE pSoe
)
{
RM_FLCN_MSG_SOE soeMessage;
NV_STATUS status;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
// Update InitMsg Queue info before recieving any messages
if (!pFlcn->bOSReady)
{
status = _soeUpdateInitMsgQueuesInfo(device, pSoe);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s Failed to attach driver!\n",
__FUNCTION__);
NVSWITCH_ASSERT(0);
return status;
}
// Attach driver to SOE Queues
_nvswitch_soe_attach_detach_driver_ls10(device, NV_TRUE);
}
// keep processing messages until no more exist in the message queue
while (NV_OK == (status = flcnQueueReadData(
device,
pFlcn,
SOE_RM_MSGQ_LOG_ID,
(RM_FLCN_MSG *)&soeMessage, NV_TRUE)))
{
NVSWITCH_PRINT(device, MMIO,
"%s: unitId=0x%02x, size=0x%02x, ctrlFlags=0x%02x, " \
"seqNumId=0x%02x\n",
__FUNCTION__,
soeMessage.hdr.unitId,
soeMessage.hdr.size,
soeMessage.hdr.ctrlFlags,
soeMessage.hdr.seqNumId);
// check to see if the message is a reply or an event.
if ((soeMessage.hdr.ctrlFlags &= RM_FLCN_QUEUE_HDR_FLAGS_EVENT) != 0)
{
flcnQueueEventHandle(device, pFlcn, (RM_FLCN_MSG *)&soeMessage, NV_OK);
}
// the message is a response from a previously queued command
else
{
flcnQueueResponseHandle(device, pFlcn, (RM_FLCN_MSG *)&soeMessage);
}
}
//
// Status NV_ERR_NOT_READY implies, Queue is empty.
// Log the message in other error cases.
//
if (status != NV_ERR_NOT_READY)
{
NVSWITCH_PRINT(device, ERROR,
"%s: unexpected error while purging message queue (status=0x%x).\n",
__FUNCTION__, (status));
}
return status;
}
static NV_STATUS
_soeHandleInitEvent_LS10
(
nvswitch_device *device,
PFLCNABLE pSoe,
RM_FLCN_MSG *pGenMsg
)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Init handle event not Supported!\n",
__FUNCTION__);
NVSWITCH_ASSERT(0);
return NV_ERR_GENERIC;
}
static NvlStatus
_soeI2CAccessSend
(
nvswitch_device *device,
void *cpuAddr,
NvU64 dmaHandle,
NvU16 xferSize
)
{
FLCN *pFlcn = device->pSoe->pFlcn;
NvU32 cmdSeqDesc;
NV_STATUS status;
RM_FLCN_CMD_SOE cmd;
RM_SOE_CORE_CMD_I2C *pI2cCmd;
NVSWITCH_TIMEOUT timeout;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_CORE;
cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, I2C);
pI2cCmd = &cmd.cmd.core.i2c;
RM_FLCN_U64_PACK(&pI2cCmd->dmaHandle, &dmaHandle);
pI2cCmd->xferSize = xferSize;
pI2cCmd->cmdType = RM_SOE_CORE_CMD_I2C_ACCESS;
cmdSeqDesc = 0;
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS * 5, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg
NULL, // pPayload
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: Failed to send I2C command to SOE status 0x%x\n",
__FUNCTION__, status);
return -NVL_ERR_INVALID_STATE;
}
return NVL_SUCCESS;
}
static NvlStatus
_soeI2cFlcnStatusToNvlStatus
(
NvU8 flcnStatus
)
{
switch (flcnStatus)
{
case FLCN_OK:
return NVL_SUCCESS;
case FLCN_ERR_INVALID_ARGUMENT:
return -NVL_BAD_ARGS;
case FLCN_ERR_OBJECT_NOT_FOUND:
return -NVL_NOT_FOUND;
case FLCN_ERROR:
return -NVL_ERR_GENERIC;
case FLCN_ERR_INVALID_STATE:
return -NVL_ERR_INVALID_STATE;
case FLCN_ERR_MORE_PROCESSING_REQUIRED:
return -NVL_MORE_PROCESSING_REQUIRED;
case FLCN_ERR_TIMEOUT:
return -NVL_IO_ERROR;
case FLCN_ERR_I2C_BUSY:
return -NVL_ERR_STATE_IN_USE;
case FLCN_ERR_NOT_SUPPORTED:
return -NVL_ERR_NOT_SUPPORTED;
default:
return -NVL_ERR_GENERIC;
}
}
static NvlStatus
_soeI2CAccess_LS10
(
nvswitch_device *device,
NVSWITCH_CTRL_I2C_INDEXED_PARAMS *pParams
)
{
NvlStatus ret;
NvU8 flcnRet;
PNVSWITCH_OBJI2C pI2c;
void *pCpuAddr;
NvU64 dmaHandle;
if (pParams == NULL)
{
return -NVL_BAD_ARGS;
}
pI2c = device->pI2c;
if (pI2c == NULL || !pI2c->soeI2CSupported)
{
return -NVL_ERR_NOT_SUPPORTED;
}
pCpuAddr = pI2c->pCpuAddr;
dmaHandle = pI2c->dmaHandle;
ret = nvswitch_os_sync_dma_region_for_cpu(device->os_handle, dmaHandle,
SOE_I2C_DMA_BUF_SIZE,
NVSWITCH_DMA_DIR_FROM_SYSMEM);
if (ret != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_sync_dma_region_for_cpu returned %d\n",
__FUNCTION__, ret);
return ret;
}
// Required for error reporting from SOE to driver
ct_assert(sizeof(NVSWITCH_CTRL_I2C_INDEXED_PARAMS) < SOE_I2C_STATUS_INDEX);
// Copy I2C struct into buffer
nvswitch_os_memcpy(pCpuAddr, pParams, sizeof(NVSWITCH_CTRL_I2C_INDEXED_PARAMS));
ret = nvswitch_os_sync_dma_region_for_device(device->os_handle, dmaHandle,
SOE_I2C_DMA_BUF_SIZE,
NVSWITCH_DMA_DIR_FROM_SYSMEM);
if (ret != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_sync_dma_region_for_device returned %d\n",
__FUNCTION__, ret);
return ret;
}
// Send I2C access command to SOE
ret = _soeI2CAccessSend(device, pCpuAddr, dmaHandle, SOE_I2C_DMA_BUF_SIZE);
if (ret != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "%s: _soeI2CAccessSend returned %d\n",
__FUNCTION__, ret);
return ret;
}
// Get result
ret = nvswitch_os_sync_dma_region_for_cpu(device->os_handle, dmaHandle,
SOE_I2C_DMA_BUF_SIZE,
NVSWITCH_DMA_DIR_TO_SYSMEM);
if (ret != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_sync_dma_region_for_cpu returned %d\n",
__FUNCTION__, ret);
return ret;
}
nvswitch_os_memcpy(pParams, pCpuAddr, sizeof(NVSWITCH_CTRL_I2C_INDEXED_PARAMS));
// Return value of the I2C operation that was performed in SOE
flcnRet = ((NvU8*)pCpuAddr)[SOE_I2C_STATUS_INDEX];
ret = _soeI2cFlcnStatusToNvlStatus(flcnRet);
return ret;
}
/**
* @brief set hal function pointers for functions defined in LR10 (i.e. this file)
*
* this function has to be at the end of the file so that all the
* other functions are already defined.
*
* @param[in] pFlcnable The flcnable for which to set hals
*/
void
soeSetupHal_LS10
(
SOE *pSoe
)
{
soe_hal *pHal = pSoe->base.pHal;
flcnable_hal *pParentHal = (flcnable_hal *)pHal;
soeSetupHal_LR10(pSoe);
pParentHal->fetchEngines = _soeFetchEngines_LS10;
pParentHal->handleInitEvent = _soeHandleInitEvent_LS10;
pHal->isCpuHalted = _soeIsCpuHalted_LS10;
pHal->service = _soeService_LS10;
pHal->serviceHalt = _soeServiceHalt_LS10;
pHal->processMessages = _soeProcessMessages_LS10;
pHal->waitForInitAck = _soeWaitForInitAck_LS10;
pHal->i2cAccess = _soeI2CAccess_LS10;
}