/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2016,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ /* You may obtain a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ /* implied. See the License for the specific language governing */ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ /// /// @file port.H /// @brief Code to support ports /// // *HWP HWP Owner: Stephen Glancy // *HWP HWP Backup: Andre Marin // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: HB:FSP #ifndef _MSS_PORT_H_ #define _MSS_PORT_H_ #include #include #include #include #include #include #include #include #include #include #include namespace mss { /// /// @brief ATTR_MSS_MVPD_FWMS getter /// @param[in] const ref to the fapi2::Target /// @param[out] uint32_t* memory to store the value /// @note Generated by gen_accessors.pl generateParameters (G) /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Mark store records from MPVD Lx /// keyword /// template<> inline fapi2::ReturnCode mvpd_fwms(const fapi2::Target& i_target, uint32_t (&o_array)[mss::MARK_STORE_COUNT]) { return mvpd_fwms(i_target, &o_array[0]); } /// /// @class Traits and policy class for port code - specialization for Nimbus. The target of registers is TARGET_TYPE_MCA. /// template<> class portTraits { public: // PORT_TYPE static constexpr enum fapi2::TargetType PORT_TYPE = fapi2::TARGET_TYPE_MCA; static constexpr uint64_t FARB0Q_REG = MCA_MBA_FARB0Q; static constexpr uint64_t FARB1Q_REG = MCA_MBA_FARB1Q; static constexpr uint64_t FARB5Q_REG = MCA_MBA_FARB5Q; static constexpr uint64_t REFRESH_REG = MCA_MBAREF0Q; static constexpr uint64_t ECC_REG = MCA_RECR; static constexpr uint64_t CAL0Q_REG = MCA_MBA_CAL0Q; static constexpr uint64_t CAL1Q_REG = MCA_MBA_CAL1Q; static constexpr uint64_t CAL2Q_REG = MCA_MBA_CAL2Q; static constexpr uint64_t CAL3Q_REG = MCA_MBA_CAL3Q; static constexpr uint64_t DSM0Q_REG = MCA_MBA_DSM0Q; static constexpr uint64_t FWMS_REG = MCA_FWMS0; static constexpr uint64_t CALFIRQ = MCA_MBACALFIRQ; static constexpr uint64_t CALFIRMASK = MCA_MBACALFIR_MASK; // Danger Will Robinson MCA_DDRPHY_PC_PER_ZCAL_CONFIG_P0 uses PHY rank ordinal numbers // which are different between PHYs. So if you're playing with this register, be sure to map rank numbers. static constexpr uint64_t PHY_ZQCAL_REG = MCA_DDRPHY_PC_PER_ZCAL_CONFIG_P0; static constexpr uint64_t PHY_PERIODIC_CAL_CONFIG_REG = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0; static constexpr uint64_t PHY_PERIODIC_CAL_RELOAD_REG = MCA_DDRPHY_PC_RELOAD_VALUE0_P0; static constexpr uint64_t PHY_CAL_TIMER_RELOAD_REG = MCA_DDRPHY_PC_CAL_TIMER_RELOAD_VALUE_P0; static constexpr uint64_t PHY_ZCAL_TIMER_RELOAD_REG = MCA_DDRPHY_PC_ZCAL_TIMER_RELOAD_VALUE_P0; static constexpr uint64_t RRQ_REG = MCA_MBA_RRQ0Q; static constexpr uint64_t WRQ_REG = MCA_MBA_WRQ0Q; static constexpr uint64_t MAGIC_NUMBER_SIM = 765; static constexpr uint64_t MAGIC_NUMBER_NOT_SIM = 196605; // DPHY01_DDRPHY_PC_RELOAD_VALUE0_P0 0x005 0x8000c0050301143f // scom 0x800(0,1)C0050301143F { # _P[0:1] // bits , scom_data , expr ; // 0:47 , 0x000000000000 , any ; # reserved // 48 , 0b0 , any ; # PERIODIC_CAL_REQ_EN // 49:63 , 0x0001 , any ; # PERIODIC_RELOAD_VALUE0 // } static constexpr uint64_t PHY_PERIODIC_CAL_RELOAD_VALUE = 0x1; enum { CFG_DDR_DPHY_NCLK = MCA_MBA_FARB5Q_CFG_DDR_DPHY_NCLK, CFG_DDR_DPHY_NCLK_LEN = MCA_MBA_FARB5Q_CFG_DDR_DPHY_NCLK_LEN, CFG_DDR_DPHY_PCLK = MCA_MBA_FARB5Q_CFG_DDR_DPHY_PCLK, CFG_DDR_DPHY_PCLK_LEN = MCA_MBA_FARB5Q_CFG_DDR_DPHY_PCLK_LEN, CFG_CCS_INST_RESET_ENABLE = MCA_MBA_FARB5Q_CFG_CCS_INST_RESET_ENABLE, CFG_DDR_RESETN = MCA_MBA_FARB5Q_CFG_DDR_RESETN, CFG_CCS_ADDR_MUX_SEL = MCA_MBA_FARB5Q_CFG_CCS_ADDR_MUX_SEL, FWMS0_MARK = MCA_FWMS0_MARK, FWMS0_EXIT_1 = MCA_FWMS0_EXIT_1, REFRESH_ENABLE = MCA_MBAREF0Q_CFG_REFRESH_ENABLE, ECC_CHECK_DISABLE = MCA_RECR_MBSECCQ_DISABLE_MEMORY_ECC_CHECK_CORRECT, ECC_CORRECT_DISABLE = MCA_RECR_MBSECCQ_DISABLE_MEMORY_ECC_CORRECT, ECC_USE_ADDR_HASH = MCA_RECR_MBSECCQ_USE_ADDRESS_HASH, PORT_FAIL_DISABLE = MCA_MBA_FARB0Q_CFG_PORT_FAIL_DISABLE, OE_ALWAYS_ON = MCA_MBA_FARB0Q_CFG_OE_ALWAYS_ON, RCD_RECOVERY_DISABLE = MCA_MBA_FARB0Q_CFG_DISABLE_RCD_RECOVERY, CAL0Q_CAL_INTERVAL_TMR0_ENABLE = MCA_MBA_CAL0Q_CFG_CAL_INTERVAL_TMR0_ENABLE, CAL0Q_TIME_BASE_TMR0 = MCA_MBA_CAL0Q_CFG_TIME_BASE_TMR0, CAL0Q_TIME_BASE_TMR0_LEN = MCA_MBA_CAL0Q_CFG_TIME_BASE_TMR0_LEN, CAL0Q_INTERVAL_COUNTER_TMR0 = MCA_MBA_CAL0Q_CFG_INTERVAL_COUNTER_TMR0, CAL0Q_INTERVAL_COUNTER_TMR0_LEN = MCA_MBA_CAL0Q_CFG_INTERVAL_COUNTER_TMR0_LEN, CAL0Q_CAL_TMR0_CAL1_ENABLE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL1_ENABLE, CAL0Q_CAL_TMR0_CAL1_TYPE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL1_TYPE, CAL0Q_CAL_TMR0_CAL1_TYPE_LEN = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL1_TYPE_LEN, CAL0Q_CAL_TMR0_CAL1_DDR_DONE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL1_DDR_DONE, CAL0Q_CAL_TMR0_CAL2_ENABLE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL2_ENABLE, CAL0Q_CAL_TMR0_CAL2_TYPE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL2_TYPE, CAL0Q_CAL_TMR0_CAL2_TYPE_LEN = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL2_TYPE_LEN, CAL0Q_CAL_TMR0_CAL2_DDR_DONE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL2_DDR_DONE, CAL0Q_CAL_TMR0_CAL3_ENABLE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL3_ENABLE, CAL0Q_CAL_TMR0_CAL3_TYPE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL3_TYPE, CAL0Q_CAL_TMR0_CAL3_TYPE_LEN = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL3_TYPE_LEN, CAL0Q_CAL_TMR0_CAL3_DDR_DONE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_CAL3_DDR_DONE, CAL0Q_CAL_TMR0_Z_SYNC = MCA_MBA_CAL0Q_CFG_CAL_TMR0_Z_SYNC, CAL0Q_CAL_TMR0_Z_SYNC_LEN = MCA_MBA_CAL0Q_CFG_CAL_TMR0_Z_SYNC_LEN, CAL0Q_CAL_TMR0_DDR_RESET_TMR = MCA_MBA_CAL0Q_CFG_CAL_TMR0_DDR_RESET_TMR, CAL0Q_CAL_TMR0_DDR_RESET_TMR_LEN = MCA_MBA_CAL0Q_CFG_CAL_TMR0_DDR_RESET_TMR_LEN, CAL0Q_CAL_TMR0_DDR_RESET_TMR_TB = MCA_MBA_CAL0Q_CFG_CAL_TMR0_DDR_RESET_TMR_TB, CAL0Q_CAL_TMR0_DDR_RESET_TMR_TB_LEN = MCA_MBA_CAL0Q_CFG_CAL_TMR0_DDR_RESET_TMR_TB_LEN, CAL0Q_CAL_TMR0_DDR_RESET_ENABLE = MCA_MBA_CAL0Q_CFG_CAL_TMR0_DDR_RESET_ENABLE, CAL0Q_CAL_TMR0_SINGLE_RANK = MCA_MBA_CAL0Q_CFG_CAL_TMR0_SINGLE_RANK, CAL0Q_RVED_51 = MCA_MBA_CAL0Q_RESERVED_51, CAL0Q_CT_1HOT_SM_ERROR = MCA_MBA_CAL0Q_INJECT_1HOT_SM_ERROR, CAL0Q_CAL_SINGLE_PORT_MODE = MCA_MBA_CAL0Q_CFG_CAL_SINGLE_PORT_MODE, CAL0Q_CAL_SINGLE_PORT_MODE_LEN = MCA_MBA_CAL0Q_CFG_CAL_SINGLE_PORT_MODE_LEN, CAL0Q_BUS_BIT = MCA_MBA_CAL0Q_DBG_BUS_BIT, CAL0Q_T_RECOVER = MCA_MBA_CAL0Q_RESET_RECOVER, CAL0Q_RANK_SM_STALL_DISABLE = MCA_MBA_CAL0Q_CFG_RANK_SM_STALL_DISABLE, CAL0Q_ENABLE_SPEC_ATTN = MCA_MBA_CAL0Q_CFG_ENABLE_SPEC_ATTN, CAL0Q_ENABLE_HOST_ATTN = MCA_MBA_CAL0Q_CFG_ENABLE_HOST_ATTN, CAL1Q_CAL_INTERVAL_TMR1_ENABLE = MCA_MBA_CAL1Q_CFG_CAL_INTERVAL_TMR1_ENABLE, CAL1Q_TIME_BASE_TMR1 = MCA_MBA_CAL1Q_CFG_TIME_BASE_TMR1, CAL1Q_TIME_BASE_TMR1_LEN = MCA_MBA_CAL1Q_CFG_TIME_BASE_TMR1_LEN, CAL1Q_INTERVAL_COUNTER_TMR1 = MCA_MBA_CAL1Q_CFG_INTERVAL_COUNTER_TMR1, CAL1Q_INTERVAL_COUNTER_TMR1_LEN = MCA_MBA_CAL1Q_CFG_INTERVAL_COUNTER_TMR1_LEN, CAL1Q_CAL_TMR1_CAL1_ENABLE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL1_ENABLE, CAL1Q_CAL_TMR1_CAL1_TYPE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL1_TYPE, CAL1Q_CAL_TMR1_CAL1_TYPE_LEN = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL1_TYPE_LEN, CAL1Q_CAL_TMR1_CAL1_DDR_DONE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL1_DDR_DONE, CAL1Q_CAL_TMR1_CAL2_ENABLE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL2_ENABLE, CAL1Q_CAL_TMR1_CAL2_TYPE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL2_TYPE, CAL1Q_CAL_TMR1_CAL2_TYPE_LEN = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL2_TYPE_LEN, CAL1Q_CAL_TMR1_CAL2_DDR_DONE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL2_DDR_DONE, CAL1Q_CAL_TMR1_CAL3_ENABLE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL3_ENABLE, CAL1Q_CAL_TMR1_CAL3_TYPE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL3_TYPE, CAL1Q_CAL_TMR1_CAL3_TYPE_LEN = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL3_TYPE_LEN, CAL1Q_CAL_TMR1_CAL3_DDR_DONE = MCA_MBA_CAL1Q_CFG_CAL_TMR1_CAL3_DDR_DONE, CAL1Q_CAL_TMR1_Z_SYNC = MCA_MBA_CAL1Q_CFG_CAL_TMR1_Z_SYNC, CAL1Q_CAL_TMR1_Z_SYNC_LEN = MCA_MBA_CAL1Q_CFG_CAL_TMR1_Z_SYNC_LEN, CAL1Q_CAL_TMR1_SINGLE_RANK = MCA_MBA_CAL1Q_CFG_CAL_TMR1_SINGLE_RANK, CAL1Q_CAL_RANK_ENABLE = MCA_MBA_CAL1Q_CFG_CAL_RANK_ENABLE, CAL1Q_CAL_RANK_ENABLE_LEN = MCA_MBA_CAL1Q_CFG_CAL_RANK_ENABLE_LEN, CAL2Q_CAL_INTERVAL_TMR2_ENABLE = MCA_MBA_CAL2Q_CFG_CAL_INTERVAL_TMR2_ENABLE, CAL2Q_TIME_BASE_TMR2 = MCA_MBA_CAL2Q_CFG_TIME_BASE_TMR2, CAL2Q_TIME_BASE_TMR2_LEN = MCA_MBA_CAL2Q_CFG_TIME_BASE_TMR2_LEN, CAL2Q_INTERVAL_COUNTER_TMR2 = MCA_MBA_CAL2Q_CFG_INTERVAL_COUNTER_TMR2, CAL2Q_INTERVAL_COUNTER_TMR2_LEN = MCA_MBA_CAL2Q_CFG_INTERVAL_COUNTER_TMR2_LEN, CAL2Q_CAL_TMR2_CAL1_ENABLE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL1_ENABLE, CAL2Q_CAL_TMR2_CAL1_TYPE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL1_TYPE, CAL2Q_CAL_TMR2_CAL1_TYPE_LEN = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL1_TYPE_LEN, CAL2Q_CAL_TMR2_CAL1_DDR_DONE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL1_DDR_DONE, CAL2Q_CAL_TMR2_CAL2_ENABLE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL2_ENABLE, CAL2Q_CAL_TMR2_CAL2_TYPE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL2_TYPE, CAL2Q_CAL_TMR2_CAL2_TYPE_LEN = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL2_TYPE_LEN, CAL2Q_CAL_TMR2_CAL2_DDR_DONE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL2_DDR_DONE, CAL2Q_CAL_TMR2_CAL3_ENABLE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL3_ENABLE, CAL2Q_CAL_TMR2_CAL3_TYPE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL3_TYPE, CAL2Q_CAL_TMR2_CAL3_TYPE_LEN = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL3_TYPE_LEN, CAL2Q_CAL_TMR2_CAL3_DDR_DONE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_CAL3_DDR_DONE, CAL2Q_CAL_TMR2_Z_SYNC = MCA_MBA_CAL2Q_CFG_CAL_TMR2_Z_SYNC, CAL2Q_CAL_TMR2_Z_SYNC_LEN = MCA_MBA_CAL2Q_CFG_CAL_TMR2_Z_SYNC_LEN, CAL2Q_CAL_TMR2_SINGLE_RANK = MCA_MBA_CAL2Q_CFG_CAL_TMR2_SINGLE_RANK, CAL2Q_CAL_TMR2_WAT_EVENT_ENABLE = MCA_MBA_CAL2Q_CFG_CAL_TMR2_WAT_EVENT_ENABLE, CAL3Q_INTERNAL_ZQ_TB = MCA_MBA_CAL3Q_CFG_INTERNAL_ZQ_TB, CAL3Q_INTERNAL_ZQ_TB_LEN = MCA_MBA_CAL3Q_CFG_INTERNAL_ZQ_TB_LEN, CAL3Q_INTERNAL_ZQ_LENGTH = MCA_MBA_CAL3Q_CFG_INTERNAL_ZQ_LENGTH, CAL3Q_INTERNAL_ZQ_LENGTH_LEN = MCA_MBA_CAL3Q_CFG_INTERNAL_ZQ_LENGTH_LEN, CAL3Q_EXTERNAL_ZQ_TB = MCA_MBA_CAL3Q_CFG_EXTERNAL_ZQ_TB, CAL3Q_EXTERNAL_ZQ_TB_LEN = MCA_MBA_CAL3Q_CFG_EXTERNAL_ZQ_TB_LEN, CAL3Q_EXTERNAL_ZQ_LENGTH = MCA_MBA_CAL3Q_CFG_EXTERNAL_ZQ_LENGTH, CAL3Q_EXTERNAL_ZQ_LENGTH_LEN = MCA_MBA_CAL3Q_CFG_EXTERNAL_ZQ_LENGTH_LEN, CAL3Q_RDCLK_SYSCLK_TB = MCA_MBA_CAL3Q_CFG_RDCLK_SYSCLK_TB, CAL3Q_RDCLK_SYSCLK_TB_LEN = MCA_MBA_CAL3Q_CFG_RDCLK_SYSCLK_TB_LEN, CAL3Q_RDCLK_SYSCLK_LENGTH = MCA_MBA_CAL3Q_CFG_RDCLK_SYSCLK_LENGTH, CAL3Q_RDCLK_SYSCLK_LENGTH_LEN = MCA_MBA_CAL3Q_CFG_RDCLK_SYSCLK_LENGTH_LEN, CAL3Q_DQS_ALIGNMENT_TB = MCA_MBA_CAL3Q_CFG_DQS_ALIGNMENT_TB, CAL3Q_DQS_ALIGNMENT_TB_LEN = MCA_MBA_CAL3Q_CFG_DQS_ALIGNMENT_TB_LEN, CAL3Q_DQS_ALIGNMENT_LENGTH = MCA_MBA_CAL3Q_CFG_DQS_ALIGNMENT_LENGTH, CAL3Q_DQS_ALIGNMENT_LENGTH_LEN = MCA_MBA_CAL3Q_CFG_DQS_ALIGNMENT_LENGTH_LEN, CAL3Q_MPR_READEYE_TB = MCA_MBA_CAL3Q_CFG_MPR_READEYE_TB, CAL3Q_MPR_READEYE_TB_LEN = MCA_MBA_CAL3Q_CFG_MPR_READEYE_TB_LEN, CAL3Q_MPR_READEYE_LENGTH = MCA_MBA_CAL3Q_CFG_MPR_READEYE_LENGTH, CAL3Q_MPR_READEYE_LENGTH_LEN = MCA_MBA_CAL3Q_CFG_MPR_READEYE_LENGTH_LEN, CAL3Q_ALL_PERIODIC_TB = MCA_MBA_CAL3Q_CFG_ALL_PERIODIC_TB, CAL3Q_ALL_PERIODIC_TB_LEN = MCA_MBA_CAL3Q_CFG_ALL_PERIODIC_TB_LEN, CAL3Q_ALL_PERIODIC_LENGTH = MCA_MBA_CAL3Q_CFG_ALL_PERIODIC_LENGTH, CAL3Q_ALL_PERIODIC_LENGTH_LEN = MCA_MBA_CAL3Q_CFG_ALL_PERIODIC_LENGTH_LEN, CAL3Q_FREEZE_ON_PARITY_ERROR_DIS = MCA_MBA_CAL3Q_CFG_FREEZE_ON_PARITY_ERROR_DIS, CALFIRQ_REFRESH_OVERRUN = MCA_MBACALFIRQ_REFRESH_OVERRUN, CALFIRMASK_REFRESH_OVERRUN = MCA_MBACALFIR_MASK_REFRESH_OVERRUN, RECR_ENABLE_UE_NOISE_WINDOW = MCA_RECR_MBSECCQ_ENABLE_UE_NOISE_WINDOW, RECR_TCE_CORRECTION = MCA_RECR_MBSECCQ_ENABLE_TCE_CORRECTION, RECR_READ_POINTER_DLY = MCA_RECR_MBSECCQ_READ_POINTER_DELAY, RECR_READ_POINTER_DLY_LEN = MCA_RECR_MBSECCQ_READ_POINTER_DELAY_LEN, RECR_MBSECCQ_DATA_INVERSION = MCA_RECR_MBSECCQ_DATA_INVERSION, RECR_MBSECCQ_DATA_INVERSION_LEN = MCA_RECR_MBSECCQ_DATA_INVERSION_LEN, DSM0Q_RDTAG_DLY = MCA_MBA_DSM0Q_CFG_RDTAG_DLY, DSM0Q_RDTAG_DLY_LEN = MCA_MBA_DSM0Q_CFG_RDTAG_DLY_LEN, DSM0Q_WRDONE_DLY = MCA_MBA_DSM0Q_CFG_WRDONE_DLY, DSM0Q_WRDONE_DLY_LEN = MCA_MBA_DSM0Q_CFG_WRDONE_DLY_LEN, FARB0Q_RCD_PROTECTION_TIME = MCA_MBA_FARB0Q_CFG_RCD_PROTECTION_TIME, FARB0Q_RCD_PROTECTION_TIME_LEN = MCA_MBA_FARB0Q_CFG_RCD_PROTECTION_TIME_LEN, FARB1Q_CFG_DDR4_PARITY_ON_CID_DIS = MCA_MBA_FARB1Q_CFG_DDR4_PARITY_ON_CID_DIS, PER_ZCAL_ENA_RANK = MCA_DDRPHY_PC_PER_ZCAL_CONFIG_P0_ENA_RANK, PER_ZCAL_ENA_RANK_LEN = MCA_DDRPHY_PC_PER_ZCAL_CONFIG_P0_ENA_RANK_LEN, PER_ZCAL_NEXT_RANK = MCA_DDRPHY_PC_PER_ZCAL_CONFIG_P0_NEXT_RANK, PER_ZCAL_NEXT_RANK_LEN = MCA_DDRPHY_PC_PER_ZCAL_CONFIG_P0_NEXT_RANK_LEN, PER_ZCAL_START = MCA_DDRPHY_PC_PER_ZCAL_CONFIG_P0_START, ZCAL_TIMER_RELOAD_VALUE = MCA_DDRPHY_PC_ZCAL_TIMER_RELOAD_VALUE_P0_PERIODIC, ZCAL_TIMER_RELOAD_VALUE_LEN = MCA_DDRPHY_PC_ZCAL_TIMER_RELOAD_VALUE_P0_PERIODIC_LEN, PC_CAL_TIMER_RELOAD_VALUE = MCA_DDRPHY_PC_CAL_TIMER_RELOAD_VALUE_P0_PERIODIC, PC_CAL_TIMER_RELOAD_VALUE_LEN = MCA_DDRPHY_PC_CAL_TIMER_RELOAD_VALUE_P0_PERIODIC_LEN, PER_ENA_RANK_PAIR = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ENA_RANK_PAIR, PER_ENA_RANK_PAIR_LEN = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ENA_RANK_PAIR_LEN, PER_ENA_ZCAL = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ENA_ZCAL, PER_ENA_SYSCLK_ALIGN = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ENA_SYSCLK_ALIGN, PER_ENA_READ_CTR = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ENA_READ_CTR, PER_ENA_RDCLK_ALIGN = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ENA_RDCLK_ALIGN, PER_ENA_DQS_ALIGN = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ENA_DQS_ALIGN, PER_NEXT_RANK_PAIR = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_NEXT_RANK_PAIR, PER_NEXT_RANK_PAIR_LEN = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_NEXT_RANK_PAIR_LEN, PER_FAST_SIM_CNTR = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_FAST_SIM_CNTR, PER_START_INIT = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_START_INIT, PER_START = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_START, PER_ABORT_ON_ERR_EN = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_ABORT_ON_ERR_EN, PER_DD2_FIX_DIS = MCA_DDRPHY_PC_PER_CAL_CONFIG_P0_DD2_FIX_DIS, RRQ_FIFO_MODE = MCA_MBA_RRQ0Q_CFG_RRQ_FIFO_MODE, WRQ_FIFO_MODE = MCA_MBA_WRQ0Q_CFG_WRQ_FIFO_MODE, }; }; /// /// @brief Sets ecc_check_disable in buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in,out] io_data the target data buffer /// @param[in] i_value ECC_CHECK_DISABLE value (on or off) to set /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void set_ecc_check_disable( fapi2::buffer& io_data, const mss::states i_value ) { FAPI_INF( "Set ECC_CHECK_DISABLE to %lu", i_value); io_data.template writeBit(i_value); } /// /// @brief Get the read pointer delay value from RECR /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_data the data buffer containing the RECR register /// @param[out] o_delay READ_POINTER_DLY value (in cycles) /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void get_read_pointer_delay( const fapi2::buffer& i_data, uint64_t& o_delay ) { i_data.template extractToRight(o_delay); FAPI_INF( "READ_POINTER_DLY: 0x%016lx", uint64_t(o_delay) ); } /// /// @brief Sets read pointer delay in buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in,out] io_data the target data buffer /// @param[in] i_delay READ_POINTER_DLY value (in cycles) to set /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void set_read_pointer_delay( fapi2::buffer& io_data, const uint64_t i_delay ) { FAPI_INF( "Set READ_POINTER_DLY to %d", i_delay); io_data.template insertFromRight(i_delay); } /// /// @brief Get the enable_ue_noise_window value from buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_data the data buffer containing the RECR register /// @param[out] o_value ENABLE_UE_NOISE_WINDOW value (on or off) /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void get_enable_ue_noise_window( const fapi2::buffer& i_data, mss::states& o_value ) { o_value = (i_data.template getBit()) ? mss::states::ON : mss::states::OFF; FAPI_INF( "ENABLE_UE_NOISE_WINDOW: %lu", o_value ); } /// /// @brief Sets enable_ue_noise_window in buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in,out] io_data the target data buffer /// @param[in] i_value ENABLE_UE_NOISE_WINDOW value (on or off) to set /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void set_enable_ue_noise_window( fapi2::buffer& io_data, const mss::states i_value ) { FAPI_INF( "Set ENABLE_UE_NOISE_WINDOW to %lu", i_value); io_data.template writeBit(i_value); } /// /// @brief Setup read pointer delay and TCE correction /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > fapi2::ReturnCode setup_read_pointer_delay (const fapi2::Target& i_target) { constexpr uint64_t MNFG_REPAIRS_DISABLED_ATTR = 56; fapi2::buffer l_data; fapi2::buffer l_mnfg_buffer; mss::states l_state = mss::OFF; FAPI_TRY( mss::read_recr_register(i_target, l_data ), "%s: Failed read_recr_register", mss::c_str(i_target)); mss::set_read_pointer_delay(l_data, mss::ON); // Check for manufacturing disable dram repair flag to disable TCE correction FAPI_TRY( mss::mnfg_flags(l_mnfg_buffer), "%s: Failed mnfg_flags check", mss::c_str(i_target) ); l_state = ( l_mnfg_buffer.getBit() ) ? mss::OFF : mss::ON; mss::set_tce_correction(l_data, l_state); FAPI_TRY( mss::write_recr_register(i_target, l_data), "%s: Failed write_recr_register", mss::c_str(i_target)); fapi_try_exit: return fapi2::current_err; } /// /// @brief Read the data state machine register /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[out] o_delay the buffer to write the register data into /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode read_dsm0q_register( const fapi2::Target& i_target, fapi2::buffer& o_delay ) { FAPI_TRY( mss::getScom(i_target, TT::DSM0Q_REG, o_delay) ); FAPI_INF( "Data State machine register is %d for %s", uint64_t(o_delay), mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Write to dsm0q register /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_delay the buffer that holds the register data to write /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode write_dsm0q_register( const fapi2::Target& i_target, const fapi2::buffer i_delay ) { FAPI_INF( "Change Data State machine register to %d for %s", i_delay, mss::c_str(i_target) ); FAPI_TRY( mss::putScom(i_target, TT::DSM0Q_REG, i_delay) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Get the wrdone delay value from DSM0Q /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_data the data buffer containing the DSM0Q register /// @param[out] o_delay WRDONE_DLY value (in cycles) /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void get_wrdone_delay( const fapi2::buffer& i_data, uint64_t& o_delay ) { i_data.template extractToRight(o_delay); FAPI_INF( "WRDONE_DLY: %d ", uint64_t(o_delay) ); } /// /// @brief Sets wrdone delay in buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_delay WRDONE_DLY value (in cycles) to set /// @param[in,out] io_data the target data buffer /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void set_wrdone_delay( const uint64_t i_delay, fapi2::buffer& io_data ) { FAPI_INF( "Set WRDONE_DLY to %d ", i_delay); io_data.template insertFromRight(i_delay); } /// /// @brief Change the wrdone delay value /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_delay WRDONE_DLY value (in cycles) to set /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode change_wrdone_delay( const fapi2::Target& i_target, const uint64_t i_delay ) { fapi2::buffer l_data; FAPI_DBG( "Change WRDONE_DLY to %d for %s", i_delay, mss::c_str(i_target) ); FAPI_TRY( read_dsm0q_register(i_target, l_data) ); set_wrdone_delay(i_delay, l_data); FAPI_TRY( write_dsm0q_register(i_target, l_data) ); FAPI_INF( "DSM0Q_REG 0x%016lx for %s", uint64_t(l_data), mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Get the rdtag delay value /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_data the data buffer containing the DSM0Q register /// @param[out] o_delay RDTAG_DLY value (in cycles) /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void get_rdtag_delay( const fapi2::buffer& i_data, uint64_t& o_delay ) { i_data.template extractToRight(o_delay); FAPI_INF( "RDTAG_DLY: %d ", uint64_t(o_delay) ); } /// /// @brief Sets rdtag delay in buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_delay RDTAG_DLY value (in cycles) to set /// @param[in,out] io_data the target data buffer /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void set_rdtag_delay( const uint64_t i_delay, fapi2::buffer& io_data ) { FAPI_DBG( "Set RDTAG_DLY to %d ", i_delay); io_data.template insertFromRight(i_delay); } /// /// @brief Change the rdtag delay value /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_delay new RDTAG_DLY value (in cycles) to set /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode change_rdtag_delay( const fapi2::Target& i_target, const uint64_t i_delay ) { fapi2::buffer l_data; FAPI_DBG( "Change RDTAG_DLY to %d for %s", i_delay, mss::c_str(i_target) ); FAPI_TRY( read_dsm0q_register(i_target, l_data) ); set_rdtag_delay(i_delay, l_data); FAPI_TRY( write_dsm0q_register(i_target, l_data) ); FAPI_INF( "DSM0Q_REG 0x%016lx for %s", uint64_t(l_data), mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Read to FARB0Q register /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[out] o_time the buffer to read the register data into /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode read_farb0q_register( const fapi2::Target& i_target, fapi2::buffer& o_time ) { FAPI_TRY( mss::getScom(i_target, TT::FARB0Q_REG, o_time) ); FAPI_INF( "FARB0Q is %d for %s", uint64_t(o_time), mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Write to FARB0Q register /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_delay the buffer containing the data to be written /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode write_farb0q_register( const fapi2::Target& i_target, const fapi2::buffer i_time ) { FAPI_INF( "Change FARB0Q_REG to 0x%016lx for %s", uint64_t(i_time), mss::c_str(i_target) ); FAPI_TRY( mss::putScom(i_target, TT::FARB0Q_REG, i_time) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Read to FARB1Q register /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[out] o_time the buffer to read the register data into /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode read_farb1q_register( const fapi2::Target& i_target, fapi2::buffer& o_time ) { FAPI_TRY( mss::getScom(i_target, TT::FARB1Q_REG, o_time) ); FAPI_INF( "FARB1Q is %d for %s", uint64_t(o_time), mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Write to FARB1Q register /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_delay the buffer containing the data to be written /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode write_farb1q_register( const fapi2::Target& i_target, const fapi2::buffer i_time ) { FAPI_INF( "Change FARB1Q_REG to 1x%116lx for %s", uint64_t(i_time), mss::c_str(i_target) ); FAPI_TRY( mss::putScom(i_target, TT::FARB1Q_REG, i_time) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Get the CID parity disable value from the buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_data the data buffer containing the DSM0Q register /// @param[out] o_value the CID parity value - use OFF_N or ON_N /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void get_cid_parity( const fapi2::buffer& i_data, mss::states& o_value ) { const auto l_value = i_data.template getBit(); o_value = l_value ? mss::states::OFF_N : mss::states::ON_N; FAPI_INF( "CID_PARITY value: %s ", l_value ? "disabled" : "enabled" ); } /// /// @brief Sets the CID parity disable value in the buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_value the CID parity disable value to set - use ON_N or OFF_N /// @param[in,out] io_data the target data buffer /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void set_cid_parity( const mss::states i_value, fapi2::buffer& io_data ) { FAPI_DBG( "Set CID_PARITY to %d ", i_value); io_data.template writeBit(i_value == mss::states::OFF_N ? true : false); } /// /// @brief Configures the CID parity disable value /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode configure_cid_parity( const fapi2::Target& i_target) { fapi2::buffer l_data; mss::states l_state = mss::states::ON_N; uint8_t l_master_ranks[MAX_DIMM_PER_PORT] = {}; FAPI_TRY(eff_num_master_ranks_per_dimm(i_target, l_master_ranks)); // If we have either DIMM having four ranks, we need to disable parity mode if((l_master_ranks[0] == 4) || (l_master_ranks[1] == 4)) { l_state = mss::states::OFF_N; } FAPI_DBG( "Change CID_PARITY to %d for %s", l_state, mss::c_str(i_target) ); FAPI_TRY( read_farb1q_register(i_target, l_data) ); set_cid_parity(l_state, l_data); FAPI_TRY( write_farb1q_register(i_target, l_data) ); FAPI_INF( "FARB1Q_REG 0x%016lx for %s", uint64_t(l_data), mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Get the RCD Protect Time value /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_data the data buffer containing the FARB0Q register /// @param[out] o_time RCD_PROTECT_TIME value (in cycles) /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void get_rcd_protect_time( const fapi2::buffer& i_data, uint64_t& o_time ) { i_data.template extractToRight(o_time); FAPI_INF( "RCD_PROTECT_TIME: %d", uint64_t(o_time) ); } /// /// @brief Sets RCD Protect Time in buffer /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_delay RCD Protect Time value (in cycles) to set /// @param[in,out] io_data the target data buffer /// template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = portTraits > void set_rcd_protect_time( const uint64_t i_time, fapi2::buffer& io_data ) { FAPI_DBG( "Set RCD_PROTECT_TIME to %d ", i_time); io_data.template insertFromRight(i_time); } /// /// @brief Change the RCD Protect Time value /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_time RCD Protect Time value (in cycles) to set /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode change_rcd_protect_time( const fapi2::Target& i_target, const uint64_t i_time ) { fapi2::buffer l_data; FAPI_TRY( read_farb0q_register(i_target, l_data) ); set_rcd_protect_time(i_time, l_data); FAPI_TRY( write_farb0q_register(i_target, l_data) ); FAPI_INF( "RCD_PROTECT_TIME %d for %s", uint64_t(i_time), mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Change the state of the RCD recovery bit /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_state the state /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode change_rcd_recovery_disable( const fapi2::Target& i_target, states i_state ) { fapi2::buffer l_data; FAPI_DBG("Change rcd recovery disable to %s %s", (i_state == HIGH ? "high" : "low"), mss::c_str(i_target)); FAPI_TRY( mss::getScom(i_target, TT::FARB0Q_REG, l_data) ); l_data.writeBit(i_state); FAPI_TRY( mss::putScom(i_target, TT::FARB0Q_REG, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Change the state of the output enable always-on bit /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @param[in] i_state the state /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode change_oe_always_on( const fapi2::Target& i_target, states i_state ) { fapi2::buffer l_data; FAPI_DBG("Change OE always on to %s %s", (i_state == HIGH ? "high" : "low"), mss::c_str(i_target)); FAPI_TRY( mss::getScom(i_target, TT::FARB0Q_REG, l_data) ); l_data.writeBit(i_state); FAPI_TRY( mss::putScom(i_target, TT::FARB0Q_REG, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Enable the MC Periodic calibration functionality /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target the target /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode enable_periodic_cal( const fapi2::Target& i_target ); /// /// @brief Enable the MC Periodic calibration functionality - MCA specialization /// @param[in] i_target the target /// @return FAPI2_RC_SUCCESS if and only if ok /// template<> fapi2::ReturnCode enable_periodic_cal( const fapi2::Target& i_target ); /// /// @brief Change the state of the force_str bit - mc_type::NIMBUS specialization /// @tparam MC the memory controller type /// @param[in] i_target the target /// @param[in] i_state the state /// @return FAPI2_RC_SUCCESS if and only if ok /// @note This bit doesn't exist on Nimbus, so this is a no-op /// template<> inline fapi2::ReturnCode change_force_str( const fapi2::Target& i_target, const states i_state ) { return fapi2::FAPI2_RC_SUCCESS; } // // We expect to come in to draminit with the following setup: // 1. ENABLE_RESET_N (FARB5Q(6)) 0 // 2. RESET_N (FARB5Q(4)) 1 - out of reset (done in draminit as a separate step) // 3. CCS_ADDR_MUX_SEL (FARB5Q(5)) - 1 // 4. CKE out of high impedence // Note: Ignore resetn as it's taken care of as a separate step // /// /// @brief Secure the entry criteria for draminit /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target A target representing a port /// @return FAPI2_RC_SUCCESS if and only if ok // This is in this header as it's hoped to be able to be shared. Seems to make more // Might make more sense in p9_mss_draminit.C ... BRS /// template< fapi2::TargetType T, typename TT = portTraits > inline fapi2::ReturnCode draminit_entry_invariant( const fapi2::Target& i_target ) { fapi2::buffer l_data; FAPI_TRY( mss::getScom(i_target, TT::FARB5Q_REG, l_data) ); if ((l_data.getBit() != HIGH) || (l_data.getBit() != LOW)) { // We have some bits not set correctly. Lets try to reset the register. FAPI_INF("FARB5Q: 0x%llx, setting MUX_SEL, clearing RESET_ENABLE", uint64_t(l_data)); l_data.setBit(); l_data.clearBit(); FAPI_TRY( mss::putScom(i_target, TT::FARB5Q_REG, l_data) ); } fapi_try_exit: return fapi2::current_err; } /// /// @brief Drive memory clocks /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target A target representing a port /// @param[in] i_pclk phy p clock - right most 2 bits /// @param[in] i_nclk phy n clock - right most 2 bits /// @return FAPI2_RC_SUCCESS if and only if ok /// @note this might need a port id added for Centaur/MBA controllers /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode drive_mem_clks( const fapi2::Target& i_target, const uint64_t i_pclk, const uint64_t i_nclk ) { fapi2::buffer l_data; FAPI_INF("Drive mem clocks pclk: 0x%x nclk 0x%x", i_pclk, i_nclk); FAPI_TRY( mss::getScom(i_target, TT::FARB5Q_REG, l_data) ); l_data.insertFromRight(i_nclk); l_data.insertFromRight(i_pclk); FAPI_TRY( mss::putScom(i_target, TT::FARB5Q_REG, l_data) ); return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: FAPI_ERR("Unable to drive mem clocks: %s", mss::c_str(i_target)); return fapi2::current_err; } /// /// @brief Set DDR resetn /// @tparam T the fapi2 target type of the target /// @tparam TT the class traits for the port /// @param[in] i_target A target representing a port /// @param[in] i_state high or low /// @return FAPI2_RC_SUCCESS if and only if ok /// @note this might need a port id added for Centaur/MBA controllers /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode ddr_resetn( const fapi2::Target& i_target, const bool i_state ) { fapi2::buffer l_data; FAPI_TRY( mss::getScom(i_target, TT::FARB5Q_REG, l_data) ); if (l_data.getBit() != i_state) { l_data.writeBit(i_state); FAPI_DBG("ddr_resetn transitioning to %d (0x%llx)", i_state, l_data); FAPI_TRY( mss::putScom(i_target, TT::FARB5Q_REG, l_data) ); } // From the DDR4 JEDEC Spec (79-A): Power-up Initialization Sequence // After RESET_n is de-asserted, wait for another 500us before CKE goes active. // Set our delay (for HW and SIM) { constexpr uint64_t DELAY_500US = 5 * mss::DELAY_100US; // Setting sim cycles for 500 us is too long for VBU, // so we set it to the smallest possible value that passes sim FAPI_TRY( fapi2::delay(DELAY_500US, mss::us_to_cycles(i_target, mss::DELAY_1NS)) ); } return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: FAPI_ERR("Unable to change resetn: %s (%d)", mss::c_str(i_target), i_state); return fapi2::current_err; } /// /// @brief Reset the ZCAL config register. /// @warning This maps PHY rank numbers per target /// @tparam T, the fapi2 target type of the target /// @param[in] i_target A target representing a port /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, typename TT = portTraits > fapi2::ReturnCode reset_zqcal_config( const fapi2::Target& i_target ) { fapi2::buffer l_phy_zqcal_config; std::vector l_ranks; FAPI_TRY( mss::rank::ranks(i_target, l_ranks) ); for (const auto r : l_ranks) { uint64_t l_phy_rank = 0; FAPI_TRY(rank::map_rank_ordinal_to_phy(i_target, r, l_phy_rank)) // Only add on an additional rank if we have a valid rank if(l_phy_rank != NO_RANK) { FAPI_TRY(l_phy_zqcal_config.setBit(TT::PER_ZCAL_ENA_RANK + l_phy_rank)); } } // Write the ZQCAL periodic config FAPI_INF("zcal periodic config: 0x%016lx", l_phy_zqcal_config); FAPI_TRY( mss::putScom(i_target, TT::PHY_ZQCAL_REG, l_phy_zqcal_config) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Convert a bitmap from the BAD_DQ_BITMAP attribute to a vector of bad DQ indexes /// @param[in] i_bad_bits an 8-bit bitmap of bad bits /// @param[in] i_nibble which nibble of the bitmap to convert /// @return std::vector of DQ bits marked as bad in the bitmap /// std::vector bad_bit_helper(const uint8_t i_bad_bits, const size_t i_nibble); /// /// @brief Place a symbol mark in a Firmware Mark Store register /// @tparam T, the fapi2 target type of the DIMM (derived) /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the bad DQ bit /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T > fapi2::ReturnCode place_symbol_mark(const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq); /// /// @brief Place a chip mark in a Hardware Mark Store register /// @tparam T, the fapi2 target type of the DIMM (derived) /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bits in the bad nibble /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T > fapi2::ReturnCode place_chip_mark(const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq); // Forward declaration for use in repair_state classes template< fapi2::TargetType T > class repair_state_machine; /// /// @class mss::repair_state /// @brief A class for keeping track of bad bit repair states in a repair_state_machine /// @tparam T, the fapi2 target type of the DIMM /// @note this is a base class /// template< fapi2::TargetType T > class repair_state { public: /// @brief default contructor repair_state() = default; /// @brief default destructor virtual ~repair_state() = default; /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the DQ bit index /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// virtual fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) = 0; /// /// @brief Perform a repair for multiple bad DQ bits in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bit indexes /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// virtual fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) = 0; protected: /// /// @brief Set a new state in the repair state machine /// @param[in,out] io_machine the repair state machine /// @param[in] i_state pointer to the new state to set /// void set_state(repair_state_machine& io_machine, std::shared_ptr> i_state); }; /// /// @class mss::no_fails /// @brief repair_state class for no fails (no marks applied) /// @tparam T, the fapi2 target type of the DIMM /// template< fapi2::TargetType T > class no_fails : public repair_state { public: /// @brief default contructor no_fails() = default; /// @brief default destructor ~no_fails() = default; /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the DQ bit index /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; /// /// @brief Perform a repair for multiple bad DQ bits in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bit indexes /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; }; /// /// @class mss::symbol_mark_only /// @brief repair_state class for when only a symbol mark has been used /// @tparam T, the fapi2 target type of the DIMM /// template< fapi2::TargetType T > class symbol_mark_only : public repair_state { public: /// @brief default contructor symbol_mark_only() = default; /// @brief default destructor ~symbol_mark_only() = default; /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the DQ bit index /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; /// /// @brief Perform a repair for multiple bad DQ bits in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bit indexes /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; }; /// /// @class mss::symbol_mark_plus_unrepaired_dq /// @brief repair_state class for when only a symbol mark has been used, and one DQ bit remains unrepaired /// @tparam T, the fapi2 target type of the DIMM /// template< fapi2::TargetType T > class symbol_mark_plus_unrepaired_dq : public repair_state { public: /// @brief default contructor symbol_mark_plus_unrepaired_dq() = default; /// @brief default destructor ~symbol_mark_plus_unrepaired_dq() = default; /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the DQ bit index /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; /// /// @brief Perform a repair for multiple bad DQ bits in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bit indexes /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; }; /// /// @class mss::chip_mark_only /// @brief repair_state class for when only a chip mark has been used /// @tparam T, the fapi2 target type of the DIMM /// template< fapi2::TargetType T > class chip_mark_only : public repair_state { public: /// @brief default contructor chip_mark_only() = default; /// @brief default destructor ~chip_mark_only() = default; /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the DQ bit index /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; /// /// @brief Perform a repair for multiple bad DQ bits in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bit indexes /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; }; /// /// @class mss::chip_mark_only /// @brief repair_state class for when both a chip mark and a symbol mark have been used /// @tparam T, the fapi2 target type of the DIMM /// template< fapi2::TargetType T > class chip_and_symbol_mark : public repair_state { public: /// @brief default contructor chip_and_symbol_mark() = default; /// @brief default destructor ~chip_and_symbol_mark() = default; /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the DQ bit index /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; /// /// @brief Perform a repair for multiple bad DQ bits in a nibble /// @param[in,out] io_machine the repair state machine /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bit indexes /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded) override; }; /// /// @class mss::repair_state_machine /// @brief state machine class used in restore_repairs_helper /// @tparam T, the fapi2 target type of the DIMM /// template< fapi2::TargetType T > class repair_state_machine { public: /// @brief constructor repair_state_machine() : iv_repair_state(std::make_shared>()) {} /// @brief default destructor ~repair_state_machine() = default; /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq the DQ bit index /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode one_bad_dq(const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded); /// /// @brief Perform a repair for multiple bad DQ bits in a nibble /// @param[in] i_target the DIMM target /// @param[in] i_rank the rank /// @param[in] i_dq one of the bad DQ bit indexes /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode multiple_bad_dq(const fapi2::Target& i_target, const uint64_t i_rank, const uint64_t i_dq, fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded); /// /// @brief Update the state of the state machine /// @param[in] i_state shared pointer to the new state /// void update_state(std::shared_ptr> i_state) { iv_repair_state = i_state; } private: std::shared_ptr> iv_repair_state; }; // TODO RTC: 157753 tparam R can be pulled from an MCA trait once we have it /// /// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute, helper function for unit testing /// @tparam T, the fapi2 target type of the DIMM (derived) /// @tparam R the maximum rank per DIMM /// @tparam B the number of bytes per rank in the bad_dq_bitmap attribute /// @param[in] i_target A target representing a DIMM /// @param[in] i_bad_bits the bad bits values from the VPD, for the specified DIMM /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T, uint64_t R, uint64_t B > fapi2::ReturnCode restore_repairs_helper( const fapi2::Target& i_target, const uint8_t i_bad_bits[R][B], fapi2::buffer& io_repairs_applied, fapi2::buffer& io_repairs_exceeded); /// /// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute /// @tparam T, the fapi2 target type of the port (derived) /// @param[in] i_target A target representing a port /// @param[out] o_repairs_applied bit mask, where a bit set means a rank had repairs applied (bit0 = rank0, etc) /// @param[out] o_repairs_exceeded bit mask, where a bit set means a DIMM had more bad bits than could be repaired (bit0 = DIMM0 etc) /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T > fapi2::ReturnCode restore_repairs( const fapi2::Target& i_target, fapi2::buffer& o_repairs_applied, fapi2::buffer& o_repairs_exceeded); /// @brief Get the attributes for the reorder queue setting /// @param[in] const ref to the mc target /// @param[out] uint8_t& reference to store the value /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Contains the settings for write/read reorder /// queue /// template< > inline fapi2::ReturnCode reorder_queue_setting(const fapi2::Target& i_target, uint8_t& o_value) { return mss::reorder_queue_setting(i_target, o_value); } }// mss #endif