diff options
author | Andre Marin <aamarin@us.ibm.com> | 2017-02-09 12:48:41 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-07-26 00:26:28 -0400 |
commit | 7b5b072e03694fa9f9b72cfd761b8b384734541a (patch) | |
tree | 47eb7d8b57f122b25a9a5be11fc86410bf63cd02 /src/import/chips | |
parent | 59bc3c6833ea12e8775e8184ef72da92dc85c07c (diff) | |
download | talos-hostboot-7b5b072e03694fa9f9b72cfd761b8b384734541a.tar.gz talos-hostboot-7b5b072e03694fa9f9b72cfd761b8b384734541a.zip |
Add initial p9c ddr_phy_reset, dimmBadDqBitmapAccessHwp, slew, & unmask_errors
Change-Id: I277496652e951e67dc2f3815633432cb00a02c62
Original-Change-Id: I1cbe3225208e6ee6c107ff84a9ebbb6248f0c7b8
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35429
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43533
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips')
14 files changed, 4627 insertions, 0 deletions
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C new file mode 100644 index 000000000..92b8eaff3 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C @@ -0,0 +1,605 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_dimmBadDqBitmapAccessHwp.C +/// @brief FW Team HWP that accesses the Bad DQ Bitmap. +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB:CI +/// + +#include <fapi2.H> +#include <p9c_dimmBadDqBitmapAccessHwp.H> + +// DQ Data format in DIMM SPD +enum dq_data : size_t +{ + DIMM_BAD_DQ_MAGIC_NUMBER = 0xbadd4471, + DIMM_BAD_DQ_VERSION = 1, + ECC_DQ_BYTE_NUMBER_INDEX = 8, + SPARE_DRAM_DQ_BYTE_NUMBER_INDEX = 9, +}; + +/// +/// @class dimmBadDqDataFormat +/// @brief Structure that holds bad DQ data +/// +struct dimmBadDqDataFormat +{ + uint32_t iv_magicNumber; + uint8_t iv_version; + uint8_t iv_reserved1; + uint8_t iv_reserved2; + uint8_t iv_reserved3; + uint8_t iv_bitmaps[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]; + + /// + /// @brief default ctor + /// + dimmBadDqDataFormat() = default; + + /// + /// @brief default dtor + /// + ~dimmBadDqDataFormat() = default; +}; + +extern "C" +{ + + /// + /// @brief Returns bits for unconnected spare DRAM. + /// @param[in] i_mba Reference to MBA + /// @param[in] i_dimm Reference to DIMM + /// @param[out] o_spareByte Reference to the spare byte returned to caller. + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode dimmGetDqBitmapSpareByte(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, + uint8_t (&o_spareByte)[MAX_RANKS_PER_DIMM]) + { + // Spare DRAM Attribute: Returns spare DRAM availability for + // all DIMMs associated with the target MBA. + uint8_t l_mbaSpare[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {}; + uint8_t l_mbaPort = 0; + uint8_t l_dimm = 0; + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DIMM_SPARE, i_mba, l_mbaSpare)); + // Find the mba port this dimm is connected to + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_PORT, i_dimm, l_mbaPort)); + // Find the dimm number associated with this dimm + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_DIMM, i_dimm, l_dimm)); + + // Iterate through each rank of this DIMM + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + // Handle spare DRAM configuration cases + switch (l_mbaSpare[l_mbaPort][l_dimm][i]) + { + case fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_NO_SPARE: + // Set DQ bits reflecting unconnected + // spare DRAM in caller's data + o_spareByte[i] = 0xFF; + break; + + case fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_LOW_NIBBLE: + o_spareByte[i] = 0x0F; + break; + + case fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_HIGH_NIBBLE: + o_spareByte[i] = 0xF0; + break; + + // As erroneous value will not be encountered. + case fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_FULL_BYTE: + default: + o_spareByte[i] = 0x0; + break; + } + } + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Called by dimmBadDqBitmapAccessHwp() to query ATTR_EFF_DIMM_SPARE + /// and set bits for unconnected spare DRAM in caller's data. + /// @param[in] i_mba Reference to MBA Target + /// @param[in] i_dimm Reference to DIMM Target + /// @param[out] o_data Reference to Bad DQ Bitmap set by + /// the caller. Only the SPARE_DRAM_DQ_BYTE_NUMBER_INDEX + /// byte is modified by this function. + /// @return FAPI2_RC_SUCCESS iff okay + /// + + fapi2::ReturnCode dimmUpdateDqBitmapSpareByte(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, + uint8_t (&o_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]) + { + + uint8_t spareByte[MAX_RANKS_PER_DIMM] = {}; + memset(spareByte, 0, sizeof(spareByte)); + + FAPI_TRY(dimmGetDqBitmapSpareByte(i_mba, i_dimm, spareByte)); + + for (uint32_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] |= spareByte[i]; + } + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Called by dimmBadDqBitmapAccessHwp() to query + /// ATTR_SPD_MODULE_MEMORY_BUS_WIDTH in order to determine + /// ECC support for this DIMM. This function will set + /// bits in the caller's data if ECC lines are not present. + /// @param[in] i_dimm Reference to DIMM Target<fapi2::TARGET_TYPE_MBA>. + /// @param[out] o_data Reference to Bad DQ Bitmap set by + /// the caller. Only the ECC_DQ_BYTE_NUMBER_INDEX + /// byte is modified by this function. + /// @return FAPI2_RC_SUCCESS iff okay + //// + fapi2::ReturnCode dimmUpdateDqBitmapEccByte( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, + uint8_t (&o_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]) + { + // Memory Bus Width Attribute + uint8_t l_eccBits = 0; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_MEMORY_BUS_WIDTH, i_dimm, l_eccBits)); + + // The ATTR_SPD_MODULE_MEMORY_BUS_WIDTH contains ENUM values + // for bus widths of 8, 16, 32, and 64 bits both with ECC + // and without ECC. WExx ENUMS deonote the ECC extension + // is present, and all have bit 3 set. Therefore, + // it is only required to check against the WE8 = 0x08 ENUM + // value in order to determine if ECC lines are present. + + // If ECCs are disconnected + if (!(fapi2::ENUM_ATTR_CEN_SPD_MODULE_MEMORY_BUS_WIDTH_WE8 & l_eccBits)) + { + // Iterate through each rank and set DQ bits in + // caller's data. + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + // Set DQ bits in caller's data + o_data[i][ECC_DQ_BYTE_NUMBER_INDEX] = 0xFF; + } + } + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Called by dimmBadDqBitmapAccessHwp() to query ATTR_SPD_BAD_DQ_DATA + /// @param[in] i_mba Reference to MBA Target + /// @param[in] i_dimm Reference to DIMM Target + /// @param[out] o_data Reference to Bad DQ Bitmap set by this function + /// @param[in] i_wiringData Reference to Centaur DQ to DIMM Connector DQ Wiring attribute. + /// @param[in] i_allMnfgFlags Manufacturing flags bitmap + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode dimmBadDqBitmapGet(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, + uint8_t (&o_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE], + const uint8_t (&i_wiringData)[DIMM_DQ_NUM_DQS], + const uint64_t i_allMnfgFlags) + { + + // DQ SPD Attribute + uint8_t (&l_spdData)[DIMM_DQ_SPD_DATA_SIZE] = + *(reinterpret_cast<uint8_t(*)[DIMM_DQ_SPD_DATA_SIZE]>(new uint8_t[DIMM_DQ_SPD_DATA_SIZE]())); + + // memset to avoid known syntax issue with previous compiler versions + // and ensure zero initialized array. + memset(l_spdData, 0, sizeof(l_spdData)); + + dimmBadDqDataFormat* l_pSpdData = reinterpret_cast<dimmBadDqDataFormat*>(l_spdData); + + // Pointer which will be used to initialize a clean bitmap during + // manufacturing mode + uint8_t (*l_pBuf)[DIMM_DQ_RANK_BITMAP_SIZE] = nullptr; + + // Get the SPD DQ attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_BAD_DQ_DATA, i_dimm, l_spdData)); + + // Zero caller's data + memset(o_data, 0, sizeof(o_data)); + + // Check the magic number and version number. Note that the + // magic number is stored in SPD in big endian format and + // platforms of any endianness can access it + if ((be32toh(l_pSpdData->iv_magicNumber) != DIMM_BAD_DQ_MAGIC_NUMBER) || + (l_pSpdData->iv_version != DIMM_BAD_DQ_VERSION)) + { + FAPI_INF("SPD DQ not initialized"); + } + else + { + // Translate bitmap from DIMM DQ to Centaur DQ point of view + // for each rank + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + // Iterate through all the DQ bits in the rank + for (uint8_t j = 0; j < DIMM_DQ_NUM_DQS; ++j) + { + // There is a byte for each 8 DQs, j/8 gives the + // byte number. The MSB in each byte is the lowest + // DQ, (0x80 >> (j % 8)) gives the bit mask + // corresponding to the DQ within the byte + const size_t BYTE_NUM = j / 8; + const size_t DQ_BIT_MASK = 0x80 >> (j % 8); + + if ((l_pSpdData->iv_bitmaps[i][BYTE_NUM]) & DQ_BIT_MASK) + { + // DIMM DQ bit is set in SPD data. + // Set Centaur DQ bit in caller's data. + // The wiring data maps Centaur DQ to DIMM DQ + // Find the Centaur DQ that maps to this DIMM DQ + uint8_t k = 0; + + for (; k < DIMM_DQ_NUM_DQS; ++k) + { + if (i_wiringData[k] == j) + { + o_data[i][k / 8] |= (0x80 >> (k % 8)); + break; + } + } + + if (k == DIMM_DQ_NUM_DQS) + { + FAPI_INF("Centaur DQ not found for %d!", j); + } + } + }// DIMM_DQ_NUM_DQS + } // MAX_RANKS_PER_DIMM + }// end else + + // Set bits for any unconnected DQs. + // First, check ECC. + FAPI_TRY(dimmUpdateDqBitmapEccByte(i_dimm, o_data)); + + // Check spare DRAM + FAPI_TRY(dimmUpdateDqBitmapSpareByte(i_mba, i_dimm, o_data)); + + // If system is in DISABLE_DRAM_REPAIRS mode + if (i_allMnfgFlags & fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DISABLE_DRAM_REPAIRS) + { + // Create a local zero-initialized bad dq bitmap + l_pBuf = new uint8_t[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE](); + + uint8_t (&l_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE] = + *(reinterpret_cast<uint8_t(*)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]>(l_pBuf)); + + // memset to avoid known syntax issue with previous + // compiler versions and ensure zero initialized array. + memset(l_data, 0, sizeof(l_data)); + + // Check ECC. + FAPI_TRY(dimmUpdateDqBitmapEccByte(i_dimm, l_data)); + // Check spare DRAM + FAPI_TRY(dimmUpdateDqBitmapSpareByte(i_mba, i_dimm, l_data)); + + // Compare l_data, which represents a bad dq bitmap with the + // appropriate spare/ECC bits set (if any) and all other DQ + // lines functional, to caller's o_data. + // If discrepancies are found, we know this is the result of + // a manufacturing mode process and these bits should not be + // recorded. + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + for (uint8_t j = 0; j < (DIMM_DQ_RANK_BITMAP_SIZE); ++j) + { + // Create and log fapi2 error if discrepancies were found + // Get this DIMM's position + uint32_t l_dimm_pos = 0; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, i_dimm, l_dimm_pos)); + + FAPI_ASSERT_NOEXIT(o_data[i][j] != l_data[i][j], + fapi2::CEN_BAD_DQ_MFG_MODE_BITS_FOUND_DURING_GET(). + set_CLEAN_BAD_DQ_BITMAP_RANK0(l_data[0][j]). + set_CLEAN_BAD_DQ_BITMAP_RANK1(l_data[1][j]). + set_CLEAN_BAD_DQ_BITMAP_RANK2(l_data[2][j]). + set_CLEAN_BAD_DQ_BITMAP_RANK3(l_data[3][j]). + set_CURRENT_BAD_DQ_BITMAP_RANK0(o_data[0][j]). + set_CURRENT_BAD_DQ_BITMAP_RANK1(o_data[1][j]). + set_CURRENT_BAD_DQ_BITMAP_RANK2(o_data[2][j]). + set_CURRENT_BAD_DQ_BITMAP_RANK3(o_data[3][j]). + set_DIMM(i_dimm), + "Read requested while in DISABLE_DRAM_REPAIRS mode found" + " extra bad bits set for rank:%d, DQ rank bitmap num:%d, DIMM pos: %d", + i, j, l_dimm_pos); + }// bitmap size + }// ranks + + // correct the output bit map + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + for (uint8_t j = 0; j < (DIMM_DQ_RANK_BITMAP_SIZE); ++j) + { + o_data[i][j] = l_data[i][j]; + } + }// end for + } + + delete [] &l_spdData; + delete [] l_pBuf; + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Called by dimmBadDqBitmapAccessHwp() to set ATTR_SPD_BAD_DQ_DATA + /// Also checks if a bad Dq bit is set by first calling dimmBadDqBitmapGet() + /// and sets ATTR_RECONFIGURE_LOOP with the 'OR' of the current value and + /// the fapi2 enum BAD_DQ_BIT_SET if appropriate + /// @param[in] i_mba Reference to MBA Target<fapi2::TARGET_TYPE_MBA>. + /// @param[in] i_dimm Reference to DIMM Target<fapi2::TARGET_TYPE_MBA>. + /// @param[in] i_data Reference to Bad DQ Bitmap set by the caller + /// @param[in] i_wiringData Reference to Centaur DQ to DIMM Connector DQ Wiring attribute. + /// @param[in] i_allMnfgFlags Manufacturing flags bitmap + /// @return FAPI2_RC_SUCCESS + /// + + fapi2::ReturnCode dimmBadDqBitmapSet( const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, + const uint8_t (&i_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE], + const uint8_t (&i_wiringData)[DIMM_DQ_NUM_DQS], + const uint64_t i_allMnfgFlags) + { + // Read current BadDqBitmap into l_prev_data + uint8_t l_prev_data[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE] = {}; + bool badDQSet = false; + + // DQ SPD Attribute + uint8_t (&l_spdData)[DIMM_DQ_SPD_DATA_SIZE] = + *(reinterpret_cast<uint8_t(*)[DIMM_DQ_SPD_DATA_SIZE]> + (new uint8_t[DIMM_DQ_SPD_DATA_SIZE]())); + + fapi2::ATTR_RECONFIGURE_LOOP_Type l_reconfigAttr = 0; + dimmBadDqDataFormat* l_pSpdData = reinterpret_cast<dimmBadDqDataFormat*>(l_spdData); + + // Pointer which will be used to initialize a clean bitmap during + // manufacturing mode + uint8_t (*l_pBuf)[DIMM_DQ_RANK_BITMAP_SIZE] = nullptr; + uint8_t spareByte[MAX_RANKS_PER_DIMM] = {}; + + FAPI_TRY(dimmBadDqBitmapGet(i_mba, i_dimm, l_prev_data, i_wiringData, i_allMnfgFlags)); + + // Check if Bad DQ bit set + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + for (uint8_t j = 0; j < (DIMM_DQ_RANK_BITMAP_SIZE); ++j) + { + if (i_data[i][j] != l_prev_data[i][j]) + { + badDQSet = true; + break; + } + } + + if (badDQSet) + { + break; + } + } + + // Set ATTR_RECONFIGURE_LOOP to indicate a bad DqBitMap was set + if (badDQSet) + { + FAPI_INF("Reconfigure needed, Bad DQ set"); + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_RECONFIGURE_LOOP, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_reconfigAttr)); + + // 'OR' values in case of multiple reasons for reconfigure + l_reconfigAttr |= fapi2::ENUM_ATTR_RECONFIGURE_LOOP_BAD_DQ_BIT_SET; + + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_RECONFIGURE_LOOP, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_reconfigAttr)); + } + + // memset to avoid known syntax issue with previous compiler versions + // and ensure zero initialized array. + memset(l_spdData, 0, sizeof(l_spdData)); + + // If system is in DISABLE_DRAM_REPAIRS mode + if (i_allMnfgFlags & fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DISABLE_DRAM_REPAIRS) + { + // Create a local zero-initialized bad dq bitmap + l_pBuf = new uint8_t[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE](); + + uint8_t (&l_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE] = + *(reinterpret_cast<uint8_t(*)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]>(l_pBuf)); + + // memset to avoid known syntax issue with previous + // compiler versions and ensure zero initialized array. + memset(l_data, 0, sizeof(l_data)); + + // Check ECC. + FAPI_TRY(dimmUpdateDqBitmapEccByte(i_dimm, l_data)); + // Check spare DRAM + FAPI_TRY(dimmUpdateDqBitmapSpareByte(i_mba, i_dimm, l_data)); + + // Compare l_data, which represents a bad dq bitmap with the + // appropriate spare/ECC bits set (if any) and all other DQ + // lines functional, to caller's i_data. + // If discrepancies are found, we know this is the result of + // a manufacturing mode process and these bits should not be + // recorded. + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + for (uint8_t j = 0; j < (DIMM_DQ_RANK_BITMAP_SIZE); ++j) + { + // Create and log fapi2 error if discrepancies were found + // Get this DIMM's position + uint32_t l_dimm_pos = 0; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, i_dimm, l_dimm_pos)); + + FAPI_ASSERT(i_data[i][j] != l_data[i][j], + fapi2::CEN_BAD_DQ_MFG_MODE_BITS_FOUND_DURING_SET(). + set_CLEAN_BAD_DQ_BITMAP_RANK0(l_data[0][j]). + set_CLEAN_BAD_DQ_BITMAP_RANK1(l_data[1][j]). + set_CLEAN_BAD_DQ_BITMAP_RANK2(l_data[2][j]). + set_CLEAN_BAD_DQ_BITMAP_RANK3(l_data[3][j]). + set_UPDATE_BAD_DQ_BITMAP_RANK0(i_data[0][j]). + set_UPDATE_BAD_DQ_BITMAP_RANK1(i_data[1][j]). + set_UPDATE_BAD_DQ_BITMAP_RANK2(i_data[2][j]). + set_UPDATE_BAD_DQ_BITMAP_RANK3(i_data[3][j]). + set_DIMM(i_dimm), + "Write requested while in DISABLE_DRAM_REPAIRS mode" + " extra bad bits set for rank:%d, DQ rank bitmap num:%d, DIMM pos: %d", + i, j, l_dimm_pos); + } + } + } + + // Set up the data to write to SPD + l_pSpdData->iv_magicNumber = htobe32(DIMM_BAD_DQ_MAGIC_NUMBER); + l_pSpdData->iv_version = DIMM_BAD_DQ_VERSION; + l_pSpdData->iv_reserved1 = 0; + l_pSpdData->iv_reserved2 = 0; + l_pSpdData->iv_reserved3 = 0; + memset(l_pSpdData->iv_bitmaps, 0, sizeof(l_pSpdData->iv_bitmaps)); + + // Get the spare byte + memset(spareByte, 0, sizeof(spareByte)); + + FAPI_TRY(dimmGetDqBitmapSpareByte(i_mba, i_dimm, spareByte)); + + // Translate bitmap from Centaur DQ to DIMM DQ point of view for + // each rank + for (uint8_t i = 0; i < MAX_RANKS_PER_DIMM; ++i) + { + // Iterate through all the DQ bits in the rank + for (uint8_t j = 0; j < DIMM_DQ_NUM_DQS; ++j) + { + const size_t BYTE_NUM = j / 8; + const size_t DQ_BIT_MASK = 0x80 >> (j % 8); + + if ((BYTE_NUM) == SPARE_DRAM_DQ_BYTE_NUMBER_INDEX) + { + // The spareByte can be one of: 0x00 0x0F 0xF0 0xFF + // If a bit is set, then that spare is unconnected + // so continue to the next num_dqs, do not translate + if (spareByte[i] & DQ_BIT_MASK) + { + continue; + } + } + + if ((i_data[i][BYTE_NUM]) & DQ_BIT_MASK) + { + // Centaur DQ bit set in callers data. + // Set DIMM DQ bit in SPD data. + // The wiring data maps Centaur DQ to DIMM DQ + uint8_t dBit = i_wiringData[j]; + l_pSpdData->iv_bitmaps[i][dBit / 8] |= (0x80 >> (dBit % 8)); + } + }// dq + }// ranks + + // Set the SPD DQ attribute + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_SPD_BAD_DQ_DATA, i_dimm, l_spdData)); + + fapi_try_exit: + delete [] &l_spdData; + delete [] l_pBuf; + + return fapi2::current_err; + } + + /// @brief FW Team HWP that accesses the Bad DQ Bitmap. + /// It accesses the raw data from DIMM SPD and does + /// any necessary processing to turn it into a + /// bitmap from a Centaur DQ point of view. If the data in SPD is not + /// valid then it has never been written and all zeroes are returned (no + /// bad DQs). + /// + /// This HWP should be called by HWP/PLAT code to access the BAD DQ Bitmap + /// + /// @param[in] i_mba Reference to MBA Target + /// @param[in] i_dimm Reference to DIMM Target + /// @param[in,out] io_data Reference to bad DQ bitmap data for the DIMM. + /// @param[in] i_get True if getting DQ Bitmap data. False if setting data. + /// @return FAPI2_RC_SUCCESS iff okay + /// @note that the MSB of each byte corresponds to the lowest DQ. + /// if (data[1][0] == 0x80) then rank 1, Centaur DQ0 is bad + /// if (data[1][0] == 0x40) then rank 1, Centaur DQ1 is bad + /// if (data[1][1] == 0x20) then rank 1, Centaur DQ10 is bad + /// + fapi2::ReturnCode dimmBadDqBitmapAccessHwp(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, + uint8_t (&io_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE], + const bool i_get) + { + // Note the use of heap based arrays to avoid large stack allocations + // Centaur DQ to DIMM Connector DQ Wiring attribute. + uint8_t (&l_wiringData)[DIMM_DQ_NUM_DQS] = + *(reinterpret_cast<uint8_t(*)[DIMM_DQ_NUM_DQS]> + (new uint8_t[DIMM_DQ_NUM_DQS]())); + + // memset to avoid known syntax issue with previous compiler versions + // and ensure zero initialized array. + memset(l_wiringData, 0, sizeof(l_wiringData)); + + // Manufacturing flags attribute + uint64_t l_allMnfgFlags = 0; + + // Get the manufacturing flags bitmap to be used in both get and set + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MNFG_FLAGS, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_allMnfgFlags)); + + // Get the Centaur DQ to DIMM Connector DQ Wiring attribute. + // Note that for C-DIMMs, this will return a simple 1:1 mapping. + // This code cannot tell the difference between C-DIMMs and IS-DIMMs. + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_DQ_TO_DIMM_CONN_DQ, + i_dimm, l_wiringData)); + + if (i_get) + { + FAPI_INF("Getting bitmap"); + FAPI_TRY(dimmBadDqBitmapGet(i_mba, i_dimm, io_data, l_wiringData, l_allMnfgFlags)); + } + else + { + FAPI_INF("Setting bitmap"); + FAPI_TRY(dimmBadDqBitmapSet(i_mba, i_dimm, io_data, l_wiringData, l_allMnfgFlags)); + } + + fapi_try_exit: + delete [] &l_wiringData; + FAPI_DBG("End"); + + return fapi2::current_err; + } + +}// extern C diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.H new file mode 100755 index 000000000..95a837775 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.H @@ -0,0 +1,78 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_dimmBadDqBitmapAccessHwp.H +/// @brief FW Team HWP that accesses the Bad DQ Bitmap. +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB +//// +// +#ifndef DIMMBADDQBITMAPACCESSHWP_H_ +#define DIMMBADDQBITMAPACCESSHWP_H_ + +#include <fapi2.H> +#include <dimmConsts.H> + +typedef fapi2::ReturnCode (*p9c_dimmBadDqBitmapAccessHwp_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA>&, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, + const uint8_t (&)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE], + const bool); + +extern "C" +{ + + /// + /// @brief FW Team HWP that accesses the Bad DQ Bitmap. + /// It accesses the raw data from DIMM SPD and does + /// any necessary processing to turn it into a + /// bitmap from a Centaur DQ point of view. If the data in SPD is not + /// valid then it has never been written and all zeroes are returned (no + /// bad DQs). + /// + /// This HWP should be called by HWP/PLAT code to access the BAD DQ Bitmap + /// + /// @param[in] i_mba Reference to MBA Target + /// @param[in] i_dimm Reference to DIMM Target + /// @param[in,out] io_data Reference to bad DQ bitmap data for the DIMM. + /// @param[in] i_get True if getting DQ Bitmap data. False if setting data. + /// @return FAPI2_RC_SUCCESS iff okay + /// @note that the MSB of each byte corresponds to the lowest DQ. + /// if (data[1][0] == 0x80) then rank 1, Centaur DQ0 is bad + /// if (data[1][0] == 0x40) then rank 1, Centaur DQ1 is bad + /// if (data[1][1] == 0x20) then rank 1, Centaur DQ10 is bad + /// + fapi2::ReturnCode dimmBadDqBitmapAccessHwp(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, + uint8_t (&io_data)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE], + const bool i_get); + +} + +#endif diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk new file mode 100755 index 000000000..6535d8ba3 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk @@ -0,0 +1,33 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] 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 + +# Include the macros and things for MSS procedures +-include 01common.mk + +PROCEDURE=p9c_dimmBadDqBitmapAccessHwp +$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE))) +#lib$(PROCEDURE)_DEPLIBS+=mss +$(call BUILD_PROCEDURE) + diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.C new file mode 100755 index 000000000..d29ebf4d8 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.C @@ -0,0 +1,186 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_dimmBadDqBitmapFuncs.C +/// @brief FW Team Utility functions that accesses the Bad DQ Bitmap. +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB:CI +/// + +#include <p9c_dimmBadDqBitmapFuncs.H> +#include <p9c_dimmBadDqBitmapAccessHwp.H> +#include <string.h> +#include <c_str.H> + + +extern "C" +{ + /// + /// @brief Utility function to check parameters and find a DIMM target + /// @param[in] i_mba mba target + /// @param[in] i_port Port number + /// @param[in] i_dimm Dimm number + /// @param[in] i_rank Rank number + /// @param[out] o_dimm Dimm target + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode dimmBadDqCheckParamFindDimm(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const uint8_t i_port, + const uint8_t i_dimm, + const uint8_t i_rank, + fapi2::Target<fapi2::TARGET_TYPE_DIMM>& o_dimm) + { + uint8_t l_port = 0; + uint8_t l_dimm = 0; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>> l_dimms; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>>::const_iterator dimmIter; + + FAPI_ASSERT((i_port < MAX_PORTS_PER_MBA) && + (i_dimm < MAX_DIMM_PER_PORT) && + (i_rank < MAX_RANKS_PER_DIMM), + fapi2::CEN_BAD_DQ_DIMM_BAD_PARAM(). + set_FFDC_PORT(i_port). + set_FFDC_DIMM(i_dimm). + set_FFDC_RANK(i_rank), + "dimmBadDqCheckParamFindDimm: %s Bad parameter. %d:%d:%d", + mss::c_str(i_mba), i_port, i_dimm, i_rank); + + // Get the functional DIMMs associated with the MBA chiplet + l_dimms = i_mba.getChildren<fapi2::TARGET_TYPE_DIMM>(); + // Find the DIMM with the correct MBA port/dimm + + for (dimmIter = l_dimms.begin(); dimmIter != l_dimms.end(); ++dimmIter) + { + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_PORT, *dimmIter, l_port)); + + if (l_port == i_port) + { + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_DIMM, *dimmIter, l_dimm)); + + if (l_dimm == i_dimm) + { + o_dimm = *dimmIter; + break; + } + } + } + + FAPI_ASSERT(dimmIter != l_dimms.end(), + fapi2::CEN_BAD_DQ_DIMM_NOT_FOUND(). + set_FFDC_PORT(i_port). + set_FFDC_DIMM(i_dimm), + "dimmBadDqCheckParamFindDimm: " + "Did not find DIMM for %s:%d:%d", + mss::c_str(i_mba), i_port, i_dimm); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief FW Team Utility function that gets the Bad DQ Bitmap. + /// @param[in] i_mba Reference to MBA Chiplet + /// @param[in] i_port MBA port number (0-(MAX_PORTS_PER_MBA - 1)) + /// @param[in] i_dimm MBA port DIMM number (0-(MAX_DIMM_PER_PORT - 1)) + /// @param[in] i_rank DIMM rank number (0-(MAX_RANKS_PER_DIMM -1)) + /// @param[out] o_data Reference to data where Bad DQ bitmap is copied to + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode dimmGetBadDqBitmap(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const uint8_t i_port, + const uint8_t i_dimm, + const uint8_t i_rank, + uint8_t (&o_data)[DIMM_DQ_RANK_BITMAP_SIZE]) + { + FAPI_INF(">>dimmGetBadDqBitmap. %s:%d:%d:%d", mss::c_str(i_mba), i_port, + i_dimm, i_rank); + + // Check parameters and find the DIMM fapi2::Target<fapi2::TARGET_TYPE_MBA> + fapi2::Target<fapi2::TARGET_TYPE_DIMM> l_dimm; + + // Get the Bad DQ bitmap by querying ATTR_BAD_DQ_BITMAP. + // Use a heap based array to avoid large stack alloc + uint8_t (&l_dqBitmap)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE] = + *(reinterpret_cast<uint8_t(*)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]> + (new uint8_t[MAX_RANKS_PER_DIMM * DIMM_DQ_RANK_BITMAP_SIZE])); + + FAPI_TRY(dimmBadDqCheckParamFindDimm(i_mba, i_port, i_dimm, i_rank, l_dimm)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_BAD_DQ_BITMAP, l_dimm, l_dqBitmap)); + + //Write contents of DQ bitmap for specific rank to o_data. + memcpy(o_data, l_dqBitmap[i_rank], DIMM_DQ_RANK_BITMAP_SIZE); + + delete [] &l_dqBitmap; + + FAPI_INF("<<dimmGetBadDqBitmap"); + fapi_try_exit: + return fapi2::current_err; + } + + /// @brief FW Team Utility function that sets the Bad DQ Bitmap. + /// @param[in] i_mba Reference to MBA Chiplet + /// @param[in] i_port MBA port number (0-(MAX_PORTS_PER_MBA - 1)) + /// @param[in] i_dimm MBA port DIMM number (0-(MAX_DIMM_PER_PORT - 1)) + /// @param[in] i_rank DIMM rank number (0-(MAX_RANKS_PER_DIMM -1)) + /// @param[in] i_data Reference to data where Bad DQ bitmap is copied from + /// @return FAPI2_RC_SUCCESS + fapi2::ReturnCode dimmSetBadDqBitmap(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const uint8_t i_port, + const uint8_t i_dimm, + const uint8_t i_rank, + const uint8_t (&i_data)[DIMM_DQ_RANK_BITMAP_SIZE]) + { + FAPI_INF(">>dimmSetBadDqBitmap. %s:%d:%d:%d", mss::c_str(i_mba), i_port, i_dimm, i_rank); + + // Check parameters and find the DIMM fapi2::Target<fapi2::TARGET_TYPE_MBA> + fapi2::Target<fapi2::TARGET_TYPE_DIMM> l_dimm; + + // Get the Bad DQ bitmap by querying ATTR_BAD_DQ_BITMAP. + // Use a heap based array to avoid large stack alloc + uint8_t (&l_dqBitmap)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE] = + *(reinterpret_cast<uint8_t(*)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]> + (new uint8_t[MAX_RANKS_PER_DIMM * DIMM_DQ_RANK_BITMAP_SIZE])); + + FAPI_TRY(dimmBadDqCheckParamFindDimm(i_mba, i_port, i_dimm, i_rank, l_dimm)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_BAD_DQ_BITMAP, l_dimm, l_dqBitmap)); + + // Add the rank bitmap to the DIMM bitmap and write the bitmap + memcpy(l_dqBitmap[i_rank], i_data, DIMM_DQ_RANK_BITMAP_SIZE); + + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_BAD_DQ_BITMAP, l_dimm, l_dqBitmap)); + + delete [] &l_dqBitmap; + + FAPI_INF("<<dimmSetBadDqBitmap"); + fapi_try_exit: + return fapi2::current_err; + } + +} // extern "C" diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.H new file mode 100755 index 000000000..eb9e253d3 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.H @@ -0,0 +1,92 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_dimmBadDqBitmapFuncs.H +/// @brief FW Team Utility functions that accesses the Bad DQ Bitmap. +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB:CI +//// +// +#ifndef DIMMBADDQBITMAPFUNCS_H_ +#define DIMMBADDQBITMAPFUNCS_H_ + +#include <fapi2.H> +#include <dimmConsts.H> + +extern "C" +{ + + /// + /// @brief FW Team Utility function that gets the Bad DQ Bitmap. + /// + /// This utility functon should be called by a HWP needing to get the Bad DQ + /// bitmap for a particular mba, port, dimm and rank. + /// + /// This function finds the corresponding DIMM fapi2::Target<fapi2::TARGET_TYPE_MBA>, calls + /// p9c_dimmBadDqBitmapAccessHwp to get the DQ bitmap and returns the data + /// for the specified rank. + /// + /// @param[in] i_mba Reference to MBA Chiplet + /// @param[in] i_port MBA port number (0-(MAX_PORTS_PER_MBA - 1)) + /// @param[in] i_dimm MBA port DIMM number (0-(MAX_DIMM_PER_PORT - 1)) + /// @param[in] i_rank DIMM rank number (0-(MAX_RANKS_PER_DIMM -1)) + /// @param[out] o_data Reference to data where Bad DQ bitmap is copied to + /// @return ReturnCode + /// + fapi2::ReturnCode dimmGetBadDqBitmap(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const uint8_t i_port, + const uint8_t i_dimm, + const uint8_t i_rank, + uint8_t (&o_data)[DIMM_DQ_RANK_BITMAP_SIZE]); + + /// + /// @brief FW Team Utility function that sets the Bad DQ Bitmap. + /// + /// This utility functon should be called by a HWP needing to set the Bad DQ + /// bitmap for a particular mba, port, dimm and rank. + /// + /// This utility function finds the corresponding DIMM fapi2::Target<fapi2::TARGET_TYPE_MBA>, calls + /// dimmBadDqBitmapAccessHwp to get the DQ bitmap, fills in the data for the + /// specified rank and calls dimmBadDqBitmapAccessHwp to set the DQ bitmap + /// + /// @param[in] i_mba Reference to MBA Chiplet + /// @param[in] i_port MBA port number (0-(MAX_PORTS_PER_MBA - 1)) + /// @param[in] i_dimm MBA port DIMM number (0-(MAX_DIMM_PER_PORT - 1)) + /// @param[in] i_rank DIMM rank number (0-(MAX_RANKS_PER_DIMM -1)) + /// @param[in] i_data Reference to data where Bad DQ bitmap is copied from + /// @return ReturnCode + /// + fapi2::ReturnCode dimmSetBadDqBitmap(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba, + const uint8_t i_port, + const uint8_t i_dimm, + const uint8_t i_rank, + const uint8_t (&i_data)[DIMM_DQ_RANK_BITMAP_SIZE]); +} + +#endif diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk new file mode 100755 index 000000000..851f0593c --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk @@ -0,0 +1,33 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] 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 + +# Include the macros and things for MSS procedures +-include 01common.mk + +PROCEDURE=p9c_dimmBadDqBitmapFuncs +$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE))) +#lib$(PROCEDURE)_DEPLIBS+=mss +$(call BUILD_PROCEDURE) + diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C new file mode 100644 index 000000000..efbf25d6f --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C @@ -0,0 +1,717 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* [+] 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 p9c_mss_ddr_phy_reset.C +/// @brief HWP to set up ddr phy +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB:CI +//// + +#include <fapi2.H> +#include <cen_gen_scom_addresses.H> +#include <cen_gen_scom_addresses_fld.H> +#include <p9c_mss_ddr_phy_reset.H> +#include <p9c_mss_unmask_errors.H> +#include <p9c_mss_slew.H> +#include <p9c_dimmBadDqBitmapFuncs.H> +#include <c_str.H> +#include <dimmConsts.H> + +enum phy +{ + POWERDOWN_1_P0_MASTER_PD_CNTL = CEN_MBA_DDRPHY_PC_POWERDOWN_1_P0_MASTER_PD_CNTL, + POWERDOWN_1_P0_WR_FIFO_STAB = CEN_MBA_DDRPHY_PC_POWERDOWN_1_P0_WR_FIFO_STAB, + + FORCE_MCLK_LOW_N = CEN_MBA_CCS_MODEQ_FORCE_MCLK_LOW_N, + DDR_DFI_RESET_RECOVER = CEN_MBA_CCS_MODEQ_MCBIST_DDR_DFI_RESET_RECOVER, + + DP18_PLL_LOCK_STATUS = CEN_MBA_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P0_LOCK, + DP18_PLL_LOCK_STATUS_LEN = CEN_MBA_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P0_LOCK_LEN, + + AD32S_PLL_LOCK_STATUS = CEN_MBA_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P0_LOCK, + AD32S_PLL_LOCK_STATUS_LEN = CEN_MBA_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P0_LOCK_LEN, + +}; + +extern "C" +{ + // TODO RTC:168629 Segregate API from p9c_ddr_phy_reset.C into a PHY dir + // prototypes of functions called in phy reset + fapi2::ReturnCode deassert_force_mclk_low (const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + fapi2::ReturnCode ddr_phy_reset_cloned(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + fapi2::ReturnCode ddr_phy_flush(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + + /// + /// @brief Does a soft reset of the DDR PHY logic and lock the DDR PLLs + /// @param[in] i_target the MBA target + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode p9c_mss_ddr_phy_reset(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) + { + FAPI_TRY(ddr_phy_reset_cloned(i_target), "ddr_phy_reset_cloned failed!"); + FAPI_TRY(mss_slew_cal(i_target), "mss_slew_cal failed!"); + FAPI_TRY(ddr_phy_flush(i_target), "ddr_phy_flush failed!"); + + // If mss_unmask_ddrphy_errors gets it's own bad rc, + // it will commit the passed in rc (if non-zero), and return it's own bad rc. + // Else if mss_unmask_ddrphy_errors runs clean, + // it will just return the passed in rc. + FAPI_TRY(mss_unmask_ddrphy_errors(i_target)); + + fapi_try_exit: + FAPI_DBG("end"); + return fapi2::current_err; + } + + /// + /// @brief PHY reset cloned + /// @param[in] i_target the MBA target + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode ddr_phy_reset_cloned(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) + { + // Loop 10 times during PLL lock polling + constexpr uint64_t MAX_POLL_LOOPS = 10; + constexpr uint64_t DP18_PLL_EXP_LOCK_STATUS = 0xF800; // DP18 PLL lock status + constexpr uint64_t AD32S_PLL_EXP_LOCK_STATUS = 0xC000; // AD32S PLL lock status + + uint32_t l_poll_count = 0; + uint32_t l_done_polling = 0; + uint8_t l_is_simulation = 0; + fapi2::buffer<uint64_t> l_data; + fapi2::buffer<uint64_t> l_dp_p0_lock_data; + fapi2::buffer<uint64_t> l_dp_p1_lock_data; + fapi2::buffer<uint64_t> l_ad_p0_lock_data; + fapi2::buffer<uint64_t> l_ad_p1_lock_data; + uint8_t l_dqBitmap[DIMM_DQ_RANK_BITMAP_SIZE] = {}; // 10 byte array of bad bits + uint8_t l_valid_dimms = 0; + uint8_t l_valid_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT]; + uint8_t l_num_mranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {}; + uint8_t l_port = 0; + uint16_t l_actual = 0; + uint16_t l_poll = 0; + uint8_t l_dimm = 0; + uint8_t l_rank = 0; + bool l_new_error = false; + uint8_t l_continue_on_dp18_pll_lock_failure = 0; + + FAPI_INF("********* mss_ddr_phy_reset start *********"); + + // + // Here are the specific instructions from section 14.7.3 of the Centaur Chip Specification: + // + // Run cen_ddr_phy_reset.C prepares the DDR PLLs. These PLLs were previously configured via scan init, but have + // been held in reset. At this point the PLL GP bit is deasserted to take the PLLs out of reset. + // + // The cen_ddr_phy_reset.C now resets the DDR PHY logic. This process will NOT destroy any configuration values + // previously loaded via the init file. The intent is for the initialized phase rotator configuration to remain valid after the + // soft reset completes. If this assumption fails to hold true, it will require replacing this step with a PHY hard reset, + // and then using inband configuration writes to restore all the DDR Configuration Registers. + // + // The following steps must be performed as part of the PHY reset procedure. + + // PLL Lock cannot happen if mclk low is asserted + // this procedure was moved from draminit to: + // Deassert Force_mclk_low signal + // see CQ 216395 (HW217109) + FAPI_TRY(deassert_force_mclk_low(i_target), " deassert_force_mclk_low Failed"); + + // + // 1. Drive all control signals to the PHY to their inactive state, idle state, or inactive value. + // (Note: The chip should already be in this state.) + FAPI_DBG("Step 1: All control signals to the PHYs should already be set to their inactive state, idle state, or inactive values.\n"); + + // + // 2. For DD0: Assert dfi_reset_all (GP4 bit 5 = "1") for at least 32 memory clock cycles. This signal DOES + // erradicate all DDR configuration register initialization, thereby requiring the DDR registers to be reprogrammed + // via SCOM after the PHY reset sequence completes. + // For DD1: Set mcbist_ddr_dfi_reset_recover ="1" (CCS_MODEQ(25) SCOM Addr: 0x030106A7 & 0x03010EA7) + // for at least 32 memory clock cycles. This signal does NOT reset the configuration registers + // within the PHY. + FAPI_DBG("Step 2: MBA CCS_MODEQ(25), Setting mcbist_ddr_dfi_reset_recover = 1 for DDR PHY soft reset.\n"); + FAPI_TRY(fapi2::getScom( i_target, CEN_MBA_CCS_MODEQ, l_data), "Error reading CCS_MODEQ register."); + l_data.setBit<DDR_DFI_RESET_RECOVER>(); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_CCS_MODEQ, l_data)); + FAPI_TRY(fapi2::delay(DELAY_100NS, DELAY_2000SIMCYCLES)); // wait 2000 simcycles (in sim mode) OR 100 nS (in hw mode) + + // + // 3. For DD0: Deassert dfi_reset_all (GP4 bit 5 = "0") + // For DD1: Deassert mcbist_ddr_dfi_reset_recover = "0" (CCS_MODEQ(25) SCOM Addr: 0x030106A7 0x03010EA7) + FAPI_DBG("Step 3: MBA CCS_MODEQ(25), Setting mcbist_ddr_dfi_reset_recover = 0 to release soft reset.\n"); + FAPI_TRY(fapi2::getScom( i_target, CEN_MBA_CCS_MODEQ, l_data), "Error reading CCS_MODEQ register."); + l_data.clearBit<DDR_DFI_RESET_RECOVER>(); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_CCS_MODEQ, l_data), "Error writing CCS_MODEQ register."); + + // + // 4. Write 0x0010 to PC IO PVT N/P FET driver control registers to assert ZCTL reset and enable the internal impedance controller. + // (SCOM Addr: 0x8000C0140301143F, 0x8000C0140301183F, 0x8001C0140301143F, 0x8001C0140301183F) + FAPI_DBG("Step 4: Write 0x0010 to PC IO PVT N/P FET driver control registers to assert ZCTL reset.\n"); + l_data = 0x0000000000000010ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P0, l_data), + "Error writing DPHY01_DDRPHY_PC_IO_PVT_FET_CONTROL_P0 register."); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P1, l_data), + "Error writing DPHY01_DDRPHY_PC_IO_PVT_FET_CONTROL_P0 register."); + + // + // 5. Write 0x0018 to PC IO PVT N/P FET driver control registers to deassert ZCTL reset while impedance controller is still enabled. + // (SCOM Addr: 0x8000C0140301143F, 0x8000C0140301183F, 0x8001C0140301143F, 0x8001C0140301183F) + FAPI_DBG("Step 5: Write 0x0018 to PC IO PVT N/P FET driver control registers to deassert ZCTL reset.\n"); + l_data = 0x0000000000000018ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P0, l_data), + "Error writing DPHY01_DDRPHY_PC_IO_PVT_FET_CONTROL_P0 register."); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P1, l_data), + "Error writing DPHY01_DDRPHY_PC_IO_PVT_FET_CONTROL_P1 register."); + + // + // 6. Write 0x0008 to PC IO PVT N/P FET driver control registers to deassert the impedance controller. + // (SCOM Addr: 0x8000C0140301143F, 0x8000C0140301183F, 0x8001C0140301143F, 0x8001C0140301183F) + FAPI_DBG("Step 6: Write 0x0008 to PC IO PVT N/P FET driver control registers to deassert the impedance controller.\n"); + l_data = 0x0000000000000008ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P0, l_data), + "Error writing DPHY01_DDRPHY_PC_IO_PVT_FET_CONTROL_P0 register."); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P1, l_data), + "Error writing DPHY01_DDRPHY_PC_IO_PVT_FET_CONTROL_P1 register."); + + // + // 7. Write 0x4000 into the PC Resets Registers. This deasserts the PLL_RESET and leaves the SYSCLK_RESET bit active + // (SCOM Addr: 0x8000C00E0301143F, 0x8001C00E0301143F, 0x8000C00E0301183F, 0x8001C00E0301183F) + FAPI_DBG("Step 7: Write 0x4000 into the PC Resets Regs. This deasserts the PLL_RESET and leaves the SYSCLK_RESET bit active.\n"); + l_data = 0x0000000000004000ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_RESETS_P0, l_data), + "Error writing DPHY01_DDRPHY_PC_RESETS_P0 register."); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_RESETS_P1, l_data), + "Error writing DPHY01_DDRPHY_PC_RESETS_P1 register."); + + // + // 8. Wait at least 1 millisecond to allow the PLLs to lock. Otherwise, poll the PC DP18 PLL Lock Status + // and the PC AD32S PLL Lock Status to determine if all PLLs have locked. + // PC DP18 PLL Lock Status should be 0xF800: (SCOM Addr: 0x8000C0000301143F, 0x8001C0000301143F, 0x8000C0000301183F, 0x8001C0000301183F) + // PC AD32S PLL Lock Status should be 0xC000: (SCOM Addr: 0x8000C0010301143F, 0x8001C0010301143F, 0x8000C0010301183F, 0x8001C0010301183F) + //------------------------ + // 8a - Poll for lock bits + FAPI_DBG("Step 8: Poll until DP18 and AD32S PLLs have locked....\n"); + + do + { + FAPI_TRY(fapi2::delay(DELAY_1US, DELAY_20000SIMCYCLES)); // wait 20000 simcycles (in sim mode) OR 1 usec (in hw mode) + l_done_polling = 1; + FAPI_TRY(fapi2::getScom( i_target, CEN_MBA_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P0_ROX, l_dp_p0_lock_data)); + l_dp_p0_lock_data.extract<DP18_PLL_LOCK_STATUS, DP18_PLL_LOCK_STATUS_LEN>(l_poll); + + if ( l_poll != DP18_PLL_EXP_LOCK_STATUS ) + { + l_done_polling = 0; + } + + FAPI_TRY(fapi2::getScom( i_target, CEN_MBA_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P1_ROX, l_dp_p1_lock_data)); + l_dp_p1_lock_data.extract<DP18_PLL_LOCK_STATUS, DP18_PLL_LOCK_STATUS_LEN>(l_poll); + + if ( l_poll != DP18_PLL_EXP_LOCK_STATUS ) + { + l_done_polling = 0; + } + + FAPI_TRY(fapi2::getScom( i_target, CEN_MBA_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P0_ROX, l_ad_p0_lock_data)); + l_ad_p0_lock_data.extract<48, 16>(l_poll); + + if ( l_poll != AD32S_PLL_EXP_LOCK_STATUS ) + { + l_done_polling = 0; + } + + FAPI_TRY(fapi2::getScom( i_target, CEN_MBA_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P1_ROX, l_ad_p1_lock_data)); + l_ad_p1_lock_data.extract<48, 16>(l_poll); + + if ( l_poll != AD32S_PLL_EXP_LOCK_STATUS ) + { + l_done_polling = 0; + } + + l_poll_count++; + } + while ((l_done_polling == 0) && (l_poll_count < MAX_POLL_LOOPS)); // Poll until PLLs are locked. + + + if (l_poll_count == MAX_POLL_LOOPS) + { + + //------------------------------- + // Check to see if we should continue even if the DP18 PLL lock fails + const auto l_centaurTarget = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>(); + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_MSS_CONTINUE_ON_DP18_PLL_LOCK_FAIL, + l_centaurTarget, + l_continue_on_dp18_pll_lock_failure)); + + FAPI_DBG("Got attribute ATTR_CENTAUR_EC_MSS_CONTINUE_ON_DP18_PLL_LOCK_FAIL: value=%X.\n", + l_continue_on_dp18_pll_lock_failure); + + //------------------------------- + // 8b - Check Port 0 DP lock bits + + // TODO RTC:168628 Log FFDC in p9c_ddr_phy_reset instead of only printing traces? + l_dp_p0_lock_data.extract<48, 16>(l_poll); + + if ( l_poll != DP18_PLL_EXP_LOCK_STATUS ) + { + if ( !l_dp_p0_lock_data.getBit<48>() ) + { + FAPI_INF("Port 0 DP 0 PLL failed to lock!"); + } + + if ( !l_dp_p0_lock_data.getBit<49>() ) + { + FAPI_INF("Port 0 DP 1 PLL failed to lock!"); + } + + if ( !l_dp_p0_lock_data.getBit<50>() ) + { + FAPI_INF("Port 0 DP 2 PLL failed to lock!"); + } + + if ( !l_dp_p0_lock_data.getBit<51>() ) + { + FAPI_INF("Port 0 DP 3 PLL failed to lock!"); + } + + if ( !l_dp_p0_lock_data.getBit<52>() ) + { + FAPI_INF("Port 0 DP 4 PLL failed to lock!"); + } + + if (!l_continue_on_dp18_pll_lock_failure) + { + l_dp_p0_lock_data.extract<48, 16>(l_actual); + + FAPI_ASSERT(false, + fapi2::CEN_MSS_DP18_0_PLL_FAILED_TO_LOCK(). + set_EXPECTED_STATUS(DP18_PLL_EXP_LOCK_STATUS). + set_ACTUAL_STATUS(l_actual). + set_MBA_IN_ERROR(i_target). + set_MEMBUF_CHIP_IN_ERROR(l_centaurTarget), + "One or more DP18 port 0 (0x0C000) PLL failed to lock!,DP18 PLL lock failed and this chip does not have the known DP18 lock bug."); + } + + // for DD1 parts that have the DP18 lock bug - keep going to initialize any other channels that might be good. + FAPI_INF("Continuing anyway to initialize any other channels that might be good..."); + } + + //------------------------------- + // 8c - Check Port 1 DP lock bits + l_dp_p1_lock_data.extract< 48, 16>(l_poll); + + if ( l_poll != DP18_PLL_EXP_LOCK_STATUS ) + { + if ( !l_dp_p1_lock_data.getBit<48>() ) + { + FAPI_INF("Port 1 DP 0 PLL failed to lock!"); + } + + if ( !l_dp_p1_lock_data.getBit<49>() ) + { + FAPI_INF("Port 1 DP 1 PLL failed to lock!"); + } + + if ( !l_dp_p1_lock_data.getBit<50>() ) + { + FAPI_INF("Port 1 DP 2 PLL failed to lock!"); + } + + if ( !l_dp_p1_lock_data.getBit<51>() ) + { + FAPI_INF("Port 1 DP 3 PLL failed to lock!"); + } + + if ( !l_dp_p1_lock_data.getBit<52>() ) + { + FAPI_INF("Port 1 DP 4 PLL failed to lock!"); + } + + if (!l_continue_on_dp18_pll_lock_failure) + { + l_dp_p1_lock_data.extract<48, 16>(l_actual); + + FAPI_ASSERT(false, + fapi2::CEN_MSS_DP18_1_PLL_FAILED_TO_LOCK(). + set_EXPECTED_STATUS(DP18_PLL_EXP_LOCK_STATUS). + set_ACTUAL_STATUS(l_actual). + set_MBA_IN_ERROR(i_target). + set_MEMBUF_CHIP_IN_ERROR(l_centaurTarget), + "One or more DP18 port 1 (0x0C000) PLL failed to lock!,DP18 PLL lock failed and this chip does not have the known DP18 lock bug."); + } + + // for DD1 parts that have the DP18 lock bug - keep going to initialize any other channels that might be good. + // FAPI_INF("One or more DP18 port 1 (0x1C000) PLL failed to lock! Lock Status = %04X",l_dp_p1_lock_data.getHalfWord(3)); + FAPI_INF("Continuing anyway to initialize any other channels that might be good..."); + } + + //------------------------------- + // 8d - Check Port 0 AD lock bits + l_ad_p0_lock_data.extract<48, 16>(l_poll); + l_ad_p0_lock_data.extract<48, 16>(l_actual); + + FAPI_ASSERT(l_poll == AD32S_PLL_EXP_LOCK_STATUS, + fapi2::CEN_MSS_AD32S_0_PLL_FAILED_TO_LOCK(). + set_EXPECTED_STATUS(AD32S_PLL_EXP_LOCK_STATUS). + set_ACTUAL_STATUS(l_actual). + set_MBA_IN_ERROR(i_target). + set_MEMBUF_CHIP_IN_ERROR(l_centaurTarget), + "One or more AD32S port 0 (0x0C001) PLL failed to lock!"); + + //------------------------------- + // 8e - Check Port 1 AD lock bits + l_ad_p1_lock_data.extract<48, 16>(l_poll); + l_ad_p1_lock_data.extract<48, 16>(l_actual); + + FAPI_ASSERT( l_poll == AD32S_PLL_EXP_LOCK_STATUS, + fapi2::CEN_MSS_AD32S_1_PLL_FAILED_TO_LOCK(). + set_EXPECTED_STATUS(AD32S_PLL_EXP_LOCK_STATUS). + set_ACTUAL_STATUS(l_actual). + set_MBA_IN_ERROR(i_target). + set_MEMBUF_CHIP_IN_ERROR(l_centaurTarget), + "One or more AD32S port 1 (0x0C001) PLL failed to lock!"); + } + else + { + FAPI_INF("AD32S PLLs are now locked. DP18 PLLs should also be locked."); + } + + // + // 9.Write '8024'x into the ADR SysClk Phase Rotator Control Registers and into the DP18 SysClk Phase Rotator Control Registers. + // This takes the dphy_nclk/SysClk alignment circuit out of reset and puts the dphy_nclk/SysClk alignment circuit into the Continuous Update Mode. + // ADR SysClk PR Control Registers : (SCOM Addr: 0x800080320301143F, 0x800084320301143F, 0x800180320301143F, 0x800184320301143F, + // 0x800080320301183F, 0x800084320301183F, 0x800180320301183F, 0x800184320301183F) + // DP18 SysClk PR Control Registers : (SCOM Addr: 0x800000070301143F, 0x800004070301143F, 0x800008070301143F, 0x80000C070301143F, 0x800010070301143F, + // 0x800000070301183F, 0x800004070301183F, 0x800008070301183F, 0x80000C070301183F, 0x800010070301183F, + // 0x800100070301143F, 0x800104070301143F, 0x800108070301143F, 0x80010C070301143F, 0x800110070301143F, + // 0x800100070301183F, 0x800104070301183F, 0x800108070301183F, 0x80010C070301183F, 0x800110070301183F) + FAPI_DBG("Step 9: Write '8024'x into the ADR SysClk Phase Rotator Control Regs and the DP18 SysClk Phase Rotator Control Regs.\n"); + l_data = 0x0000000000008024ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S1, l_data)); + + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_4, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_4, l_data)); + + // + // 10.Wait at least 5932 memory clock cycles to allow the clock alignment circuit to perform initial alignment. + FAPI_DBG("Step 10: Wait at least 5932 memory clock cycles to allow the clock alignment circuit to perform initial alignment.\n"); + + // wait 2000000 simcycles (in sim mode) OR 100 usec (in hw mode) + FAPI_TRY(fapi2::delay(DELAY_100US, DELAY_2000000SIMCYCLES)); + + // + // 11.Write 0x0000 into the PC Resets Register. This deasserts the SysClk Reset + // (SCOM Addr: 0x8000C00E0301143F, 0x8001C00E0301143F, 0x8000C00E0301183F, 0x8001C00E0301183F) + FAPI_DBG("Step 11: Write 0x0000 into the PC Resets Register. This deasserts the SysClk Reset.\n"); + l_data = 0x0000000000000000ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_RESETS_P0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_RESETS_P1, l_data)); + + // + // 12.Write '8020'x into the ADR SysClk Phase Rotator Control Registers and into the DP18 SysClk Phase Rotator Control Registers. + // This takes the dphy_nclk/SysClk alignment circuit out of Continuous Update Mode. + // ADR SysClk PR Control Registers : (SCOM Addr: 0x800080320301143F, 0x800084320301143F, 0x800180320301143F, 0x800184320301143F, + // 0x800080320301183F, 0x800084320301183F, 0x800180320301183F, 0x800184320301183F) + // DP18 SysClk PR Control Registers : (SCOM Addr: 0x800000070301143F, 0x800004070301143F, 0x800008070301143F, 0x80000C070301143F, 0x800010070301143F, + // 0x800000070301183F, 0x800004070301183F, 0x800008070301183F, 0x80000C070301183F, 0x800010070301183F, + // 0x800100070301143F, 0x800104070301143F, 0x800108070301143F, 0x80010C070301143F, 0x800110070301143F, + // 0x800100070301183F, 0x800104070301183F, 0x800108070301183F, 0x80010C070301183F, 0x800110070301183F) + FAPI_DBG("Step 12: Write '8020'x into the ADR SysClk Phase Rotator Control Regs and the DP18 SysClk Phase Rotator Control Regs.\n"); + l_data = 0x0000000000008020ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S1, l_data)); + + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_4, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_4, l_data)); + + // Work-around required to get alignment in simulation + // Read the ATTR_IS_SIMULATION attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_is_simulation)); + + if (l_is_simulation) + { + FAPI_DBG("Step 12.1 (SIM ONLY): Write '8000'x into the ADR SysClk Phase Rotator Control Regs and the DP18 SysClk Phase Rotator Control Regs.\n"); + l_data = 0x0000000000008000ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S1, l_data)); + + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_4, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_4, l_data)); + + FAPI_DBG("Step 12.2 (SIM ONLY): Write '8080'x into the ADR SysClk Phase Rotator Control Regs and the DP18 SysClk Phase Rotator Control Regs.\n"); + l_data = 0x0000000000008080ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S1, l_data)); + + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_1, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_2, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_3, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P0_4, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_DP18_SYSCLK_PR_P1_4, l_data)); + } + + // + // 13.Wait at least 32 memory clock cycles. + FAPI_DBG("Step 13: Wait at least 32 memory clock cycles.\n"); + FAPI_TRY(fapi2::delay(DELAY_100NS, DELAY_2000SIMCYCLES)); // wait 2000 simcycles (in sim mode) OR 100 nS (in hw mode) + + // + // 14.Write 0x0018 to PC IO PVT N/P FET driver control register to enable internal ZQ calibration. + // This step takes approximately 2112 (64 * 33) memory clock cycles. + // (SCOM Addr: 0x8000C0140301143F, 0x8000C0140301183F, 0x8001C0140301143F, 0x8001C0140301183F) + FAPI_DBG("Step 14: Write 0x0018 to PC IO PVT N/P FET driver control register to enable internal ZQ calibration.\n"); + l_data = 0x0000000000000018ull; + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P0, l_data)); + FAPI_TRY(fapi2::putScom( i_target, CEN_MBA_DDRPHY_PC_IO_PVT_FET_CONTROL_P1, l_data)); + + // + // Now do some error checking and mark bad channels + // Check to see if there were any register access problems on DP registers, or corresponding PLLs that did not lock. + // If so, mark the DP pairs as bad. + + // Loop through only valid (functional) dimms. + // For each valid dimm, loop through all the ranks belonging to that dimm. + // If there was either a register access error, or if the PLL did not lock, then mark the DP pair as bad. + // Do this by setting the dqBitmap attribute for all dimms and ranks associated with that PLL or register. + // Read the dqBitmap first, so that you do not clear values that may already be set. + // (Some DP channels may already be marked as bad.) + + // TODO RTC:168627 Find out if we can avoid ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR + // Find out which dimms are functional + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR, i_target, l_valid_dimms)); + l_valid_dimm[0][0] = (l_valid_dimms & 0x80); + l_valid_dimm[0][1] = (l_valid_dimms & 0x40); + l_valid_dimm[1][0] = (l_valid_dimms & 0x08); + l_valid_dimm[1][1] = (l_valid_dimms & 0x04); + + // Find out how many ranks are on each dimm + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, l_num_mranks_per_dimm)); + + // Loop through each PORT (0,1) + for(l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++ ) + { + // Loop through each DIMM:(0,1) + for(l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++ ) + { + if (l_valid_dimm[l_port][l_dimm]) + { + // Ok, this DIMM is functional. So loop through the RANKs of this dimm. + for(l_rank = 0; l_rank < l_num_mranks_per_dimm[l_port][l_dimm]; ++l_rank ) + { + // Get the bad DQ Bitmap for l_port, l_dimm, l_rank + FAPI_TRY(dimmGetBadDqBitmap(i_target, l_port, l_dimm, l_rank, l_dqBitmap)); + + // Mark the bad bits for each register that had problems or PLL that did not lock + l_new_error = false; + + if ( l_port == 0 ) + { + if ( !l_dp_p0_lock_data.getBit<48>() ) + { + l_dqBitmap[0] = 0xff; + l_dqBitmap[1] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p0_lock_data.getBit<49>() ) + { + l_dqBitmap[2] = 0xff; + l_dqBitmap[3] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p0_lock_data.getBit<50>() ) + { + l_dqBitmap[4] = 0xff; + l_dqBitmap[5] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p0_lock_data.getBit<51>() ) + { + l_dqBitmap[6] = 0xff; + l_dqBitmap[7] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p0_lock_data.getBit<52>() ) + { + l_dqBitmap[8] = 0xff; + l_dqBitmap[9] = 0xff; + l_new_error = true; + } + } + else + { + if ( !l_dp_p1_lock_data.getBit<48>() ) + { + l_dqBitmap[0] = 0xff; + l_dqBitmap[1] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p1_lock_data.getBit<49>() ) + { + l_dqBitmap[2] = 0xff; + l_dqBitmap[3] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p1_lock_data.getBit<50>() ) + { + l_dqBitmap[4] = 0xff; + l_dqBitmap[5] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p1_lock_data.getBit<51>() ) + { + l_dqBitmap[6] = 0xff; + l_dqBitmap[7] = 0xff; + l_new_error = true; + } + + if ( !l_dp_p1_lock_data.getBit<52>() ) + { + l_dqBitmap[8] = 0xff; + l_dqBitmap[9] = 0xff; + l_new_error = true; + } + } + + // If there are new errors, write back the bad DQ Bitmap for l_port, l_dimm, l_rank + if ( l_new_error ) + { + FAPI_TRY(dimmSetBadDqBitmap(i_target, l_port, l_dimm, l_rank, l_dqBitmap)); + } + } // End of loop over RANKs + } + } // End of loop over DIMMs + } // End of loop over PORTs + + fapi_try_exit: + FAPI_INF("********* mss_ddr_phy_reset complete *********"); + return fapi2::current_err; + } + + /// + /// @brief deassert MCLK + /// @param[in] i_target the MBA target + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode deassert_force_mclk_low (const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) + { + fapi2::buffer<uint64_t> l_data_buffer; + + FAPI_INF( "+++++++++++++++++++++ DEASSERTING FORCE MCLK LOW +++++++++++++++++++++"); + + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_CCS_MODEQ, l_data_buffer)); + l_data_buffer.setBit<63>(); + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_CCS_MODEQ, l_data_buffer)); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Flush DDR PHY + /// @param[in] i_target the MBA target + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode ddr_phy_flush(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) + { + fapi2::buffer<uint64_t> l_data; + fapi2::buffer<uint64_t> l_mask; + + FAPI_INF(" Performing ddr_phy_flush routine"); + + FAPI_INF("ADR/DP18 FLUSH: 1) set PC_POWERDOWN_1 register, powerdown enable(48), flush bit(58)"); + l_data.setBit<48>(); // set MASTER_PD_CNTL bit + l_data.setBit<58>(); // set WR_FIFO_STAB bit + + l_mask.setBit<48>(); // set MASTER_PD_CNTL bit + l_mask.setBit<58>(); // set WR_FIFO_STAB mask bit + + FAPI_TRY(fapi2::putScomUnderMask(i_target, CEN_MBA_DDRPHY_PC_POWERDOWN_1_P0, l_data, l_mask)); + FAPI_TRY(fapi2::putScomUnderMask(i_target, CEN_MBA_DDRPHY_PC_POWERDOWN_1_P1, l_data, l_mask)); + FAPI_TRY(fapi2::delay(DELAY_100NS, DELAY_2000SIMCYCLES)); // wait 2000 simcycles (in sim mode) OR 100 nS (in hw mode) + + FAPI_INF("ADR/DP18 FLUSH: 2) clear PC_POWERDOWN_1 register, powerdown enable(48), flush bit(58)"); + l_data.flush<0>(); // clear data buffer + l_mask.flush<0>(); // clear mask buffer + l_mask.setBit<48>(); // set MASTER_PD_CNTL bit + l_mask.setBit<58>(); // set WR_FIFO_STAB mask bit + + FAPI_TRY(fapi2::putScomUnderMask(i_target, CEN_MBA_DDRPHY_PC_POWERDOWN_1_P0, l_data, l_mask)); + FAPI_TRY(fapi2::putScomUnderMask(i_target, CEN_MBA_DDRPHY_PC_POWERDOWN_1_P1, l_data, l_mask)); + + fapi_try_exit: + return fapi2::current_err; + } + +}//end extern C diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.H new file mode 100644 index 000000000..a4a4ae204 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.H @@ -0,0 +1,55 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_mss_ddr_phy_reset.C +/// @brief HWP header file to set up ddr phy +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB:CI +//// + +#ifndef MSS_DDR_PHY_RESETHWPB_H_ +#define MSS_DDR_PHY_RESETHWPB_H_ + +#include <fapi2.H> + +typedef fapi2::ReturnCode (*p9c_mss_ddr_phy_reset_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + +extern "C" +{ + /// + /// @brief Does a soft reset of the DDR PHY logic and lock the DDR PLLs + /// @param[in] i_target the MBA target + /// @return FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode p9c_mss_ddr_phy_reset(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + +} // extern "C" + +#endif // MSS_DDR_PHY_RESETHWPB_H_ diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk new file mode 100755 index 000000000..3b16d530f --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk @@ -0,0 +1,34 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] 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 + +# Include the macros and things for MSS procedures +-include 01common.mk +PROCEDURE=p9c_mss_ddr_phy_reset +OBJS+=p9c_dimmBadDqBitmapFuncs.o +OBJS+=p9c_mss_unmask_errors.o +OBJS+=p9c_mss_slew.o +$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE))) +#lib$(PROCEDURE)_DEPLIBS+=mss +$(call BUILD_PROCEDURE) diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.C new file mode 100755 index 000000000..d678d9354 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.C @@ -0,0 +1,2285 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_mss_unmask_errors.C +/// @brief Tools for DDR4 DIMMs centaur procedures +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB:CI +// +// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + +#include <p9c_mss_unmask_errors.H> +#include <cen_gen_scom_addresses.H> +#include <fapi2.H> + +/// +/// @brief Sets action regs and mask settings for pervasive errors to their runtime settings. +/// @param[in] i_target Centaur target +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode mss_unmask_pervasive_errors(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target) +{ + FAPI_INF("ENTER mss_unmask_pervasive_errors()"); + + //************************* + //************************* + // TP_PERV_LFIR + //************************* + //************************* + + fapi2::buffer<uint64_t> l_tp_perv_lfir_mask_or; + fapi2::buffer<uint64_t> l_tp_perv_lfir_mask_and; + fapi2::buffer<uint64_t> l_tp_perv_lfir_action0; + fapi2::buffer<uint64_t> l_tp_perv_lfir_action1; + fapi2::buffer<uint64_t> l_mem_perv_lfir_mask_or; + fapi2::buffer<uint64_t> l_mem_perv_lfir_mask_and; + fapi2::buffer<uint64_t> l_mem_perv_lfir_action0; + fapi2::buffer<uint64_t> l_mem_perv_lfir_action1; + fapi2::buffer<uint64_t> l_nest_perv_lfir_mask_or; + fapi2::buffer<uint64_t> l_nest_perv_lfir_mask_and; + fapi2::buffer<uint64_t> l_nest_perv_lfir_action0; + fapi2::buffer<uint64_t> l_nest_perv_lfir_action1; + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + // Read action0 + FAPI_TRY(fapi2::getScom(i_target, CEN_LOCAL_FIR_ACTION0_PCB, l_tp_perv_lfir_action0)); + + // Read action1 + FAPI_TRY(fapi2::getScom(i_target, CEN_LOCAL_FIR_ACTION1_PCB, l_tp_perv_lfir_action1)); + + l_tp_perv_lfir_mask_or.flush<0>(); + l_tp_perv_lfir_mask_and.flush<1>(); + + // 0 CFIR internal parity error recoverable unmask + l_tp_perv_lfir_action0.clearBit<0>(); + l_tp_perv_lfir_action1.setBit<0>(); + l_tp_perv_lfir_mask_and.clearBit<0>(); + + // 1 GPIO (PCB error) recoverable mask (forever) + // 2 CC (PCB error) recoverable mask (forever) + // 3 CC (OPCG, parity, scan collision) recoverable mask (forever) + // 4 PSC (PCB error) recoverable mask (forever) + // 5 PSC (parity error) recoverable mask (forever) + // 6 Thermal (parity error) recoverable mask (forever) + // 7 Thermal (PCB error) recoverable mask (forever) + // 8 Thermal (critical Trip error) recoverable mask (forever) + // 9 Thermal (fatal Trip error) recoverable mask (forever) + // 10 Thermal (Voltage trip error) recoverable mask (forever) + // 11 Trace Array recoverable mask (forever) + // 12 Trace Array recoverable mask (forever) + l_tp_perv_lfir_action0.clearBit<1, 12>(); + l_tp_perv_lfir_action1.setBit<1, 12>(); + l_tp_perv_lfir_mask_or.setBit<1, 12>(); + + // 13 ITR recoverable unmask + l_tp_perv_lfir_action0.clearBit<13>(); + l_tp_perv_lfir_action1.setBit<13>(); + l_tp_perv_lfir_mask_and.clearBit<13>(); + + // 14 ITR recoverable unmask + l_tp_perv_lfir_action0.clearBit<14>(); + l_tp_perv_lfir_action1.setBit<14>(); + l_tp_perv_lfir_mask_and.clearBit<14>(); + + + // 15 ITR (itr_tc_pcbsl_slave_fir_err) recoverable mask (forever) + // 16 PIB recoverable mask (forever) + // 17 PIB recoverable mask (forever) + // 18 PIB recoverable mask (forever) + l_tp_perv_lfir_action0.clearBit<15, 4>(); + l_tp_perv_lfir_action1.setBit<15, 4>(); + l_tp_perv_lfir_mask_or.setBit<15, 4>(); + + + // NOTE: 19 and 20 already cleared and unmasked in cen_mem_pll_setup.C + // 19 nest PLLlock recoverable unmask + // 20 mem PLLlock recoverable unmask + + // 21:39 unused local errors recoverable mask (forever) + // 40 local xstop in another chiplet recoverable mask (forever) + l_tp_perv_lfir_action0.clearBit<21, 20>(); + l_tp_perv_lfir_action1.setBit<21, 20>(); + l_tp_perv_lfir_mask_or.setBit<21, 20>(); + + // 41:63 Reserved not implemented, so won't touch these + + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, CEN_LOCAL_FIR_ACTION0_PCB, l_tp_perv_lfir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, CEN_LOCAL_FIR_ACTION1_PCB, l_tp_perv_lfir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, CEN_LOCAL_FIR_MASK_PCB2, l_tp_perv_lfir_mask_or)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_LOCAL_FIR_MASK_PCB1, l_tp_perv_lfir_mask_and)); + + + //************************* + //************************* + // NEST_PERV_LFIR + //************************* + //************************* + + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_nest_perv_lfir_action0.flush<0>(); + l_nest_perv_lfir_action1.flush<0>(); + l_nest_perv_lfir_mask_or.flush<0>(); + l_nest_perv_lfir_mask_and.flush<1>(); + + // 0 CFIR internal parity error recoverable unmask + l_nest_perv_lfir_action0.clearBit<0>(); + l_nest_perv_lfir_action1.setBit<0>(); + l_nest_perv_lfir_mask_and.clearBit<0>(); + + // 1 GPIO (PCB error) recoverable mask (forever) + // 2 CC (PCB error) recoverable mask (forever) + // 3 CC (OPCG, parity, scan collision) recoverable mask (forever) + // 4 PSC (PCB error) recoverable mask (forever) + // 5 PSC (parity error) recoverable mask (forever) + // 6 Thermal (parity error) recoverable mask (forever) + // 7 Thermal (PCB error) recoverable mask (forever) + // 8 Thermal (critical Trip error) recoverable mask (forever) + // 9 Thermal (fatal Trip error) recoverable mask (forever) + // 10 Thermal (Voltage trip error) recoverable mask (forever) + // 11 Trace Array recoverable mask (forever) + // 12 Trace Array recoverable mask (forever) + // 13:39 unused local errors recoverable mask (forever) + // 40 local xstop in another chiplet recoverable mask (forever) + l_nest_perv_lfir_action0.clearBit<1, 40>(); + l_nest_perv_lfir_action1.setBit<1, 40>(); + l_nest_perv_lfir_mask_or.setBit<1, 40>(); + + // 41:63 Reserved not implemented, so won't touch these + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, CEN_TCN_LOCAL_FIR_ACTION0_PCB, l_nest_perv_lfir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, CEN_TCN_LOCAL_FIR_ACTION1_PCB, l_nest_perv_lfir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, CEN_TCN_LOCAL_FIR_MASK_PCB2, l_nest_perv_lfir_mask_or)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_TCN_LOCAL_FIR_MASK_PCB1, l_nest_perv_lfir_mask_and)); + + //************************* + //************************* + // MEM_PERV_LFIR + //************************* + //************************* + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mem_perv_lfir_action0.flush<0>(); + l_mem_perv_lfir_action1.flush<0>(); + l_mem_perv_lfir_mask_or.flush<0>(); + l_mem_perv_lfir_mask_and.flush<1>(); + + // 0 CFIR internal parity error recoverable unmask + l_mem_perv_lfir_action0.clearBit<0>(); + l_mem_perv_lfir_action1.setBit<0>(); + l_mem_perv_lfir_mask_and.clearBit<0>(); + + // 1 GPIO (PCB error) recoverable mask (forever) + // 2 CC (PCB error) recoverable mask (forever) + // 3 CC (OPCG, parity, scan collision) recoverable mask (forever) + // 4 PSC (PCB error) recoverable mask (forever) + // 5 PSC (parity error) recoverable mask (forever) + // 6 Thermal (parity error) recoverable mask (forever) + // 7 Thermal (PCB error) recoverable mask (forever) + // 8 Thermal (critical Trip error) recoverable mask (forever) + // 9 Thermal (fatal Trip error) recoverable mask (forever) + // 10 Thermal (Voltage trip error) recoverable mask (forever) + // 11 mba01 Trace Array recoverable mask (forever) + // 12 mba01 Trace Array recoverable mask (forever) + // 13 mba23 Trace Array recoverable mask (forever) + // 14 mba23 Trace Array recoverable mask (forever) + // 15:39 unused local errors recoverable mask (forever) + // 40 local xstop in another chiplet recoverable mask (forever) + l_mem_perv_lfir_action0.clearBit<1, 40>(); + l_mem_perv_lfir_action1.setBit<1, 40>(); + l_mem_perv_lfir_mask_or.setBit<1, 40>(); + + // 41:63 Reserved not implemented, so won't touch these + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, CEN_TCM_LOCAL_FIR_ACTION0_PCB, l_mem_perv_lfir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, CEN_TCM_LOCAL_FIR_ACTION1_PCB, l_mem_perv_lfir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, CEN_TCM_LOCAL_FIR_MASK_PCB2, l_mem_perv_lfir_mask_or)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_TCM_LOCAL_FIR_MASK_PCB1, l_mem_perv_lfir_mask_and)); + +fapi_try_exit: + FAPI_INF("EXIT mss_unmask_pervasive_errors()"); + return fapi2::current_err; +} + +/// +/// @brief Sets action regs and mask settings for inband errors to their runtime settings. +/// @param[in] i_target Centaur target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of cen_mem_startclocks.C +/// +fapi2::ReturnCode mss_unmask_inband_errors(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target) + +{ + FAPI_INF("ENTER mss_unmask_inband_errors()"); + + //************************* + //************************* + // MBS_FIR_REG + //************************* + //************************* + + fapi2::buffer<uint64_t> l_mbs_fir_mask; + fapi2::buffer<uint64_t> l_mbs_fir_mask_or; + fapi2::buffer<uint64_t> l_mbs_fir_mask_and; + fapi2::buffer<uint64_t> l_mbs_fir_action0; + fapi2::buffer<uint64_t> l_mbs_fir_action1; + + uint8_t l_dd2_fir_bit_defn_changes = 0; + + // Get attribute that tells us if mbspa 0 cmd complete attention is fixed for dd2 + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES, i_target, + l_dd2_fir_bit_defn_changes), + "Error getting ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES"); + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, CEN_MBS_FIR_MASK_REG, l_mbs_fir_mask)); + + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbs_fir_action0.flush<0>(); + l_mbs_fir_action1.flush<0>(); + l_mbs_fir_mask_or.flush<0>(); + l_mbs_fir_mask_and.flush<1>(); + + // 0 host_protocol_error channel checkstop unmask + l_mbs_fir_action0.clearBit<0>(); + l_mbs_fir_action1.clearBit<0>(); + l_mbs_fir_mask_and.clearBit<0>(); + + // 1 int_protocol_error channel checkstop unmask + l_mbs_fir_action0.clearBit<1>(); + l_mbs_fir_action1.clearBit<1>(); + l_mbs_fir_mask_and.clearBit<1>(); + + // 2 invalid_address_error channel checkstop mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<2>(); + l_mbs_fir_action1.clearBit<2>(); + l_mbs_fir_mask_or.setBit<2>(); + + // 3 external_timeout recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<3>(); + l_mbs_fir_action1.setBit<3>(); + l_mbs_fir_mask_or.setBit<3>(); + + // 4 internal_timeout recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<4>(); + l_mbs_fir_action1.setBit<4>(); + l_mbs_fir_mask_or.setBit<4>(); + + // 5 int_buffer_ce recoverable unmask + l_mbs_fir_action0.clearBit<5>(); + l_mbs_fir_action1.setBit<5>(); + l_mbs_fir_mask_and.clearBit<5>(); + + // 6 int_buffer_ue channel checkstop unmask + // HW278850: 8B ecc UE from SRB,PFB not transformed to SUE when allocating into L4 + l_mbs_fir_action0.clearBit<6>(); + l_mbs_fir_action1.clearBit<6>(); + l_mbs_fir_mask_and.clearBit<6>(); + + // 7 int_buffer_sue recoverable mask (forever) + l_mbs_fir_action0.clearBit<7>(); + l_mbs_fir_action1.setBit<7>(); + l_mbs_fir_mask_or.setBit<7>(); + + // 8 int_parity_error channel checkstop unmask + l_mbs_fir_action0.clearBit<8>(); + l_mbs_fir_action1.clearBit<8>(); + l_mbs_fir_mask_and.clearBit<8>(); + + // 9 cache_srw_ce recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<9>(); + l_mbs_fir_action1.setBit<9>(); + l_mbs_fir_mask_or.setBit<9>(); + + // 10 cache_srw_ue recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<10>(); + l_mbs_fir_action1.setBit<10>(); + l_mbs_fir_mask_or.setBit<10>(); + + // 11 cache_srw_sue recoverable mask (forever) + l_mbs_fir_action0.clearBit<11>(); + l_mbs_fir_action1.setBit<11>(); + l_mbs_fir_mask_or.setBit<11>(); + + // 12 cache_co_ce recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<12>(); + l_mbs_fir_action1.setBit<12>(); + l_mbs_fir_mask_or.setBit<12>(); + + // 13 cache_co_ue recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<13>(); + l_mbs_fir_action1.setBit<13>(); + l_mbs_fir_mask_or.setBit<13>(); + + // 14 cache_co_sue recoverable mask (forever) + l_mbs_fir_action0.clearBit<14>(); + l_mbs_fir_action1.setBit<14>(); + l_mbs_fir_mask_or.setBit<14>(); + + // 15 dir_ce recoverable DD1: mask (forever) + // 15 dir_ce recoverable DD2: mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<15>(); + l_mbs_fir_action1.setBit<15>(); + l_mbs_fir_mask_or.setBit<15>(); + + // 16 dir_ue channel checkstop mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<16>(); + l_mbs_fir_action1.clearBit<16>(); + l_mbs_fir_mask_or.setBit<16>(); + + // 17 dir_member_deleted recoverable mask (forever) + l_mbs_fir_action0.clearBit<17>(); + l_mbs_fir_action1.setBit<17>(); + l_mbs_fir_mask_or.setBit<17>(); + + // 18 dir_all_members_deleted channel checkstop mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<18>(); + l_mbs_fir_action1.clearBit<18>(); + l_mbs_fir_mask_or.setBit<18>(); + + // 19 lru_error recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<19>(); + l_mbs_fir_action1.setBit<19>(); + l_mbs_fir_mask_or.setBit<19>(); + + // 20 eDRAM error channel checkstop mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<20>(); + l_mbs_fir_action1.clearBit<20>(); + l_mbs_fir_mask_or.setBit<20>(); + + // 21 emergency_throttle_set recoverable mask (forever) + l_mbs_fir_action0.clearBit<21>(); + l_mbs_fir_action1.setBit<21>(); + l_mbs_fir_mask_or.setBit<21>(); + + // 22 Host Inband Read Error recoverable mask (forever) + l_mbs_fir_action0.clearBit<22>(); + l_mbs_fir_action1.setBit<22>(); + l_mbs_fir_mask_or.setBit<22>(); + + // 23 Host Inband Write Error recoverable mask (forever) + l_mbs_fir_action0.clearBit<23>(); + l_mbs_fir_action1.setBit<23>(); + l_mbs_fir_mask_or.setBit<23>(); + + // 24 OCC Inband Read Error recoverable mask (forever) + l_mbs_fir_action0.clearBit<24>(); + l_mbs_fir_action1.setBit<24>(); + l_mbs_fir_mask_or.setBit<24>(); + + // 25 OCC Inband Write Error recoverable mask (forever) + l_mbs_fir_action0.clearBit<25>(); + l_mbs_fir_action1.setBit<25>(); + l_mbs_fir_mask_or.setBit<25>(); + + // 26 srb_buffer_ce recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<26>(); + l_mbs_fir_action1.setBit<26>(); + l_mbs_fir_mask_or.setBit<26>(); + + // 27 srb_buffer_ue recoverable mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<27>(); + l_mbs_fir_action1.setBit<27>(); + l_mbs_fir_mask_or.setBit<27>(); + + // 28 srb_buffer_sue recoverable mask (forever) + l_mbs_fir_action0.clearBit<28>(); + l_mbs_fir_action1.setBit<28>(); + l_mbs_fir_mask_or.setBit<28>(); + + if (l_dd2_fir_bit_defn_changes) + { + // 29 dir_purge_ce recoverable mask + l_mbs_fir_action0.clearBit<29>(); + l_mbs_fir_action1.setBit<29>(); + l_mbs_fir_mask_or.setBit<29>(); + + // 30 proximal_ce_ue channel checkstop mask (until unmask_fetch_errors) + l_mbs_fir_action0.clearBit<30>(); + l_mbs_fir_action1.clearBit<30>(); + l_mbs_fir_mask_or.setBit<30>(); + + // 31 spare recoverable mask + l_mbs_fir_action0.clearBit<31>(); + l_mbs_fir_action1.setBit<31>(); + l_mbs_fir_mask_or.setBit<31>(); + + // 32 spare recoverable mask + l_mbs_fir_action0.clearBit<32>(); + l_mbs_fir_action1.setBit<32>(); + l_mbs_fir_mask_or.setBit<33>(); + + // 33 internal_scom_error recoverable unmask + l_mbs_fir_action0.clearBit<33>(); + l_mbs_fir_action1.setBit<33>(); + l_mbs_fir_mask_and.clearBit<33>(); + + // 34 internal_scom_error_copy recoverable unmask + l_mbs_fir_action0.clearBit<34>(); + l_mbs_fir_action1.setBit<34>(); + l_mbs_fir_mask_and.clearBit<34>(); + + // 35:63 Reserved not implemented, so won't touch these + } + + else + { + // 29 internal_scom_error recoverable unmask + l_mbs_fir_action0.clearBit<29>(); + l_mbs_fir_action1.setBit<29>(); + l_mbs_fir_mask_and.clearBit<29>(); + + // 30 internal_scom_error_copy recoverable unmask + l_mbs_fir_action0.clearBit<30>(); + l_mbs_fir_action1.setBit<30>(); + l_mbs_fir_mask_and.clearBit<30>(); + + // 31:63 Reserved not implemented, so won't touch these + } + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, CEN_MBS_FIR_ACTION0_REG_RO, l_mbs_fir_action0)); + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, CEN_MBS_FIR_ACTION1_REG_RO, l_mbs_fir_action1)); + + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, CEN_MBS_FIR_MASK_REG_WO_OR, l_mbs_fir_mask_or)); + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_MBS_FIR_MASK_REG_WO_AND, l_mbs_fir_mask_and)) + + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, CEN_MBS_FIR_ACTION0_REG_RO, l_mbs_fir_action0)); + FAPI_TRY(fapi2::getScom(i_target, CEN_MBS_FIR_ACTION1_REG_RO, l_mbs_fir_action1)); + FAPI_TRY(fapi2::getScom(i_target, CEN_MBS_FIR_MASK_REG, l_mbs_fir_mask)); + + //************************************************ + +fapi_try_exit: + FAPI_INF("EXIT mss_unmask_inband_errors()"); + return fapi2::current_err; + +} + +/// +/// @brief Sets action regs and mask settings for ddr phy errors to runtime settings. +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of proc_cen_framelock.C +/// +fapi2::ReturnCode mss_unmask_ddrphy_errors(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) +{ + FAPI_INF("ENTER mss_unmask ddrphy_errors()"); + + //************************* + //************************* + // DDRPHY_FIR_REG + //************************* + //************************* + + fapi2::buffer<uint64_t> l_ddrphy_fir_mask; + fapi2::buffer<uint64_t> l_ddrphy_fir_mask_or; + fapi2::buffer<uint64_t> l_ddrphy_fir_mask_and; + fapi2::buffer<uint64_t> l_ddrphy_fir_action0; + fapi2::buffer<uint64_t> l_ddrphy_fir_action1; + fapi2::buffer<uint64_t> l_mbafir_mask; + fapi2::buffer<uint64_t> l_mbafir_mask_or; + fapi2::buffer<uint64_t> l_mbafir_mask_and; + fapi2::buffer<uint64_t> l_mbafir_action0; + fapi2::buffer<uint64_t> l_mbafir_action1; + + uint8_t l_dd2_fir_bit_defn_changes = 0; + fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> l_targetCentaur; + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_ddrphy_fir_action0.flush<0>(); + l_ddrphy_fir_action1.flush<0>(); + l_ddrphy_fir_mask_or.flush<0>(); + l_ddrphy_fir_mask_and.flush<0>(); + l_ddrphy_fir_mask_and.setBit<48, 16>(); + + // 0:47 Reserved not implemented, so won't touch these + + // 48 ddr0_fsm_ckstp channel checkstop unmask + l_ddrphy_fir_action0.clearBit<48>(); + l_ddrphy_fir_action1.clearBit<48>(); + l_ddrphy_fir_mask_and.clearBit<48>(); + + // 49 ddr0_parity_ckstp channel checkstop unmask + l_ddrphy_fir_action0.clearBit<49>(); + l_ddrphy_fir_action1.clearBit<49>(); + l_ddrphy_fir_mask_and.clearBit<49>(); + + // 50 ddr0_calibration_error recoverable mask (forever) + l_ddrphy_fir_action0.clearBit<50>(); + l_ddrphy_fir_action1.setBit<50>(); + l_ddrphy_fir_mask_or.setBit<50>(); + + // 51 ddr0_fsm_err recoverable unmask + l_ddrphy_fir_action0.clearBit<51>(); + l_ddrphy_fir_action1.setBit<51>(); + l_ddrphy_fir_mask_and.clearBit<51>(); + + // 52 ddr0_parity_err recoverable unmask + l_ddrphy_fir_action0.clearBit<52>(); + l_ddrphy_fir_action1.setBit<52>(); + l_ddrphy_fir_mask_and.clearBit<52>(); + + // 53 ddr01_fir_parity_err recoverable unmask + l_ddrphy_fir_action0.clearBit<53>(); + l_ddrphy_fir_action1.setBit<53>(); + l_ddrphy_fir_mask_and.clearBit<53>(); + + // 54 Reserved recoverable mask (forever) + l_ddrphy_fir_action0.clearBit<54>(); + l_ddrphy_fir_action1.setBit<54>(); + l_ddrphy_fir_mask_or.setBit<54>(); + + // 55 Reserved recoverable mask (forever) + l_ddrphy_fir_action0.clearBit<55>(); + l_ddrphy_fir_action1.setBit<55>(); + l_ddrphy_fir_mask_or.setBit<55>(); + + // 56 ddr1_fsm_ckstp channel checkstop unmask + l_ddrphy_fir_action0.clearBit<56>(); + l_ddrphy_fir_action1.clearBit<56>(); + l_ddrphy_fir_mask_and.clearBit<56>(); + + // 57 ddr1_parity_ckstp channel checkstop unmask + l_ddrphy_fir_action0.clearBit<57>(); + l_ddrphy_fir_action1.clearBit<57>(); + l_ddrphy_fir_mask_and.clearBit<57>(); + + // 58 ddr1_calibration_error recoverable mask (forever) + l_ddrphy_fir_action0.clearBit<58>(); + l_ddrphy_fir_action1.setBit<58>(); + l_ddrphy_fir_mask_or.setBit<58>(); + + // 59 ddr1_fsm_err recoverable unmask + l_ddrphy_fir_action0.clearBit<59>(); + l_ddrphy_fir_action1.setBit<59>(); + l_ddrphy_fir_mask_and.clearBit<59>(); + + // 60 ddr1_parity_err recoverable unmask + l_ddrphy_fir_action0.clearBit<60>(); + l_ddrphy_fir_action1.setBit<60>(); + l_ddrphy_fir_mask_and.clearBit<60>(); + + // 61 Reserved recoverable mask (forever) + l_ddrphy_fir_action0.clearBit<61>(); + l_ddrphy_fir_action1.setBit<61>(); + l_ddrphy_fir_mask_or.setBit<61>(); + + // 62 Reserved recoverable mask (forever) + l_ddrphy_fir_action0.clearBit<62>(); + l_ddrphy_fir_action1.setBit<62>(); + l_ddrphy_fir_mask_or.setBit<62>(); + + // 63 Reserved recoverable mask (forever) + l_ddrphy_fir_action0.clearBit<63>(); + l_ddrphy_fir_action1.setBit<63>(); + l_ddrphy_fir_mask_or.setBit<63>(); + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_PHY01_DDRPHY_FIR_ACTION0_REG_RO, l_ddrphy_fir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_PHY01_DDRPHY_FIR_ACTION1_REG_RO, l_ddrphy_fir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_PHY01_DDRPHY_FIR_MASK_REG_WO_OR, l_ddrphy_fir_mask_or)); + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_PHY01_DDRPHY_FIR_MASK_REG_WO_AND, l_ddrphy_fir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_PHY01_DDRPHY_FIR_ACTION0_REG_RO, l_ddrphy_fir_action0)); + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_PHY01_DDRPHY_FIR_ACTION1_REG_RO, l_ddrphy_fir_action1)); + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_PHY01_DDRPHY_FIR_MASK_REG, l_ddrphy_fir_mask)); + + //************************************************ + + + //************************* + //************************* + // MBAFIR + //************************* + //************************* + + // Get Centaur target for the given MBA + l_targetCentaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>(); + // Get attribute that tells us if mbspa 0 cmd complete attention is fixed for dd2 + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES, l_targetCentaur, + l_dd2_fir_bit_defn_changes), "Error getting ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES"); + + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, + CEN_MBA_MBAFIRMASK, + l_mbafir_mask)); + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbafir_action0.flush<0>(); + l_mbafir_action1.flush<0>(); + l_mbafir_mask_or.flush<0>(); + l_mbafir_mask_and.flush<1>(); + + + // 0 Invalid_Maint_Cmd recoverable masked (forever) + l_mbafir_action0.clearBit<0>(); + l_mbafir_action1.setBit<0>(); + l_mbafir_mask_or.setBit<0>(); + + // 1 Invalid_Maint_Address recoverable masked (forever) + l_mbafir_action0.clearBit<1>(); + l_mbafir_action1.setBit<1>(); + l_mbafir_mask_or.setBit<1>(); + + // 2 Multi_address_Maint_timeout recoverable masked (until mss_unmask_maint_errors) + l_mbafir_action0.clearBit<2>(); + l_mbafir_action1.setBit<2>(); + l_mbafir_mask_or.setBit<2>(); + + // 3 Internal_fsm_error channel checkstop unmask + l_mbafir_action0.clearBit<3>(); + l_mbafir_action1.clearBit<3>(); + l_mbafir_mask_and.clearBit<3>(); + + // 4 MCBIST_Error recoverable mask (forever) + l_mbafir_action0.clearBit<4>(); + l_mbafir_action1.setBit<4>(); + l_mbafir_mask_or.setBit<4>(); + + // 5 scom_cmd_reg_pe channel checkstop unmask + l_mbafir_action0.clearBit<5>(); + l_mbafir_action1.clearBit<5>(); + l_mbafir_mask_and.clearBit<5>(); + + // 6 channel_chkstp_err channel checkstop unmask + l_mbafir_action0.clearBit<6>(); + l_mbafir_action1.clearBit<6>(); + l_mbafir_mask_and.clearBit<6>(); + + // 7 wrd_caw2_data_ce_ue_err channel checkstop masked (until mss_unmask_maint_errors) + l_mbafir_action0.clearBit<7>(); + l_mbafir_action1.clearBit<7>(); + l_mbafir_mask_or.setBit<7>(); + + if (l_dd2_fir_bit_defn_changes) + { + // 8 maint_1hot_st_error_dd2 channel checkstop unmask + l_mbafir_action0.clearBit<8>(); + l_mbafir_action1.clearBit<8>(); + l_mbafir_mask_and.clearBit<8>(); + } + else + { + // 8 RESERVED recoverable mask (forever) + l_mbafir_action0.clearBit<8>(); + l_mbafir_action1.setBit<8>(); + l_mbafir_mask_or.setBit<8>(); + } + + // 9:14 RESERVED recoverable mask (forever) + l_mbafir_action0.clearBit<9, 6>(); + l_mbafir_action1.setBit<9, 6>(); + l_mbafir_mask_or.setBit<9, 6>(); + + // 15 internal scom error recoverable unmask + l_mbafir_action0.clearBit<15>(); + l_mbafir_action1.setBit<15>(); + l_mbafir_mask_and.clearBit<15>(); + + // 16 internal scom error clone recoverable unmask + l_mbafir_action0.clearBit<16>(); + l_mbafir_action1.setBit<16>(); + l_mbafir_mask_and.clearBit<16>(); + + + // 17:63 RESERVED not implemented, so won't touch these + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, + CEN_MBA_MBAFIRACT0, + l_mbafir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, + CEN_MBA_MBAFIRACT1, + l_mbafir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, + CEN_MBA_MBAFIRMASK_WO_OR, + l_mbafir_mask_or)); + + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, + CEN_MBA_MBAFIRMASK_WO_AND, + l_mbafir_mask_and)); + + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, + CEN_MBA_MBAFIRACT0, + l_mbafir_action0)); + FAPI_TRY(fapi2::getScom(i_target, + CEN_MBA_MBAFIRACT1, + l_mbafir_action1)); + FAPI_TRY(fapi2::getScom(i_target, + CEN_MBA_MBAFIRMASK, + l_mbafir_mask)); + + //************************************************ + +fapi_try_exit: + FAPI_INF("EXIT mss_unmask_ddrphy_errors()"); + return fapi2::current_err; +} + +/// +/// @brief Sets MBACALFIR action regs to their runtime settings. +/// Unmasks errors that are valid for PRD to handle after mss_draminit procedure. +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit.C. +/// +fapi2::ReturnCode mss_unmask_draminit_errors(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) +{ + FAPI_INF("ENTER mss_unmask_draminit_errors()"); + + //************************* + //************************* + // MBACALFIR + //************************* + //************************* + + fapi2::buffer<uint64_t> l_mbacalfir_mask; + fapi2::buffer<uint64_t> l_mbacalfir_mask_or; + fapi2::buffer<uint64_t> l_mbacalfir_mask_and; + fapi2::buffer<uint64_t> l_mbacalfir_action0; + fapi2::buffer<uint64_t> l_mbacalfir_action1; + + uint8_t l_dd2_fir_bit_defn_changes = 0; + fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> l_targetCentaur; + uint8_t l_dimm_type = 0; + + // Get Centaur target for the given MBA + l_targetCentaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>(); + + // Get attribute that tells us if mbspa 0 cmd complete attention is fixed for dd2 + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES, l_targetCentaur, + l_dd2_fir_bit_defn_changes), "Error getting ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES"); + + // Get DIMM type + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, i_target, l_dimm_type), "Error getting ATTR_CEN_EFF_DIMM_TYPE"); + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_MASK, l_mbacalfir_mask)); + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbacalfir_action0.flush<0>(); + l_mbacalfir_action1.flush<0>(); + l_mbacalfir_mask_or.flush<0>(); + l_mbacalfir_mask_and.flush<1>(); + + // 0 MBA Recoverable Error recoverable mask (until after draminit_training) + l_mbacalfir_action0.clearBit<0>(); + l_mbacalfir_action1.setBit<0>(); + l_mbacalfir_mask_or.setBit<0>(); + + // 1 MBA Nonrecoverable Error channel checkstop mask (until after draminit_mc) + l_mbacalfir_action0.clearBit<1>(); + l_mbacalfir_action1.clearBit<1>(); + l_mbacalfir_mask_or.setBit<1>(); + + // 2 Refresh Overrun recoverable mask (until after draminit_mc) + l_mbacalfir_action0.clearBit<2>(); + l_mbacalfir_action1.setBit<2>(); + l_mbacalfir_mask_or.setBit<2>(); + + // 3 WAT error recoverable mask (forever) + l_mbacalfir_action0.clearBit<3>(); + l_mbacalfir_action1.setBit<3>(); + l_mbacalfir_mask_or.setBit<3>(); + + // 4 RCD Parity Error 0 recoverable unmask (if RDIMM or LRDIMM) + l_mbacalfir_action0.clearBit<4>(); + l_mbacalfir_action1.setBit<4>(); + + if ((l_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM) + || (l_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM)) + { + l_mbacalfir_mask_and.clearBit<4>(); + } + else + { + l_mbacalfir_mask_or.setBit<4>(); + } + + // 5 ddr0_cal_timeout_err recoverable mask (until after draminit_mc) + l_mbacalfir_action0.clearBit<5>(); + l_mbacalfir_action1.setBit<5>(); + l_mbacalfir_mask_or.setBit<5>(); + + // 6 ddr1_cal_timeout_err recoverable mask (until after draminit_mc) + l_mbacalfir_action0.clearBit<6>(); + l_mbacalfir_action1.setBit<6>(); + l_mbacalfir_mask_or.setBit<6>(); + + // 7 RCD Parity Error 1 recoverable unmask (if RDIMM or LRDIMM) + l_mbacalfir_action0.clearBit<7>(); + l_mbacalfir_action1.setBit<7>(); + + if ((l_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM) + || (l_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM)) + { + l_mbacalfir_mask_and.clearBit<7>(); + } + else + { + l_mbacalfir_mask_or.setBit<7>(); + } + + // 8 mbx to mba par error channel checkstop mask (until after draminit_training_adv) + l_mbacalfir_action0.clearBit<8>(); + l_mbacalfir_action1.clearBit<8>(); + l_mbacalfir_mask_or.setBit<8>(); + + // 9 mba_wrd ue recoverable mask (until mainline traffic) + l_mbacalfir_action0.clearBit<9>(); + l_mbacalfir_action1.setBit<9>(); + l_mbacalfir_mask_or.setBit<9>(); + + // 10 mba_wrd ce recoverable mask (until mainline traffic) + l_mbacalfir_action0.clearBit<10>(); + l_mbacalfir_action1.setBit<10>(); + l_mbacalfir_mask_or.setBit<10>(); + + // 11 mba_maint ue recoverable mask (until after draminit_training_adv) + l_mbacalfir_action0.clearBit<11>(); + l_mbacalfir_action1.setBit<11>(); + l_mbacalfir_mask_or.setBit<11>(); + + // 12 mba_maint ce recoverable mask (until after draminit_training_adv) + l_mbacalfir_action0.clearBit<12>(); + l_mbacalfir_action1.setBit<12>(); + l_mbacalfir_mask_or.setBit<12>(); + + // 13 ddr_cal_reset_timeout channel checkstop unmask + l_mbacalfir_action0.clearBit<13>(); + l_mbacalfir_action1.clearBit<13>(); + l_mbacalfir_mask_and.clearBit<13>(); + + // 14 wrq_data_ce recoverable mask (until mainline traffic) + l_mbacalfir_action0.clearBit<14>(); + l_mbacalfir_action1.setBit<14>(); + l_mbacalfir_mask_or.setBit<14>(); + + // 15 wrq_data_ue recoverable mask (until mainline traffic) + l_mbacalfir_action0.clearBit<15>(); + l_mbacalfir_action1.setBit<15>(); + l_mbacalfir_mask_or.setBit<15>(); + + // 16 wrq_data_sue recoverable mask (forever) + l_mbacalfir_action0.clearBit<16>(); + l_mbacalfir_action1.setBit<16>(); + l_mbacalfir_mask_or.setBit<16>(); + + // 17 wrq_rrq_hang_err recoverable mask (until after draminit_training_adv) + l_mbacalfir_action0.clearBit<17>(); + l_mbacalfir_action1.setBit<17>(); + l_mbacalfir_mask_or.setBit<17>(); + + // 18 sm_1hot_err channel checkstop unmask + l_mbacalfir_action0.clearBit<18>(); + l_mbacalfir_action1.clearBit<18>(); + l_mbacalfir_mask_and.clearBit<18>(); + + // 19 wrd_scom_error recoverable unmask + l_mbacalfir_action0.clearBit<19>(); + l_mbacalfir_action1.setBit<19>(); + l_mbacalfir_mask_and.clearBit<19>(); + + if (l_dd2_fir_bit_defn_changes) + { + // 20 rhmr_prim_reached_max recoverable mask (forever) + l_mbacalfir_action0.clearBit<20>(); + l_mbacalfir_action1.setBit<20>(); + l_mbacalfir_mask_or.setBit<20>(); + + // 21 rhmr_sec_reached_max recoverable mask (forever) + l_mbacalfir_action0.clearBit<21>(); + l_mbacalfir_action1.setBit<21>(); + l_mbacalfir_mask_or.setBit<21>(); + + // 22 rhmr_sec_already_full recoverable mask (forever) + l_mbacalfir_action0.clearBit<22>(); + l_mbacalfir_action1.setBit<22>(); + l_mbacalfir_mask_or.setBit<22>(); + + // 23 Reserved recoverable mask (forever) + l_mbacalfir_action0.clearBit<23>(); + l_mbacalfir_action1.setBit<23>(); + l_mbacalfir_mask_or.setBit<23>(); + + // 24 internal_scom_error recoverable unmask + l_mbacalfir_action0.clearBit<24>(); + l_mbacalfir_action1.setBit<24>(); + l_mbacalfir_mask_and.clearBit<24>(); + + // 25 internal_scom_error_copy recoverable unmask + l_mbacalfir_action0.clearBit<25>(); + l_mbacalfir_action1.setBit<25>(); + l_mbacalfir_mask_and.clearBit<25>(); + + // 26-63 Reserved not implemented, so won't touch these + } + else + { + // 20 internal_scom_error recoverable unmask + l_mbacalfir_action0.clearBit<20>(); + l_mbacalfir_action1.setBit<20>(); + l_mbacalfir_mask_and.clearBit<20>(); + + // 21 internal_scom_error_copy recoverable unmask + l_mbacalfir_action0.clearBit<21>(); + l_mbacalfir_action1.setBit<21>(); + l_mbacalfir_mask_and.clearBit<21>(); + + // 22-63 Reserved not implemented, so won't touch these + } + + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_MBACALFIR_ACTION0, l_mbacalfir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_MBACALFIR_ACTION1, l_mbacalfir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_MBACALFIR_MASK_WO_OR, l_mbacalfir_mask_or)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_MBACALFIR_MASK_WO_AND, l_mbacalfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_ACTION0, l_mbacalfir_action0)); + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_ACTION1, l_mbacalfir_action1)); + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_MASK, l_mbacalfir_mask)); + + //************************************************ + +fapi_try_exit: + FAPI_INF("EXIT mss_unmask_draminit_errors()"); + return fapi2::current_err; +} + +/// +/// @brief Unmasks MBACALFIR errors that are valid for PRD to handle after mss_draminit_training +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_training.C. +/// +fapi2::ReturnCode mss_unmask_draminit_training_errors(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) +{ + FAPI_INF("ENTER mss_unmask_draminit_training_errors()"); + + //************************* + //************************* + // MBACALFIR + //************************* + //************************* + + fapi2::buffer<uint64_t> l_mbacalfir_mask; + fapi2::buffer<uint64_t> l_mbacalfir_mask_and; + + // NOTE: In the IPL sequence, mss_unmask_draminit_errors has already been + // called, which has already set the MBACALFIR action regs to their runtime + // values, so no need to touch the action regs here. + + // NOTE: In the IPL sequence, mss_unmask_draminit_errors has already been + // called, which has already unmasked the approproiate MBACALFIR errors + // following mss_draminit. So all we will do here is unmask a few more + // errors that would be considered valid after the mss_draminit_training + // procedure. + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_MASK, l_mbacalfir_mask)); + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbacalfir_mask_and.flush<1>(); + + // 0 MBA Recoverable Error recoverable umask + FAPI_TRY(l_mbacalfir_mask_and.clearBit(0)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_MBACALFIR_MASK_WO_AND, l_mbacalfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_MASK, l_mbacalfir_mask)); + + //************************************************ + +fapi_try_exit: + FAPI_INF("EXIT mss_unmask_draminit_training_errors()"); + return fapi2::current_err; +} + +/// +/// @brief Unmasks MBACALFIR errors that are valid for PRD to handle after mss_draminit_training_advanced +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_training_advanced.C. +/// +fapi2::ReturnCode mss_unmask_draminit_training_advanced_errors(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target) +{ + FAPI_INF("ENTER mss_unmask_draminit_training_advanced_errors()"); + + //************************* + //************************* + // MBACALFIR + //************************* + //************************* + + fapi2::buffer<uint64_t> l_mbacalfir_mask; + fapi2::buffer<uint64_t> l_mbacalfir_mask_and; + fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> l_targetCentaur; + uint8_t l_mbaPosition = 0; // 0 = mba01, 1 = mba23 + + constexpr uint32_t l_mbsfir_mask_address[] = + { + // port0/1 port2/3 + CEN_MCBISTS01_MBSFIRMASK, CEN_MCBISTS23_MBSFIRMASK + }; + + constexpr uint32_t l_mbsfir_mask_or_address[] = + { + // port0/1 port2/3 + CEN_MCBISTS01_MBSFIRMASK_WO_OR, CEN_MCBISTS23_MBSFIRMASK_WO_OR + }; + + constexpr uint32_t l_mbsfir_mask_and_address[] = + { + // port0/1 port2/3 + CEN_MCBISTS01_MBSFIRMASK_WO_AND, CEN_MCBISTS23_MBSFIRMASK_WO_AND + }; + + constexpr uint32_t l_mbsfir_action0_address[] = + { + // port0/1 port2/3 + CEN_MCBISTS01_MBSFIRACT0, CEN_MCBISTS23_MBSFIRACT0 + }; + + constexpr uint32_t l_mbsfir_action1_address[] = + { + // port0/1 port2/3 + CEN_MCBISTS01_MBSFIRACT1, CEN_MCBISTS23_MBSFIRACT1 + }; + + fapi2::buffer<uint64_t> l_mbsfir_mask; + fapi2::buffer<uint64_t> l_mbsfir_mask_or; + fapi2::buffer<uint64_t> l_mbsfir_mask_and; + fapi2::buffer<uint64_t> l_mbsfir_action0; + fapi2::buffer<uint64_t> l_mbsfir_action1; + + // NOTE: In the IPL sequence, mss_unmask_draminit_errors has already been + // called, which has already set the MBACALFIR action regs to their runtime + // values, so no need to touch the action regs here. + + // NOTE: In the IPL sequence, mss_unmask_draminit_errors and + // mss_unmask_draminit_training has already been + // called, which has already unmasked the approproiate MBACALFIR errors + // following mss_draminit and mss_draminit_training. So all we will do here + // is unmask a few more errors that would be considered valid after the + // mss_draminit_training_advanced procedure. + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_MASK, l_mbacalfir_mask)); + + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbacalfir_mask_and.flush<1>(); + + // 8 mbx to mba par error channel checkstop unmask + l_mbacalfir_mask_and.clearBit<8>(); + + // 11 mba_maint ue recoverable unmask + l_mbacalfir_mask_and.clearBit<11>(); + + // 12 mba_maint ce recoverable unmask + l_mbacalfir_mask_and.clearBit<12>(); + + // 17 wrq_rrq_hang_err recoverable unmask + l_mbacalfir_mask_and.clearBit<17>(); + + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_MBACALFIR_MASK_WO_AND, l_mbacalfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBACALFIR_MASK, l_mbacalfir_mask)); + + //************************************************ + + //************************* + //************************* + // MBSFIR + //************************* + //************************* + + // Get Centaur target for the given MBA + l_targetCentaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>(); + // Get MBA position: 0 = mba01, 1 = mba23 + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target, l_mbaPosition), "Error getting MBA position"); + + // Read mask + FAPI_TRY(fapi2::getScom(l_targetCentaur, + l_mbsfir_mask_address[l_mbaPosition], + l_mbsfir_mask)); + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbsfir_action0.flush<0>(); + l_mbsfir_action1.flush<0>(); + l_mbsfir_mask_or.flush<0>(); + l_mbsfir_mask_and.flush<1>(); + + // 0 scom_par_errors channel checkstop unmask + l_mbsfir_action0.clearBit<0>(); + l_mbsfir_action1.clearBit<0>(); + l_mbsfir_mask_and.clearBit<0>(); + + // 1 mbx_par_errors channel checkstop unmask + l_mbsfir_action0.clearBit<1>(); + l_mbsfir_action1.clearBit<1>(); + l_mbsfir_mask_and.clearBit<1>(); + + // 2 DD1: reserved recoverable mask (forever) + // 2 DD2: dram_eventn_bit0 recoverable mask (forever) + l_mbsfir_action0.clearBit<2>(); + l_mbsfir_action1.setBit<2>(); + l_mbsfir_mask_or.setBit<2>(); + + // 3 DD1: reserved recoverable mask (forever) + // 3 DD2: dram_eventn_bit1 recoverable mask (forever) + l_mbsfir_action0.clearBit<3>(); + l_mbsfir_action1.setBit<3>(); + l_mbsfir_mask_or.setBit<3>(); + + // 4:14 RESERVED recoverable mask (forever) + l_mbsfir_action0.clearBit<4, 11>(); + l_mbsfir_action1.setBit<4, 11>(); + l_mbsfir_mask_or.setBit<4, 11>(); + + // 2:14 RESERVED recoverable mask (forever) + l_mbsfir_action0.clearBit<2, 13>(); + l_mbsfir_action1.setBit<2, 13>(); + l_mbsfir_mask_or.setBit<2, 13>(); + + // 15 internal scom error recoverable unmask + l_mbsfir_action0.clearBit<15>(); + l_mbsfir_action1.setBit<15>(); + l_mbsfir_mask_and.clearBit<15>(); + + // 16 internal scom error clone recoverable unmask + l_mbsfir_action0.clearBit<16>(); + l_mbsfir_action1.setBit<16>(); + l_mbsfir_mask_and.clearBit<16>(); + + // 17:63 RESERVED not implemented, so won't touch these + + // Write action0 + FAPI_TRY(fapi2::putScom(l_targetCentaur, + l_mbsfir_action0_address[l_mbaPosition], + l_mbsfir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(l_targetCentaur, + l_mbsfir_action1_address[l_mbaPosition], + l_mbsfir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(l_targetCentaur, + l_mbsfir_mask_or_address[l_mbaPosition], + l_mbsfir_mask_or)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(l_targetCentaur, + l_mbsfir_mask_and_address[l_mbaPosition], + l_mbsfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(l_targetCentaur, + l_mbsfir_action0_address[l_mbaPosition], + l_mbsfir_action0)); + + FAPI_TRY(fapi2::getScom(l_targetCentaur, + l_mbsfir_action1_address[l_mbaPosition], + l_mbsfir_action1)); + + FAPI_TRY(fapi2::getScom(l_targetCentaur, + l_mbsfir_mask_address[l_mbaPosition], + l_mbsfir_mask)); + + //************************************************ + +fapi_try_exit: + FAPI_INF("EXIT mss_unmask_draminit_training_advanced_errors()"); + return fapi2::current_err; + +} + +/// +/// @brief Sets action regs and unmasks maint errors prior to the maint logic +/// Being used in memdiags so that PRD will be able to handle them +/// if they happen during memdiags. +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_mc.C. +/// +fapi2::ReturnCode mss_unmask_maint_errors(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target) +{ + FAPI_INF("ENTER mss_unmask_maint_errors()"); + + std::vector<fapi2::Target<fapi2::TARGET_TYPE_MBA>> l_mbaChiplets; + uint8_t l_mbaPosition = 0; // 0 = mba01, 1 = mba23 + + fapi2::buffer<uint64_t> l_mbacalfir_mask; + fapi2::buffer<uint64_t> l_mbacalfir_mask_and; + + fapi2::buffer<uint64_t> l_mbafir_mask; + fapi2::buffer<uint64_t> l_mbafir_mask_and; + + fapi2::buffer<uint64_t> l_mbaspa_mask; + + constexpr uint32_t l_mbeccfir_mask_address[] = + { + // port0/1 port2/3 + CEN_ECC01_MBECCFIR_MASK, CEN_ECC23_MBECCFIR_MASK + }; + + constexpr uint32_t l_mbeccfir_mask_or_address[] = + { + // port0/1 port2/3 + CEN_ECC01_MBECCFIR_MASK_WO_OR, CEN_ECC23_MBECCFIR_MASK_WO_OR + }; + + constexpr uint32_t l_mbeccfir_mask_and_address[] = + { + // port0/1 port2/3 + CEN_ECC01_MBECCFIR_MASK_WO_AND, CEN_ECC23_MBECCFIR_MASK_WO_AND + }; + + constexpr uint32_t l_mbeccfir_action0_address[] = + { + // port0/1 port2/3 + CEN_ECC01_MBECCFIR_ACTION0_RO, CEN_ECC23_MBECCFIR_ACTION0_RO + }; + + constexpr uint32_t l_mbeccfir_action1_address[] = + { + // port0/1 port2/3 + CEN_ECC01_MBECCFIR_ACTION1_RO, CEN_ECC23_MBECCFIR_ACTION1_RO + }; + + fapi2::buffer<uint64_t> l_mbeccfir_mask; + fapi2::buffer<uint64_t> l_mbeccfir_mask_or; + fapi2::buffer<uint64_t> l_mbeccfir_mask_and; + fapi2::buffer<uint64_t> l_mbeccfir_action0; + fapi2::buffer<uint64_t> l_mbeccfir_action1; + + uint8_t l_mbspa_0_fixed_for_dd2 = 0; + + // Get attribute that tells us if mbspa 0 cmd complete attention is fixed for dd2 + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_HW217608_MBSPA_0_CMD_COMPLETE_ATTN_FIXED, i_target, + l_mbspa_0_fixed_for_dd2), "Error getting ATTR_CEN_CENTAUR_EC_FEATURE_HW217608_MBSPA_0_CMD_COMPLETE_ATTN_FIXED"); + + // Get associated functional MBAs on this centaur + l_mbaChiplets = i_target.getChildren<fapi2::TARGET_TYPE_MBA>(); + + // Loop through functional MBAs on this Centaur + for (uint32_t i = 0; i < l_mbaChiplets.size(); ++i) + { + + // Get MBA position: 0 = mba01, 1 = mba23 + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_mbaChiplets[i], l_mbaPosition), "Error getting MBA position"); + + //************************* + //************************* + // MBACALFIR + //************************* + //************************* + + // NOTE: In the IPL sequence, mss_unmask_draminit_errors has already been + // called, which has already set the MBACALFIR action regs to their runtime + // values, so no need to touch the action regs here. + + // NOTE: In the IPL sequence, mss_unmask_draminit_errors, + // mss_unmask_draminit_training and mss_unmask_draminit_training_advanced + // have already been called, which have already unmasked the approproiate + // MBACALFIR errors following mss_draminit, mss_draminit_training, and + // mss_unmask_draminit_training_advanced. So all we will do here + // is unmask a few more errors that would be considered valid after the + // mss_draminit_mc procedure. + + // Read mask + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], + CEN_MBA_MBACALFIR_MASK, + l_mbacalfir_mask)); + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbacalfir_mask_and.flush<1>(); + + // 1 MBA Nonrecoverable Error channel checkstop unmask + l_mbacalfir_mask_and.clearBit<1>(); + + // 2 Refresh Overrun recoverable unmask + l_mbacalfir_mask_and.clearBit<2>(); + + // 5 ddr0_cal_timeout_err recoverable unmask + l_mbacalfir_mask_and.clearBit<5>(); + + // 6 ddr1_cal_timeout_err recoverable unmask + l_mbacalfir_mask_and.clearBit<6>(); + + // Write mask AND + FAPI_TRY(fapi2::putScom(l_mbaChiplets[i], + CEN_MBA_MBACALFIR_MASK_WO_AND, + l_mbacalfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], + CEN_MBA_MBACALFIR_MASK, + l_mbacalfir_mask)); + + //************************************************ + + + //************************* + //************************* + // MBAFIR + //************************* + //************************* + + // NOTE: In the IPL sequence, mss_unmask_ddr_phy_errors has already been + // called, which has already set the MBAFIR action regs to their runtime + // values, so no need to touch the action regs here. + + // NOTE: In the IPL sequence, mss_unmask_ddr_phy_errors, + // has already been called, which has already unmasked the approproiate + // MBAFIR errors following mss_ddr_phy_reset. So all we will do here + // is unmask a few more errors that would be considered valid after the + // mss_draminit_mc procedure. + + // Read mask + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], + CEN_MBA_MBAFIRMASK, + l_mbafir_mask)); + + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbafir_mask_and.flush<1>(); + + // 2 Multi_address_Maint_timeout recoverable unmask + l_mbafir_mask_and.clearBit<2>(); + + + // 7 wrd_caw2_data_ce_ue_err channel checkstop unmask + l_mbafir_mask_and.clearBit<7>(); + + // Write mask AND + FAPI_TRY(fapi2::putScom(l_mbaChiplets[i], + CEN_MBA_MBAFIRMASK_WO_AND, + l_mbafir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], + CEN_MBA_MBAFIRMASK, + l_mbafir_mask)); + + //************************************************ + + + //************************* + //************************* + // MBSPA + //************************* + //************************* + + + // Read mask + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], + CEN_MBA_MBSPAMSKQ, + l_mbaspa_mask)); + + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_mbeccfir_action0.flush<0>(); + l_mbeccfir_action1.flush<0>(); + l_mbeccfir_mask_or.flush<0>(); + l_mbeccfir_mask_and.flush<1>(); + + // 0:7 Memory MPE Rank 0:7 recoverable mask (until mainline traffic) + l_mbeccfir_action0.clearBit<0, 8>(); + l_mbeccfir_action1.setBit<0, 8>(); + l_mbeccfir_mask_or.setBit<0, 8>(); + + // 8:15 Reserved recoverable mask (forever) + l_mbeccfir_action0.clearBit<8, 8>(); + l_mbeccfir_action1.setBit<8, 8>(); + l_mbeccfir_mask_or.setBit<8, 8>(); + + // 16 Memory NCE recoverable mask (until mainline traffic) + l_mbeccfir_action0.clearBit<16>(); + l_mbeccfir_action1.setBit<16>(); + l_mbeccfir_mask_or.setBit<16>(); + + // 17 Memory RCE recoverable mask (until mainline traffic) + l_mbeccfir_action0.clearBit<17>(); + l_mbeccfir_action1.setBit<17>(); + l_mbeccfir_mask_or.setBit<17>(); + + // 18 Memory SUE recoverable mask (forever) + l_mbeccfir_action0.clearBit<18>(); + l_mbeccfir_action1.setBit<18>(); + l_mbeccfir_mask_or.setBit<18>(); + + // 19 Memory UE recoverable mask (until mainline traffic) + l_mbeccfir_action0.clearBit<19>(); + l_mbeccfir_action1.setBit<19>(); + l_mbeccfir_mask_or.setBit<19>(); + + // 20:27 Maint MPE Rank 0:7 recoverable mask (forever) + // NOTE: FW wants to mask these and rely instead on detecting the + // cmd complete attention, then checking these manually to see if + // they cause the cmd to stop + l_mbeccfir_action0.clearBit<20, 8>(); + l_mbeccfir_action1.setBit<20, 8>(); + l_mbeccfir_mask_or.setBit<20, 8>(); + + // 28:35 Reserved recoverable mask (forever) + l_mbeccfir_action0.clearBit<28, 8>(); + l_mbeccfir_action1.setBit<28, 8>(); + l_mbeccfir_mask_or.setBit<28, 8>(); + + // 36 Maintenance NCE recoverable mask (forever) + // NOTE: PRD planning to use maint CE thresholds instead. + l_mbeccfir_action0.clearBit<36>(); + l_mbeccfir_action1.setBit<36>(); + l_mbeccfir_mask_or.setBit<36>(); + + // 37 Maintenance SCE recoverable mask (forever) + // NOTE: Don't care if symbol still bad after it's symbol marked. + l_mbeccfir_action0.clearBit<37>(); + l_mbeccfir_action1.setBit<37>(); + l_mbeccfir_mask_or.setBit<37>(); + + // 38 Maintenance MCE recoverable mask (forever) + // NOTE: PRD plans to check manually as part of verify chip mark procedure. + l_mbeccfir_action0.clearBit<38>(); + l_mbeccfir_action1.setBit<38>(); + l_mbeccfir_mask_or.setBit<38>(); + + // 39 Maintenance RCE recoverable mask (forever) + // NOTE: PRD planning to use maint RCE thresholds instead. + l_mbeccfir_action0.clearBit<39>(); + l_mbeccfir_action1.setBit<39>(); + l_mbeccfir_mask_or.setBit<39>(); + + // 40 Maintenance SUE recoverable mask (forever) + l_mbeccfir_action0.clearBit<40>(); + l_mbeccfir_action1.setBit<40>(); + l_mbeccfir_mask_or.setBit<40>(); + + // 41 Maintenance UE recoverable mask (forever) + // NOTE: FW wants to mask these and rely instead on detecting the + // cmd complete attention, then checking these manually to see if + // they cause the cmd to stop + l_mbeccfir_action0.clearBit<41>(); + l_mbeccfir_action1.setBit<41>(); + l_mbeccfir_mask_or.setBit<41>(); + + // 42 MPE during maintenance mark mode recoverable mask (forever) + l_mbeccfir_action0.clearBit<42>(); + l_mbeccfir_action1.setBit<42>(); + l_mbeccfir_mask_or.setBit<42>(); + + // 43 Prefetch Memory UE recoverable mask (until mainline traffic) + l_mbeccfir_action0.clearBit<43>(); + l_mbeccfir_action1.setBit<43>(); + l_mbeccfir_mask_or.setBit<43>(); + + // 44 Memory RCD parity error recoverable mask (forever) + l_mbeccfir_action0.clearBit<44>(); + l_mbeccfir_action1.setBit<44>(); + l_mbeccfir_mask_or.setBit<44>(); + + // 45 Maint RCD parity error. recoverable mask (forever) + l_mbeccfir_action0.clearBit<45>(); + l_mbeccfir_action1.setBit<45>(); + l_mbeccfir_mask_or.setBit<45>(); + + // 46 Recoverable reg parity recoverable unmask + l_mbeccfir_action0.clearBit<46>(); + l_mbeccfir_action1.setBit<46>(); + l_mbeccfir_mask_and.clearBit<46>(); + + + // 47 Unrecoverable reg parity channel checkstop unmask + l_mbeccfir_action0.clearBit<47>(); + l_mbeccfir_action1.clearBit<47>(); + l_mbeccfir_mask_and.clearBit<47>(); + + // 48 Maskable reg parity error recoverable unmask + l_mbeccfir_action0.clearBit<48>(); + l_mbeccfir_action1.setBit<48>(); + l_mbeccfir_mask_and.clearBit<48>(); + + // 49 ecc datapath parity error channel checkstop unmask + l_mbeccfir_action0.clearBit<49>(); + l_mbeccfir_action1.clearBit<49>(); + l_mbeccfir_mask_and.clearBit<49>(); + + // 50 internal scom error recovereble unmask + l_mbeccfir_action0.clearBit<50>(); + l_mbeccfir_action1.setBit<50>(); + l_mbeccfir_mask_and.clearBit<50>(); + + // 51 internal scom error clone recovereble unmask + l_mbeccfir_action0.clearBit<51>(); + l_mbeccfir_action1.setBit<51>(); + l_mbeccfir_mask_and.clearBit<51>(); + + // 52:63 Reserved not implemented, so won't touch these + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, + l_mbeccfir_action0_address[l_mbaPosition], + l_mbeccfir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, + l_mbeccfir_action1_address[l_mbaPosition], + l_mbeccfir_action1)); + + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, + l_mbeccfir_mask_or_address[l_mbaPosition], + l_mbeccfir_mask_or)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, + l_mbeccfir_mask_and_address[l_mbaPosition], + l_mbeccfir_mask_and)); + + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, + l_mbeccfir_action0_address[l_mbaPosition], + l_mbeccfir_action0)); + + FAPI_TRY(fapi2::getScom(i_target, + l_mbeccfir_action1_address[l_mbaPosition], + l_mbeccfir_action1)); + + FAPI_TRY(fapi2::getScom(i_target, + l_mbeccfir_mask_address[l_mbaPosition], + l_mbeccfir_mask)); + + //************************************************ + + } // End for loop through functional MBAs on this Centaur + + FAPI_INF("EXIT mss_unmask_maint_errors()"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Sets action regs and unmasks fetch errors prior to the start of mainline traffic. +/// @param[in] i_target Centaur target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_mc.C. +/// +fapi2::ReturnCode mss_unmask_fetch_errors(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target) +{ + FAPI_INF("ENTER mss_unmask_fetch_errors()"); + + uint8_t l_dimm_type = 0; + uint8_t l_cfg_wrdone_dly = 0; + uint8_t l_cfg_rdtag_dly = 0; + uint8_t l_max_cfg_rcd_protection_time = 0; + + fapi2::buffer<uint64_t> l_mba_dsm0; + fapi2::buffer<uint64_t> l_mba_farb0; + + + //************************* + //************************* + // SCAC_LFIR + //************************* + //************************* + + fapi2::buffer<uint64_t> l_scac_lfir_mask; + fapi2::buffer<uint64_t> l_scac_lfir_mask_or; + fapi2::buffer<uint64_t> l_scac_lfir_mask_and; + fapi2::buffer<uint64_t> l_scac_lfir_action0; + fapi2::buffer<uint64_t> l_scac_lfir_action1; + fapi2::buffer<uint64_t> l_mbs_fir_mask; + fapi2::buffer<uint64_t> l_mbs_fir_mask_and; + uint8_t l_dd2_fir_bit_defn_changes = 0; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_L4>> l_L4_vector; + bool l_L4_functional = false; + uint8_t l_mbaPosition = 0; // 0 = mba01, 1 = mba23 + uint32_t l_mbeccfir_mask_address[] = + { + // port0/1 port2/3 + CEN_ECC01_MBECCFIR_MASK, CEN_ECC23_MBECCFIR_MASK + }; + + uint32_t l_mbeccfir_mask_and_address[] = + { + // port0/1 port2/3 + CEN_ECC01_MBECCFIR_MASK_WO_AND, CEN_ECC23_MBECCFIR_MASK_WO_AND + }; + + fapi2::buffer<uint64_t> l_mbeccfir_mask; + fapi2::buffer<uint64_t> l_mbeccfir_mask_and; + fapi2::buffer<uint64_t> l_mbacalfir_mask; + fapi2::buffer<uint64_t> l_mbacalfir_mask_and; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_MBA>> l_mbaChiplets; + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_FIRMASK, l_scac_lfir_mask)); + + + + //(Action0, Action1, Mask) + // + // (0,0,0) = checkstop + // (0,1,0) = recoverable error + // (1,0,0) = report unused + // (1,1,0) = machine check + // (x,x,1) = error is masked + + l_scac_lfir_action0.flush<0>(); + l_scac_lfir_action1.flush<0>(); + l_scac_lfir_mask_or.flush<0>(); + l_scac_lfir_mask_and.flush<1>(); + + // 0 I2CMInvAddr recoverable masked (forever) + l_scac_lfir_action0.clearBit<0>(); + l_scac_lfir_action1.setBit<0>(); + l_scac_lfir_mask_or.setBit<0>(); + + // 1 I2CMInvWrite recoverable masked (forever) + l_scac_lfir_action0.clearBit<1>(); + l_scac_lfir_action1.setBit<1>(); + l_scac_lfir_mask_or.setBit<1>(); + + // 2 I2CMInvRead recoverable masked (forever) + l_scac_lfir_action0.clearBit<2>(); + l_scac_lfir_action1.setBit<2>(); + l_scac_lfir_mask_or.setBit<2>(); + + // 3 I2CMApar recoverable masked (forever) + l_scac_lfir_action0.clearBit<3>(); + l_scac_lfir_action1.setBit<3>(); + l_scac_lfir_mask_or.setBit<3>(); + + // 4 I2CMPar recoverable masked (forever) + l_scac_lfir_action0.clearBit<4>(); + l_scac_lfir_action1.setBit<4>(); + l_scac_lfir_mask_or.setBit<4>(); + + // 5 I2CMLBPar recoverable masked (forever) + l_scac_lfir_action0.clearBit<5>(); + l_scac_lfir_action1.setBit<5>(); + l_scac_lfir_mask_or.setBit<5>(); + + // 6:9 Expansion recoverable masked (forever) + l_scac_lfir_action0.clearBit<6, 4>(); + l_scac_lfir_action1.setBit<6, 4>(); + l_scac_lfir_mask_or.setBit<6, 4>(); + + // 10 I2CMInvCmd recoverable masked (forever) + l_scac_lfir_action0.clearBit<10>(); + l_scac_lfir_action1.setBit<10>(); + l_scac_lfir_mask_or.setBit<10>(); + + // 11 I2CMPErr recoverable masked (forever) + l_scac_lfir_action0.clearBit<11>(); + l_scac_lfir_action1.setBit<11>(); + l_scac_lfir_mask_or.setBit<11>(); + + // 12 I2CMOverrun recoverable masked (forever) + l_scac_lfir_action0.clearBit<12>(); + l_scac_lfir_action1.setBit<12>(); + l_scac_lfir_mask_or.setBit<12>(); + + // 13 I2CMAccess recoverable masked (forever) + l_scac_lfir_action0.clearBit<13>(); + l_scac_lfir_action1.setBit<13>(); + l_scac_lfir_mask_or.setBit<13>(); + + // 14 I2CMArb recoverable masked (forever) + l_scac_lfir_action0.clearBit<14>(); + l_scac_lfir_action1.setBit<14>(); + l_scac_lfir_mask_or.setBit<14>(); + + // 15 I2CMNack recoverable masked (forever) + l_scac_lfir_action0.clearBit<15>(); + l_scac_lfir_action1.setBit<15>(); + l_scac_lfir_mask_or.setBit<15>(); + + // 16 I2CMStop recoverable masked (forever) + l_scac_lfir_action0.clearBit<16>(); + l_scac_lfir_action1.setBit<16>(); + l_scac_lfir_mask_or.setBit<16>(); + + // 17 LocalPib1 recoverable masked (forever) + l_scac_lfir_action0.clearBit<17>(); + l_scac_lfir_action1.setBit<17>(); + l_scac_lfir_mask_or.setBit<17>(); + + // 18 LocalPib2 recoverable masked (forever) + l_scac_lfir_action0.clearBit<18>(); + l_scac_lfir_action1.setBit<18>(); + l_scac_lfir_mask_or.setBit<18>(); + + // 19 LocalPib3 recoverable masked (forever) + l_scac_lfir_action0.clearBit<19>(); + l_scac_lfir_action1.setBit<19>(); + l_scac_lfir_mask_or.setBit<19>(); + + // 20 LocalPib4 recoverable masked (forever) + l_scac_lfir_action0.clearBit<20>(); + l_scac_lfir_action1.setBit<20>(); + l_scac_lfir_mask_or.setBit<20>(); + + // 21 LocalPib5 recoverable masked (forever) + l_scac_lfir_action0.clearBit<21>(); + l_scac_lfir_action1.setBit<21>(); + l_scac_lfir_mask_or.setBit<21>(); + + // 22 LocalPib6 recoverable masked (forever) + l_scac_lfir_action0.clearBit<22>(); + l_scac_lfir_action1.setBit<22>(); + l_scac_lfir_mask_or.setBit<22>(); + + // 23 LocalPib7 recoverable masked (forever) + l_scac_lfir_action0.clearBit<23>(); + l_scac_lfir_action1.setBit<23>(); + l_scac_lfir_mask_or.setBit<23>(); + + // 24 StallError recoverable masked (forever) + l_scac_lfir_action0.clearBit<24>(); + l_scac_lfir_action1.setBit<24>(); + l_scac_lfir_mask_or.setBit<24>(); + + // 25 RegParErr channel checkstop unmask + l_scac_lfir_action0.clearBit<25>(); + l_scac_lfir_action1.clearBit<25>(); + l_scac_lfir_mask_and.clearBit<25>(); + + // 26 RegParErrX channel checkstop unmask + l_scac_lfir_action0.clearBit<26>(); + l_scac_lfir_action1.clearBit<26>(); + l_scac_lfir_mask_and.clearBit<26>(); + + // 27:31 Reserved recoverable masked (forever) + l_scac_lfir_action0.clearBit<27, 5>(); + l_scac_lfir_action1.setBit<27, 5>(); + l_scac_lfir_mask_or.setBit<27, 5>(); + + // 32 SMErr recoverable unmask + l_scac_lfir_action0.clearBit<32>(); + l_scac_lfir_action1.setBit<32>(); + l_scac_lfir_mask_and.clearBit<32>(); + + // 33 RegAccErr recoverable unmask + l_scac_lfir_action0.clearBit<33>(); + l_scac_lfir_action1.setBit<33>(); + l_scac_lfir_mask_and.clearBit<33>(); + + // 34 ResetErr recoverable masked (forever) + l_scac_lfir_action0.clearBit<34>(); + l_scac_lfir_action1.setBit<34>(); + l_scac_lfir_mask_or.setBit<34>(); + + // 35 internal_scom_error recoverable unmask + l_scac_lfir_action0.clearBit<35>(); + l_scac_lfir_action1.setBit<35>(); + l_scac_lfir_mask_and.clearBit<35>(); + + // 36 internal_scom_error_clone recoverable unmask + l_scac_lfir_action0.clearBit<36>(); + l_scac_lfir_action1.setBit<36>(); + l_scac_lfir_mask_and.clearBit<36>(); + + // 37:63 Reserved + // Can we write to these bits? + + // Write action0 + FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_FIRACTION0_RO, l_scac_lfir_action0)); + + // Write action1 + FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_FIRACTION1_RO, l_scac_lfir_action1)); + + // Write mask OR + FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_FIRMASK_WO_OR, l_scac_lfir_mask_or)); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_FIRMASK_WO_AND, l_scac_lfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_FIRACTION0_RO, l_scac_lfir_action0)); + FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_FIRACTION1_RO, l_scac_lfir_action1)); + FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_FIRMASK, l_scac_lfir_mask)); + + //************************************************ + + //************************* + //************************* + // MBS_FIR_REG + //************************* + //************************* + + // NOTE: In the IPL sequence, mss_unmask_inband_errors has already been + // called, which has already set the MBS_FIR_REG action regs to their + // runtime values, so no need to touch the action regs here. + + // NOTE: In the IPL sequence, mss_unmask_inband_errors, + // has already been called, which has already unmasked the approproiate + // MBS_FIR_REG errors following mss_unmask_inband_errors. So all we will do + // here is unmask errors requiring mainline traffic which would be + // considered valid after the mss_thermal_init procedure. + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES, i_target, + l_dd2_fir_bit_defn_changes), + "Error getting ATTR_CEN_CENTAUR_EC_FEATURE_DD2_FIR_BIT_DEFN_CHANGES"); + + // Check if L4 is functional + l_L4_vector = i_target.getChildren<fapi2::TARGET_TYPE_L4>(); + + if (l_L4_vector.size() > 0) + { + l_L4_functional = true; + } + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, CEN_MBS_FIR_MASK_REG, l_mbs_fir_mask)); + + + l_mbs_fir_mask_and.flush<1>(); + + // 2 invalid_address_error channel checkstop unmask + l_mbs_fir_mask_and.clearBit<2>(); + + // 3 external_timeout recoverable unmask + l_mbs_fir_mask_and.clearBit<3>(); + + // 4 internal_timeout recoverable unmask + l_mbs_fir_mask_and.clearBit<4>(); + + + if (l_L4_functional) + { + // 9 cache_srw_ce recoverable unmask + l_mbs_fir_mask_and.clearBit<9>(); + + // 10 cache_srw_ue recoverable unmask + l_mbs_fir_mask_and.clearBit<10>(); + + // 12 cache_co_ce recoverable unmask + l_mbs_fir_mask_and.clearBit<12>(); + + // 13 cache_co_ue recoverable unmask + l_mbs_fir_mask_and.clearBit<13>(); + + // 15 dir_ce + if (l_dd2_fir_bit_defn_changes) + { + // NOTE: SW248520: Known DD1 problem - higher temp causes + // L4 Dir CEs. Want to ignore. Unmask for DD2 only + + // recoverable unmask + l_mbs_fir_mask_and.clearBit<15>(); + } + + // 16 dir_ue channel checkstop unmask + l_mbs_fir_mask_and.clearBit<16>(); + + // 18 dir_all_members_deleted channel checkstop unmask + l_mbs_fir_mask_and.clearBit<18>(); + + // 19 lru_error recoverable unmask + l_mbs_fir_mask_and.clearBit<19>(); + + // 20 eDRAM error channel checkstop unmask + l_mbs_fir_mask_and.clearBit<20>(); + } + + // 26 srb_buffer_ce recoverable unmask + l_mbs_fir_mask_and.clearBit<26>(); + + // 27 srb_buffer_ue recoverable unmask + l_mbs_fir_mask_and.clearBit<27>(); + + if (l_dd2_fir_bit_defn_changes && l_L4_functional) + { + // 30 proximal_ce_ue channel checkstop unmask + l_mbs_fir_mask_and.clearBit<30>(); + } + + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, CEN_MBS_FIR_MASK_REG_WO_AND, l_mbs_fir_mask_and)); + + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, CEN_MBS_FIR_MASK_REG, l_mbs_fir_mask)); + + //************************************************ + + + // Get associated functional MBAs on this centaur + l_mbaChiplets = i_target.getChildren<fapi2::TARGET_TYPE_MBA>(); + + // Loop through functional MBAs on this Centaur + for (uint32_t i = 0; i < l_mbaChiplets.size(); ++i) + { + + // Get MBA position: 0 = mba01, 1 = mba23 + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_mbaChiplets[i], l_mbaPosition), + "Error getting MBA position"); + + // Get DIMM type + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, l_mbaChiplets[i], l_dimm_type), + "Error getting ATTR_CEN_EFF_DIMM_TYPE"); + + // If RDIMM or LRDIMM, load max_cfg_rcd_protection_time and enable RCD recovery + if ((l_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM) + || (l_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM)) + { + + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], CEN_MBA_MBA_DSM0Q, l_mba_dsm0)); + + // Get 24:29 cfg_wrdone_dly + l_mba_dsm0.extract < 24, 6, 8 - 6 > (l_cfg_wrdone_dly); + + // Get 36:41 cfg_rdtag_dly + l_mba_dsm0.extract < 36, 6, 8 - 6 > (l_cfg_rdtag_dly); + + // Pick lower of the two: cfg_wrdone_dly and cfg_rdtag_dly, and use that for l_max_cfg_rcd_protection_time + if (l_cfg_wrdone_dly <= l_cfg_rdtag_dly) + { + l_max_cfg_rcd_protection_time = l_cfg_wrdone_dly; + } + else + { + l_max_cfg_rcd_protection_time = l_cfg_rdtag_dly; + } + + // Read FARB0 + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], CEN_MBA_MBA_FARB0Q, l_mba_farb0)); + + // Load l_max_cfg_rcd_protection_time + FAPI_TRY(l_mba_farb0.insert( l_max_cfg_rcd_protection_time, 48, 6, 8 - 6 )); + + // Clear bit 54, cfg_disable_rcd_recovery, to enable RCD recovery + l_mba_farb0.clearBit<54>(); + + // Write FARB0 + FAPI_TRY(fapi2::putScom(l_mbaChiplets[i], CEN_MBA_MBA_FARB0Q, l_mba_farb0)); + } + + + //************************* + //************************* + // MBASPA + //************************* + //************************* + // NOTE: FW wants to mask these and rely instead on detecting the + // cmd complete attention, then checking these manually to see if + // they cause the cmd to stop + + //************************* + //************************* + // MBECCFIR + //************************* + //************************* + + // Read mask + FAPI_TRY(fapi2::getScom(i_target, + l_mbeccfir_mask_address[l_mbaPosition], + l_mbeccfir_mask)); + + // NOTE: In the IPL sequence, mss_unmask_maint_errors has already been + // called, which has already set the MBECCFIR action regs to their runtime + // values, so no need to touch the action regs here. + + // NOTE: In the IPL sequence, mss_unmask_maint_errors, + // has already been called, which has already unmasked the approproiate + // MBECCFIR errors following mss_unmask_maint_errors. So all we will do + // here is unmask errors requiring mainline traffic which would be + // considered valid after the mss_thermal_init procedure. + + l_mbeccfir_mask_and.flush<1>(); + + // 0:7 Memory MPE Rank 0:7 recoverable unmask + l_mbeccfir_mask_and.clearBit<0, 8>(); + + // 16 Memory NCE recoverable unmask + l_mbeccfir_mask_and.clearBit<16>(); + + // 17 Memory RCE recoverable unmask + l_mbeccfir_mask_and.clearBit<17>(); + + // 19 Memory UE recoverable unmask + l_mbeccfir_mask_and.clearBit<19>(); + +#if 0 // Should this be removed - AAM ? + // NOTE: FW wants to mask these and rely instead on detecting the + // cmd complete attention, then checking these manually to see if + // they cause the cmd to stop + + // 20:27 Maint MPE Rank 0:7 recoverable unmask + l_mbeccfir_mask_and.clearBit<20, 8>(); + + // 41 Maintenance UE recoverable unmask + l_mbeccfir_mask_and.clearBit<41>(); +#endif + + // 43 Prefetch Memory UE recoverable unmask + l_mbeccfir_mask_and.clearBit<43>(); + + // Write mask AND + FAPI_TRY(fapi2::putScom(i_target, + l_mbeccfir_mask_and_address[l_mbaPosition], + l_mbeccfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(i_target, + l_mbeccfir_mask_address[l_mbaPosition], + l_mbeccfir_mask)); + + //************************************************ + } + + //************************* + //************************* + // MBACALFIR + //************************* + //************************* + + + // NOTE: In the IPL sequence, mss_unmask_draminit_errors has already been + // called, which has already set the MBACALFIR action regs to their runtime + // values, so no need to touch the action regs here. + + // NOTE: In the IPL sequence, various bits have already been unmasked + // after the approproiate procedures. So all we will do here is unmask + // errors requiring mainline traffic which would be considered valid after + // the mss_thermal_init procedure. + + // Loop through functional MBAs on this Centaur + for (uint32_t i = 0; i < l_mbaChiplets.size(); ++i) + { + + // Read mask + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], + CEN_MBA_MBACALFIR_MASK, + l_mbacalfir_mask)); + + + l_mbacalfir_mask_and.flush<1>(); + + // 9 mba_wrd ue recoverable unmask + l_mbacalfir_mask_and.clearBit<9>(); + + // 10 mba_wrd ce recoverable unmask + l_mbacalfir_mask_and.clearBit<10>(); + + // 14 wrq_data_ce recoverable unmask + l_mbacalfir_mask_and.clearBit<14>(); + + // 15 wrq_data_ue recoverable unmask + l_mbacalfir_mask_and.clearBit<15>(); + + // Write mask AND + FAPI_TRY(fapi2::putScom(l_mbaChiplets[i], + CEN_MBA_MBACALFIR_MASK_WO_AND, + l_mbacalfir_mask_and)); + + //************************************************ + // DEBUG: read them all back to verify + FAPI_TRY(fapi2::getScom(l_mbaChiplets[i], + CEN_MBA_MBACALFIR_MASK, + l_mbacalfir_mask)); + + //************************************************ + } + +fapi_try_exit: + FAPI_INF("EXIT mss_unmask_fetch_errors()"); + return fapi2::current_err; +} diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H new file mode 100755 index 000000000..002c86d1f --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H @@ -0,0 +1,161 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_mss_unmask_errors.H +/// @brief Utility functions to set action regs and unmask FIR bits at the end of various mss IPL procedures. +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: Memtools +// +// + + +#ifndef _MSS_UNMASK_ERRORS_H +#define _MSS_UNMASK_ERRORS_H + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> + + +//------------------------------------------------------------------------------ +// mss_unmask_pervasive_errors +//------------------------------------------------------------------------------ + +/// +/// @brief Sets action regs and mask settings for pervasive errors to their runtime settings. +/// @param[in] i_target Centaur target +/// @return FAPI2_RC_SUCCESS iff okay +//// +fapi2::ReturnCode mss_unmask_pervasive_errors( const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target); + + + +//------------------------------------------------------------------------------ +// mss_unmask_inband_errors +//------------------------------------------------------------------------------ + + +/// +/// @brief Sets action regs and mask settings for inband errors to their runtime settings. +/// @param[in] i_target Centaur target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of cen_mem_startclocks.C +/// +fapi2::ReturnCode mss_unmask_inband_errors( const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target); + + +//------------------------------------------------------------------------------ +// mss_unmask_ddrphy_errors +//------------------------------------------------------------------------------ + + +/// +/// @brief Sets action regs and mask settings for ddr phy errors to runtime settings. +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of proc_cen_framelock.C +/// +fapi2::ReturnCode mss_unmask_ddrphy_errors( const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + + +//------------------------------------------------------------------------------ +// mss_unmask_draminit_errors +//------------------------------------------------------------------------------ + + +/// +/// @brief Sets MBACALFIR action regs to their runtime settings. +/// Unmasks errors that are valid for PRD to handle after mss_draminit procedure. +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit.C. +/// +fapi2::ReturnCode mss_unmask_draminit_errors( const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + + +//------------------------------------------------------------------------------ +// mss_unmask_draminit_training_errors +//------------------------------------------------------------------------------ + + +/// +/// @brief Unmasks MBACALFIR errors that are valid for PRD to handle after mss_draminit_training +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_training.C. +fapi2::ReturnCode mss_unmask_draminit_training_errors( + const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + + +//------------------------------------------------------------------------------ +// mss_unmask_draminit_training_advanced_errors +//------------------------------------------------------------------------------ + + +/// +/// @brief Unmasks MBACALFIR errors that are valid for PRD to handle after mss_draminit_training_advanced +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_training_advanced.C. +/// +fapi2::ReturnCode mss_unmask_draminit_training_advanced_errors( + const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target); + + +//------------------------------------------------------------------------------ +// mss_unmask_maint_errors +//------------------------------------------------------------------------------ + + +/// +/// @brief Sets action regs and unmasks maint errors prior to the maint logic +/// Being used in memdiags so that PRD will be able to handle them +/// if they happen during memdiags. +/// @param[in] i_target MBA target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_mc.C. +/// +fapi2::ReturnCode mss_unmask_maint_errors(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target); + + +//------------------------------------------------------------------------------ +// mss_unmask_fetch_errors +//------------------------------------------------------------------------------ + + +/// +/// @brief Sets action regs and unmasks fetch errors prior to the start of mainline traffic. +/// @param[in] i_target Centaur target +/// @return FAPI2_RC_SUCCESS iff okay +/// @note To be called at the end of mss_draminit_mc.C. +/// +fapi2::ReturnCode mss_unmask_fetch_errors(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target); + + +#endif //// _MSS_UNMASK_ERRORS_H //// diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk new file mode 100755 index 000000000..79bc9e413 --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk @@ -0,0 +1,32 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] 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 + +# Include the macros and things for MSS procedures +-include 01common.mk + +PROCEDURE=p9c_mss_unmask_errors +$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE))) +#lib$(PROCEDURE)_DEPLIBS+=mss +$(call BUILD_PROCEDURE) diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.C b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.C new file mode 100644 index 000000000..686d6137e --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.C @@ -0,0 +1,287 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] 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 p9c_mss_ddr_phy_reset_wrap.C +/// @brief FW Team Utility functions that accesses the Bad DQ Bitmap. +/// +/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com> +/// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com> +/// *HWP Team: Memory +/// *HWP Level: 2 +/// *HWP Consumed by: HB +//// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <prcdUtils.H> + +#include <croClientCapi.H> +#include <ecmdClientCapi.H> +#include <ecmdDataBuffer.H> +#include <ecmdUtils.H> +#include <ecmdSharedUtils.H> +#include <fapi2.H> +#include <fapi2ClientCapi.H> +#include <fapi2SharedUtils.H> + +#include <p9c_mss_ddr_phy_reset.H> + + +//------------------------------------------------------------------------------ +// Function definitions +//------------------------------------------------------------------------------ + +// display help message +void help() +{ + // procedure constants + std::string PROCEDURE = "p9c_mss_ddr_phy_reset_wrap"; + std::string REVISION = "$Revision: 1.8 $"; + + // build help message + char outstr[256]; + snprintf(outstr, sizeof(outstr), "\nThis is the help text for the procedure %s (%s).\n", + PROCEDURE.c_str(), REVISION.c_str()); + ecmdOutput(outstr); + ecmdOutput(" [-h] [-k#] [-n#] [-s#] [-p#] [-d] [-quiet] [-verif]\n"); + ecmdOutput("\n"); + ecmdOutput("Additional options:\n"); + ecmdOutput(" -h Display this help message.\n"); + + ecmdOutput(" -k# Specify which cage to act on (default = 0).\n"); + ecmdOutput(" -n# Specify which node to act on (default = 0).\n"); + ecmdOutput(" -s# Specify which slot to act on (default = 0).\n"); + ecmdOutput(" -p# Specify which chip position to act on (default = 0).\n"); + ecmdOutput(" -quiet Suppress printing of eCMD DLL/procedure information (default = false).\n"); + ecmdOutput(" -verif Run procedure in sim verification mode (default = false).\n"); + return; +} + +// main function +int +main(int argc, char* argv[]) +{ + // procedure constants + const std::string PROCEDURE = "mss_ddr_phy_reset_wrap"; + const std::string REVISION = "$Revision: 1.8 $"; + + // from prcdUtils + extern bool GLOBAL_SIM_MODE; + extern bool GLOBAL_VERIF_MODE; + + // flow/control variables + uint32_t rc = ECMD_SUCCESS; + fapi2::ReturnCode rc_fapi; + ecmdDllInfo DLLINFO; + ecmdLooperData node_looper; + ecmdChipTarget node_target; + char outstr[256]; + + // required parameters & optional flags + + // load and initialize the eCMD Dll + // if left NULL, which DLL to load is determined by the ECMD_DLL_FILE + // environment variable if set to a specific value, the specified DLL + // will be loaded + rc = ecmdLoadDll(""); + + if (rc) + { + return rc; + } + + do + { + // initalize FAPI extension + rc = fapi2InitExtension(); + + if (rc) + { + ecmdOutputError("Error initializing FAPI extension!\n"); + break; + } + + // establish if this is a simulation run or not + rc = ecmdQueryDllInfo(DLLINFO); + + if (rc) + { + ecmdOutput("Error querying DLL!\n"); + break; + } + + if (DLLINFO.dllEnv == ECMD_DLL_ENV_SIM) + { + GLOBAL_SIM_MODE = true; + } + + // show help message + if (ecmdParseOption(&argc, &argv, "-h")) + { + help(); + break; + } + + + // run procedure in sim verification mode + if (ecmdParseOption(&argc, &argv, "-verif")) + { + GLOBAL_VERIF_MODE = true; + } + + // parse out common eCMD args like -p0, -c0, -coe, etc.. + // any found args will be removed from arg list upon return + rc = ecmdCommandArgs(&argc, &argv); + + if (rc) + { + ecmdOutputError("Error parsing eCMD arguments\n"); + break; + } + + // unsupported arguments left over? + if (argc != 1) + { + ecmdOutputError("Unknown/unsupported arguments specified!\n"); + help(); + rc = ECMD_INVALID_ARGS; + break; + } + + // print procedure information header + if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE)) + { + // print informational message + snprintf(outstr, sizeof(outstr), "Procedure %s: %s\n", + PROCEDURE.c_str(), REVISION.c_str()); + ecmdOutput(outstr); + + // always print the DLL info to the screen, unless in quiet mode + rc = ecmdDisplayDllInfo(); + + if (rc) + { + ecmdOutputError("Error displaying DLL info!"); + break; + } + } + + // configure looper to iterate over all nodes + node_target.cageState = ECMD_TARGET_FIELD_WILDCARD; + node_target.nodeState = ECMD_TARGET_FIELD_WILDCARD; + node_target.slotState = ECMD_TARGET_FIELD_UNUSED; + node_target.posState = ECMD_TARGET_FIELD_UNUSED; + node_target.coreState = ECMD_TARGET_FIELD_UNUSED; + node_target.threadState = ECMD_TARGET_FIELD_UNUSED; + rc = ecmdConfigLooperInit(node_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, node_looper); + + if (rc) + { + ecmdOutputError("Error initializing node looper!\n"); + break; + } + + // loop over specified configured nodes + while (ecmdConfigLooperNext(node_target, node_looper)) + { + ecmdLooperData cen_looper; + ecmdChipTarget cen_target; + + if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE)) + { + snprintf(outstr, sizeof(outstr), "Processing %s\n", + ecmdWriteTarget(node_target).c_str()); + ecmdOutput(outstr); + } + + cen_target.chipType = "cen"; + cen_target.chipTypeState = ECMD_TARGET_FIELD_VALID; + cen_target.chipUnitType = "mba"; + cen_target.chipUnitTypeState = ECMD_TARGET_FIELD_VALID; + + cen_target.cage = node_target.cage; + cen_target.node = node_target.node; + + cen_target.cageState = ECMD_TARGET_FIELD_VALID; + cen_target.nodeState = ECMD_TARGET_FIELD_VALID; + cen_target.slotState = ECMD_TARGET_FIELD_WILDCARD; + cen_target.posState = ECMD_TARGET_FIELD_WILDCARD; + cen_target.coreState = ECMD_TARGET_FIELD_UNUSED; + cen_target.threadState = ECMD_TARGET_FIELD_UNUSED; + cen_target.chipUnitNumState = ECMD_TARGET_FIELD_WILDCARD; + + rc = ecmdConfigLooperInit(cen_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, cen_looper); + + if (rc) + { + ecmdOutputError("Error initializing chip looper!\n"); + break; + } + + // loop over configured positions inside current node + while(ecmdConfigLooperNext(cen_target, cen_looper)) + { + if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE)) + { + snprintf(outstr, sizeof(outstr), "Going to call %s on %s\n", + PROCEDURE.c_str(), + ecmdWriteTarget(cen_target).c_str()); + ecmdOutput(outstr); + } + + // invoke FAPI procedure core + fapi2::Target<fapi2::TARGET_TYPE_MBA> fapi_target(&cen_target); + FAPI_EXEC_HWP(rc_fapi, + p9c_mss_ddr_phy_reset, + fapi_target); + rc = (uint32_t) rc_fapi; + + if (rc) + { + snprintf(outstr, sizeof(outstr), "ERROR: %s FAPI call exited with bad return code = %s 0x%08x\n", + PROCEDURE.c_str(), + ecmdParseReturnCode(rc).c_str(), rc); + ecmdOutputError(outstr); + break; + } + } + + if (rc) + { + break; + } + } + + if (rc) + { + break; + } + } + while(0); + + ecmdUnloadDll(); + return rc; +} diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.mk b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.mk new file mode 100755 index 000000000..2c7f5bf6f --- /dev/null +++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.mk @@ -0,0 +1,29 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_ddr_phy_reset_wrap.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2015,2017 +# [+] 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 + +WRAPPER=p9c_mss_ddr_phy_reset_wrap +$(WRAPPER)_USELIBS+=p9c_mss_ddr_phy_reset +$(WRAPPER)_DEPLIBS+=cen +$(call BUILD_WRAPPER) |