Files
open-gpu-kernel-modules/src/common/nvswitch/kernel/inc/io_nvswitch.h
Andy Ritger 1739a20efc 515.43.04
2022-05-09 13:18:59 -07:00

438 lines
20 KiB
C

/*
* 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.
*/
#ifndef _IO_NVSWITCH_H_
#define _IO_NVSWITCH_H_
// NVSWITCH_REG_* MMIO wrappers are to be used for absolute symbolic BAR0 offset
// register references like SMC, CLOCK, BUS, and PRIV_MASTER.
//
#define NVSWITCH_REG_RD32(_d, _dev, _reg) \
( \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_RD: %s, %s (+%04x)\n", \
__FUNCTION__, \
#_dev, #_reg, NV ## _dev ## _reg) \
, \
nvswitch_reg_read_32(_d, NV##_dev##_reg) \
); \
((void)(_d))
#define NVSWITCH_REG_WR32(_d, _dev, _reg, _data) \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_WR: %s, %s (+%04x) 0x%08x\n", \
__FUNCTION__, \
#_dev, #_reg, NV ## _dev ## _reg, _data); \
nvswitch_reg_write_32(_d, NV##_dev##_reg, _data); \
((void)(_d))
//
// NVSWITCH_OFF_* MMIO wrappers are used to access a fully formed BAR0 offset.
//
#define NVSWITCH_OFF_RD32(_d, _off) \
nvswitch_reg_read_32(_d, _off); \
((void)(_d))
#define NVSWITCH_OFF_WR32(_d, _off, _data) \
nvswitch_reg_write_32(_d, _off, _data); \
((void)(_d))
#define NVSWITCH_ENGINE_DESCRIPTOR_UC_SIZE 64
#define NVSWITCH_ENGINE_DESCRIPTOR_MC_SIZE 3
#define NVSWITCH_ENGINE_INSTANCE_INVALID ((NvU32) (~0))
typedef struct engine_descriptor
{
const char *eng_name;
NvU32 eng_id; // REGISTER_RW_ENGINE_*
NvU32 eng_count;
NvU32 uc_addr[NVSWITCH_ENGINE_DESCRIPTOR_UC_SIZE];
NvU32 bc_addr;
NvU32 mc_addr[NVSWITCH_ENGINE_DESCRIPTOR_MC_SIZE];
NvU32 mc_addr_count;
} NVSWITCH_ENGINE_DESCRIPTOR_TYPE;
#define NVSWITCH_DECLARE_IO_DESCRIPTOR(_engine, _bcast) \
NVSWITCH_ENGINE_DESCRIPTOR_TYPE _engine;
#define NVSWITCH_BASE_ADDR_INVALID ((NvU32) (~0))
//
// All IP-based (0-based register manuals) engines that ever existed on *ANY*
// architecture(s) must be listed here in order to use the common IO wrappers.
// New engines need to be added here as well as in the chip-specific lists in
// their respective headers that generate chip-specific handlers.
// Absolute BAR0 offset-based units are legacy units in which the unit's offset
// in BAR0 is included in the register definition in the manuals. For these
// legacy units the discovered base is not used since it is already part of the
// register. Legacy units (e.g. PSMC, CLOCK, BUS, and PRIV_MASTER) should use
// NVSWITCH_REG_RD/WR IO wrappers.
//
#define NVSWITCH_LIST_ALL_ENGINES(_op) \
_op(XVE) \
_op(SAW) \
_op(SOE) \
_op(SMR) \
_op(GIN) \
_op(XAL) \
_op(XAL_FUNC) \
_op(XPL) \
_op(XTL) \
_op(XTL_CONFIG) \
_op(UXL) \
_op(GPU_PTOP) \
_op(PMC) \
_op(PBUS) \
_op(ROM2) \
_op(GPIO) \
_op(FSP) \
_op(SYSCTRL) \
_op(CLKS_SYS) \
_op(CLKS_SYSB) \
_op(CLKS_P0) \
_op(SAW_PM) \
_op(PCIE_PM) \
_op(PRT_PRI_HUB) \
_op(PRT_PRI_RS_CTRL) \
_op(SYS_PRI_HUB) \
_op(SYS_PRI_RS_CTRL) \
_op(SYSB_PRI_HUB) \
_op(SYSB_PRI_RS_CTRL) \
_op(PRI_MASTER_RS) \
_op(PTIMER) \
\
_op(NPG) \
_op(NPORT) \
\
_op(NVLW) \
_op(MINION) \
_op(NVLIPT) \
_op(NVLIPT_LNK) \
_op(NVLTLC) \
_op(NVLDL) \
_op(CPR) \
\
_op(NXBAR) \
_op(TILE) \
_op(TILEOUT) \
\
_op(NPG_PERFMON) \
_op(NPORT_PERFMON) \
\
_op(NVLW_PERFMON) \
_op(RX_PERFMON) \
_op(TX_PERFMON) \
\
_op(NXBAR_PERFMON) \
_op(TILE_PERFMON) \
_op(TILEOUT_PERFMON) \
#define ENGINE_ID_LIST(_eng) \
NVSWITCH_ENGINE_ID_##_eng,
//
// ENGINE_IDs are the complete list of all engines that are supported on
// *ANY* architecture(s) that may support them. Any one architecture may or
// may not understand how to operate on any one specific engine.
// Architectures that share a common ENGINE_ID are not guaranteed to have
// compatible manuals.
//
typedef enum nvswitch_engine_id
{
NVSWITCH_LIST_ALL_ENGINES(ENGINE_ID_LIST)
NVSWITCH_ENGINE_ID_SIZE,
} NVSWITCH_ENGINE_ID;
//
// NVSWITCH_ENG_* MMIO wrappers are to be used for top level discovered
// devices like SAW, FUSE, PMGR, XVE, etc.
//
#define NVSWITCH_GET_ENG_DESC_TYPE 0
#define NVSWITCH_GET_ENG_DESC_TYPE_UNICAST NVSWITCH_GET_ENG_DESC_TYPE
#define NVSWITCH_GET_ENG_DESC_TYPE_BCAST 1
#define NVSWITCH_GET_ENG_DESC_TYPE_MULTICAST 2
#define NVSWITCH_GET_ENG(_d, _eng, _bcast, _engidx) \
((_d)->hal.nvswitch_get_eng_base( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast, \
_engidx))
#define NVSWITCH_ENG_COUNT(_d, _eng, _bcast) \
((_d)->hal.nvswitch_get_eng_count( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast))
#define NVSWITCH_ENG_IS_VALID(_d, _eng, _engidx) \
( \
NVSWITCH_GET_ENG(_d, _eng, , _engidx) != NVSWITCH_BASE_ADDR_INVALID \
)
#define NVSWITCH_ENG_WR32(_d, _eng, _bcast, _engidx, _dev, _reg, _data) \
{ \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_WR %s[%d]: %s, %s (%06x+%04x) 0x%08x\n", \
__FUNCTION__, \
#_eng#_bcast, _engidx, \
#_dev, #_reg, \
NVSWITCH_GET_ENG(_d, _eng, _bcast, _engidx), \
NV ## _dev ## _reg, _data); \
\
((_d)->hal.nvswitch_eng_wr( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast, \
_engidx, \
NV ## _dev ## _reg, _data)); \
}
#define NVSWITCH_ENG_RD32(_d, _eng, _bcast, _engidx, _dev, _reg) \
( \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_RD %s[%d]: %s, %s (%06x+%04x)\n", \
__FUNCTION__, \
#_eng#_bcast, _engidx, \
#_dev, #_reg, \
NVSWITCH_GET_ENG(_d, _eng, _bcast, _engidx), \
NV ## _dev ## _reg) \
, \
((_d)->hal.nvswitch_eng_rd( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast, \
_engidx, \
NV ## _dev ## _reg)) \
); \
((void)(_d))
#define NVSWITCH_ENG_WR32_IDX(_d, _eng, _bcast, _engidx, _dev, _reg, _idx, _data) \
{ \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_WR %s[%d]: %s, %s(%d) (%06x+%04x) 0x%08x\n", \
__FUNCTION__, \
#_eng#_bcast, _engidx, \
#_dev, #_reg, _idx, \
NVSWITCH_GET_ENG(_d, _eng, _bcast, _engidx), \
NV ## _dev ## _reg(_idx), _data); \
\
((_d)->hal.nvswitch_eng_wr( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast, \
_engidx, \
NV ## _dev ## _reg(_idx), _data)); \
}
#define NVSWITCH_ENG_RD32_IDX(_d, _eng, _bcast, _engidx, _dev, _reg, _idx) \
( \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_RD %s[%d]: %s, %s(%d) (%06x+%04x)\n", \
__FUNCTION__, \
#_eng#_bcast, _engidx, \
#_dev, #_reg, _idx, \
NVSWITCH_GET_ENG(_d, _eng, _bcast, _engidx), \
NV ## _dev ## _reg(_idx)) \
, \
((_d)->hal.nvswitch_eng_rd( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast, \
_engidx, \
NV ## _dev ## _reg(_idx))) \
); \
((void)(_d))
#define NVSWITCH_ENG_OFF_WR32(_d, _eng, _bcast, _engidx, _offset, _data) \
{ \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_WR %s[%d]: 0x%x (%06x+%04x) 0x%08x\n", \
__FUNCTION__, \
#_eng#_bcast, _engidx, \
_offset, \
NVSWITCH_GET_ENG(_d, _eng, _bcast, _engidx), \
_offset, _data); \
((_d)->hal.nvswitch_eng_wr( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast, \
_engidx, \
_offset, _data)); \
}
#define NVSWITCH_ENG_OFF_RD32(_d, _eng, _bcast, _engidx, _offset) \
( \
NVSWITCH_PRINT(_d, MMIO, \
"%s: MEM_RD %s[%d]: 0x%x (%06x+%04x)\n", \
__FUNCTION__, \
#_eng#_bcast, _engidx, \
_offset, \
NVSWITCH_GET_ENG(_d, _eng, _bcast, _engidx), \
_offset) \
, \
((_d)->hal.nvswitch_eng_rd( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE##_bcast, \
_engidx, \
_offset)) \
)
//
// Per-link information
//
#define NVSWITCH_MAX_LINK_COUNT 64
#define NVSWITCH_MAX_SEED_BUFFER_SIZE NVSWITCH_MAX_SEED_NUM + 1
#define NVSWITCH_MAX_INBAND_BUFFER_SIZE 256*8
#define NVSWITCH_MAX_INBAND_BITS_SENT_AT_ONCE 32
#define NVSWITCH_MAX_INBAND_BUFFER_ENTRIES NVSWITCH_MAX_INBAND_BUFFER_SIZE/NVSWITCH_MAX_INBAND_BITS_SENT_AT_ONCE
//
// Inband data structure
//
struct nvswitch_inband_data
{
// Inband bufer at sender Minion
NvU32 sendBuffer[NVSWITCH_MAX_INBAND_BUFFER_ENTRIES];
// Inband buffer at receiver Minion
NvU32 receiveBuffer[NVSWITCH_MAX_INBAND_BUFFER_ENTRIES];
// Is the current Minion a sender or receiver of Inband Data?
NvBool bIsSenderMinion;
// Bool to say fail or not
NvBool bTransferFail;
// # of transmisions done - count
// NvU32 txCount;
};
typedef struct
{
NvBool valid;
NvU32 link_clock_khz;
NvBool fatal_error_occurred;
NvBool ingress_packet_latched;
NvBool egress_packet_latched;
NvBool nea; // Near end analog
NvBool ned; // Near end digital
NvU32 lane_rxdet_status_mask;
NvBool bIsRepeaterMode;
// Minion Inband Data structure
struct nvswitch_inband_data inBandData;
} NVSWITCH_LINK_TYPE;
//
// Per link register access routines
// LINK_* MMIO wrappers are used to reference per-link engine instances
//
#define NVSWITCH_LINK_COUNT(_d) \
(nvswitch_get_num_links(_d))
#define NVSWITCH_GET_LINK_ENG_INST(_d, _linknum, _eng) \
nvswitch_get_link_eng_inst(_d, _linknum, NVSWITCH_ENGINE_ID_##_eng)
#define NVSWITCH_IS_LINK_ENG_VALID(_d, _linknum, _eng) \
( \
(NVSWITCH_GET_ENG(_d, _eng, , \
NVSWITCH_GET_LINK_ENG_INST(_d, _linknum, _eng)) \
!= NVSWITCH_BASE_ADDR_INVALID) && \
nvswitch_is_link_valid(_d, _linknum) \
)
#define NVSWITCH_LINK_OFFSET(_d, _physlinknum, _eng, _dev, _reg) \
( \
NVSWITCH_ASSERT(NVSWITCH_IS_LINK_ENG_VALID(_d, _physlinknum, _eng)) \
, \
NVSWITCH_PRINT(_d, MMIO, \
"%s: LINK_OFFSET link[%d] %s: %s,%s (+%04x)\n", \
__FUNCTION__, \
_physlinknum, \
#_eng, #_dev, #_reg, NV ## _dev ## _reg) \
, \
NVSWITCH_GET_ENG(_d, _eng, , \
NVSWITCH_GET_LINK_ENG_INST(_d, _physlinknum, _eng)) + \
NV##_dev##_reg \
)
#define NVSWITCH_LINK_WR32(_d, _physlinknum, _eng, _dev, _reg, _data) \
NVSWITCH_ASSERT(NVSWITCH_IS_LINK_ENG_VALID(_d, _physlinknum, _eng)); \
NVSWITCH_PRINT(_d, MMIO, \
"%s: LINK_WR link[%d] %s: %s,%s (+%04x) 0x%08x\n", \
__FUNCTION__, \
_physlinknum, \
#_eng, #_dev, #_reg, NV ## _dev ## _reg, _data); \
((_d)->hal.nvswitch_eng_wr( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE_UNICAST, \
NVSWITCH_GET_LINK_ENG_INST(_d, _physlinknum, _eng), \
NV ## _dev ## _reg, _data)); \
((void)(_d))
#define NVSWITCH_LINK_RD32(_d, _physlinknum, _eng, _dev, _reg) \
( \
NVSWITCH_ASSERT(NVSWITCH_IS_LINK_ENG_VALID(_d, _physlinknum, _eng)) \
, \
NVSWITCH_PRINT(_d, MMIO, \
"%s: LINK_RD link[%d] %s: %s,%s (+%04x)\n", \
__FUNCTION__, \
_physlinknum, \
#_eng, #_dev, #_reg, NV ## _dev ## _reg) \
, \
((_d)->hal.nvswitch_eng_rd( \
_d, \
NVSWITCH_ENGINE_ID_##_eng, \
NVSWITCH_GET_ENG_DESC_TYPE_UNICAST, \
NVSWITCH_GET_LINK_ENG_INST(_d, _physlinknum, _eng), \
NV ## _dev ## _reg)) \
); \
((void)(_d))
#define NVSWITCH_LINK_WR32_IDX(_d, _physlinknum, _eng, _dev, _reg, _idx, _data) \
NVSWITCH_LINK_WR32(_d, _physlinknum, _eng, _dev, _reg(_idx), _data); \
((void)(_d))
#define NVSWITCH_LINK_RD32_IDX(_d, _physlinknum, _eng, _dev, _reg, _idx) \
NVSWITCH_LINK_RD32(_d, _physlinknum, _eng, _dev, _reg(_idx)); \
((void)(_d))
#endif //_IO_NVSWITCH_H_