mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-03-03 04:09:50 +00:00
525.53
This commit is contained in:
195
src/common/nvswitch/kernel/ls10/clock_ls10.c
Normal file
195
src/common/nvswitch/kernel/ls10/clock_ls10.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2020-2021 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 "common_nvswitch.h"
|
||||
#include "ls10/ls10.h"
|
||||
#include "ls10/clock_ls10.h"
|
||||
|
||||
#include "nvswitch/ls10/dev_trim.h"
|
||||
#include "nvswitch/ls10/dev_soe_ip.h"
|
||||
#include "nvswitch/ls10/dev_npgperf_ip.h"
|
||||
#include "nvswitch/ls10/dev_nvlw_ip.h"
|
||||
#include "nvswitch/ls10/dev_nport_ip.h"
|
||||
#include "nvswitch/ls10/dev_minion_ip.h"
|
||||
#include "nvswitch/ls10/dev_timer_ip.h"
|
||||
#include "nvswitch/ls10/dev_minion_ip.h"
|
||||
#include "nvswitch/ls10/dev_pri_hub_prt_ip.h"
|
||||
#include "nvswitch/ls10/dev_pri_masterstation_ip.h"
|
||||
|
||||
//
|
||||
// Initialize the software state of the switch PLL
|
||||
//
|
||||
NvlStatus
|
||||
nvswitch_init_pll_config_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
NVSWITCH_PLL_LIMITS pll_limits;
|
||||
NVSWITCH_PLL_INFO pll;
|
||||
NvlStatus retval = NVL_SUCCESS;
|
||||
|
||||
//
|
||||
// These parameters could come from schmoo'ing API, settings file or a ROM.
|
||||
// If no configuration ROM settings are present, use the PLL documentation
|
||||
//
|
||||
// PLL40G_SMALL_ESD.doc
|
||||
//
|
||||
|
||||
pll_limits.ref_min_mhz = 100;
|
||||
pll_limits.ref_max_mhz = 100;
|
||||
pll_limits.vco_min_mhz = 1750;
|
||||
pll_limits.vco_max_mhz = 3800;
|
||||
pll_limits.update_min_mhz = 13; // 13.5MHz
|
||||
pll_limits.update_max_mhz = 38; // 38.4MHz
|
||||
|
||||
pll_limits.m_min = NV_CLOCK_NVSW_SYS_SWITCHPLL_COEFF_MDIV_MIN;
|
||||
pll_limits.m_max = NV_CLOCK_NVSW_SYS_SWITCHPLL_COEFF_MDIV_MAX;
|
||||
pll_limits.n_min = NV_CLOCK_NVSW_SYS_SWITCHPLL_COEFF_NDIV_MIN;
|
||||
pll_limits.n_max = NV_CLOCK_NVSW_SYS_SWITCHPLL_COEFF_NDIV_MAX;
|
||||
pll_limits.pl_min = NV_CLOCK_NVSW_SYS_SWITCHPLL_COEFF_PLDIV_MIN;
|
||||
pll_limits.pl_max = NV_CLOCK_NVSW_SYS_SWITCHPLL_COEFF_PLDIV_MAX;
|
||||
pll_limits.valid = NV_TRUE;
|
||||
|
||||
//
|
||||
// set well known coefficients to achieve frequency
|
||||
//
|
||||
|
||||
pll.src_freq_khz = 100000; // 100MHz
|
||||
pll.M = 3;
|
||||
pll.N = 80;
|
||||
pll.PL = 2;
|
||||
pll.dist_mode = 0; // Ignored. Only 1x supported
|
||||
pll.refclk_div = NV_CLOCK_NVSW_SYS_RX_BYPASS_REFCLK_DIV_INIT;
|
||||
|
||||
retval = nvswitch_validate_pll_config(device, &pll, pll_limits);
|
||||
if (retval != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, WARN,
|
||||
"Selecting default PLL setting.\n");
|
||||
|
||||
// Select default, safe clock
|
||||
pll.src_freq_khz = 100000; // 100MHz
|
||||
pll.M = 3;
|
||||
pll.N = 80;
|
||||
pll.PL = 2;
|
||||
pll.dist_mode = 0; // Ignored. Only 1x supported
|
||||
pll.refclk_div = NV_CLOCK_NVSW_SYS_RX_BYPASS_REFCLK_DIV_INIT;
|
||||
|
||||
retval = nvswitch_validate_pll_config(device, &pll, pll_limits);
|
||||
if (retval != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"Default PLL setting failed.\n");
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
device->switch_pll = pll;
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Check that the PLLs are initialized. VBIOS is expected to configure PLLs
|
||||
//
|
||||
NvlStatus
|
||||
nvswitch_init_pll_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
NvU32 pllRegVal;
|
||||
|
||||
//
|
||||
// Clocks should only be initialized on silicon or a clocks netlist on emulation
|
||||
//
|
||||
if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
|
||||
{
|
||||
NVSWITCH_PRINT(device, WARN,
|
||||
"%s: Skipping setup of NVSwitch clocks\n",
|
||||
__FUNCTION__);
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
pllRegVal = NVSWITCH_ENG_RD32(device, CLKS_SYS, , 0, _CLOCK_NVSW_SYS, _SWITCHPLL_CFG);
|
||||
if (!FLD_TEST_DRF(_CLOCK_NVSW_SYS, _SWITCHPLL_CFG, _PLL_LOCK, _TRUE, pllRegVal))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: _PLL_LOCK failed\n",
|
||||
__FUNCTION__);
|
||||
return -NVL_INITIALIZATION_TOTAL_FAILURE;
|
||||
}
|
||||
|
||||
pllRegVal = NVSWITCH_ENG_RD32(device, CLKS_SYS, , 0, _CLOCK_NVSW_SYS, _SWITCHPLL_CTRL);
|
||||
if (!FLD_TEST_DRF_NUM(_CLOCK_NVSW_SYS, _SWITCHPLL_CTRL, _PLL_FREQLOCK, 1, pllRegVal))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: _PLL_FREQLOCK failed\n",
|
||||
__FUNCTION__);
|
||||
return -NVL_INITIALIZATION_TOTAL_FAILURE;
|
||||
}
|
||||
|
||||
pllRegVal = NVSWITCH_ENG_RD32(device, CLKS_SYS, , 0, _CLOCK_NVSW_SYS, _SWITCHCLK_SWITCH_DIVIDER);
|
||||
if (!FLD_TEST_DRF_NUM(_CLOCK_NVSW_SYS, _SWITCHCLK_SWITCH_DIVIDER, _SWITCH_DIVIDER_DONE, 1, pllRegVal))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: _SWITCH_DIVIDER_DONE failed\n",
|
||||
__FUNCTION__);
|
||||
return -NVL_INITIALIZATION_TOTAL_FAILURE;
|
||||
}
|
||||
|
||||
pllRegVal = NVSWITCH_ENG_RD32(device, CLKS_SYS, , 0, _CLOCK_NVSW_SYS, _SYSTEM_CLK_SWITCH_DIVIDER);
|
||||
if (!FLD_TEST_DRF_NUM(_CLOCK_NVSW_SYS, _SYSTEM_CLK_SWITCH_DIVIDER, _SWITCH_DIVIDER_DONE, 1, pllRegVal))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: _SWITCH_DIVIDER_DONE for SYSTEMCLK failed\n",
|
||||
__FUNCTION__);
|
||||
return -NVL_INITIALIZATION_TOTAL_FAILURE;
|
||||
}
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize clock gating.
|
||||
//
|
||||
void
|
||||
nvswitch_init_clock_gating_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
//
|
||||
// CG and PROD settings were already handled by:
|
||||
// - nvswitch_nvs_top_prod_ls10
|
||||
// - nvswitch_npg_prod_ls10
|
||||
// - nvswitch_apply_prod_nvlw_ls10
|
||||
// - nvswitch_apply_prod_nxbar_ls10
|
||||
//
|
||||
// which were all called by nvswitch_initialize_ip_wrappers_ls10
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
1391
src/common/nvswitch/kernel/ls10/discovery_ls10.c
Normal file
1391
src/common/nvswitch/kernel/ls10/discovery_ls10.c
Normal file
File diff suppressed because it is too large
Load Diff
376
src/common/nvswitch/kernel/ls10/flcn_ls10.c
Normal file
376
src/common/nvswitch/kernel/ls10/flcn_ls10.c
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* 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 "common_nvswitch.h"
|
||||
#include "ls10/ls10.h"
|
||||
#include "flcn/flcn_nvswitch.h"
|
||||
|
||||
#include "nvswitch/ls10/dev_falcon_v4.h"
|
||||
#include "nvswitch/ls10/dev_riscv_pri.h"
|
||||
|
||||
//
|
||||
// Functions shared with LR10
|
||||
//
|
||||
|
||||
void flcnSetupHal_LR10(PFLCN pFlcn);
|
||||
|
||||
static NvU32
|
||||
_flcnRiscvRegRead_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn,
|
||||
NvU32 offset
|
||||
)
|
||||
{
|
||||
// Probably should perform some checks on the offset, the device, and the engine descriptor
|
||||
return nvswitch_reg_read_32(device, NV_FALCON2_SOE_BASE + offset);
|
||||
}
|
||||
|
||||
static void
|
||||
_flcnRiscvRegWrite_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn,
|
||||
NvU32 offset,
|
||||
NvU32 data
|
||||
)
|
||||
{
|
||||
// Probably should perform some checks on the offset, the device, and the engine descriptor
|
||||
nvswitch_reg_write_32(device, NV_FALCON2_SOE_BASE + offset, data);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the size of the falcon data memory.
|
||||
*
|
||||
* @param[in] pGpu OBJGPU pointer
|
||||
* @param[in] pFlcn Falcon object pointer
|
||||
* @param[in] bFalconReachable If set, returns size that can be reached by Falcon
|
||||
*
|
||||
* @return IMEM size in bytes
|
||||
*/
|
||||
static NvU32
|
||||
_flcnDmemSize_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn
|
||||
)
|
||||
{
|
||||
NvU32 data = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_HWCFG3);
|
||||
return (DRF_VAL(_PFALCON, _FALCON_HWCFG3, _DMEM_TOTAL_SIZE, data) <<
|
||||
FALCON_DMEM_BLKSIZE2);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Get the destination after masking
|
||||
* off all but the OFFSET and BLOCK in IMEM
|
||||
*
|
||||
* @param[in] dst Destination in IMEM
|
||||
*
|
||||
* @returns dst with only OFFSET and BLOCK bits set
|
||||
*/
|
||||
static NvU32
|
||||
_flcnSetImemAddr_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn,
|
||||
NvU32 dst
|
||||
)
|
||||
{
|
||||
NVSWITCH_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
*
|
||||
* @brief Copy contents of pSrc to IMEM
|
||||
*
|
||||
* @param[in] pGpu OBJGPU pointer
|
||||
* @param[in] pFlcn Falcon object pointer
|
||||
* @param[in] dst Destination in IMEM
|
||||
* @param[in] pSrc IMEM contents
|
||||
* @param[in] sizeInBytes Total IMEM size in bytes
|
||||
* @param[in] bSecure NV_TRUE if IMEM is signed
|
||||
* @param[in] tag IMEM tag
|
||||
* @param[in] port PMB port to copy IMEM
|
||||
*
|
||||
* @returns void
|
||||
*/
|
||||
static void
|
||||
_flcnImemCopyTo_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn,
|
||||
NvU32 dst,
|
||||
NvU8 *pSrc,
|
||||
NvU32 sizeBytes,
|
||||
NvBool bSecure,
|
||||
NvU32 tag,
|
||||
NvU8 port
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
*
|
||||
* @brief Mask the DMEM destination to have only the BLK and OFFSET bits set
|
||||
*
|
||||
* @param[in] dst Destination in DMEM
|
||||
*
|
||||
* @returns masked destination value in DMEM
|
||||
*/
|
||||
|
||||
static NvU32
|
||||
_flcnSetDmemAddr_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn,
|
||||
NvU32 dst
|
||||
)
|
||||
{
|
||||
return (dst & (DRF_SHIFTMASK(NV_PFALCON_FALCON_DMEMC_OFFS) |
|
||||
DRF_SHIFTMASK(NV_PFALCON_FALCON_DMEMC_BLK)));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Depending on the direction of the copy, copies 'sizeBytes' to/from 'pBuf'
|
||||
* from/to DMEM offset 'dmemAddr' using DMEM access port 'port'.
|
||||
*
|
||||
* @param[in] pGpu GPU object pointer
|
||||
* @param[in] pFlcn Falcon object pointer
|
||||
* @param[in] dmemAddr The DMEM offset for the copy
|
||||
* @param[in] pBuf The pointer to the buffer containing the data to copy
|
||||
* @param[in] sizeBytes The number of bytes to copy
|
||||
* @param[in] port The DMEM port index to use when accessing DMEM
|
||||
* @param[in] bCopyFrom Boolean representing the copy direction (to/from DMEM)
|
||||
*
|
||||
* @return NV_OK if the data was successfully copied
|
||||
* NV_ERR_INVALID_ARGUMENT if the input argument(s) is/are invalid
|
||||
*/
|
||||
static NV_STATUS
|
||||
_flcnDmemTransfer_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn,
|
||||
NvU32 dmemAddr,
|
||||
NvU8 *pBuf,
|
||||
NvU32 sizeBytes,
|
||||
NvU8 port,
|
||||
NvBool bCopyFrom
|
||||
)
|
||||
{
|
||||
NvU32 numWords;
|
||||
NvU32 numBytes;
|
||||
NvU32 *pData = (NvU32 *)pBuf;
|
||||
NvU32 reg32;
|
||||
NvU32 i;
|
||||
|
||||
// simply return if the copy-size is zero
|
||||
if (sizeBytes == 0)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Zero-byte copy requested\n");
|
||||
NVSWITCH_ASSERT(0);
|
||||
return -NVL_BAD_ARGS;
|
||||
}
|
||||
|
||||
// the DMEM address must be 4-byte aligned
|
||||
if (!NV_IS_ALIGNED(dmemAddr, FLCN_DMEM_ACCESS_ALIGNMENT))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Source not 4-byte aligned. dmemAddr=0x%08x\n", dmemAddr);
|
||||
NVSWITCH_ASSERT(0);
|
||||
return -NVL_BAD_ARGS;
|
||||
}
|
||||
|
||||
// calculate the number of words and bytes
|
||||
numWords = sizeBytes >> 2;
|
||||
numBytes = sizeBytes & NVSWITCH_MASK_BITS(2);
|
||||
|
||||
// mask off all but the OFFSET and BLOCK in DMEM offset
|
||||
reg32 = flcnSetDmemAddr_HAL(device, pFlcn, dmemAddr);
|
||||
|
||||
if (bCopyFrom)
|
||||
{
|
||||
// mark auto-increment on read
|
||||
reg32 = FLD_SET_DRF_NUM(_PFALCON, _FALCON_DMEMC, _AINCR, 0x1, reg32);
|
||||
}
|
||||
else
|
||||
{
|
||||
// mark auto-increment on write
|
||||
reg32 = FLD_SET_DRF_NUM(_PFALCON, _FALCON_DMEMC, _AINCW, 0x1, reg32);
|
||||
}
|
||||
|
||||
flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_DMEMC(port), reg32);
|
||||
|
||||
// directly copy as many words as possible
|
||||
for (i = 0; i < numWords; i++)
|
||||
{
|
||||
if (bCopyFrom)
|
||||
{
|
||||
pData[i] = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMEMD(port));
|
||||
}
|
||||
else
|
||||
{
|
||||
flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_DMEMD(port), pData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are left over bytes to copy
|
||||
if (numBytes > 0)
|
||||
{
|
||||
NvU32 bytesCopied = numWords << 2;
|
||||
|
||||
//
|
||||
// Read the contents first. If we're copying to the DMEM, we've set
|
||||
// autoincrement on write, so reading does not modify the pointer. We
|
||||
// can, thus, do a read/modify/write without needing to worry about the
|
||||
// pointer having moved forward. There is no special explanation needed
|
||||
// if we're copying from the DMEM since this is the last access to HW
|
||||
// in that case.
|
||||
//
|
||||
reg32 = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMEMD(port));
|
||||
|
||||
if (bCopyFrom)
|
||||
{
|
||||
// Copy byte-by-byte into the buffer as required
|
||||
for (i = 0; i < numBytes; i++)
|
||||
{
|
||||
pBuf[bytesCopied + i] = ((NvU8 *)®32)[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Modify what we read byte-by-byte before writing to dmem
|
||||
for (i = 0; i < numBytes; i++)
|
||||
{
|
||||
((NvU8 *)®32)[i] = pBuf[bytesCopied + i];
|
||||
}
|
||||
flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_DMEMD(port), reg32);
|
||||
}
|
||||
}
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_flcnDbgInfoCaptureRiscvPcTrace_LS10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
PFLCN pFlcn
|
||||
)
|
||||
{
|
||||
NvU32 ctl, ridx, widx, count, bufferSize;
|
||||
NvBool full;
|
||||
|
||||
flcnRiscvRegWrite_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACECTL,
|
||||
DRF_DEF(_PRISCV_RISCV, _TRACECTL, _MODE, _FULL) |
|
||||
DRF_DEF(_PRISCV_RISCV, _TRACECTL, _UMODE_ENABLE, _TRUE) |
|
||||
DRF_DEF(_PRISCV_RISCV, _TRACECTL, _MMODE_ENABLE, _TRUE) |
|
||||
DRF_DEF(_PRISCV_RISCV, _TRACECTL, _INTR_ENABLE, _FALSE) |
|
||||
DRF_DEF(_PRISCV_RISCV, _TRACECTL, _HIGH_THSHD, _INIT));
|
||||
|
||||
ctl = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACECTL);
|
||||
|
||||
full = FLD_TEST_DRF_NUM(_PRISCV_RISCV, _TRACECTL,_FULL, 1, ctl);
|
||||
|
||||
if (full)
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO, "%s: Trace buffer full. Entries may have been lost.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
// Reset and disable buffer, we don't need it during dump
|
||||
flcnRiscvRegWrite_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACECTL, 0);
|
||||
|
||||
widx = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACE_WTIDX);
|
||||
widx = DRF_VAL(_PRISCV_RISCV, _TRACE_WTIDX, _WTIDX, widx);
|
||||
|
||||
ridx = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACE_RDIDX);
|
||||
bufferSize = DRF_VAL(_PRISCV_RISCV, _TRACE_RDIDX, _MAXIDX, ridx);
|
||||
ridx = DRF_VAL(_PRISCV_RISCV, _TRACE_RDIDX, _RDIDX, ridx);
|
||||
|
||||
count = widx > ridx ? widx - ridx : bufferSize + widx - ridx;
|
||||
|
||||
//
|
||||
// Trace buffer is full when write idx == read idx and full is set,
|
||||
// otherwise it is empty.
|
||||
//
|
||||
if (widx == ridx && !full)
|
||||
count = 0;
|
||||
|
||||
if (count)
|
||||
{
|
||||
NvU32 entry;
|
||||
NVSWITCH_PRINT(device, INFO, "%s: Tracebuffer has %d entries. Starting with latest.\n", __FUNCTION__, count);
|
||||
ridx = widx;
|
||||
for (entry = 0; entry < count; ++entry)
|
||||
{
|
||||
NvU64 pc;
|
||||
|
||||
ridx = ridx > 0 ? ridx - 1 : bufferSize - 1;
|
||||
flcnRiscvRegWrite_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACE_RDIDX, DRF_NUM(_PRISCV_RISCV, _TRACE_RDIDX, _RDIDX, ridx));
|
||||
pc = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACEPC_HI);
|
||||
pc = (pc << 32) | flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACEPC_LO);
|
||||
NVSWITCH_PRINT(device, INFO, "%s: TRACE[%d] = 0x%16llx\n", __FUNCTION__, entry, pc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO, "%s: Trace buffer is empty.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
// reset trace buffer
|
||||
flcnRiscvRegWrite_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACE_RDIDX, 0);
|
||||
flcnRiscvRegWrite_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACE_WTIDX, 0);
|
||||
|
||||
// Clear full and empty bits
|
||||
ctl = FLD_SET_DRF_NUM(_PRISCV_RISCV, _TRACECTL, _FULL, 0, ctl);
|
||||
ctl = FLD_SET_DRF_NUM(_PRISCV_RISCV, _TRACECTL, _EMPTY, 0, ctl);
|
||||
flcnRiscvRegWrite_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACECTL, ctl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set hal function pointers for functions defined in
|
||||
* LS10 (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] pFlcn The flcn for which to set hals
|
||||
*/
|
||||
void
|
||||
flcnSetupHal_LS10
|
||||
(
|
||||
PFLCN pFlcn
|
||||
)
|
||||
{
|
||||
flcn_hal *pHal = pFlcn->pHal;
|
||||
|
||||
flcnSetupHal_LR10(pFlcn);
|
||||
pHal->riscvRegRead = _flcnRiscvRegRead_LS10;
|
||||
pHal->riscvRegWrite = _flcnRiscvRegWrite_LS10;
|
||||
pHal->dmemTransfer = _flcnDmemTransfer_LS10;
|
||||
pHal->setDmemAddr = _flcnSetDmemAddr_LS10;
|
||||
pHal->imemCopyTo = _flcnImemCopyTo_LS10;
|
||||
pHal->setImemAddr = _flcnSetImemAddr_LS10;
|
||||
pHal->dmemSize = _flcnDmemSize_LS10;
|
||||
pHal->dbgInfoCaptureRiscvPcTrace = _flcnDbgInfoCaptureRiscvPcTrace_LS10;
|
||||
}
|
||||
|
||||
257
src/common/nvswitch/kernel/ls10/inforom_ls10.c
Normal file
257
src/common/nvswitch/kernel/ls10/inforom_ls10.c
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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 "common_nvswitch.h"
|
||||
#include "ls10/ls10.h"
|
||||
#include "ls10/inforom_ls10.h"
|
||||
#include "inforom/ifrstruct.h"
|
||||
#include "soe/soeififr.h"
|
||||
#include "rmsoecmdif.h"
|
||||
#include "flcn/flcn_nvswitch.h"
|
||||
#include "rmflcncmdif_nvswitch.h"
|
||||
|
||||
NvlStatus
|
||||
nvswitch_inforom_nvl_log_error_event_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
void *pNvlGeneric,
|
||||
void *pNvlErrorEvent,
|
||||
NvBool *bDirty
|
||||
)
|
||||
{
|
||||
return -NVL_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NvlStatus nvswitch_inforom_nvl_update_link_correctable_error_info_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
void *pNvlGeneric,
|
||||
void *pData,
|
||||
NvU8 linkId,
|
||||
NvU8 nvliptInstance,
|
||||
NvU8 localLinkIdx,
|
||||
void *pNvlErrorCounts,
|
||||
NvBool *bDirty
|
||||
)
|
||||
{
|
||||
return -NVL_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_oms_inforom_flush_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
return -NVL_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_initialize_oms_state_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
INFOROM_OMS_STATE *pOmsState
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NvBool
|
||||
nvswitch_oms_get_device_disable_ls10
|
||||
(
|
||||
INFOROM_OMS_STATE *pOmsState
|
||||
)
|
||||
{
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_oms_set_device_disable_ls10
|
||||
(
|
||||
INFOROM_OMS_STATE *pOmsState,
|
||||
NvBool bForceDeviceDisable
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_inforom_ecc_get_total_errors_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
INFOROM_ECC_OBJECT *pEccGeneric,
|
||||
NvU64 *pCorrectedTotal,
|
||||
NvU64 *pUncorrectedTotal
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_bbx_add_sxid_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 exceptionType,
|
||||
NvU32 data0,
|
||||
NvU32 data1,
|
||||
NvU32 data2
|
||||
)
|
||||
{
|
||||
NvlStatus status;
|
||||
FLCN *pFlcn;
|
||||
RM_FLCN_CMD_SOE bbxCmd;
|
||||
NvU32 cmdSeqDesc;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
|
||||
if (!nvswitch_is_inforom_supported_ls10(device))
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO, "InfoROM is not supported, skipping\n");
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
// Avoid logging SOE related SXIDs to prevent recursive errors
|
||||
if (exceptionType > NVSWITCH_ERR_HW_SOE && exceptionType < NVSWITCH_ERR_HW_SOE_LAST)
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO, "Not logging SXID: %d to InfoROM\n", exceptionType);
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
pFlcn = device->pSoe->pFlcn;
|
||||
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
|
||||
|
||||
nvswitch_os_memset(&bbxCmd, 0, sizeof(bbxCmd));
|
||||
bbxCmd.hdr.unitId = RM_SOE_UNIT_IFR;
|
||||
bbxCmd.hdr.size = sizeof(bbxCmd);
|
||||
bbxCmd.cmd.ifr.cmdType = RM_SOE_IFR_BBX_SXID_ADD;
|
||||
bbxCmd.cmd.ifr.bbxSxidAdd.exceptionType = exceptionType;
|
||||
bbxCmd.cmd.ifr.bbxSxidAdd.data[0] = data0;
|
||||
bbxCmd.cmd.ifr.bbxSxidAdd.data[1] = data1;
|
||||
bbxCmd.cmd.ifr.bbxSxidAdd.data[2] = data2;
|
||||
|
||||
status = flcnQueueCmdPostBlocking(device, pFlcn,
|
||||
(PRM_FLCN_CMD)&bbxCmd,
|
||||
NULL, // pMsg
|
||||
NULL, // pPayload
|
||||
SOE_RM_CMDQ_LOG_ID,
|
||||
&cmdSeqDesc,
|
||||
&timeout);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s: BBX cmd %d failed. rc:%d\n",
|
||||
__FUNCTION__, bbxCmd.cmd.ifr.cmdType, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_bbx_unload_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
NvlStatus status;
|
||||
FLCN *pFlcn;
|
||||
RM_FLCN_CMD_SOE bbxCmd;
|
||||
NvU32 cmdSeqDesc;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
|
||||
pFlcn = device->pSoe->pFlcn;
|
||||
nvswitch_timeout_create(NVSWITCH_INTERVAL_750MSEC_IN_NS, &timeout);
|
||||
|
||||
nvswitch_os_memset(&bbxCmd, 0, sizeof(bbxCmd));
|
||||
bbxCmd.hdr.unitId = RM_SOE_UNIT_IFR;
|
||||
bbxCmd.hdr.size = sizeof(bbxCmd);
|
||||
bbxCmd.cmd.ifr.cmdType = RM_SOE_IFR_BBX_SHUTDOWN;
|
||||
|
||||
status = flcnQueueCmdPostBlocking(device, pFlcn,
|
||||
(PRM_FLCN_CMD)&bbxCmd,
|
||||
NULL, // pMsg
|
||||
NULL, // pPayload
|
||||
SOE_RM_CMDQ_LOG_ID,
|
||||
&cmdSeqDesc,
|
||||
&timeout);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s: BBX cmd %d failed. rc:%d\n",
|
||||
__FUNCTION__, bbxCmd.cmd.ifr.cmdType, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_bbx_load_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU64 time_ns,
|
||||
NvU8 osType,
|
||||
NvU32 osVersion
|
||||
)
|
||||
{
|
||||
NvlStatus status;
|
||||
FLCN *pFlcn;
|
||||
RM_FLCN_CMD_SOE bbxCmd;
|
||||
NvU32 cmdSeqDesc = 0;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
|
||||
pFlcn = device->pSoe->pFlcn;
|
||||
nvswitch_timeout_create(NVSWITCH_INTERVAL_750MSEC_IN_NS, &timeout);
|
||||
|
||||
nvswitch_os_memset(&bbxCmd, 0, sizeof(bbxCmd));
|
||||
bbxCmd.hdr.unitId = RM_SOE_UNIT_IFR;
|
||||
bbxCmd.hdr.size = sizeof(bbxCmd);
|
||||
bbxCmd.cmd.ifr.cmdType = RM_SOE_IFR_BBX_INITIALIZE;
|
||||
bbxCmd.cmd.ifr.bbxInit.osType = osType;
|
||||
bbxCmd.cmd.ifr.bbxInit.osVersion = osVersion;
|
||||
RM_FLCN_U64_PACK(&bbxCmd.cmd.ifr.bbxInit.time, &time_ns);
|
||||
|
||||
NVSWITCH_PRINT(device, INFO, "RM_SOE_IFR_BBX_INITIALIZE called, time_ns=%llu \n", time_ns);
|
||||
|
||||
status = flcnQueueCmdPostBlocking(device, pFlcn,
|
||||
(PRM_FLCN_CMD)&bbxCmd,
|
||||
NULL, // pMsg
|
||||
NULL, // pPayload
|
||||
SOE_RM_CMDQ_LOG_ID,
|
||||
&cmdSeqDesc,
|
||||
&timeout);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s: BBX cmd %d failed. rc:%d\n",
|
||||
__FUNCTION__, bbxCmd.cmd.ifr.cmdType, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_bbx_get_sxid_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NVSWITCH_GET_SXIDS_PARAMS *params
|
||||
)
|
||||
{
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
7294
src/common/nvswitch/kernel/ls10/intr_ls10.c
Normal file
7294
src/common/nvswitch/kernel/ls10/intr_ls10.c
Normal file
File diff suppressed because it is too large
Load Diff
1396
src/common/nvswitch/kernel/ls10/link_ls10.c
Normal file
1396
src/common/nvswitch/kernel/ls10/link_ls10.c
Normal file
File diff suppressed because it is too large
Load Diff
5624
src/common/nvswitch/kernel/ls10/ls10.c
Normal file
5624
src/common/nvswitch/kernel/ls10/ls10.c
Normal file
File diff suppressed because it is too large
Load Diff
975
src/common/nvswitch/kernel/ls10/minion_ls10.c
Normal file
975
src/common/nvswitch/kernel/ls10/minion_ls10.c
Normal file
@@ -0,0 +1,975 @@
|
||||
/*
|
||||
* 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 "nvlink_export.h"
|
||||
|
||||
#include "common_nvswitch.h"
|
||||
#include "ls10/ls10.h"
|
||||
#include "ls10/minion_ls10.h"
|
||||
#include "ls10/minion_nvlink_defines_public_ls10.h"
|
||||
#include "regkey_nvswitch.h"
|
||||
|
||||
#include "nvswitch/ls10/dev_minion_ip.h"
|
||||
#include "nvswitch/ls10/dev_minion_ip_addendum.h"
|
||||
#include "nvswitch/ls10/dev_ingress_ip.h"
|
||||
#include "nvswitch/ls10/dev_egress_ip.h"
|
||||
#include "nvswitch/ls10/dev_riscv_pri.h"
|
||||
#include "nvswitch/ls10/dev_nvlphyctl_ip.h"
|
||||
|
||||
#include "flcn/flcn_nvswitch.h"
|
||||
|
||||
/*
|
||||
* @Brief : Check if MINION is already running.
|
||||
*
|
||||
* The function assumes that if one of MINIONs is running, all of them are
|
||||
* running. This approach needs to be fixed.
|
||||
*
|
||||
* TODO: Refactor minion code to check for each minion's status individually.
|
||||
*
|
||||
* @param[in] device Bootstrap MINIONs on this device
|
||||
*/
|
||||
static NvBool
|
||||
_nvswitch_check_running_minions
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
NvU32 data, i;
|
||||
NvBool bMinionRunning = NV_FALSE;
|
||||
|
||||
for (i = 0; i < NUM_MINION_ENGINE_LS10; i++)
|
||||
{
|
||||
if (!NVSWITCH_ENG_VALID_LS10(device, MINION, i))
|
||||
{
|
||||
NVSWITCH_PRINT(device, SETUP,
|
||||
"%s: MINION instance %d is not valid.\n",
|
||||
__FUNCTION__, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
data = NVSWITCH_MINION_RD32_LS10(device, i, _CMINION, _FALCON_IRQSTAT);
|
||||
if (FLD_TEST_DRF(_CMINION, _FALCON_IRQSTAT, _HALT, _FALSE, data))
|
||||
{
|
||||
data = NVSWITCH_MINION_RD32_LS10(device, i, _MINION, _MINION_STATUS);
|
||||
if (FLD_TEST_DRF(_MINION, _MINION_STATUS, _STATUS, _BOOT, data))
|
||||
{
|
||||
//
|
||||
// Set initialized flag if MINION is running.
|
||||
// We don't want to bootstrap a falcon that is already running.
|
||||
//
|
||||
nvswitch_set_minion_initialized(device, i, NV_TRUE);
|
||||
|
||||
NVSWITCH_PRINT(device, SETUP,
|
||||
"%s: MINION instance %d is already bootstrapped.\n",
|
||||
__FUNCTION__, i);
|
||||
bMinionRunning = NV_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bMinionRunning;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_get_dl_status_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 linkId,
|
||||
NvU32 statusIdx,
|
||||
NvU32 statusArgs,
|
||||
NvU32 *statusData
|
||||
)
|
||||
{
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
NvBool keepPolling;
|
||||
NvU32 regData, localLinkNumber;
|
||||
localLinkNumber = linkId % NVSWITCH_LINKS_PER_MINION_LS10;
|
||||
|
||||
if (NVSWITCH_IS_LINK_ENG_VALID_LS10(device, MINION, linkId) &&
|
||||
!nvswitch_is_minion_initialized(device, NVSWITCH_GET_LINK_ENG_INST(device, linkId, MINION)))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: MINION %d is not initialized for link %08x.\n",
|
||||
__FUNCTION__, NVSWITCH_GET_LINK_ENG_INST(device, linkId, MINION),
|
||||
linkId);
|
||||
return -NVL_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// Query the DL status interface to get the data
|
||||
NVSWITCH_MINION_LINK_WR32_LS10(device, linkId, _MINION, _NVLINK_DL_STAT(localLinkNumber),
|
||||
DRF_NUM(_MINION, _NVLINK_DL_STAT, _ARGS, statusArgs) |
|
||||
DRF_NUM(_MINION, _NVLINK_DL_STAT, _STATUSIDX, statusIdx));
|
||||
|
||||
if (IS_FMODEL(device) || IS_EMULATION(device) || IS_RTLSIM(device))
|
||||
{
|
||||
nvswitch_timeout_create(20 * NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
|
||||
}
|
||||
|
||||
// Poll for READY bit to be set
|
||||
do
|
||||
{
|
||||
keepPolling = (nvswitch_timeout_check(&timeout)) ? NV_FALSE : NV_TRUE;
|
||||
|
||||
regData = NVSWITCH_MINION_LINK_RD32_LS10(device, linkId, _MINION, _NVLINK_DL_STAT(localLinkNumber));
|
||||
if (FLD_TEST_DRF_NUM(_MINION, _NVLINK_DL_STAT, _READY, 1, regData))
|
||||
{
|
||||
*statusData = NVSWITCH_MINION_LINK_RD32_LS10(device, linkId, _MINION, _NVLINK_DL_STATDATA(localLinkNumber));
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
if (IS_FMODEL(device) || IS_RTLSIM(device))
|
||||
{
|
||||
nvswitch_os_sleep(1);
|
||||
}
|
||||
}
|
||||
while (keepPolling);
|
||||
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: Timeout waiting for DL_STAT request to complete"
|
||||
" NV_MINION_NVLINK_DL_STAT(%d) = 0x%08x\n",
|
||||
__FUNCTION__, linkId, regData);
|
||||
return -NVL_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @Brief : Send MINION DL CMD for a particular link
|
||||
*
|
||||
* @param[in] device Send command to MINION on this device
|
||||
* @param[in] linkNumber DLCMD will be sent on this link number
|
||||
*
|
||||
* @return Returns true if the DLCMD passed
|
||||
*/
|
||||
NvlStatus
|
||||
nvswitch_minion_send_command_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 linkNumber,
|
||||
NvU32 command,
|
||||
NvU32 scratch0
|
||||
)
|
||||
{
|
||||
NvU32 data = 0, localLinkNumber, statData = 0;
|
||||
NvU32 ingressEccRegVal = 0, egressEccRegVal = 0;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
NvBool keepPolling;
|
||||
|
||||
localLinkNumber = linkNumber % NVSWITCH_LINKS_PER_MINION_LS10;
|
||||
|
||||
if (NVSWITCH_IS_LINK_ENG_VALID_LS10(device, MINION, linkNumber) &&
|
||||
!nvswitch_is_minion_initialized(device, NVSWITCH_GET_LINK_ENG_INST(device, linkNumber, MINION)))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: MINION %d is not initialized for link %08x.\n",
|
||||
__FUNCTION__, NVSWITCH_GET_LINK_ENG_INST(device, linkNumber, MINION),
|
||||
linkNumber);
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
data = NVSWITCH_MINION_LINK_RD32_LS10(device, linkNumber, _MINION, _NVLINK_DL_CMD(localLinkNumber));
|
||||
if (FLD_TEST_DRF_NUM(_MINION, _NVLINK_DL_CMD, _FAULT, 1, data))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: MINION %d is in fault state. NV_MINION_NVLINK_DL_CMD(%d) = %08x\n",
|
||||
__FUNCTION__, NVSWITCH_GET_LINK_ENG_INST(device, linkNumber, MINION),
|
||||
linkNumber, data);
|
||||
return -NVL_ERR_GENERIC;
|
||||
}
|
||||
|
||||
// Write to minion scratch if needed by command
|
||||
switch (command)
|
||||
{
|
||||
case NV_MINION_NVLINK_DL_CMD_COMMAND_CONFIGEOM:
|
||||
data = 0;
|
||||
data = FLD_SET_DRF_NUM(_MINION, _MISC_0, _SCRATCH_SWRW_0, scratch0, data);
|
||||
NVSWITCH_MINION_WR32_LS10(device,
|
||||
NVSWITCH_GET_LINK_ENG_INST(device, linkNumber, MINION), _MINION, _MISC_0, data);
|
||||
break;
|
||||
case NV_MINION_NVLINK_DL_CMD_COMMAND_INITPHASE1:
|
||||
//
|
||||
// WAR bug 2708497
|
||||
// Before INITPHASE1, we must clear these values, then set back to
|
||||
// _PROD after the call
|
||||
// NV_INGRESS_ERR_ECC_CTRL_NCISOC_PARITY_ENABLE
|
||||
// NV_EGRESS_ERR_ECC_CTRL_NCISOC_PARITY_ENABLE
|
||||
//
|
||||
|
||||
ingressEccRegVal = NVSWITCH_NPORT_RD32_LS10(device, linkNumber, _INGRESS, _ERR_ECC_CTRL);
|
||||
NVSWITCH_NPORT_WR32_LS10(device, linkNumber, _INGRESS, _ERR_ECC_CTRL,
|
||||
FLD_SET_DRF(_INGRESS, _ERR_ECC_CTRL, _NCISOC_PARITY_ENABLE, _DISABLE, ingressEccRegVal));
|
||||
|
||||
egressEccRegVal = NVSWITCH_NPORT_RD32_LS10(device, linkNumber, _EGRESS, _ERR_ECC_CTRL);
|
||||
NVSWITCH_NPORT_WR32_LS10(device, linkNumber, _EGRESS, _ERR_ECC_CTRL,
|
||||
FLD_SET_DRF(_EGRESS, _ERR_ECC_CTRL, _NCISOC_PARITY_ENABLE, _DISABLE, egressEccRegVal));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
data = FLD_SET_DRF_NUM(_MINION, _NVLINK_DL_CMD, _COMMAND, command, data);
|
||||
data = FLD_SET_DRF_NUM(_MINION, _NVLINK_DL_CMD, _FAULT, 1, data);
|
||||
NVSWITCH_MINION_LINK_WR32_LS10(device, linkNumber, _MINION, _NVLINK_DL_CMD(localLinkNumber), data);
|
||||
|
||||
if (IS_FMODEL(device) || IS_EMULATION(device) || IS_RTLSIM(device))
|
||||
{
|
||||
nvswitch_timeout_create(10 * NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout);
|
||||
}
|
||||
|
||||
//
|
||||
// We will exit this if the command is successful OR
|
||||
// if timeout waiting for the READY bit to be set OR
|
||||
// if it generates a MINION FAULT
|
||||
//
|
||||
do
|
||||
{
|
||||
keepPolling = (nvswitch_timeout_check(&timeout)) ? NV_FALSE : NV_TRUE;
|
||||
|
||||
data = NVSWITCH_MINION_LINK_RD32_LS10(device, linkNumber, _MINION, _NVLINK_DL_CMD(localLinkNumber));
|
||||
if (FLD_TEST_DRF_NUM(_MINION, _NVLINK_DL_CMD, _READY, 1, data))
|
||||
{
|
||||
// The command has completed, success?
|
||||
if (FLD_TEST_DRF_NUM(_MINION, _NVLINK_DL_CMD, _FAULT, 1, data))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: NVLink MINION command faulted!"
|
||||
" NV_MINION_NVLINK_DL_CMD(%d) = 0x%08x\n",
|
||||
__FUNCTION__, linkNumber, data);
|
||||
|
||||
// Pull fault code and subcode
|
||||
if (nvswitch_minion_get_dl_status(device, linkNumber,
|
||||
NV_NVLSTAT_MN00, 0, &statData) == NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: Minion DLCMD Fault code = 0x%x, Sub-code = 0x%x\n",
|
||||
__FUNCTION__,
|
||||
DRF_VAL(_NVLSTAT, _MN00, _LINK_INTR_CODE, statData),
|
||||
DRF_VAL(_NVLSTAT, _MN00, _LINK_INTR_SUBCODE, statData));
|
||||
}
|
||||
else
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: Failed to get code and subcode from DLSTAT, link %d\n",
|
||||
__FUNCTION__, linkNumber);
|
||||
}
|
||||
|
||||
// Clear the fault and return
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: Clearing NVLink MINION fault for link %d\n",
|
||||
__FUNCTION__, linkNumber);
|
||||
|
||||
data = FLD_SET_DRF_NUM(_MINION, _NVLINK_DL_CMD, _FAULT, 1, 0x0);
|
||||
NVSWITCH_MINION_LINK_WR32_LS10(device, linkNumber, _MINION, _NVLINK_DL_CMD(localLinkNumber), data);
|
||||
return -NVL_ERR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NVSWITCH_PRINT(device, SETUP,
|
||||
"%s: NVLink MINION command %x was sent successfully for link %d\n",
|
||||
__FUNCTION__, command, linkNumber);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nvswitch_os_sleep(1);
|
||||
}
|
||||
while (keepPolling);
|
||||
|
||||
if (!FLD_TEST_DRF_NUM(_MINION, _NVLINK_DL_CMD, _READY, 1, data))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: Timeout waiting for NVLink MINION command to complete!"
|
||||
" NV_MINION_NVLINK_DL_CMD(%d) = 0x%08x\n",
|
||||
__FUNCTION__, linkNumber, data);
|
||||
return -NVL_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (command == NV_MINION_NVLINK_DL_CMD_COMMAND_INITPHASE1)
|
||||
{
|
||||
NVSWITCH_NPORT_WR32_LS10(device, linkNumber, _INGRESS, _ERR_ECC_CTRL, ingressEccRegVal);
|
||||
NVSWITCH_NPORT_WR32_LS10(device, linkNumber, _EGRESS, _ERR_ECC_CTRL, egressEccRegVal);
|
||||
}
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @Brief : Bootstrap all MINIONs on the specified device
|
||||
*
|
||||
* @param[in] device Bootstrap MINIONs on this device
|
||||
*/
|
||||
NvlStatus
|
||||
nvswitch_init_minion_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
|
||||
if (_nvswitch_check_running_minions(device))
|
||||
{
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
status = -NVL_INITIALIZATION_TOTAL_FAILURE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_set_minion_initialized_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 idx_minion,
|
||||
NvBool initialized
|
||||
)
|
||||
{
|
||||
ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
|
||||
|
||||
if (!NVSWITCH_ENG_VALID_LS10(device, MINION, idx_minion))
|
||||
{
|
||||
return -NVL_BAD_ARGS;
|
||||
}
|
||||
|
||||
chip_device->engMINION[idx_minion].initialized = initialized;
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
NvBool
|
||||
nvswitch_is_minion_initialized_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 idx_minion
|
||||
)
|
||||
{
|
||||
ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
|
||||
|
||||
if (!NVSWITCH_ENG_VALID_LS10(device, MINION, idx_minion))
|
||||
{
|
||||
return NV_FALSE;
|
||||
}
|
||||
return (chip_device->engMINION[idx_minion].initialized != 0);
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_set_sim_mode_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
nvlink_link *link
|
||||
)
|
||||
{
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
NvU32 dlcmd;
|
||||
NvU32 linkNumber = link->linkNumber;
|
||||
NvU32 localLinkNumber = linkNumber % NVSWITCH_LINKS_PER_MINION_LS10;
|
||||
|
||||
switch (device->regkeys.set_simmode)
|
||||
{
|
||||
case NV_SWITCH_REGKEY_MINION_SET_SIMMODE_FAST:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_FAST;
|
||||
break;
|
||||
case NV_SWITCH_REGKEY_MINION_SET_SIMMODE_MEDIUM:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_MEDIUM;
|
||||
break;
|
||||
case NV_SWITCH_REGKEY_MINION_SET_SIMMODE_SLOW:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_SLOW;
|
||||
break;
|
||||
default:
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkNumber, dlcmd, 0);
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: DLCMD 0x%x failed on link: %d\n",
|
||||
__FUNCTION__, dlcmd, linkNumber);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Setting RXCAL_EN_ALARM timer value
|
||||
NVSWITCH_MINION_LINK_WR32_LS10(device, linkNumber, _MINION,
|
||||
_NVLINK_DL_CMD_DATA(localLinkNumber),
|
||||
NV_MINION_DL_CMD_DATA_RXCAL_EN_ALARM);
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkNumber,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_RXCAL_EN_ALARM, 0);
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: DLCMD DBG_SETSIMMODE_RXCAL_EN_ALARM failed on link: %d\n",
|
||||
__FUNCTION__, linkNumber);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Setting INIT_CAL_DONE timer value
|
||||
NVSWITCH_MINION_LINK_WR32_LS10(device, linkNumber, _MINION,
|
||||
_NVLINK_DL_CMD_DATA(localLinkNumber),
|
||||
NV_MINION_DL_CMD_DATA_INIT_CAL_DONE);
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkNumber,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_INIT_CAL_DONE, 0);
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: DLCMD DBG_SETSIMMODE_INIT_CAL_DONE failed on link: %d\n",
|
||||
__FUNCTION__, linkNumber);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_set_smf_settings_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
nvlink_link *link
|
||||
)
|
||||
{
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
NvU32 dlcmd;
|
||||
NvU32 linkNumber = link->linkNumber;
|
||||
|
||||
switch (device->regkeys.set_smf_settings)
|
||||
{
|
||||
case NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS_SLOW:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_SMF_VALUES_SLOW;
|
||||
break;
|
||||
case NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS_MEDIUM:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_SMF_VALUES_MEDIUM;
|
||||
break;
|
||||
case NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS_FAST:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_SMF_VALUES_FAST;
|
||||
break;
|
||||
case NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS_MEDIUM_SERIAL:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_SMF_VALUES_MEDIUM_SERIAL;
|
||||
break;
|
||||
default:
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkNumber, dlcmd, 0);
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: DLCMD 0x%x failed on link: %d\n",
|
||||
__FUNCTION__, dlcmd, linkNumber);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_select_uphy_tables_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
nvlink_link *link
|
||||
)
|
||||
{
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
NvU32 dlcmd;
|
||||
NvU32 linkNumber = link->linkNumber;
|
||||
|
||||
switch (device->regkeys.select_uphy_tables)
|
||||
{
|
||||
case NV_SWITCH_REGKEY_MINION_SELECT_UPHY_TABLES_SHORT:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_UPHY_TABLES_SHORT;
|
||||
break;
|
||||
case NV_SWITCH_REGKEY_MINION_SELECT_UPHY_TABLES_FAST:
|
||||
dlcmd = NV_MINION_NVLINK_DL_CMD_COMMAND_DBG_SETSIMMODE_UPHY_TABLES_FAST;
|
||||
break;
|
||||
default:
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkNumber, dlcmd, 0);
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: DLCMD 0x%x failed on link: %d\n",
|
||||
__FUNCTION__, dlcmd, linkNumber);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_get_rxdet_status_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 linkId
|
||||
)
|
||||
{
|
||||
NvU32 statData;
|
||||
NvlStatus status;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
NvBool keepPolling;
|
||||
|
||||
if (IS_FMODEL(device) || IS_EMULATION(device) || IS_RTLSIM(device))
|
||||
{
|
||||
nvswitch_timeout_create(30*NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
nvswitch_timeout_create(20 * NVSWITCH_INTERVAL_1MSEC_IN_NS, &timeout);
|
||||
}
|
||||
|
||||
// Poll for READY bit to be set
|
||||
do
|
||||
{
|
||||
keepPolling = (nvswitch_timeout_check(&timeout)) ? NV_FALSE : NV_TRUE;
|
||||
|
||||
// Check RXDET status on MINION DL STAT interface
|
||||
status = nvswitch_minion_get_dl_status(device, linkId, NV_NVLSTAT_LNK2, 0, &statData);
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (FLD_TEST_DRF(_NVLSTAT, _LNK2, _RXDET_LINK_STATUS, _FOUND, statData))
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO,
|
||||
"%s: RXDET LINK_STATUS = FOUND on link: %d\n",
|
||||
__FUNCTION__, linkId);
|
||||
|
||||
// Retrieve which lanes were found (should be all)
|
||||
device->link[linkId].lane_rxdet_status_mask =
|
||||
DRF_VAL(_NVLSTAT, _LNK2, _RXDET_LANE_STATUS, statData);
|
||||
|
||||
//
|
||||
// MINION doesn't have knowledge of lane reversal and therefore
|
||||
// reports logical lanes. We must reverse the bitmask here if applicable
|
||||
// since RM reports physical lanes.
|
||||
//
|
||||
if (nvswitch_link_lane_reversed_lr10(device, linkId))
|
||||
{
|
||||
NVSWITCH_REVERSE_BITMASK_32(NVSWITCH_NUM_LANES_LS10,
|
||||
device->link[linkId].lane_rxdet_status_mask);
|
||||
}
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
if (FLD_TEST_DRF(_NVLSTAT, _LNK2, _RXDET_LINK_STATUS, _TIMEOUT, statData))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: RXDET LINK_STATUS = TIMEOUT on link: %d\n",
|
||||
__FUNCTION__, linkId);
|
||||
|
||||
// Retrieve which lanes were found
|
||||
device->link[linkId].lane_rxdet_status_mask =
|
||||
DRF_VAL(_NVLSTAT, _LNK2, _RXDET_LANE_STATUS, statData);
|
||||
|
||||
//
|
||||
// MINION doesn't have knowledge of lane reversal and therefore
|
||||
// reports logical lanes. We must reverse the bitmask here if applicable
|
||||
// since RM reports physical lanes.
|
||||
//
|
||||
if (nvswitch_link_lane_reversed_lr10(device, linkId))
|
||||
{
|
||||
NVSWITCH_REVERSE_BITMASK_32(NVSWITCH_NUM_LANES_LS10,
|
||||
device->link[linkId].lane_rxdet_status_mask);
|
||||
}
|
||||
|
||||
return -NVL_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
nvswitch_os_sleep(1);
|
||||
}
|
||||
while (keepPolling);
|
||||
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: Timeout waiting for RXDET STATUS on link: %d\n",
|
||||
__FUNCTION__, linkId);
|
||||
|
||||
return -NVL_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @Brief : Check if the RISCV CPU has started
|
||||
*
|
||||
* @param[in] device The Nvswitch device
|
||||
* @param[in] idx_minion MINION instance to use
|
||||
*/
|
||||
NvBool
|
||||
nvswitch_minion_is_riscv_active_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 idx_minion
|
||||
)
|
||||
{
|
||||
NvU32 val;
|
||||
|
||||
val = NVSWITCH_MINION_RD32_LS10(device, idx_minion, _CMINION_RISCV, _CPUCTL);
|
||||
|
||||
return FLD_TEST_DRF(_CMINION, _RISCV_CPUCTL, _ACTIVE_STAT, _ACTIVE, val);
|
||||
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_clear_dl_error_counters_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 linkId
|
||||
)
|
||||
{
|
||||
NvlStatus status;
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_DLSTAT_CLR_DLERRCNT, 0);
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s : Failed to clear error count to MINION for link # %d\n",
|
||||
__FUNCTION__, linkId);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_send_inband_data_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 linkId,
|
||||
nvswitch_inband_send_data *inBandData
|
||||
)
|
||||
{
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
#if defined(INCLUDE_NVLINK_LIB)
|
||||
NvlStatus tempStatus = NVL_SUCCESS;
|
||||
NvU32 localLinkNumber = linkId % NVSWITCH_LINKS_PER_MINION_LS10;
|
||||
NvU8 *sendBuffer = inBandData->sendBuffer;
|
||||
NvU32 bufferSize = inBandData->bufferSize;
|
||||
NvU32 data = 0;
|
||||
NvU32 regval = 0;
|
||||
NvU32 statData = 0;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
NvBool bKeepPolling = NV_TRUE;
|
||||
|
||||
if (bufferSize == 0 || bufferSize > NVLINK_INBAND_MAX_XFER_SIZE)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Bad Inband data size %d. Skipping Inband Send\n", bufferSize);
|
||||
return -NVL_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// Buffer Size must be reduced by 1 as per the minion protocol
|
||||
regval = DRF_NUM(_MINION, _INBAND_SEND_DATA, _BUFFER_SIZE, (bufferSize - 1));
|
||||
|
||||
regval |= DRF_NUM(_MINION, _INBAND_SEND_DATA, _FLAGS,inBandData->hdr.data);
|
||||
|
||||
NVSWITCH_MINION_WR32_LS10(device,
|
||||
NVSWITCH_GET_LINK_ENG_INST(device, linkId, MINION),
|
||||
_MINION, _NVLINK_DL_CMD_DATA(localLinkNumber),
|
||||
regval);
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_WRITE_TX_BUFFER_START, 0);
|
||||
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer transfer for TX_BUFFER_START failed\n", linkId);
|
||||
return status;
|
||||
}
|
||||
|
||||
while (bufferSize != 0)
|
||||
{
|
||||
nvswitch_os_memcpy(&data, sendBuffer, NV_MIN(sizeof(data), bufferSize));
|
||||
|
||||
NVSWITCH_MINION_WR32_LS10(device,
|
||||
NVSWITCH_GET_LINK_ENG_INST(device, linkId, MINION),
|
||||
_MINION, _NVLINK_DL_CMD_DATA(localLinkNumber),
|
||||
data);
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_WRITE_TX_BUFFER_MIDDLE, 0);
|
||||
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer transfer failed\n", linkId);
|
||||
goto clear_buffer;
|
||||
}
|
||||
|
||||
bufferSize -= NV_MIN(sizeof(data), bufferSize);
|
||||
sendBuffer += NV_MIN(sizeof(data), bufferSize);
|
||||
}
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_WRITE_TX_BUFFER_END, 0);
|
||||
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer transfer for TX_BUFFER_END\n", linkId);
|
||||
goto clear_buffer;
|
||||
}
|
||||
|
||||
// Wait for buffer complete or buffer fail
|
||||
nvswitch_timeout_create(2 * NVSWITCH_INTERVAL_4SEC_IN_NS, &timeout);
|
||||
do
|
||||
{
|
||||
bKeepPolling = !nvswitch_timeout_check(&timeout);
|
||||
// DLSTAT need to explicitly checked
|
||||
status = nvswitch_minion_get_dl_status(device, linkId, NV_NVLSTAT_UC01, 0, &statData);
|
||||
|
||||
if (status != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO,"%s : Failed to poll DLSTAT register for (%s):(%d)\n",
|
||||
__FUNCTION__, device->name, linkId);
|
||||
status = -NVL_ERR_INVALID_STATE;
|
||||
goto clear_buffer;
|
||||
}
|
||||
|
||||
if (FLD_TEST_DRF(_NVLSTAT, _UC01, _INBAND_BUFFER_COMPLETE, _TRUE, statData))
|
||||
{
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
if (FLD_TEST_DRF(_NVLSTAT, _UC01, _INBAND_BUFFER_FAIL, _TRUE, statData))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer transfer BUFFER_FAILED\n", linkId);
|
||||
status = -NVL_ERR_INVALID_STATE;
|
||||
goto clear_buffer;
|
||||
}
|
||||
//
|
||||
// Consider a case where both FM and RM trying to write on the same NVLink at the same time.
|
||||
// Both are waiting on each other to read the buffer, but they have also blocked the ISR,
|
||||
// as while waiting they hold the device lock. Thus, it is necessary to unblock one of them.
|
||||
// And to do that we have service BUFFER_AVAILABLE while waiting.
|
||||
//
|
||||
nvswitch_service_minion_all_links_ls10(device);
|
||||
|
||||
nvswitch_os_sleep(10);
|
||||
|
||||
} while (bKeepPolling);
|
||||
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Neither got BUFFER_FAIL nor BUFFER_COMPLETE\n", linkId);
|
||||
|
||||
clear_buffer:
|
||||
tempStatus = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_CLEAR_TX_BUFFER,
|
||||
0);
|
||||
if (tempStatus != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer transfer for TX_BUFFER_CLEAR\n", linkId);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Check if we received BUFFER_COMPLETE is seen while doing a BUFFER_CLEAR
|
||||
tempStatus = nvswitch_minion_get_dl_status(device, linkId, NV_NVLSTAT_UC01, 0, &statData);
|
||||
|
||||
if (tempStatus != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO,"%s : Failed to poll DLSTAT register for (%s):(%d)\n",
|
||||
__FUNCTION__, device->name, linkId);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (FLD_TEST_DRF(_NVLSTAT, _UC01, _INBAND_BUFFER_COMPLETE, _TRUE, statData))
|
||||
{
|
||||
status = NVL_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = bKeepPolling ? status: -NVL_ERR_STATE_IN_USE;
|
||||
}
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_minion_receive_inband_data_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 linkId
|
||||
)
|
||||
{
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
#if defined(INCLUDE_NVLINK_LIB)
|
||||
NvlStatus tempStatus = NVL_SUCCESS;
|
||||
NvU32 numEntries = 0;
|
||||
NvU32 i;
|
||||
NvU32 localLinkNumber = linkId % NVSWITCH_LINKS_PER_MINION_LS10;
|
||||
NvU8 *receiveBuffer;
|
||||
NvU32 regVal, dataSize, remainingBuffer, bytesToXfer;
|
||||
nvlink_inband_drv_hdr_t hdr;
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_READ_RX_BUFFER_START,
|
||||
0);
|
||||
if (status != NV_OK)
|
||||
goto cleanup;
|
||||
|
||||
regVal = NVSWITCH_MINION_RD32_LS10(device,
|
||||
NVSWITCH_GET_LINK_ENG_INST(device, linkId, MINION),
|
||||
_MINION, _NVLINK_DL_CMD_DATA(localLinkNumber));
|
||||
|
||||
// Add 1 to the data as per minion protocol
|
||||
dataSize = DRF_VAL(_MINION, _INBAND_SEND_DATA, _BUFFER_SIZE, regVal) + 1;
|
||||
hdr.data = DRF_VAL(_MINION, _INBAND_SEND_DATA, _FLAGS, regVal);
|
||||
numEntries = NV_ALIGN_UP(dataSize, NVLINK_INBAND_MAX_XFER_AT_ONCE)/
|
||||
NVLINK_INBAND_MAX_XFER_AT_ONCE;
|
||||
remainingBuffer = dataSize;
|
||||
|
||||
if ((hdr.data & (NVLINK_INBAND_DRV_HDR_TYPE_START |
|
||||
NVLINK_INBAND_DRV_HDR_TYPE_MID |
|
||||
NVLINK_INBAND_DRV_HDR_TYPE_END)) == 0)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "InBand: HDR is wrong\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (hdr.data & NVLINK_INBAND_DRV_HDR_TYPE_START)
|
||||
{
|
||||
if (device->link[linkId].inbandData.message != NULL)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "InBand: Got TYPE_START for existing data\n");
|
||||
NVSWITCH_ASSERT(0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
device->link[linkId].inbandData.message =
|
||||
nvswitch_os_malloc(sizeof(nvswitch_inband_data_list));
|
||||
if (device->link[linkId].inbandData.message == NULL)
|
||||
{
|
||||
status = -NVL_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
device->link[linkId].inbandData.message->dataSize = 0;
|
||||
}
|
||||
|
||||
if (device->link[linkId].inbandData.message == NULL)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "InBand: Data being sent without _START\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
receiveBuffer = device->link[linkId].inbandData.message->data;
|
||||
|
||||
receiveBuffer += device->link[linkId].inbandData.message->dataSize;
|
||||
|
||||
if (((dataSize + device->link[linkId].inbandData.message->dataSize) >
|
||||
NVSWITCH_INBAND_DATA_SIZE) ||
|
||||
(dataSize > NVLINK_INBAND_MAX_XFER_SIZE) ||
|
||||
(dataSize == 0))
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "InBand: Msg is of wrong Size :DataSize = %d Msg Size= %d\n",
|
||||
dataSize, device->link[linkId].inbandData.message->dataSize);
|
||||
NVSWITCH_ASSERT(0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < numEntries; i++)
|
||||
{
|
||||
status = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_READ_RX_BUFFER_MIDDLE, 0);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer receive"
|
||||
"for entry %d failed\n", linkId, i);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
regVal = NVSWITCH_MINION_RD32_LS10(device,
|
||||
NVSWITCH_GET_LINK_ENG_INST(device, linkId, MINION),
|
||||
_MINION, _NVLINK_DL_CMD_DATA(localLinkNumber));
|
||||
|
||||
bytesToXfer = NV_MIN(remainingBuffer, NVLINK_INBAND_MAX_XFER_AT_ONCE);
|
||||
|
||||
nvswitch_os_memcpy(receiveBuffer, ®Val, bytesToXfer);
|
||||
|
||||
receiveBuffer += bytesToXfer;
|
||||
remainingBuffer -= bytesToXfer;
|
||||
}
|
||||
|
||||
status = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_READ_RX_BUFFER_END, 0);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer receive"
|
||||
"for entry %d failed\n", linkId, numEntries);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
device->link[linkId].inbandData.message->dataSize += dataSize;
|
||||
|
||||
if (hdr.data & NVLINK_INBAND_DRV_HDR_TYPE_END)
|
||||
{
|
||||
nvswitch_filter_messages(device, linkId);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
tempStatus = nvswitch_minion_send_command(device, linkId,
|
||||
NV_MINION_NVLINK_DL_CMD_COMMAND_CLEAR_RX_BUFFER,
|
||||
0);
|
||||
if (tempStatus != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Link %d Inband Buffer transfer for RX_BUFFER_CLEAR\n", linkId);
|
||||
return;
|
||||
}
|
||||
if (device->link[linkId].inbandData.message != NULL)
|
||||
{
|
||||
nvswitch_os_free(device->link[linkId].inbandData.message);
|
||||
device->link[linkId].inbandData.message = NULL;
|
||||
}
|
||||
//TODO: Check if we need to send a failure msg to client?
|
||||
#endif
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_minion_get_ali_debug_registers_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
nvlink_link *link,
|
||||
NVSWITCH_MINION_ALI_DEBUG_REGISTERS *params
|
||||
)
|
||||
{
|
||||
NvU32 localLinkNumber = link->linkNumber % NVSWITCH_LINKS_PER_MINION_LS10;
|
||||
if (!nvswitch_minion_get_dl_status(device, link->linkNumber,
|
||||
NV_NVLSTAT_MN00, 0, &(params->dlstatMn00)) == NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO,"%s : Failed to poll DLSTAT _MN00 register for (%s):(%d)\n",
|
||||
__FUNCTION__, device->name, link->linkNumber);
|
||||
}
|
||||
|
||||
if (!nvswitch_minion_get_dl_status(device, link->linkNumber, NV_NVLSTAT_UC01, 0, &(params->dlstatUc01)))
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO,"%s : Failed to poll DLSTAT UC01 register for (%s):(%d)\n",
|
||||
__FUNCTION__, device->name, link->linkNumber);
|
||||
}
|
||||
|
||||
params->dlstatLinkIntr = NVSWITCH_MINION_LINK_RD32_LS10(device, link->linkNumber,
|
||||
_MINION, _NVLINK_LINK_INTR(localLinkNumber));
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
1844
src/common/nvswitch/kernel/ls10/multicast_ls10.c
Normal file
1844
src/common/nvswitch/kernel/ls10/multicast_ls10.c
Normal file
File diff suppressed because it is too large
Load Diff
349
src/common/nvswitch/kernel/ls10/pmgr_ls10.c
Normal file
349
src/common/nvswitch/kernel/ls10/pmgr_ls10.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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 "common_nvswitch.h"
|
||||
#include "regkey_nvswitch.h"
|
||||
#include "ls10/ls10.h"
|
||||
#include "ls10/pmgr_ls10.h"
|
||||
#include "error_nvswitch.h"
|
||||
#include "pmgr_nvswitch.h"
|
||||
#include "rom_nvswitch.h"
|
||||
#include "export_nvswitch.h"
|
||||
#include "soe/soe_nvswitch.h"
|
||||
#include "soe/soeifcore.h"
|
||||
|
||||
#include "nvswitch/ls10/dev_pmgr.h"
|
||||
|
||||
static NvBool
|
||||
_nvswitch_i2c_ports_priv_locked_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
NvU32 regVal;
|
||||
|
||||
regVal = NVSWITCH_REG_RD32(device, _PMGR, _I2C_PRIV_LEVEL_MASK(NVSWITCH_I2C_PORT_I2CA));
|
||||
if (FLD_TEST_DRF(_PMGR, _I2C_PRIV_LEVEL_MASK, _WRITE_PROTECTION_LEVEL0, _DISABLE, regVal))
|
||||
{
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
regVal = NVSWITCH_REG_RD32(device, _PMGR, _I2C_PRIV_LEVEL_MASK(NVSWITCH_I2C_PORT_I2CB));
|
||||
if (FLD_TEST_DRF(_PMGR, _I2C_PRIV_LEVEL_MASK, _WRITE_PROTECTION_LEVEL0, _DISABLE, regVal))
|
||||
{
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
regVal = NVSWITCH_REG_RD32(device, _PMGR, _I2C_PRIV_LEVEL_MASK(NVSWITCH_I2C_PORT_I2CC));
|
||||
if (FLD_TEST_DRF(_PMGR, _I2C_PRIV_LEVEL_MASK, _WRITE_PROTECTION_LEVEL0, _DISABLE, regVal))
|
||||
{
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
static NvlStatus
|
||||
_nvswitch_i2c_init_soe_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
NvlStatus ret;
|
||||
PNVSWITCH_OBJI2C pI2c;
|
||||
|
||||
pI2c = device->pI2c;
|
||||
|
||||
if (!nvswitch_is_soe_supported(device))
|
||||
{
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Setup DMA
|
||||
ret = nvswitch_os_alloc_contig_memory(device->os_handle, &pI2c->pCpuAddr, SOE_I2C_DMA_BUF_SIZE,
|
||||
(device->dma_addr_width == 32));
|
||||
if (ret != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_alloc_contig_memory returned %d\n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nvswitch_os_memset(pI2c->pCpuAddr, 0, SOE_I2C_DMA_BUF_SIZE);
|
||||
|
||||
ret = nvswitch_os_map_dma_region(device->os_handle, pI2c->pCpuAddr, &pI2c->dmaHandle,
|
||||
SOE_I2C_DMA_BUF_SIZE, NVSWITCH_DMA_DIR_BIDIRECTIONAL);
|
||||
if (ret != NVL_SUCCESS)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_map_dma_region returned %d\n", __FUNCTION__, ret);
|
||||
nvswitch_os_free_contig_memory(device->os_handle, pI2c->pCpuAddr, SOE_I2C_DMA_BUF_SIZE);
|
||||
pI2c->pCpuAddr = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
/*! @brief Set up a port to use a PMGR implementation.
|
||||
*
|
||||
* @param[in] device NvSwitch device
|
||||
* @param[in] port The port identifier for the bus.
|
||||
*/
|
||||
static void
|
||||
_nvswitch_i2c_set_port_pmgr_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 port
|
||||
)
|
||||
{
|
||||
PNVSWITCH_OBJI2C pI2c = device->pI2c;
|
||||
|
||||
NVSWITCH_ASSERT(port < NVSWITCH_MAX_I2C_PORTS);
|
||||
|
||||
pI2c->PortInfo[port] = FLD_SET_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, pI2c->PortInfo[port]);
|
||||
pI2c->Ports[port].defaultSpeedMode = NVSWITCH_I2C_SPEED_MODE_100KHZ;
|
||||
pI2c->PortInfo[port] = FLD_SET_DRF(_I2C, _PORTINFO,
|
||||
_ACCESS_ALLOWED, _TRUE,
|
||||
pI2c->PortInfo[port]);
|
||||
}
|
||||
|
||||
//
|
||||
// Pre-initialize the software & hardware state of the switch I2C & GPIO interface
|
||||
//
|
||||
void
|
||||
nvswitch_init_pmgr_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
PNVSWITCH_OBJI2C pI2c;
|
||||
|
||||
// Initialize I2C object
|
||||
nvswitch_i2c_init(device);
|
||||
|
||||
pI2c = device->pI2c;
|
||||
|
||||
if (pI2c != NULL)
|
||||
{
|
||||
pI2c->kernelI2CSupported = NV_TRUE;
|
||||
pI2c->soeI2CSupported = NV_TRUE;
|
||||
|
||||
if (_nvswitch_i2c_ports_priv_locked_ls10(device))
|
||||
{
|
||||
NVSWITCH_PRINT(device, WARN, "%s: I2C ports priv locked!\n", __FUNCTION__);
|
||||
pI2c->kernelI2CSupported = NV_FALSE;
|
||||
}
|
||||
|
||||
if (_nvswitch_i2c_init_soe_ls10(device) != NVL_SUCCESS)
|
||||
{
|
||||
pI2c->soeI2CSupported = NV_FALSE;
|
||||
}
|
||||
|
||||
// Setup the 3 I2C ports
|
||||
_nvswitch_i2c_set_port_pmgr_ls10(device, NVSWITCH_I2C_PORT_I2CA);
|
||||
_nvswitch_i2c_set_port_pmgr_ls10(device, NVSWITCH_I2C_PORT_I2CB);
|
||||
_nvswitch_i2c_set_port_pmgr_ls10(device, NVSWITCH_I2C_PORT_I2CC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const NVSWITCH_GPIO_INFO nvswitch_gpio_pin_Default[] =
|
||||
{
|
||||
NVSWITCH_DESCRIBE_GPIO_PIN( 0, _INSTANCE_ID0, 0, IN), // Instance ID bit 0
|
||||
NVSWITCH_DESCRIBE_GPIO_PIN( 1, _INSTANCE_ID1, 0, IN), // Instance ID bit 1
|
||||
NVSWITCH_DESCRIBE_GPIO_PIN( 2, _INSTANCE_ID2, 0, IN), // Instance ID bit 2
|
||||
};
|
||||
|
||||
static const NvU32 nvswitch_gpio_pin_Default_size = NV_ARRAY_ELEMENTS(nvswitch_gpio_pin_Default);
|
||||
|
||||
//
|
||||
// Initialize the software state of the switch I2C & GPIO interface
|
||||
// Temporarily forcing default GPIO values.
|
||||
//
|
||||
|
||||
// TODO: This function should be updated with the board values from DCB.
|
||||
|
||||
void
|
||||
nvswitch_init_pmgr_devices_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
|
||||
PNVSWITCH_OBJI2C pI2c = device->pI2c;
|
||||
|
||||
if (IS_FMODEL(device) || IS_EMULATION(device) || IS_RTLSIM(device))
|
||||
{
|
||||
// GPIOs not modelled on non-silicon
|
||||
chip_device->gpio_pin = NULL;
|
||||
chip_device->gpio_pin_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
chip_device->gpio_pin = nvswitch_gpio_pin_Default;
|
||||
chip_device->gpio_pin_size = nvswitch_gpio_pin_Default_size;
|
||||
}
|
||||
|
||||
pI2c->device_list = NULL;
|
||||
pI2c->device_list_size = 0;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_get_rom_info_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NVSWITCH_EEPROM_TYPE *eeprom
|
||||
)
|
||||
{
|
||||
NVSWITCH_PRINT(device, WARN, "%s: Function not implemented\n", __FUNCTION__);
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* RM Control command to determine the physical id of the device.
|
||||
*/
|
||||
NvU32
|
||||
nvswitch_read_physical_id_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
|
||||
NvU32 physical_id = 0;
|
||||
NvU32 data;
|
||||
NvU32 idx_gpio;
|
||||
NvU32 input_inv;
|
||||
NvU32 function_offset;
|
||||
|
||||
for (idx_gpio = 0; idx_gpio < chip_device->gpio_pin_size; idx_gpio++)
|
||||
{
|
||||
if ((chip_device->gpio_pin[idx_gpio].function >= NVSWITCH_GPIO_ENTRY_FUNCTION_INSTANCE_ID0) &&
|
||||
(chip_device->gpio_pin[idx_gpio].function <= NVSWITCH_GPIO_ENTRY_FUNCTION_INSTANCE_ID6))
|
||||
{
|
||||
if (chip_device->gpio_pin[idx_gpio].misc == NVSWITCH_GPIO_ENTRY_MISC_IO_INV_IN)
|
||||
{
|
||||
input_inv = NV_PMGR_GPIO_INPUT_CNTL_1_INV_YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
input_inv = NV_PMGR_GPIO_INPUT_CNTL_1_INV_NO;
|
||||
}
|
||||
|
||||
NVSWITCH_REG_WR32(device, _PMGR, _GPIO_INPUT_CNTL_1,
|
||||
DRF_NUM(_PMGR, _GPIO_INPUT_CNTL_1, _PINNUM, chip_device->gpio_pin[idx_gpio].pin) |
|
||||
DRF_NUM(_PMGR, _GPIO_INPUT_CNTL_1, _INV, input_inv) |
|
||||
DRF_DEF(_PMGR, _GPIO_INPUT_CNTL_1, _BYPASS_FILTER, _NO));
|
||||
|
||||
data = NVSWITCH_REG_RD32(device, _PMGR, _GPIO_INPUT_CNTL_1);
|
||||
function_offset = chip_device->gpio_pin[idx_gpio].function -
|
||||
NVSWITCH_GPIO_ENTRY_FUNCTION_INSTANCE_ID0;
|
||||
physical_id |=
|
||||
(DRF_VAL(_PMGR, _GPIO_INPUT_CNTL_1, _READ, data) << function_offset);
|
||||
}
|
||||
}
|
||||
|
||||
NVSWITCH_PRINT(device, SETUP, "%s Device position Id = 0x%x\n", __FUNCTION__, physical_id);
|
||||
|
||||
return physical_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* RM Control command to perform indexed I2C.
|
||||
*/
|
||||
NvlStatus
|
||||
nvswitch_ctrl_i2c_indexed_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NVSWITCH_CTRL_I2C_INDEXED_PARAMS *pParams
|
||||
)
|
||||
{
|
||||
PNVSWITCH_OBJI2C pI2c;
|
||||
|
||||
pI2c = device->pI2c;
|
||||
|
||||
if (pI2c == NULL)
|
||||
{
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (pParams == NULL)
|
||||
{
|
||||
return -NVL_BAD_ARGS;
|
||||
}
|
||||
|
||||
// SW I2C only supported by kernel driver
|
||||
if (device->regkeys.force_kernel_i2c == NV_SWITCH_REGKEY_FORCE_KERNEL_I2C_ENABLE ||
|
||||
FLD_TEST_DRF(SWITCH_CTRL, _I2C_FLAGS, _FLAVOR, _SW, pParams->flags))
|
||||
{
|
||||
if (!pI2c->kernelI2CSupported)
|
||||
{
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
return nvswitch_ctrl_i2c_indexed_lr10(device, pParams);
|
||||
}
|
||||
|
||||
if (pI2c->soeI2CSupported)
|
||||
{
|
||||
return soeI2CAccess_HAL(device, pParams);
|
||||
}
|
||||
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return if I2C transactions can be supported.
|
||||
*
|
||||
* @param[in] device The NvSwitch Device.
|
||||
*
|
||||
*/
|
||||
NvBool
|
||||
nvswitch_is_i2c_supported_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
return ((device->pI2c != NULL) &&
|
||||
(device->pI2c->soeI2CSupported || device->pI2c->kernelI2CSupported));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return if I2C device and port is allowed access
|
||||
*
|
||||
* @param[in] device The NvSwitch Device.
|
||||
* @param[in] port The I2C Port.
|
||||
* @param[in] addr The I2C device to access.
|
||||
* @param[in] bIsRead Boolean if I2C transaction is a read.
|
||||
*
|
||||
*/
|
||||
NvBool
|
||||
nvswitch_i2c_is_device_access_allowed_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 port,
|
||||
NvU8 addr,
|
||||
NvBool bIsRead
|
||||
)
|
||||
{
|
||||
// Check will be performed in SOE
|
||||
return NV_TRUE;
|
||||
}
|
||||
222
src/common/nvswitch/kernel/ls10/smbpbi_ls10.c
Normal file
222
src/common/nvswitch/kernel/ls10/smbpbi_ls10.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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 "common_nvswitch.h"
|
||||
|
||||
#include "flcn/flcn_nvswitch.h"
|
||||
#include "rmflcncmdif_nvswitch.h"
|
||||
#include "nvVer.h"
|
||||
|
||||
NvlStatus
|
||||
nvswitch_smbpbi_alloc_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_smbpbi_post_init_hal_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_smbpbi_destroy_hal_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_smbpbi_get_dem_num_messages_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU8 *pMsgCount
|
||||
)
|
||||
{
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_inforom_dem_load_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_smbpbi_dem_load_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
return -NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_smbpbi_log_message_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NvU32 num,
|
||||
NvU32 msglen,
|
||||
NvU8 *osErrorString
|
||||
)
|
||||
{
|
||||
struct smbpbi *pSmbpbi = device->pSmbpbi;
|
||||
RM_FLCN_CMD_SOE cmd;
|
||||
RM_SOE_SMBPBI_CMD_LOG_MESSAGE *pLogCmd = &cmd.cmd.smbpbiCmd.logMessage;
|
||||
NvU8 offset;
|
||||
NvU8 segSize;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
NvU32 cmdSeqDesc;
|
||||
FLCN *pFlcn;
|
||||
NvlStatus status;
|
||||
|
||||
if ((pSmbpbi == NULL) || (device->pSoe == NULL) ||
|
||||
(pSmbpbi->logMessageNesting++ != 0))
|
||||
{
|
||||
goto nvswitch_smbpbi_log_message_exit;
|
||||
}
|
||||
|
||||
pFlcn = device->pSoe->pFlcn;
|
||||
|
||||
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.unitId = RM_SOE_UNIT_SMBPBI;
|
||||
cmd.hdr.size = RM_SOE_CMD_SIZE(SMBPBI, LOG_MESSAGE);
|
||||
cmd.cmd.smbpbiCmd.cmdType = RM_SOE_SMBPBI_CMD_ID_LOG_MESSAGE;
|
||||
|
||||
msglen = NV_MIN(msglen, RM_SOE_SMBPBI_CMD_LOG_MESSAGE_MAX_STRING);
|
||||
|
||||
pLogCmd->sxidId = num;
|
||||
pLogCmd->msgLen = msglen;
|
||||
pLogCmd->timeStamp = nvswitch_os_get_platform_time() / NVSWITCH_NSEC_PER_SEC;
|
||||
|
||||
for (offset = 0; msglen > 0; offset += segSize)
|
||||
{
|
||||
segSize = NV_MIN(msglen, RM_SOE_SMBPBI_CMD_LOG_MESSAGE_STRING_SEGMENT_SZ);
|
||||
nvswitch_os_memcpy(pLogCmd->errorString, osErrorString + offset, segSize);
|
||||
|
||||
pLogCmd->msgOffset = offset;
|
||||
pLogCmd->segSize = segSize;
|
||||
|
||||
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS, &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);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s: SMBPBI Log Message command failed. rc:%d\n",
|
||||
__FUNCTION__, status);
|
||||
break;
|
||||
}
|
||||
|
||||
msglen -= segSize;
|
||||
}
|
||||
|
||||
pSmbpbi->logMessageNesting = 0;
|
||||
|
||||
nvswitch_smbpbi_log_message_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_smbpbi_send_init_data_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
struct smbpbi *pSmbpbi = device->pSmbpbi;
|
||||
RM_FLCN_CMD_SOE cmd;
|
||||
RM_SOE_SMBPBI_CMD_INIT_DATA *pInitDataCmd = &cmd.cmd.smbpbiCmd.initData;
|
||||
NVSWITCH_TIMEOUT timeout;
|
||||
NvU32 cmdSeqDesc;
|
||||
FLCN *pFlcn = device->pSoe->pFlcn;
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
|
||||
ct_assert(sizeof(NV_VERSION_STRING) <= sizeof(pInitDataCmd->driverVersionString));
|
||||
|
||||
if (pSmbpbi == NULL)
|
||||
{
|
||||
goto nvswitch_smbpbi_send_init_data_exit;
|
||||
}
|
||||
|
||||
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.unitId = RM_SOE_UNIT_SMBPBI;
|
||||
cmd.hdr.size = RM_SOE_CMD_SIZE(SMBPBI, INIT_DATA);
|
||||
cmd.cmd.smbpbiCmd.cmdType = RM_SOE_SMBPBI_CMD_ID_INIT_DATA;
|
||||
|
||||
nvswitch_os_strncpy((char *)pInitDataCmd->driverVersionString,
|
||||
NV_VERSION_STRING,
|
||||
sizeof(pInitDataCmd->driverVersionString));
|
||||
pInitDataCmd->driverVersionString[sizeof(pInitDataCmd->driverVersionString) - 1] = 0;
|
||||
|
||||
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS, &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);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "%s: SMBPBI Init Data command failed. rc:%d\n",
|
||||
__FUNCTION__, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
NVSWITCH_PRINT(device, INFO, "%s: SMBPBI Init Data sent to SOE.\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
|
||||
nvswitch_smbpbi_send_init_data_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_smbpbi_send_unload_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_smbpbi_dem_flush_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
}
|
||||
1128
src/common/nvswitch/kernel/ls10/soe_ls10.c
Normal file
1128
src/common/nvswitch/kernel/ls10/soe_ls10.c
Normal file
File diff suppressed because it is too large
Load Diff
1512
src/common/nvswitch/kernel/ls10/sugen_ls10.c
Normal file
1512
src/common/nvswitch/kernel/ls10/sugen_ls10.c
Normal file
File diff suppressed because it is too large
Load Diff
358
src/common/nvswitch/kernel/ls10/therm_ls10.c
Normal file
358
src/common/nvswitch/kernel/ls10/therm_ls10.c
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* 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 "export_nvswitch.h"
|
||||
|
||||
#include "common_nvswitch.h"
|
||||
#include "ls10/ls10.h"
|
||||
#include "ls10/therm_ls10.h"
|
||||
#include "error_nvswitch.h"
|
||||
#include "soe/soeiftherm.h"
|
||||
|
||||
#include "nvswitch/ls10/dev_therm.h"
|
||||
|
||||
//
|
||||
// Thermal functions
|
||||
//
|
||||
|
||||
//
|
||||
// Initialize thermal offsets for External Tdiode.
|
||||
//
|
||||
|
||||
NvlStatus
|
||||
nvswitch_init_thermal_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
|
||||
|
||||
// Mark everything invalid
|
||||
chip_device->tdiode.method = NVSWITCH_THERM_METHOD_UNKNOWN;
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_nvswitch_read_max_tsense_temperature_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info,
|
||||
NvU32 channel
|
||||
)
|
||||
{
|
||||
NvU32 offset;
|
||||
NvU32 temperature;
|
||||
|
||||
temperature = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_MAXIMUM_TEMPERATURE);
|
||||
temperature = DRF_VAL(_THERM_TSENSE, _MAXIMUM_TEMPERATURE, _MAXIMUM_TEMPERATURE, temperature);
|
||||
temperature = NV_TSENSE_FXP_9_5_TO_24_8(temperature);
|
||||
|
||||
if (channel == NVSWITCH_THERM_CHANNEL_LR10_TSENSE_MAX)
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_0_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_0_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
|
||||
// Temperature of the sensor reported equals calculation of the max temperature reported
|
||||
// from the TSENSE HUB plus the temperature offset programmed by SW. This offset needs to
|
||||
// be substracted to get the actual temperature of the sensor.
|
||||
temperature -= NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
}
|
||||
|
||||
info->temperature[channel] = temperature;
|
||||
info->status[channel] = NVL_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_nvswitch_read_external_tdiode_temperature_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info,
|
||||
NvU32 channel
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// nvswitch_therm_read_temperature
|
||||
//
|
||||
// Temperature and voltage are only available on SKUs which have thermal and
|
||||
// voltage sensors.
|
||||
//
|
||||
|
||||
NvlStatus
|
||||
nvswitch_ctrl_therm_read_temperature_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info
|
||||
)
|
||||
{
|
||||
NvU32 channel;
|
||||
NvU32 val;
|
||||
NvU32 offset;
|
||||
|
||||
if (!info->channelMask)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: No channel given in the input.\n",
|
||||
__FUNCTION__);
|
||||
|
||||
return -NVL_BAD_ARGS;
|
||||
}
|
||||
|
||||
nvswitch_os_memset(info->temperature, 0x0, sizeof(info->temperature));
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_MAX;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
_nvswitch_read_max_tsense_temperature_ls10(device, info, channel);
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_OFFSET_MAX;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
_nvswitch_read_max_tsense_temperature_ls10(device, info, channel);
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TDIODE;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
_nvswitch_read_external_tdiode_temperature_ls10(device, info, channel);
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TDIODE_OFFSET;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
_nvswitch_read_external_tdiode_temperature_ls10(device, info, channel);
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_0;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_0_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_0_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_0);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_0, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_1;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_1_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_1_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_1);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_1, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_2;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_2_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_2_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_2);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_2, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_3;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_3_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_3_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_3);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_3, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_4;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_4_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_4_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_4);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_4, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_5;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_5_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_5_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_5);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_5, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_6;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_6_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_6_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_6);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_6, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_7;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_7_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_7_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_7);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_7, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
channel = NVSWITCH_THERM_CHANNEL_LS10_TSENSE_8;
|
||||
if (info->channelMask & NVBIT(channel))
|
||||
{
|
||||
offset = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_8_TEMPERATURE_MODIFICATIONS);
|
||||
offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_8_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset);
|
||||
offset = NV_TSENSE_FXP_9_5_TO_24_8(offset);
|
||||
|
||||
val = NVSWITCH_REG_RD32(device, _THERM, _TSENSE_U2_A_0_BJT_8);
|
||||
val = DRF_VAL(_THERM, _TSENSE_U2_A_0_BJT_8, _TEMPERATURE, val);
|
||||
val = NV_TSENSE_FXP_9_5_TO_24_8(val);
|
||||
val -= offset;
|
||||
|
||||
info->temperature[channel] = val;
|
||||
info->channelMask &= ~NVBIT(channel);
|
||||
}
|
||||
|
||||
if (info->channelMask)
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR,
|
||||
"%s: ChannelMask %x absent on LS10.\n",
|
||||
__FUNCTION__, info->channelMask);
|
||||
|
||||
return -NVL_BAD_ARGS;
|
||||
}
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
NvlStatus
|
||||
nvswitch_ctrl_therm_get_temperature_limit_ls10
|
||||
(
|
||||
nvswitch_device *device,
|
||||
NVSWITCH_CTRL_GET_TEMPERATURE_LIMIT_PARAMS *info
|
||||
)
|
||||
{
|
||||
NvU32 threshold;
|
||||
NvU32 temperature;
|
||||
|
||||
threshold = nvswitch_reg_read_32(device, NV_THERM_TSENSE_THRESHOLD_TEMPERATURES);
|
||||
|
||||
switch (info->thermalEventId)
|
||||
{
|
||||
case NVSWITCH_CTRL_THERMAL_EVENT_ID_WARN:
|
||||
{
|
||||
// Get Slowdown temperature
|
||||
temperature = DRF_VAL(_THERM_TSENSE, _THRESHOLD_TEMPERATURES,
|
||||
_WARNING_TEMPERATURE, threshold);
|
||||
break;
|
||||
}
|
||||
case NVSWITCH_CTRL_THERMAL_EVENT_ID_OVERT:
|
||||
{
|
||||
// Get Shutdown temperature
|
||||
temperature = DRF_VAL(_THERM_TSENSE, _THRESHOLD_TEMPERATURES,
|
||||
_OVERTEMP_TEMPERATURE, threshold);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
NVSWITCH_PRINT(device, ERROR, "Invalid Thermal Event Id: 0x%x\n", info->thermalEventId);
|
||||
return -NVL_BAD_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
info->temperatureLimit = NV_TSENSE_FXP_9_5_TO_24_8(temperature);
|
||||
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
// Background task to monitor thermal warn and adjust link mode
|
||||
void
|
||||
nvswitch_monitor_thermal_alert_ls10
|
||||
(
|
||||
nvswitch_device *device
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user