/* * 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_