diff options
author | Thi Tran <thi@us.ibm.com> | 2015-12-11 12:49:53 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-05-18 18:06:56 -0400 |
commit | 9d7257c5f3932d0a561b6884e7c157d714b7964d (patch) | |
tree | b10994e4c8835f27cf99d9f438e8e6a7dfb8192a /src/import/chips | |
parent | bf6752205969942a7f8fed73ce3dabe72e67c109 (diff) | |
download | talos-hostboot-9d7257c5f3932d0a561b6884e7c157d714b7964d.tar.gz talos-hostboot-9d7257c5f3932d0a561b6884e7c157d714b7964d.zip |
L2 - p9_build_smp HWPs
Change-Id: I603cc314d907653d22606329d881e9cc908468be
Original-Change-Id: Ic3b000e1c9844499c478e29f2d370d037a8fc262
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22704
Tested-by: Jenkins Server
Reviewed-by: Joseph J. McGill <jmcgill@us.ibm.com>
Tested-by: Auto Mirror
Tested-by: PPE CI
Tested-by: Hostboot CI
Reviewed-by: CHRISTINA L. GRAVES <clgraves@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/24708
Tested-by: FSP CI Jenkins
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips')
10 files changed, 3638 insertions, 164 deletions
diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.C b/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.C index b918ab5ea..8e2b89f53 100644 --- a/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.C +++ b/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.C @@ -7,7 +7,7 @@ /* */ /* EKB Project */ /* */ -/* COPYRIGHT 2015 */ +/* COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,6 +46,15 @@ extern "C" //ADU register field/bit definitions + // ADU Option Register field/bit definitions + const uint32_t FBC_ALTD_WITH_PRE_QUIESCE = 23; + const uint32_t FBC_ALTD_PRE_QUIESCE_COUNT_START_BIT = 28; // Bits 28:47 + const uint32_t FBC_ALTD_PRE_QUIESCE_COUNT_NUM_OF_BITS = 20; + + const uint32_t FBC_ALTD_WITH_POST_INIT = 51; + const uint32_t FBC_ALTD_POST_INIT_COUNT_START_BIT = 54; // Bits 54:63 + const uint32_t FBC_ALTD_POST_INIT_COUNT_NUM_OF_BITS = 10; + // ADU Command Register field/bit definitions const uint32_t ALTD_CMD_START_OP_BIT = 2; const uint32_t ALTD_CMD_CLEAR_STATUS_BIT = 3; @@ -69,15 +78,21 @@ extern "C" const uint32_t ALTD_CMD_TSIZE_START_BIT = 32; const uint32_t ALTD_CMD_TSIZE_END_BIT = 39; - const uint32_t ALTD_CMD_TTYPE_NUM_BITS = (ALTD_CMD_TTYPE_END_BIT - - ALTD_CMD_TTYPE_START_BIT + 1); - const uint32_t ALTD_CMD_TSIZE_NUM_BITS = (ALTD_CMD_TSIZE_END_BIT - - ALTD_CMD_TSIZE_START_BIT + 1); - const uint32_t ALTD_CMD_TTYPE_CL_DMA_RD = 3; //0b0000011 - const uint32_t ALTD_CMD_TTYPE_DMA_PR_WR = 38;//0b0100110 - const uint32_t ALTD_CMD_TTYPE_CI_PR_RD = 52; //0b0110100 - const uint32_t ALTD_CMD_TTYPE_CI_PR_WR = 55; //0b0110111 + const uint32_t ALTD_CMD_SCOPE_NUM_BITS = (ALTD_CMD_SCOPE_END_BIT - + ALTD_CMD_SCOPE_START_BIT) + 1; + const uint32_t ALTD_CMD_TTYPE_NUM_BITS = (ALTD_CMD_TTYPE_END_BIT - + ALTD_CMD_TTYPE_START_BIT) + 1; + const uint32_t ALTD_CMD_TSIZE_NUM_BITS = (ALTD_CMD_TSIZE_END_BIT - + ALTD_CMD_TSIZE_START_BIT) + 1; + + const uint32_t ALTD_CMD_TTYPE_CL_DMA_RD = 3; //0b0000011 + const uint32_t ALTD_CMD_TTYPE_DMA_PR_WR = 38; //0b0100110 + const uint32_t ALTD_CMD_TTYPE_CI_PR_RD = 52; //0b0110100 + const uint32_t ALTD_CMD_TTYPE_CI_PR_WR = 55; //0b0110111 + const uint32_t ALTD_CMD_TTYPE_PB_OPER = 0b0111111; + const uint32_t ALTD_CMD_TTYPE_PMISC_OPER = 0b0110001; + //these should be 1, 2, 3, 4 but they are shifted over one to the left because for //ci_pr_rd and ci_pr_w the secondary encode is 0ttt ssss0 const uint32_t ALTD_CMD_CI_TSIZE_1 = 2; @@ -93,6 +108,15 @@ extern "C" //I think that the secondary encoding should always be 0 for cl_dma_rd const uint32_t ALTD_CMD_DMAR_TSIZE = 0; + // Values for PB/SWITCH operations + const uint32_t ALTD_CMD_PB_OPERATION_TSIZE = 0b00001000; + const uint32_t ALTD_CMD_SWITCH_ACTION_TSIZE = 0b00000010; + const uint32_t ALTD_CMD_SCOPE_SYSTEM = 0b00000101; + + // OPTION reg values for SWITCH operation + const uint32_t QUIESCE_SWITCH_WAIT_COUNT = 128; + const uint32_t INIT_SWITCH_WAIT_COUNT = 128; + // ADU Status Register field/bit definitions const uint32_t ALTD_STATUS_BUSY_BIT = 0; const uint32_t ALTD_STATUS_WAIT_CMD_ARBIT = 1; @@ -130,7 +154,6 @@ extern "C" const uint32_t PROC_ADU_UTILS_ADU_HW_NS_DELAY = 100000000; const uint32_t PROC_ADU_UTILS_ADU_SIM_CYCLE_DELAY = 100000; - //--------------------------------------------------------------------------------- // Function definitions //--------------------------------------------------------------------------------- @@ -203,6 +226,45 @@ extern "C" return rc; } + + + /// + /// @brief Setup the value for ADU option register to enable + /// quiesce & init around a switch operation. + /// + /// @param [in] i_target Proc target + /// + /// @return FAPI2_RC_SUCCESS if OK + /// + fapi2::ReturnCode setQuiesceInit( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> altd_option_reg_data(0); + + // Set up quiesce + altd_option_reg_data.setBit<FBC_ALTD_WITH_PRE_QUIESCE>(); + altd_option_reg_data.insertFromRight<FBC_ALTD_PRE_QUIESCE_COUNT_START_BIT, + FBC_ALTD_PRE_QUIESCE_COUNT_NUM_OF_BITS> + (QUIESCE_SWITCH_WAIT_COUNT); + + // Setup Post-command init + altd_option_reg_data.setBit<FBC_ALTD_WITH_POST_INIT>(); + altd_option_reg_data.insertFromRight<FBC_ALTD_POST_INIT_COUNT_START_BIT, + FBC_ALTD_POST_INIT_COUNT_NUM_OF_BITS> + (INIT_SWITCH_WAIT_COUNT); + + // Write to ADU option reg + FAPI_INF("OPTION reg value 0x%016llX", altd_option_reg_data); + FAPI_TRY(fapi2::putScom(i_target, PU_ALTD_OPTION_REG, altd_option_reg_data), + "Error writing to PU_ALTD_OPTION_REG register"); + + fapi_try_exit: + FAPI_DBG("Exiting..."); + return fapi2::current_err; + } + //--------------------------------------------------------------------------------- // NOTE: description in header //--------------------------------------------------------------------------------- @@ -212,111 +274,218 @@ extern "C" const bool i_rnw, const uint32_t i_flags) { - FAPI_DBG("Start"); + FAPI_DBG("Start Addr 0x%.16llX, Flag 0x%.8X", i_address, i_flags); + fapi2::ReturnCode rc; fapi2::buffer<uint64_t> altd_cmd_reg_data(0x0); fapi2::buffer<uint64_t> altd_addr_reg_data(i_address); fapi2::buffer<uint64_t> altd_data_reg_data(0x0); + fapi2::buffer<uint64_t> altd_option_reg(0x0); + p9_ADU_oper_flag l_myAduFlag; + p9_ADU_oper_flag::OperationType_t l_operType; + p9_ADU_oper_flag::Transaction_size_t l_transSize; - //write to the altd_cmd_reg to set the fbc_locked bit + // Write to the altd_cmd_reg to set the fbc_locked bit altd_cmd_reg_data.setBit<ALTD_CMD_LOCK_BIT>(); FAPI_TRY(fapi2::putScom(i_target, PU_ALTD_CMD_REG, altd_cmd_reg_data), "Error writing the lock bit to ALTD_CMD Register"); - //write the address into altd_addr_reg + //Write the address into altd_addr_reg + FAPI_DBG("Write PU_ALTD_ADDR_REG 0x%.16llX, Value 0x%.16llX", + PU_ALTD_ADDR_REG, altd_addr_reg_data); FAPI_TRY(fapi2::putScom(i_target, PU_ALTD_ADDR_REG, altd_addr_reg_data), "Error writing to ALTD_ADDR Register"); - //write the altd_cmd_reg - //set fbc_altd_rnw if it's a read - if (i_rnw) - { - altd_cmd_reg_data.setBit<ALTD_CMD_RNW_BIT>(); - } - //clear fbc_altd_rnw if it's a write - else - { - altd_cmd_reg_data.clearBit<ALTD_CMD_RNW_BIT>(); - } + // Process input flag + l_myAduFlag.getFlag(i_flags); + l_operType = l_myAduFlag.getOperationType(); + l_transSize = l_myAduFlag.getTransactionSize(); - //set the ttype and tsize - //if it's a CI write/read - if (i_flags & FLAG_CI) + // --------------------------------------------- + // Setting for DMA and CI operations + // --------------------------------------------- + if ( (l_operType == p9_ADU_oper_flag::CACHE_INHIBIT) || + (l_operType == p9_ADU_oper_flag::DMA_PARTIAL) ) { + + // --------------------------------------------- + // DMA & CI common settings + // --------------------------------------------- + // Write the altd_cmd_reg + // Set fbc_altd_rnw if it's a read if (i_rnw) { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_CI_PR_RD); + altd_cmd_reg_data.setBit<ALTD_CMD_RNW_BIT>(); } + // Clear fbc_altd_rnw if it's a write else { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_CI_PR_WR); + altd_cmd_reg_data.clearBit<ALTD_CMD_RNW_BIT>(); } - //if tsize = 1 - if (((i_flags & FLAG_SIZE) >> FLAG_SIZE_SHIFT) == 1) - { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, - ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_1); - } - else if (((i_flags & FLAG_SIZE) >> FLAG_SIZE_SHIFT) == 2) - { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, - ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_2); - } - else if (((i_flags & FLAG_SIZE) >> FLAG_SIZE_SHIFT) == 4) - { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, - ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_4); - } - else - { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, - ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_8); - } - } - //if it's not a CI write/read - else - { - //if a read set dma_cl_rd - //set the tsize to 8 - if (i_rnw) + // If auto-inc set the auto-inc bit + if (l_myAduFlag.getAutoIncrement() == true) { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_CL_DMA_RD); - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, - ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAR_TSIZE); + altd_cmd_reg_data.setBit<ALTD_CMD_AUTO_INC_BIT>(); } - //if a write set pr_dma_wr - //set the tsize to 8 - else + + // --------------------------------------------------- + // Cache Inhibit specific: TTYPE & TSIZE + // --------------------------------------------------- + if (l_operType == p9_ADU_oper_flag::CACHE_INHIBIT) { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_DMA_PR_WR); + FAPI_DBG("ADU operation type: Cache Inhibited"); + + // Set TTYPE + if (i_rnw) + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_CI_PR_RD); + } + else + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_CI_PR_WR); + } - if (((i_flags & FLAG_SIZE) >> FLAG_SIZE_SHIFT) == 1) + // Set TSIZE + if ( l_transSize == FLAG_SIZE_TSIZE_1 ) + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_1); + } + else if ( l_transSize == FLAG_SIZE_TSIZE_2 ) + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_2); + } + else if ( l_transSize == FLAG_SIZE_TSIZE_4 ) { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_1); + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_4); } - else if (((i_flags & FLAG_SIZE) >> FLAG_SIZE_SHIFT) == 2) + else { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_2); + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_CI_TSIZE_8); } - else if (((i_flags & FLAG_SIZE) >> FLAG_SIZE_SHIFT) == 4) + } + + // --------------------------------------------------- + // DMA specific: TTYPE & TSIZE + // --------------------------------------------------- + else if (l_operType == p9_ADU_oper_flag::DMA_PARTIAL) + { + FAPI_DBG("ADU operation type: DMA"); + + // If a read, set ALTD_CMD_TTYPE_CL_DMA_RD + // Set the tsize to ALTD_CMD_DMAR_TSIZE + if (i_rnw) { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_4); + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_CL_DMA_RD); + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAR_TSIZE); } + // If a write set ALTD_CMD_TTYPE_DMA_PR_WR + // Set the tsize according to flag setting else { - altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_8); + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, + ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_DMA_PR_WR); + + // Set TSIZE + if ( l_transSize == FLAG_SIZE_TSIZE_1 ) + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_1); + } + else if ( l_transSize == FLAG_SIZE_TSIZE_2 ) + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_2); + } + else if ( l_transSize == FLAG_SIZE_TSIZE_4 ) + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_4); + } + else + { + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_DMAW_TSIZE_8); + } } } } - //if auto-inc set the auto-inc bit (bit 19) - if (i_flags & FLAG_AUTOINC) + // --------------------------------------------- + // Setting for PB and PMISC operations + // --------------------------------------------- + if ( (l_operType == p9_ADU_oper_flag::PB_OPER) || + (l_operType == p9_ADU_oper_flag::PMISC_OPER) ) { - altd_cmd_reg_data.setBit<ALTD_CMD_AUTO_INC_BIT>(); + + // --------------------------------------------- + // PB & PMISC common settings + // --------------------------------------------- + + // Set the start op bit + altd_cmd_reg_data.setBit<ALTD_CMD_START_OP_BIT>(); + + // Set operation scope + altd_cmd_reg_data.insertFromRight<ALTD_CMD_SCOPE_START_BIT, + ALTD_CMD_SCOPE_NUM_BITS>(ALTD_CMD_SCOPE_SYSTEM); + + // Set DROP_PRIORITY = HIGH + altd_cmd_reg_data.setBit<ALTD_CMD_DROP_PRIORITY_BIT>(); + + // Set AXTYPE = Address only + altd_cmd_reg_data.setBit<ALTD_CMD_ADDRESS_ONLY_BIT>(); + + // Set OVERWRITE_PBINIT + altd_cmd_reg_data.setBit<ALTD_CMD_OVERWRITE_PBINIT_BIT>(); + + // Set TM_QUIESCE + altd_cmd_reg_data.setBit<ALTD_CMD_WITH_TM_QUIESCE_BIT>(); + + + // --------------------------------------------------- + // PB specific: TTYPE & TSIZE + // --------------------------------------------------- + if (l_operType == p9_ADU_oper_flag::PB_OPER) + { + FAPI_DBG("ADU operation type: PB"); + + // Set TTYPE + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, + ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_PB_OPER); + + // TSIZE for PB operation is fixed value: 0b00001000 + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_PB_OPERATION_TSIZE); + } + + // --------------------------------------------------- + // PMISC specific: TTYPE & TSIZE + // --------------------------------------------------- + else if (l_operType == p9_ADU_oper_flag::PMISC_OPER) + { + FAPI_DBG("ADU operation type: PMISC"); + + // Set TTYPE + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TTYPE_START_BIT, + ALTD_CMD_TTYPE_NUM_BITS>(ALTD_CMD_TTYPE_PMISC_OPER); + + // TSIZE for PMISC operation is fixed value: 0b00000010 + altd_cmd_reg_data.insertFromRight<ALTD_CMD_TSIZE_START_BIT, + ALTD_CMD_TSIZE_NUM_BITS>(ALTD_CMD_SWITCH_ACTION_TSIZE); + + // Set quiesce and init around a switch operation in option reg + FAPI_TRY(setQuiesceInit(i_target), "setQuiesceInit() returns error"); + } } //This sets everything that should be set for the ALTD_CMD_Register + FAPI_INF("CMD reg value 0x%016llX", altd_cmd_reg_data); + FAPI_TRY(fapi2::putScom(i_target, PU_ALTD_CMD_REG, altd_cmd_reg_data), "Error writing to ALTD_CMD Register"); @@ -332,7 +501,7 @@ extern "C" const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const bool i_firstGranule, const uint64_t i_address, - const uint32_t i_flags, + p9_ADU_oper_flag& i_aduOper, const uint8_t i_write_data[]) { FAPI_DBG("Start"); @@ -343,27 +512,41 @@ extern "C" uint64_t write_data = 0x0ull; int eccIndex = 8; + // Get ADU operation info from flag + bool l_itagMode = i_aduOper.getItagMode(); + bool l_eccMode = i_aduOper.getEccMode(); + bool l_overrideEccMode = i_aduOper.getEccItagOverrideMode(); + bool l_autoIncMode = i_aduOper.getAutoIncrement(); + bool l_fastMode = i_aduOper.getFastMode(); + bool l_accessForceEccReg = (l_itagMode | l_eccMode | l_overrideEccMode); + + // Dump ADU write settings + FAPI_DBG("Modes: ITAG 0x%.8X, ECC 0x%.8X, OVERRIDE_ECC 0x%.8X", + l_itagMode, l_eccMode, l_overrideEccMode); + FAPI_DBG(" AUTOINC 0x%.8X, FASTMODE 0x%.8X", + l_autoIncMode, l_fastMode); + for (int i = 0; i < 8; i++) { - write_data = write_data + ((uint64_t)(i_write_data) << (56 - (8 * i))); + write_data |= ( static_cast<uint64_t>(i_write_data[i]) << (56 - (8 * i)) ); } fapi2::buffer<uint64_t> altd_data_reg_data(write_data); - if ((i_flags & FLAG_ITAG) || (i_flags & FLAG_ECC) || (i_flags & FLAG_OVERWRITE_ECC)) + if (l_accessForceEccReg == true) { FAPI_TRY(fapi2::getScom(i_target, PU_FORCE_ECC_REG, force_ecc_reg_data), "Error reading the FORCE_ECC Register"); } //if we want to write the itag bit set it - if (i_flags & FLAG_ITAG) + if (l_itagMode == true) { eccIndex++; force_ecc_reg_data.setBit<ALTD_DATA_ITAG_BIT>(); } //if we want to write the ecc data get the data - if (i_flags & FLAG_ECC) + if (l_eccMode == true) { force_ecc_reg_data.insertFromRight < ALTD_DATA_TX_ECC_START_BIT, (ALTD_DATA_TX_ECC_END_BIT - ALTD_DATA_TX_ECC_START_BIT) + 1 > @@ -371,12 +554,12 @@ extern "C" } //if we want to overwrite the ecc data - if (i_flags & FLAG_OVERWRITE_ECC) + if (l_overrideEccMode == true) { force_ecc_reg_data.setBit<ALTD_DATA_TX_ECC_OVERWRITE_BIT>(); } - if ((i_flags & FLAG_ITAG) || (i_flags & FLAG_ECC) || (i_flags & FLAG_OVERWRITE_ECC)) + if (l_accessForceEccReg == true) { FAPI_TRY(fapi2::putScom(i_target, PU_FORCE_ECC_REG, force_ecc_reg_data), "Error writing to the FORCE_ECC Register"); } @@ -386,7 +569,7 @@ extern "C" "Error writing to ALTD_DATA Register"); //Set the ALTD_CMD_START_OP bit to start the write(first granule for autoinc case or not autoinc) - if (i_firstGranule || !(i_flags & adu_flags::FLAG_AUTOINC)) + if ( i_firstGranule || (l_autoIncMode == false) ) { //read the altd_cmd_register FAPI_TRY(fapi2::getScom(i_target, PU_ALTD_CMD_REG, altd_cmd_reg_data), "Error reading from the ALTD_CMD_REG"); @@ -397,7 +580,7 @@ extern "C" } //if we are not in fastmode delay to allow time for the write to go through before we check the status - if (!(i_flags & FLAG_FASTMODE_ADU)) + if (l_fastMode == false) { FAPI_TRY(fapi2::delay(PROC_ADU_UTILS_ADU_HW_NS_DELAY, PROC_ADU_UTILS_ADU_SIM_CYCLE_DELAY), @@ -416,7 +599,7 @@ extern "C" const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const bool i_firstGranule, const uint64_t i_address, - const uint32_t i_flags, + p9_ADU_oper_flag& i_aduOper, uint8_t o_read_data[]) { FAPI_DBG("Start"); @@ -427,8 +610,18 @@ extern "C" fapi2::buffer<uint64_t> force_ecc_reg_data; int eccIndex = 8; + // Get ADU operation info from flag + bool l_itagMode = i_aduOper.getItagMode(); + bool l_eccMode = i_aduOper.getEccMode(); + bool l_autoIncMode = i_aduOper.getAutoIncrement(); + bool l_fastMode = i_aduOper.getFastMode(); + + // Dump ADU read settings + FAPI_DBG("Modes: ITAG 0x%.8X, ECC 0x%.8X, AUTOINC 0x%.8X, FASTMODE 0x%.8X", + l_itagMode, l_eccMode, l_autoIncMode, l_fastMode); + //Set the ALTD_CMD_START_OP bit to start the read(first granule for autoinc case or not autoinc) - if (i_firstGranule || !(i_flags & adu_flags::FLAG_AUTOINC)) + if ( i_firstGranule || (l_autoIncMode == false) ) { //read the altd_cmd_register FAPI_TRY(fapi2::getScom(i_target, PU_ALTD_CMD_REG, altd_cmd_reg_data), "Error reading from the ALTD_CMD_REG"); @@ -439,7 +632,7 @@ extern "C" } //if we are not in fastmode delay to allow time for the read to go through before we get the data - if (!(i_flags & FLAG_FASTMODE_ADU)) + if ( l_fastMode == false ) { FAPI_TRY(fapi2::delay(PROC_ADU_UTILS_ADU_HW_NS_DELAY, PROC_ADU_UTILS_ADU_SIM_CYCLE_DELAY), @@ -448,19 +641,19 @@ extern "C" //if we want to include the itag and ecc data collect them before the read - if ((i_flags & FLAG_ITAG) || (i_flags & FLAG_ECC)) + if ( l_itagMode || l_eccMode ) { FAPI_TRY(fapi2::getScom(i_target, PU_FORCE_ECC_REG, force_ecc_reg_data), "Error reading from the FORCE_ECC Register"); } - if (i_flags & FLAG_ITAG) + if (l_itagMode) { eccIndex = 9; o_read_data[8] = force_ecc_reg_data.getBit<ALTD_DATA_ITAG_BIT>(); } - if (i_flags & FLAG_ECC) + if (l_eccMode) { o_read_data[eccIndex] = (force_ecc_reg_data >> ALTD_DATA_TX_ECC_END_BIT) & ALTD_DATA_ECC_MASK; } @@ -531,54 +724,125 @@ extern "C" fapi2::ReturnCode p9_adu_coherent_status_check( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, - const bool i_busy_bit_set_expected) + const adu_status_busy_handler i_busyBitHandler, + const bool i_addressOnlyOper, + bool& o_busyBitStatus) { FAPI_DBG("Start"); - fapi2::buffer<uint64_t> altd_status_reg_data(0x0); - bool busyBitSetCorrectly = true; + fapi2::buffer<uint64_t> l_statusReg(0x0); + bool l_statusError = false; - //check the ALTD_STATUS_REG - FAPI_TRY(fapi2::getScom(i_target, PU_ALTD_STATUS_REG, altd_status_reg_data), + // Check the ALTD_STATUS_REG + FAPI_TRY(fapi2::getScom(i_target, PU_ALTD_STATUS_REG, l_statusReg), "Error reading from ALTD_STATUS Register"); + FAPI_DBG("PU_ALTD_STATUS_REG reg value 0x%016llX", l_statusReg); + + // ---- Handle busy options ---- + + // Get busy bit output + o_busyBitStatus = l_statusReg.getBit<ALTD_STATUS_BUSY_BIT>(); + + // Handle busy bit according to specified input + if (o_busyBitStatus == true) + { + // Exit if busy + if (i_busyBitHandler == EXIT_ON_BUSY) + { + goto fapi_try_exit; + } + else if (i_busyBitHandler == EXPECTED_BUSY_BIT_CLEAR) + { + l_statusError = true; + } + } + else if (i_busyBitHandler == EXPECTED_BUSY_BIT_SET) + { + l_statusError = true; + } + + // ---- Check for other errors ---- + // Check the WAIT_CMD_ARBIT bit and make sure it's 0 + // Check the ADDR_DONE bit and make sure it's set + // Check the DATA_DONE bit and make sure it's set + // Check the WAIT_RESP bit to make sure it's clear + // Check the OVERRUN_ERR to make sure it's clear + // Check the AUTOINC_ERR to make sure it's clear + // Check the COMMAND_ERR to make sure it's clear + // Check the ADDRESS_ERR to make sure it's clear + // Check the COMMAND_HANG_ERR to make sure it's clear + // Check the DATA_HANG_ERR to make sure it's clear + // Check the PBINIT_MISSING to make sure it's clear + // Check the ECC_CE to make sure it's clear + // Check the ECC_UE to make sure it's clear + // Check the ECC_SUE to make sure it's clear + l_statusError = + ( l_statusError || + l_statusReg.getBit<ALTD_STATUS_WAIT_CMD_ARBIT>() || + !l_statusReg.getBit<ALTD_STATUS_ADDR_DONE_BIT>() || + l_statusReg.getBit<ALTD_STATUS_WAIT_RESP_BIT>() || + l_statusReg.getBit<ALTD_STATUS_OVERRUN_ERROR_BIT>() || + l_statusReg.getBit<ALTD_STATUS_AUTOINC_ERR_BIT>() || + l_statusReg.getBit<ALTD_STATUS_COMMAND_ERR_BIT>() || + l_statusReg.getBit<ALTD_STATUS_ADDRESS_ERR_BIT>() || + l_statusReg.getBit<ALTD_STATUS_PB_OP_HANG_ERR_BIT>() || + l_statusReg.getBit<ALTD_STATUS_PB_DATA_HANG_ERR_BIT>() || + l_statusReg.getBit<ALTD_STATUS_PBINIT_MISSING_BIT>() || + l_statusReg.getBit<ALTD_STATUS_ECC_CE_BIT>() || + l_statusReg.getBit<ALTD_STATUS_ECC_UE_BIT>() || + l_statusReg.getBit<ALTD_STATUS_ECC_SUE_BIT>() + ); + + // If Address only operation, do not check for ALTD_STATUS_DATA_DONE_BIT + if ( i_addressOnlyOper == false ) + { + l_statusError |= !l_statusReg.getBit<ALTD_STATUS_DATA_DONE_BIT>(); + } - //If busy set is expected and the altd_status_busy bit is set or busy set is not expected and teh altd_status_busy bit is not set then the busy bit is set correctly - if (i_busy_bit_set_expected == altd_status_reg_data.getBit<ALTD_STATUS_BUSY_BIT>()) + // If error, display trace + if (l_statusError) { - busyBitSetCorrectly = true; + FAPI_ERR("Status mismatch detected"); + + FAPI_ERR("ADU Status bits: "); + FAPI_ERR(" FBC_ALTD_BUSY = %d", + o_busyBitStatus ? 1 : 0); + FAPI_ERR(" FBC_ALTD_WAIT_CMD_ARBIT = %d", + l_statusReg.getBit<ALTD_STATUS_WAIT_CMD_ARBIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_ADDR_DONE_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_ADDR_DONE_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_DATA_DONE_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_DATA_DONE_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_WAIT_RESP_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_WAIT_RESP_BIT>() ? 1 : 0); + + FAPI_ERR("ADU Error bits:"); + FAPI_ERR(" ALTD_STATUS_OVERRUN_ERROR_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_OVERRUN_ERROR_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_AUTOINC_ERR_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_AUTOINC_ERR_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_COMMAND_ERR_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_COMMAND_ERR_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_ADDRESS_ERR_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_ADDRESS_ERR_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_PB_OP_HANG_ERR_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_PB_OP_HANG_ERR_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_PB_DATA_HANG_ERR_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_PB_DATA_HANG_ERR_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_PBINIT_MISSING_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_PBINIT_MISSING_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_ECC_CE_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_ECC_CE_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_ECC_UE_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_ECC_UE_BIT>() ? 1 : 0); + FAPI_ERR(" ALTD_STATUS_ECC_SUE_BIT = %d", + l_statusReg.getBit<ALTD_STATUS_ECC_SUE_BIT>() ? 1 : 0); } - //check the FBC_ALTD_BUSY bit and make sure it's 0 unless we are in autoinc and this is not the last granule - //check the WAIT_CMD_ARBIT bit and make sure it's 0 - //check the ADDR_DONE bit and make sure it's set - //check the DATA_DONE bit and make sure it's set - //check the WAIT_RESP bit to make sure it's clear - //check the OVERRUN_ERR to make sure it's clear - //check the AUTOINC_ERR to make sure it's clear - //check the COMMAND_ERR to make sure it's clear - //check the ADDRESS_ERR to make sure it's clear - //check the COMMAND_HANG_ERR to make sure it's clear - //check the DATA_HANG_ERR to make sure it's clear - //check the PBINIT_MISSING to make sure it's clear - //check the ECC_CE to make sure it's clear - //check the ECC_UE to make sure it's clear - //check the ECC_SUE to make sure it's clear - FAPI_ASSERT(( busyBitSetCorrectly - && !altd_status_reg_data.getBit<ALTD_STATUS_WAIT_CMD_ARBIT>() - //TODO These were causing problems when I tried running on vhdl, need to figure out what the problem is - //&& altd_status_reg_data.getBit<ALTD_STATUS_ADDR_DONE_BIT>() - //&& altd_status_reg_data.getBit<ALTD_STATUS_DATA_DONE_BIT>() - //&& !altd_status_reg_data.getBit<ALTD_STATUS_WAIT_RESP_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_OVERRUN_ERROR_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_AUTOINC_ERR_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_COMMAND_ERR_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_ADDRESS_ERR_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_PB_OP_HANG_ERR_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_PB_DATA_HANG_ERR_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_PBINIT_MISSING_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_ECC_CE_BIT>() && !altd_status_reg_data.getBit<ALTD_STATUS_ECC_UE_BIT>() - && !altd_status_reg_data.getBit<ALTD_STATUS_ECC_SUE_BIT>()), - fapi2::P9_ADU_STATUS_REG_ERR().set_TARGET(i_target).set_STATUSREG(altd_status_reg_data), "Status Register check error"); + FAPI_ASSERT( (l_statusError == false), fapi2::P9_ADU_STATUS_REG_ERR() + .set_TARGET(i_target) + .set_STATUSREG(l_statusReg), + "Status Register check error"); fapi_try_exit: FAPI_DBG("Exiting..."); diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.H b/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.H index e819cfb84..3d8126162 100644 --- a/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.H +++ b/src/import/chips/p9/procedures/hwp/nest/p9_adu_coherent_utils.H @@ -7,7 +7,7 @@ /* */ /* EKB Project */ /* */ -/* COPYRIGHT 2015 */ +/* COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,16 @@ #include <fapi2.H> #include <p9_adu_constants.H> +// Definitions of how to handle Busy state of the ADU when +// checking its status. +enum adu_status_busy_handler +{ + EXPECTED_BUSY_BIT_CLEAR = 0, // Expect to be clear, error if not + EXPECTED_BUSY_BIT_SET = 1, // Expect to be set, error if not + EXIT_ON_BUSY = 2 // Return Busy status without checking + // any other errors. +}; + extern"C" { @@ -50,6 +60,479 @@ extern"C" //----------------------------------------------------------------------------------- //----------------------------------------------------------------------------------- +// Classes +//----------------------------------------------------------------------------------- +/// +/// @brief Manage ADU operation flag that is used to program the +// ADU CMD register, PU_ALTD_CMD_REG (Addr: 0x00090001) +/// + class p9_ADU_oper_flag + { + public: + + // Type of ADU operations + enum OperationType_t + { + CACHE_INHIBIT = 0, + DMA_PARTIAL = 1, + PB_OPER = 2, + PMISC_OPER = 3, + }; + + // Transaction size + enum Transaction_size_t + { + TSIZE_1 = 1, + TSIZE_2 = 2, + TSIZE_4 = 4, + TSIZE_8 = 8, + }; + + // Constructor + inline p9_ADU_oper_flag() + : iv_operType(CACHE_INHIBIT), iv_autoInc(false), iv_lockPick(false), + iv_numLockAttempts(1), iv_cleanUp(true), iv_fastMode(false), + iv_itag(false), iv_ecc(false), iv_eccItagOverwrite(false), + iv_transSize(TSIZE_1) + { + } + + /// + /// @brief Set the ADU operation type + /// + /// @param[in] i_type ADU operation type + /// + /// @return void. + /// + inline void setOperationType(const OperationType_t i_type) + { + iv_operType = i_type; + return; + } + + /// + /// @brief Get the ADU operation type setting. + /// + /// @return iv_operType. + /// + inline const OperationType_t getOperationType(void) + { + return iv_operType; + } + + /// @brief Set the Auto Increment option, for CI/DMA operations only. + /// + /// @param[in] i_value True: Enable auto inc; False: Disable + /// + /// @return void. + /// + inline void setAutoIncrement(bool i_value) + { + if ( (iv_operType != CACHE_INHIBIT) && + (iv_operType != DMA_PARTIAL) ) + { + FAPI_ERR("WARNING: Set AUTOINC for non CI/DMA operation, Operation type 0x%.8X", + iv_operType); + } + + iv_autoInc = i_value; + return; + } + + /// @brief Get the Auto Increment setting, for CI/DMA operations only. + /// + /// @return iv_autoInc. + /// + inline const bool getAutoIncrement(void) + { + if ( (iv_operType != CACHE_INHIBIT) && + (iv_operType != DMA_PARTIAL) ) + { + FAPI_ERR("WARNING: AUTOINC value is invalid for non CI/DMA operation, Operation type 0x%.8X", + iv_operType); + } + + return iv_autoInc; + } + + /// + /// @brief Set ADU lock control + /// + /// @param[in] i_value True: Attempt lock ADU before operation + /// False: No lock attempt + /// + /// @return void + /// + inline void setLockControl(bool i_value) + { + iv_lockPick = i_value; + return; + } + + /// + /// @brief Get the ADU lock control setting. + /// + /// @return iv_lockPick. + /// + inline const bool getLockControl(void) + { + return iv_lockPick; + } + + /// + /// @brief Set number of lock attempts + /// + /// @param[in] i_value Num of lock attempts to try. If still can't lock + /// ADU, return an error. + /// + /// @return void + /// + inline void setNumLockAttempts(uint8_t i_value) + { + if (iv_lockPick == false) + { + FAPI_ERR("WARNING: Set lock attempts value with lock pick = false"); + } + + iv_numLockAttempts = i_value; + return; + } + + /// + /// @brief Get number of lock attempts setting. + /// + /// @return iv_numLockAttempts. + /// + inline const uint8_t getNumLockAttempts(void) + { + if (iv_lockPick == false) + { + FAPI_ERR("WARNING: Lock control is not set, num of lock attempts setting is invalid."); + } + + return iv_numLockAttempts; + } + + /// + /// @brief Clean up if operation fails + /// + /// @param[in] i_value True: Clean up and release lock if oper fails. + /// False: Leave ADU in fail state. + /// + /// @return void. + /// + inline void setOperFailCleanup(bool i_value) + { + iv_cleanUp = i_value; + return; + } + + /// + /// @brief Get the clean up for failed operation setting. + /// + /// @return iv_cleanUp. + /// + inline const bool getOperFailCleanup(void) + { + return iv_cleanUp; + } + + /// + /// @brief Set fast read/write mode. + /// For fast read/write mode, no status check. Otherwise, + /// do status check after every read/write. + /// + /// @param[in] i_value True: Enable fast read/write mode. + /// False: Disable fast read/write mode. + /// + /// @return void. + /// + inline void setFastMode(bool i_value) + { + iv_fastMode = i_value; + return; + } + + /// + /// @brief Get the Fast mode setting. + /// + /// @return iv_fastMode. + /// + inline const bool getFastMode(void) + { + return iv_fastMode; + } + + /// + /// @brief Set itag collection mode. + /// Collect/set itag with each 8B read/write + /// For a write only set if itag data should be 1 + /// + /// @param[in] i_value True: Collect itag + /// False: Don't collect itag. + /// + /// @return void. + /// + inline void setItagMode(bool i_value) + { + iv_itag = i_value; + return; + } + + /// + /// @brief the ITAG collection mode. + /// + /// @return iv_itag. + /// + inline const bool getItagMode(void) + { + return iv_itag; + } + + /// + /// @brief Set Ecc mode. + /// Collect/set ecc with each 8B read/write + /// + /// @param[in] i_value True: Collect ECC + /// False: Don't collect ECC. + /// + /// @return void. + /// + inline void setEccMode(bool i_value) + { + iv_ecc = i_value; + return; + } + + /// + /// @brief Get the Ecc mode setting. + /// + /// @return iv_ecc. + /// + inline const bool getEccMode(void) + { + return iv_ecc; + } + + /// + /// @brief Overwrite ECC/ITAG data mode. + /// + /// @param[in] i_value Overwrite ECC + /// False: Don't overwrite ECC + /// + /// @return void. + /// + inline void setEccItagOverrideMode(bool i_value) + { + iv_eccItagOverwrite = i_value; + return; + } + + /// + /// @brief Get the Overwrite ECC/ITAG data mode. + /// + /// @return iv_eccItagOverwrite. + /// + inline const bool getEccItagOverrideMode(void) + { + return iv_eccItagOverwrite; + } + + /// + /// @brief Set transaction size + /// + /// @param[in] i_value Transaction size + /// + /// @return void. + /// + inline void setTransactionSize(Transaction_size_t i_value) + { + iv_transSize = i_value; + return; + } + + /// + /// @brief Get the transaction size + /// + /// @return iv_transSize. + /// + inline const Transaction_size_t getTransactionSize(void) + { + return iv_transSize; + } + + /// + /// @brief Assemble the 32-bit ADU flag based on current + /// info contained in this class. + /// This flag is to be used in ADU interface call + /// See flag bit definitions in p9_adu_constants.H + /// + /// @return uint32_t + /// + inline uint32_t setFlag(); + + /// + /// @brief Update the class instant variables with info + /// embedded in the passed in flag value. + /// + /// @return void. + /// + inline void getFlag(uint32_t i_flag); + + private: + + // Class variables + OperationType_t iv_operType; // Operation type + bool iv_autoInc; // Auto increment + bool iv_lockPick; // Lock ADU before operation + uint8_t iv_numLockAttempts; // Number of lock attempts + bool iv_cleanUp; + bool iv_fastMode; // Fast ADU read/write mode + bool iv_itag; // Itag mode + bool iv_ecc; // ECC mode + bool iv_eccItagOverwrite; // ECC/ITAG overwrite mode + Transaction_size_t iv_transSize; // Transaction size + }; + +/// +/// See doxygen in class definition +/// + uint32_t p9_ADU_oper_flag::setFlag() + { + uint32_t l_aduFlag = 0; + + // Operation type + l_aduFlag |= (iv_operType << FLAG_ADU_TTYPE_SHIFT); + + // Auto Inc + if (iv_autoInc == true) + { + l_aduFlag |= FLAG_AUTOINC; + } + + // Lock pick + if (iv_lockPick == true) + { + l_aduFlag |= FLAG_LOCK_PICK; + } + + // Lock attempts + l_aduFlag |= (iv_numLockAttempts << FLAG_LOCK_TRIES_SHIFT); + + // Leave dirty + if (iv_cleanUp == false) + { + l_aduFlag |= FLAG_LEAVE_DIRTY; + } + + // Fast mode + if (iv_fastMode == true) + { + l_aduFlag |= FLAG_ADU_FASTMODE; + } + + // Itag + if (iv_itag == true) + { + l_aduFlag |= FLAG_ITAG; + } + + // ECC + if (iv_ecc == true) + { + l_aduFlag |= FLAG_ECC; + } + + // Overwrite ECC + if (iv_eccItagOverwrite == true) + { + l_aduFlag |= FLAG_OVERWRITE_ECC; + } + + // Transaction size + if (iv_transSize == TSIZE_1) + { + l_aduFlag |= FLAG_SIZE_TSIZE_1; + } + else if (iv_transSize == TSIZE_2) + { + l_aduFlag |= FLAG_SIZE_TSIZE_2; + } + else if (iv_transSize == TSIZE_4) + { + l_aduFlag |= FLAG_SIZE_TSIZE_4; + } + else if (iv_transSize == TSIZE_8) + { + l_aduFlag |= FLAG_SIZE_TSIZE_8; + } + else + { + FAPI_ERR("Invalid transaction size: iv_transSize %d", iv_transSize); + } + + // Debug trace + FAPI_DBG("p9_ADU_oper_flag::setFlag()"); + FAPI_DBG(" iv_operType 0x%.8X, iv_autoInc 0x%.8X, iv_lockPick 0x%.8X, iv_numLockAttempts 0x%.8X", + iv_operType, iv_autoInc, iv_lockPick, iv_numLockAttempts); + FAPI_DBG(" iv_cleanUp 0x%.8X, iv_fastMode 0x%.8X, iv_itag 0x%.8X, iv_ecc 0x%.8X", + iv_cleanUp, iv_fastMode, iv_itag, iv_ecc); + FAPI_DBG(" iv_eccItagOverwrite 0x%.8X, iv_transSize 0x%.8X", + iv_eccItagOverwrite, iv_transSize); + FAPI_DBG(" ADU Flag value: 0x%.8X", l_aduFlag); + + return l_aduFlag; + } + +/// +/// See doxygen in class definition +/// + void p9_ADU_oper_flag::getFlag(const uint32_t i_flag) + { + // Decode Operation type + iv_operType = static_cast<OperationType_t> + ( (i_flag & FLAG_ADU_TTYPE) >> FLAG_ADU_TTYPE_SHIFT); + + // Auto Inc + iv_autoInc = (i_flag & FLAG_AUTOINC); + + // Lock pick + iv_lockPick = (i_flag & FLAG_LOCK_PICK); + + // Lock attempts + iv_numLockAttempts = ( (i_flag & FLAG_LOCK_TRIES) >> FLAG_LOCK_TRIES_SHIFT); + + // Leave dirty + iv_cleanUp = ~(i_flag & FLAG_LEAVE_DIRTY); + + // Fast mode + iv_fastMode = (i_flag & FLAG_ADU_FASTMODE); + + // Itag + iv_itag = (i_flag & FLAG_ITAG); + + // ECC + iv_ecc = (i_flag & FLAG_ECC); + + // Overwrite ECC + iv_eccItagOverwrite = (i_flag & FLAG_OVERWRITE_ECC); + + // Transaction size + iv_transSize = static_cast<Transaction_size_t> + ( (i_flag & FLAG_SIZE) >> FLAG_ADU_SIZE_SHIFT ); + + // Debug trace + FAPI_DBG("p9_ADU_oper_flag::getFlag() - Flag value 0x%.8X", i_flag); + FAPI_DBG(" iv_operType 0x%.8X, iv_autoInc 0x%.8X, iv_lockPick 0x%.8X, iv_numLockAttempts 0x%.8X", + iv_operType, iv_autoInc, iv_lockPick, iv_numLockAttempts); + FAPI_DBG(" iv_cleanUp 0x%.8X, iv_fastMode 0x%.8X, iv_itag 0x%.8X, iv_ecc 0x%.8X", + iv_cleanUp, iv_fastMode, iv_itag, iv_ecc); + FAPI_DBG(" iv_eccItagOverwrite 0x%.8X, iv_transSize 0x%.8X", + iv_eccItagOverwrite, iv_transSize); + return; + } + +//----------------------------------------------------------------------------------- // Function prototypes //----------------------------------------------------------------------------------- @@ -94,28 +577,28 @@ extern"C" /// @param[in] i_target => P9 chip target /// @param[in] i_firstGranule => the first 8B granule that we are writing /// @param[in] i_address => address for this write -/// @param[in] i_flags => flags that contain information that the ADU needs to know to set up registers +/// @param[in] i_aduOper => Contains information that the ADU needs to know to set up registers /// @param[in] i_write_data => the data that is to be written to the ADU /// @return FAPI_RC_SUCCESS if writing the ADU is a success fapi2::ReturnCode p9_adu_coherent_adu_write( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const bool i_firstGranule, const uint64_t i_address, - const uint32_t i_flags, + p9_ADU_oper_flag& i_aduOper, const uint8_t i_write_data[]); /// @brief does the read for the ADU /// @param[in] i_target => P9 chip target /// @param[in] i_firstGranule => the first 8B granule that we are reading /// @param[in] i_address => address for this read -/// @param[in] i_flags => flags that contain information that the ADU needs to know to set up registers +/// @param[in] i_aduOper => Contains information that the ADU needs to know to set up registers /// @param[out] o_read_data => the data that is read from the ADU /// @return FAPI_RC_SUCCESS if reading the ADU is a success fapi2::ReturnCode p9_adu_coherent_adu_read( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const bool i_firstGranule, const uint64_t i_address, - const uint32_t i_flags, + p9_ADU_oper_flag& i_aduOper, uint8_t o_read_data[]); /// @brief this does a reset for the ADU @@ -136,12 +619,21 @@ extern"C" fapi2::ReturnCode p9_adu_coherent_clear_autoinc( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target); -/// @brief this will check the status of the pba -/// @param[in] i_target => P9 chip target +/// @brief This function checks the status of the adu. +/// If ADU is busy, it will handle +/// +/// @param[in] i_target P9 chip target +/// @param[in] i_busyBitHandler Instruction on how to handle the ADU busy +/// @param[in] i_addressOnlyOper Indicate the check is called after an Address +/// only operation +/// @param[out] o_busyStatus ADU status busy bit. +/// /// @return FAPI_RC_SUCCESS if the status check is a success fapi2::ReturnCode p9_adu_coherent_status_check( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, - const bool i_busy_bit_set_expected); + const adu_status_busy_handler i_busyBitHandler, + const bool i_addressOnlyOper, + bool& o_busyBitStatus); /// @brief this will acquire and release a lock as well as deal with any lock picking /// @param[in] i_target => P9 chip target diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_adu_constants.H b/src/import/chips/p9/procedures/hwp/nest/p9_adu_constants.H index effa28985..9c582e0bf 100644 --- a/src/import/chips/p9/procedures/hwp/nest/p9_adu_constants.H +++ b/src/import/chips/p9/procedures/hwp/nest/p9_adu_constants.H @@ -7,7 +7,7 @@ /* */ /* EKB Project */ /* */ -/* COPYRIGHT 2015 */ +/* COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -35,39 +35,90 @@ extern "C" { - //---------------------------------------------------------------------------------------------- - // Constant definitions - //---------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------- +// Constant definitions +//---------------------------------------------------------------------------------------------- - //if the flag is more than 1 bit there will be a start and end bit for the flag - //these give the bit position that is expected for the flags +//if the flag is more than 1 bit there will be a start and end bit for the flag +//these give the bit position that is expected for the flags enum adu_flags { - //cache-inhibited (true = ci, false = dma partial) - FLAG_CI = 0x80000000ull, - //utilize ADU HW auto-increment function (true = use autoinc, false = don't use autoinc) - FLAG_AUTOINC = 0x40000000ull, - //pick ADU lock (if required) (true = use lock pick, false = don't pick lock) - FLAG_LOCK_PICK = 0x20000000ull, - //in the case of a fail with lock held, reset ADU and release lock (true = , false = ) - FLAG_LEAVE_DIRTY = 0x10000000ull, - //check status only at the end of read/write stream (true = don't do status check, false = do status check after every read/write) - FLAG_FASTMODE_ADU = 0x8000000ull, - //collect/set itag with each 8B read/write (true = collect itag, false = don't collect itag) for a write only set if itag data should be 1 - FLAG_ITAG = 0x4000000ull, - //collect/set ecc with each 8B read/write (true = collect ecc, false = don't collect ecc) - FLAG_ECC = 0x2000000ull, - //overwrite the ecc/itag data - FLAG_OVERWRITE_ECC = 0x1000000ull, - //transaction size (choice is 1, 2, 4, or 8) - FLAG_SIZE = 0xFF0000ull, - //number of ADU lock acquisitions to attempt before giving up or attempting lock pick - FLAG_LOCK_TRIES = 0xFFFFull + // Operation type + // 0b000: DMA partial + // 0b001: Cache-inhibited + // 0b010: PB op + // 0b011: PMISC op + FLAG_ADU_TTYPE = 0xE0000000ull, // Bits 0:2 + + // Utilize ADU HW auto-increment function + // 0: Don't use autoinc + // 1: Use autoinc + FLAG_AUTOINC = 0x10000000ull, // Bit 3 + + // Pick ADU lock (if required) + // 0: Don't use lock pick + // 1: Use lock pick + FLAG_LOCK_PICK = 0x08000000ull, // Bit 4 + + // In case of a fail with lock held, reset + // ADU and release lock + // 0: Reset & release + // 1: Leave dirty + FLAG_LEAVE_DIRTY = 0x04000000ull, // Bit 5 + + // Check status only at the end of read/write stream + // 0: Do status check after every read/write + // 1: Don't do status check + FLAG_ADU_FASTMODE = 0x02000000ull, // Bit 6 + + // Collect/set itag with each 8B read/write + // For a write only set if itag data should be 1 + // 0: Don't collect itag + // 1: Collect itag + FLAG_ITAG = 0x01000000ull, // Bit 7 + + // Collect/set ecc with each 8B read/write + // 0: Don't collect ecc + // 1: Collect ecc + FLAG_ECC = 0x00800000ull, // Bit 8 + + // Overwrite the ecc/itag data + // 0: Don't overwrite ECC + // 1: Overwrite ECC + FLAG_OVERWRITE_ECC = 0x00400000ull, // Bit 9 + + // Transaction size (choice is 1, 2, 4, or 8) + // 0b00: TSIZE_1 + // 0b01: TSIZE_2 + // 0b10: TSIZE_4 + // 0b11: TSIZE_8 + FLAG_SIZE = 0x00300000ull, // Bits 10:11 + + // Number of ADU lock acquisitions to attempt + // before giving up or attempting lock pick + FLAG_LOCK_TRIES = 0x000F0000, // Bit 12:15 + + // Reserved bits + FLAG_NOT_USED_BITS = 0x0000FFFF, // Bit 16:31 }; - const uint64_t FLAG_SIZE_SHIFT = 17; +// Operation type values + const uint32_t FLAG_ADU_TTYPE_DMA = 0x00000000ull; // DMA partial + const uint32_t FLAG_ADU_TTYPE_CI = 0x20000000ull; // Cache inhibit + const uint32_t FLAG_ADU_TTYPE_PB = 0x40000000ull; // PB operation + const uint32_t FLAG_ADU_TTYPE_PMISC = 0x60000000ull; // Switch operation + +// Flag size values + const uint32_t FLAG_SIZE_TSIZE_1 = 0x00000000ull; + const uint32_t FLAG_SIZE_TSIZE_2 = 0x00100000ull; + const uint32_t FLAG_SIZE_TSIZE_4 = 0x00200000ull; + const uint32_t FLAG_SIZE_TSIZE_8 = 0x00300000ull; + +// Shift positions + const uint64_t FLAG_ADU_TTYPE_SHIFT = 29; + const uint64_t FLAG_LOCK_TRIES_SHIFT = 16; + const uint64_t FLAG_ADU_SIZE_SHIFT = 20; } //extern "C" #endif //_P9_ADU_CONSTANTS_H_ - diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_adu.C b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_adu.C new file mode 100644 index 000000000..6b29158e0 --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_adu.C @@ -0,0 +1,828 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/hwp/nest/p9_build_smp_adu.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2015,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file p9_build_smp_adu.C +/// @brief Interface for ADU operations required to support fabric +/// configuration actions (FAPI2) +/// +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// *HWP Consumed by: HB,FSP +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <p9_build_smp_adu.H> +#include <p9_adu_coherent_utils.H> +#include <p9_misc_scom_addresses.H> + +//------------------------------------------------------------------------------ +// Constants +//------------------------------------------------------------------------------ + +// Poll threshold +const uint32_t P9_BUILD_SMP_MAX_STATUS_POLLS = 100; + +// ADU lock +const uint32_t P9_BUILD_SMP_PHASE1_ADU_LOCK_ATTEMPTS = 1; +const bool P9_BUILD_SMP_PHASE1_ADU_PICK_LOCK = false; + +const uint32_t P9_BUILD_SMP_PHASE2_ADU_LOCK_ATTEMPTS = 5; +const bool P9_BUILD_SMP_PHASE2_ADU_PICK_LOCK = true; + +// ADU pMISC Mode register field/bit definitions +const uint32_t ADU_PMISC_MODE_ENABLE_PB_SWITCH_AB_BIT = 30; +const uint32_t ADU_PMISC_MODE_ENABLE_PB_SWITCH_CD_BIT = 31; + +enum p9_build_smp_ffdc_reg_index +{ + PB_MODE_CENT_DATA_INDEX = 0, + PB_HP_MODE_NEXT_CENT_DATA_INDEX = 1, + PB_HP_MODE_CURR_CENT_DATA_INDEX = 2, + PB_HPX_MODE_NEXT_CENT_DATA_INDEX = 3, + PB_HPX_MODE_CURR_CENT_DATA_INDEX = 4, + X_GP0_DATA_INDEX = 5, + PB_X_MODE_DATA_INDEX = 6, + A_GP0_DATA_INDEX = 7, + ADU_IOS_LINK_EN_DATA_INDEX = 8, + PB_A_MODE_DATA_INDEX = 9, + ADU_PMISC_MODE_DATA_INDEX = 10 +}; + +extern "C" +{ + +//------------------------------------------------------------------------------ +// Function definitions +//------------------------------------------------------------------------------ +/// +/// @brief Check ADU status matches expected state/value +/// NOTE: intended to be run while holding ADU lock +/// +/// @param[in] i_target P9 target +/// @param[in] i_smp Structure encapsulating SMP topology +/// @param[in] i_dump_all_targets Dump FFDC for all targets in SMP? +/// true=yes; false=no (only for i_target) +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_adu_check_status( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, + p9_build_smp_system& i_smp, + const bool i_dump_all_targets) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + uint32_t l_numPolls = 0; + bool l_busyBitStatus = false; + + // SMP SWITCH expect BUSY BIT to be clear + adu_status_busy_handler l_busyHandling = EXIT_ON_BUSY; + + // Wait for operation to be completed (busy bit cleared) + while (l_numPolls < P9_BUILD_SMP_MAX_STATUS_POLLS) + { + l_rc = p9_adu_coherent_status_check(i_target, l_busyHandling, true, + l_busyBitStatus); + + if (l_rc) + { + FAPI_ERR("p9_adu_coherent_status_check() returns error"); + break; + } + + if (l_busyBitStatus == true) + { + l_numPolls++; + + // Last try, set handler to expect busy bit clear, if not then + // p9_adu_coherent_status_check() will log an error so that + // we don't have to deal with the error separately here. + if (l_numPolls == (P9_BUILD_SMP_MAX_STATUS_POLLS - 1)) + { + l_busyHandling = EXPECTED_BUSY_BIT_CLEAR; + } + } + else + { + // Operation done, break out + break; + } + } + + FAPI_DBG("Num of polls %u", l_numPolls); + + // TODO: RTC 147511 - Need to add code to dump FFDC + // Note: variable_buffer doesn't currently support resize because it's + // an expensive operation. + // Per Joe's suggestion, may be we can size statically by the maximum + // number of chips possible in the system. It's not efficient, but + // this is an error path. +#if 0 + + // Additional error handling for SMP build + if (l_rc) + { + fapi2::current_err = l_rc; + + + // Dump FFDC + // There is no clean way to represent the collection in XML (given an + // arbitrary number of chips), so collect manually and store into data + // buffers which can be post-processed from the error log + std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator n_iter; + std::map<p9_fab_smp_chip_id, p9_build_smp_chip>::iterator p_iter; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>*> targets_to_collect; + fapi2::buffer<uint64_t> l_scomData; + fapi2::variable_buffer l_chipIds; + fapi2::variable_buffer l_ffdcRegData[P9_BUILD_SMP_FFDC_NUM_REGS]; + bool l_ffdcScomError = false; + + // Determine set of chips to collect + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + if (i_dump_all_targets || + (p_iter->second.chip->this_chip == i_target)) + { + targets_to_collect.push_back( + &(p_iter->second.chip->this_chip)); + } + } + } + + // Size the FFDC buffers + rc_ecmd |= chip_ids.setByteLength(targets_to_collect.size()); + + for (uint8_t i = 0; i < P9_BUILD_SMP_FFDC_NUM_REGS; i++) + { + rc_ecmd |= ffdc_reg_data[i].setDoubleWordLength(targets_to_collect.size()); + } + + // extract FFDC data + std::vector<bool>::iterator n = nv_present.begin(); + + for (std::vector<fapi::Target*>::iterator t = targets_to_collect.begin(); + t != targets_to_collect.end(); + t++, n++) + { + // log node/chip ID + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + n_iter++) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + p_iter++) + { + if ((&(p_iter->second.chip->this_chip)) == *t) + { + uint8_t id = ((n_iter->first & 0x3) << 4) | + (p_iter->first & 0x3); + + rc_ecmd |= chip_ids.setByte(t - targets_to_collect.begin(), id); + } + } + } + + // collect SCOM data + for (uint8_t i = 0; i < P9_BUILD_SMP_FFDC_NUM_REGS; i++) + { + // skip A / F link registers if NV link logic is present + if ((*n) && + ((i == static_cast<uint8_t>(A_GP0_DATA_INDEX)) || + (i == static_cast<uint8_t>(ADU_IOS_LINK_EN_DATA_INDEX)) || + (i == static_cast<uint8_t>(PB_A_MODE_DATA_INDEX)))) + { + rc_ecmd |= scom_data.flushTo1(); + } + else + { + rc = fapiGetScom(*(*t), P9_BUILD_SMP_FFDC_REGS[i], scom_data); + + if (!rc.ok()) + { + ffdc_scom_error = true; + } + } + + rc_ecmd |= scom_data.extractPreserve( + ffdc_reg_data[i], + 0, 64, + 64 * (t - targets_to_collect.begin())); + } + } + + const fapi::Target& TARGET = i_target; + const p9_adu_utils_adu_status& ADU_STATUS_DATA = status; + const uint8_t& ADU_NUM_POLLS = num_polls; + const uint8_t& NUM_CHIPS = targets_to_collect.size(); + const uint8_t& FFDC_VALID = !rc_ecmd && !ffdc_scom_error; + const ecmdDataBufferBase& CHIP_IDS = chip_ids; + const ecmdDataBufferBase& PB_MODE_CENT_DATA = ffdc_reg_data[0]; + const ecmdDataBufferBase& PB_HP_MODE_NEXT_CENT_DATA = ffdc_reg_data[1]; + const ecmdDataBufferBase& PB_HP_MODE_CURR_CENT_DATA = ffdc_reg_data[2]; + const ecmdDataBufferBase& PB_HPX_MODE_NEXT_CENT_DATA = ffdc_reg_data[3]; + const ecmdDataBufferBase& PB_HPX_MODE_CURR_CENT_DATA = ffdc_reg_data[4]; + const ecmdDataBufferBase& X_GP0_DATA = ffdc_reg_data[5]; + const ecmdDataBufferBase& PB_X_MODE_DATA = ffdc_reg_data[6]; + const ecmdDataBufferBase& A_GP0_DATA = ffdc_reg_data[7]; + const ecmdDataBufferBase& ADU_IOS_LINK_EN_DATA = ffdc_reg_data[8]; + const ecmdDataBufferBase& PB_A_MODE_DATA = ffdc_reg_data[9]; + const ecmdDataBufferBase& ADU_PMISC_MODE_DATA = ffdc_reg_data[10]; + FAPI_SET_HWP_ERROR(rc, RC_PROC_BUILD_SMP_ADU_STATUS_MISMATCH); + break; + + } + + fapi_try_exit: +#endif + + FAPI_DBG("End"); + return fapi2::current_err; + } + +// NOTE: see comments above function prototype in header + fapi2::ReturnCode p9_build_smp_quiesce_pb(p9_build_smp_system& i_smp, + const p9_build_smp_operation i_op) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + bool l_lockPick = false; + uint8_t l_numAttempts = 1; + uint64_t l_address = 0; // Address phase + p9_ADU_oper_flag l_myAduFlag; + + // Node/Chip iterators + std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator n_iter; + std::map<p9_fab_smp_chip_id, p9_build_smp_chip>::iterator p_iter; + std::vector<p9_build_smp_chip*>::iterator quiesce_iter; + + // Lock flag + bool adu_is_dirty = false; + + FAPI_DBG("Acquiring lock for all ADU units in fabric"); + + // Set pick lock & num of tries + l_lockPick = (i_op == SMP_ACTIVATE_PHASE1) ? + P9_BUILD_SMP_PHASE1_ADU_PICK_LOCK : + P9_BUILD_SMP_PHASE2_ADU_PICK_LOCK; + l_numAttempts = (i_op == SMP_ACTIVATE_PHASE1) ? + P9_BUILD_SMP_PHASE1_ADU_LOCK_ATTEMPTS : + P9_BUILD_SMP_PHASE2_ADU_LOCK_ATTEMPTS; + + // Loop through all chips, lock & reset ADU + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + // Acquire ADU lock + FAPI_TRY(p9_adu_coherent_manage_lock( + p_iter->second.chip->this_chip, + l_lockPick, + true, // Acquire lock + l_numAttempts), + "p9_adu_coherent_manage_lock() - Lock returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // NOTE: lock is now held, if an operation fails from this point + // to the end of the procedure: + // o attempt to cleanup/release lock (so that procedure does + // not leave the ADU in a locked state) + // o return rc of original fail + adu_is_dirty = true; + + // Reset ADU + l_rc = p9_adu_coherent_utils_reset_adu( + p_iter->second.chip->this_chip); + + if (l_rc) + { + FAPI_ERR("Error from p9_adu_coherent_utils_reset_adu()"); + goto adu_reset_unlock; + } + } + } + + FAPI_DBG("All ADU locks held"); + + // Setup ADU flag to peform quiesce + l_myAduFlag.setOperationType(p9_ADU_oper_flag::PB_OPER); + + // Issue quiesce on all specified chips + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + if (p_iter->second.issue_quiesce_next) + { + char l_targetStr[fapi2::MAX_ECMD_STRING_LEN]; + fapi2::toString(p_iter->second.chip->this_chip, l_targetStr, + sizeof(l_targetStr)); + FAPI_INF("Issuing quiesce from %s", l_targetStr); + + // Setup and launch command + l_rc = p9_adu_coherent_setup_adu(p_iter->second.chip->this_chip, + l_address, + false, // write + l_myAduFlag.setFlag()); + + if (l_rc) + { + FAPI_ERR("Error from p9_adu_coherent_setup_adu()"); + goto adu_reset_unlock; + } + + // Check status + l_rc = p9_build_smp_adu_check_status( + p_iter->second.chip->this_chip, + i_smp, + (i_op == SMP_ACTIVATE_PHASE2)); + + if (l_rc) + { + FAPI_ERR("Error from p9_build_smp_adu_check_status"); + goto adu_reset_unlock; + } + } + } + } + + // Loop through all chips, unlock ADUs + FAPI_DBG("Releasing lock for all ADU units in drawer"); + + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + // Release ADU lock + l_lockPick = false; + l_numAttempts = (i_op == SMP_ACTIVATE_PHASE1) ? + P9_BUILD_SMP_PHASE1_ADU_LOCK_ATTEMPTS : + P9_BUILD_SMP_PHASE2_ADU_LOCK_ATTEMPTS; + FAPI_TRY(p9_adu_coherent_manage_lock(p_iter->second.chip->this_chip, + l_lockPick, + false, // Release lock + l_numAttempts), + "p9_adu_coherent_manage_lock() - Release returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + FAPI_DBG("All ADU locks released"); + // No error for entire operation, ADU locks released. + adu_is_dirty = false; + + adu_reset_unlock: + + // If error has occurred and any ADU is dirty, + // attempt to reset all ADUs and free locks (propogate rc of original fail) + if (l_rc && adu_is_dirty) + { + // Save original error + fapi2::ReturnCode l_savedRc = l_rc; + + FAPI_INF("Attempting to reset/free lock on all ADUs"); + + // loop through all chips, unlock ADUs + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + // Ignore l_rc1 when attempting to reset/unlock + l_rc = p9_adu_coherent_utils_reset_adu( + p_iter->second.chip->this_chip); + l_rc = p9_adu_coherent_manage_lock( + p_iter->second.chip->this_chip, + false, // No lock pick + false, // Lock release + 1); // Attempt 1 time + } + } + + // Return original error + fapi2::current_err = l_savedRc; + } + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Set action which will occur on fabric pmisc switch command +/// NOTE: intended to be run while holding ADU lock +/// +/// @param[in] i_target P9 target +/// @param[in] i_switch_ab Perform switch AB operation? +/// @param[in] i_switch_cd Perform switch CD operation? +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_adu_set_switch_action( + const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, + const bool i_switch_ab, + const bool i_switch_cd) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + fapi2::buffer<uint64_t> pmisc_data; + fapi2::buffer<uint64_t> pmisc_mask; + + // Build ADU pMisc Mode register content + FAPI_DBG("Writing ADU pMisc Mode register. Switch_ab %s, Switch_cd %s", + i_switch_ab ? "true" : "false", i_switch_cd ? "true" : "false"); + + // Switch AB bit + pmisc_data.writeBit<ADU_PMISC_MODE_ENABLE_PB_SWITCH_AB_BIT>(i_switch_ab); + pmisc_mask.setBit<ADU_PMISC_MODE_ENABLE_PB_SWITCH_AB_BIT>(); + + // Switch CD bit + pmisc_data.writeBit<ADU_PMISC_MODE_ENABLE_PB_SWITCH_CD_BIT>(i_switch_cd); + pmisc_mask.setBit<ADU_PMISC_MODE_ENABLE_PB_SWITCH_CD_BIT>(); + + FAPI_TRY(fapi2::putScomUnderMask(i_target, PU_SND_MODE_REG, + pmisc_data, pmisc_mask), + "putScomUnderMask() returns an error. Address 0x%.16llX", PU_SND_MODE_REG); + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +// NOTE: see comments above function prototype in header + fapi2::ReturnCode p9_build_smp_switch_ab(p9_build_smp_system& i_smp, + const p9_build_smp_operation i_op) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + p9_ADU_oper_flag l_myAduFlag; + + // Chip/Node map iterators + std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator n_iter; + std::map<p9_fab_smp_chip_id, p9_build_smp_chip>::iterator p_iter; + + // Lock flag + bool adu_is_dirty = false; + bool l_lockPick = false; + uint8_t l_numAttempts = 1; + uint64_t l_address = 0; // Address phase + + // Loop through all chips, lock & reset ADU & set switch action + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + // Set pick lock & num of tries + l_lockPick = (i_op == SMP_ACTIVATE_PHASE1) ? + P9_BUILD_SMP_PHASE1_ADU_PICK_LOCK : + P9_BUILD_SMP_PHASE2_ADU_PICK_LOCK; + l_numAttempts = (i_op == SMP_ACTIVATE_PHASE1) ? + P9_BUILD_SMP_PHASE1_ADU_LOCK_ATTEMPTS : + P9_BUILD_SMP_PHASE2_ADU_LOCK_ATTEMPTS; + + // Acquire ADU lock + FAPI_TRY(p9_adu_coherent_manage_lock( + p_iter->second.chip->this_chip, + l_lockPick, + true, // Acquire lock + l_numAttempts), + "p9_adu_coherent_manage_lock() - Lock returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // NOTE: lock is now held, if an operation fails from this point + // to the end of the procedure: + // o attempt to cleanup/release lock (so that procedure does + // not leave the ADU in a locked state) + // o return rc of original fail + adu_is_dirty = true; + + // Reset ADU + l_rc = p9_adu_coherent_utils_reset_adu( + p_iter->second.chip->this_chip); + + if (l_rc) + { + FAPI_ERR("Error from p9_adu_coherent_utils_reset_adu()"); + goto adu_reset_unlock; + } + + // Condition for switch AB operation + // all chips which were not quiesced prior to switch AB will + // need to observe the switch + l_rc = p9_build_smp_adu_set_switch_action( + p_iter->second.chip->this_chip, + !p_iter->second.quiesced_next, + false); + + if (l_rc) + { + FAPI_ERR("(Set): Error from p9_build_smp_adu_set_switch_action()"); + goto adu_reset_unlock; + } + } + } + + FAPI_DBG("All ADU locks held"); + + // Setup ADU flag to peform switch + l_myAduFlag.setOperationType(p9_ADU_oper_flag::PMISC_OPER); + + char l_targetStr[fapi2::MAX_ECMD_STRING_LEN]; + fapi2::toString(i_smp.nodes[i_smp.master_chip_curr_node_id].chips[i_smp.master_chip_curr_chip_id].chip->this_chip, + l_targetStr, + sizeof(l_targetStr)); + FAPI_INF("Issuing switch AB from %s", l_targetStr); + + // Setup and launch command + l_rc = p9_adu_coherent_setup_adu( + i_smp.nodes[i_smp.master_chip_curr_node_id].chips[i_smp.master_chip_curr_chip_id].chip->this_chip, + l_address, + false, // write + l_myAduFlag.setFlag()); + + if (l_rc) + { + FAPI_ERR("Error from p9_adu_coherent_setup_adu()"); + goto adu_reset_unlock; + } + + // Check status + l_rc = p9_build_smp_adu_check_status( + i_smp.nodes[i_smp.master_chip_curr_node_id].chips[i_smp.master_chip_curr_chip_id].chip->this_chip, + i_smp, + (i_op == SMP_ACTIVATE_PHASE2)); + + if (l_rc) + { + FAPI_ERR("Error from p9_build_smp_adu_check_status"); + goto adu_reset_unlock; + } + + // Loop through all chips, unlock ADUs + FAPI_DBG("Releasing lock for all ADU units in drawer"); + + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + // Release ADU lock + l_lockPick = false; + l_numAttempts = (i_op == SMP_ACTIVATE_PHASE1) ? + P9_BUILD_SMP_PHASE1_ADU_LOCK_ATTEMPTS : + P9_BUILD_SMP_PHASE2_ADU_LOCK_ATTEMPTS; + FAPI_TRY(p9_adu_coherent_manage_lock(p_iter->second.chip->this_chip, + l_lockPick, + false, l_numAttempts), + "p9_adu_coherent_manage_lock() - Release returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + FAPI_DBG("All ADU locks released"); + // No error for entire operation, ADU locks released. + adu_is_dirty = false; + + adu_reset_unlock: + + // If error has occurred and any ADU is dirty, + // attempt to reset all ADUs and free locks (propogate rc of original fail) + if (l_rc && adu_is_dirty) + { + // Save original error + fapi2::ReturnCode l_savedRc = l_rc; + + FAPI_INF("Attempting to reset/free lock on all ADUs"); + + // loop through all chips, unlock ADUs + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + // Ignore l_rc when attempting to reset/unlock + l_rc = p9_build_smp_adu_set_switch_action( + p_iter->second.chip->this_chip, + false, false); + l_rc = p9_adu_coherent_utils_reset_adu( + p_iter->second.chip->this_chip); + l_rc = p9_adu_coherent_manage_lock( + p_iter->second.chip->this_chip, + false, // No lock pick + false, // Lock release + 1); // Attempt 1 time + } + } + + // Return original error + fapi2::current_err = l_savedRc; + } + + fapi_try_exit: + + FAPI_DBG("End"); + return fapi2::current_err; + } + +// NOTE: see comments above function prototype in header + fapi2::ReturnCode p9_build_smp_switch_cd( + p9_build_smp_chip& i_smp_chip, + p9_build_smp_system& i_smp) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + p9_ADU_oper_flag l_myAduFlag; + + // Lock flag + bool adu_is_dirty = false; + bool l_lockPick = false; + uint8_t l_numAttempts = 1; + uint64_t l_address = 0; // Address phase + + FAPI_DBG("Acquiring lock for ADU"); + + // Acquire ADU lock + // only required to obtain lock for this chip, as this function will + // only be executed when fabric is configured as single chip island + + // Set pick lock & num of tries + l_lockPick = P9_BUILD_SMP_PHASE1_ADU_PICK_LOCK; + l_numAttempts = P9_BUILD_SMP_PHASE1_ADU_LOCK_ATTEMPTS; + + // Acquire ADU lock + FAPI_TRY(p9_adu_coherent_manage_lock( + i_smp_chip.chip->this_chip, + l_lockPick, + true, // Acquire lock + l_numAttempts), + "p9_adu_coherent_manage_lock() - Lock returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // NOTE: lock is now held, if an operation fails from this point + // to the end of the procedure: + // o attempt to cleanup/release lock (so that procedure does + // not leave the ADU in a locked state) + // o return rc of original fail + adu_is_dirty = true; + + // Reset ADU + l_rc = p9_adu_coherent_utils_reset_adu(i_smp_chip.chip->this_chip); + + if (l_rc) + { + FAPI_ERR("Error from p9_adu_coherent_utils_reset_adu()"); + goto adu_reset_unlock; + } + + // Condition for switch CD operation + l_rc = p9_build_smp_adu_set_switch_action(i_smp_chip.chip->this_chip, + false, // Switch A/B + true); // Switch C/D + + if (l_rc) + { + FAPI_ERR("(Set): Error from p9_build_smp_adu_set_switch_action()"); + goto adu_reset_unlock; + } + + + FAPI_DBG("All ADU locks held"); + + // Setup ADU flag to peform switch + l_myAduFlag.setOperationType(p9_ADU_oper_flag::PMISC_OPER); + + char l_targetStr[fapi2::MAX_ECMD_STRING_LEN]; + fapi2::toString(i_smp_chip.chip->this_chip, l_targetStr, + sizeof(l_targetStr)); + FAPI_INF("Issuing switch CD from %s", l_targetStr); + + // Setup and launch command + l_rc = p9_adu_coherent_setup_adu(i_smp_chip.chip->this_chip, + l_address, + false, // write + l_myAduFlag.setFlag()); + + if (l_rc) + { + FAPI_ERR("Error from p9_adu_coherent_setup_adu()"); + goto adu_reset_unlock; + } + + // Check status + l_rc = p9_build_smp_adu_check_status(i_smp_chip.chip->this_chip, + i_smp, false); + + if (l_rc) + { + FAPI_ERR("Error from p9_build_smp_adu_check_status"); + goto adu_reset_unlock; + } + + // Reset switch controls + l_rc = p9_build_smp_adu_set_switch_action(i_smp_chip.chip->this_chip, + false, false); + + if (l_rc) + { + FAPI_ERR("(Reset): Error from p9_build_smp_adu_set_switch_action()"); + goto adu_reset_unlock; + } + + // Release ADU lock + FAPI_DBG("Releasing lock for ADU"); + l_lockPick = false; + l_numAttempts = P9_BUILD_SMP_PHASE1_ADU_LOCK_ATTEMPTS; + FAPI_TRY(p9_adu_coherent_manage_lock(i_smp_chip.chip->this_chip, + l_lockPick, + false, // Release + l_numAttempts), + "p9_adu_coherent_manage_lock() - Release returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + FAPI_DBG("All ADU locks released"); + // No error for entire operation, ADU locks released. + adu_is_dirty = false; + + adu_reset_unlock: + + // If error has occurred and any ADU is dirty, + // attempt to reset all ADUs and free locks (propogate rc of original fail) + if (l_rc && adu_is_dirty) + { + FAPI_INF("Attempting to reset/free lock on ADU"); + + // Save original error + fapi2::ReturnCode l_savedRc = l_rc; + + // Ignore l_rc when attempting to reset/unlock + l_rc = p9_build_smp_adu_set_switch_action(i_smp_chip.chip->this_chip, + false, false); + l_rc = p9_adu_coherent_utils_reset_adu(i_smp_chip.chip->this_chip); + l_rc = p9_adu_coherent_manage_lock(i_smp_chip.chip->this_chip, + false, // No lock pick + false, // Lock release + 1); // Attempt 1 time + // Return original error + fapi2::current_err = l_savedRc; + } + + fapi_try_exit: + + FAPI_DBG("End"); + return fapi2::current_err; + } + +} // extern "C" + + diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_adu.H b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_adu.H new file mode 100644 index 000000000..4d986921a --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_adu.H @@ -0,0 +1,88 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/hwp/nest/p9_build_smp_adu.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2015,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file p9_build_smp_adu.H +/// @brief Interface for ADU operations required to support fabric +/// configuration actions (FAPI2) +/// +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// *HWP Consumed by: HB,FSP +/// + +#ifndef _P9_BUILD_SMP_ADU_H_ +#define _P9_BUILD_SMP_ADU_H_ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <fapi2.H> +#include <p9_build_smp.H> + +extern "C" { + +//------------------------------------------------------------------------------ +// Function prototypes +//------------------------------------------------------------------------------ + +/// +/// @brief Perform fabric C/D configuration switch on a single chip +/// +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_smp Structure encapsulating SMP topology +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_switch_cd(p9_build_smp_chip& i_smp_chip, + p9_build_smp_system& i_smp); + +/// +/// @brief Quiesce slave fabrics by issuing fabric quiesce operation on +/// specified chips +/// NOTE: ADU atomic lock will be obtained for all chips prior +/// to issuing quiesce operation on specified chips +/// +/// @param[in] i_smp Structure encapsulating SMP topology +/// @param[in] i_op Enumerated type representing SMP build phase +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_quiesce_pb(p9_build_smp_system& i_smp, + const p9_build_smp_operation i_op); + + +/// +/// @brief Perform fabric A/B configuration switch on all chips present in SMP +/// NOTE: ADU atomic lock will be obtained for all chips prior to +/// issuing switch from master chip (defined by i_master_smp_chip) +/// +/// @param[in] i_smp Structure encapsulating SMP topology +/// @param[in] i_op Enumerated type representing SMP build phase +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_switch_ab(p9_build_smp_system& i_smp, + const p9_build_smp_operation i_op); + + +} // extern "C" + +#endif // _P9_BUILD_SMP_ADU_H_ diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.C b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.C new file mode 100644 index 000000000..b51612afb --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.C @@ -0,0 +1,1197 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2015,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file p9_build_smp_fbc_ab.C +/// +/// @brief Fabric configuration (hotplug, AB) functions. +/// +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// *HWP Consumed by: HB,FSP +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <p9_build_smp_fbc_ab.H> +#include <p9_build_smp_adu.H> +#include <p9_fab_smp_utils.H> +#include <p9_build_smp_epsilon.H> +#include <p9_misc_scom_addresses.H> + +//------------------------------------------------------------------------------ +// Constant definitions +//------------------------------------------------------------------------------ + +// The start/end bits for each link in each link delay regs are the same +const uint32_t OPTIC_EVEN_LINK_DELAY_START_BIT[P9_FAB_SMP_NUM_OPTIC_LINKS] = +{ 4, 36, 4, 36 }; + +const uint32_t X_EVEN_LINK_DELAY_START_BIT[P9_FAB_SMP_NUM_X_LINKS] = +{ 4, 36, 4 }; + +// All link delays have same bit len +const uint32_t LINK_DELAY_BIT_LEN = 12; + +//------------------------------------------------------------------------------ +// Function definitions +//------------------------------------------------------------------------------ + +// See doxygen in header file +template<fapi2::TargetType T> +fapi2::ReturnCode p9_build_smp_query_link_state( + const p9_build_smp_chip& i_smp_chip, + const uint8_t i_source_link_id, + const fapi2::Target<T>& i_dest_target, + bool& o_link_is_enabled, + p9_fab_smp_node_id& o_dest_target_node_id, + p9_fab_smp_chip_id& o_dest_target_chip_id) +{ + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + if (fapi2::is_same<T, fapi2::TARGET_TYPE_XBUS>()) + { + FAPI_DBG("Bus type %s, SourceId %d", "X-BUS", i_source_link_id); + } + else if (fapi2::is_same<T, fapi2::TARGET_TYPE_OBUS>()) + { + FAPI_DBG("Bus type %s, SourceId %d", "O-BUS", i_source_link_id); + } + + // TODO: RTC 147511 - Need to set enabled/disabled based on ATTR_PG attributes. + if (i_dest_target.get() == NULL) + { + FAPI_DBG("No target link"); + o_link_is_enabled = false; + o_dest_target_node_id = FBC_NODE_ID_0; + o_dest_target_chip_id = FBC_CHIP_ID_0; + } + else + { + o_link_is_enabled = true; + + // Extract chip/node ID from destination chip + FAPI_TRY(p9_fab_smp_get_node_id_attr(i_dest_target, + o_dest_target_node_id), + "p9_fab_smp_get_node_id_attr() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + FAPI_TRY(p9_fab_smp_get_chip_id_attr(i_dest_target, + o_dest_target_chip_id), + "p9_fab_smp_get_chip_id_attr() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + +fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; +} + +/// +/// @brief Read PB Link Mode register and extract per-link training delays +/// +/// @tparam T template parameter, passed in target. +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_link_en Per-link enable values +/// @param[in] i_link_target Link endpoint targets +/// @param[out] o_link_delay_local Array of link round trip delay values +/// (measured by local chip) +/// @param[out] o_link_delay_remote Array of link round trip delay values +/// (measured by remote chips) +/// @param[out] o_link_number_remote Array of link numbers +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// +template<fapi2::TargetType T> +fapi2::ReturnCode p9_build_smp_get_link_delays( + const p9_build_smp_chip& i_smp_chip, + const bool i_link_en[], + fapi2::Target<T> i_link_target[], + uint16_t o_link_delay_local[], + uint16_t o_link_delay_remote[], + uint8_t o_link_number_remote[]); + +// Specialization for OBUS +template<> +fapi2::ReturnCode p9_build_smp_get_link_delays( + const p9_build_smp_chip& i_smp_chip, + const bool i_link_en[], + fapi2::Target<fapi2::TARGET_TYPE_OBUS> i_link_target[], + uint16_t o_link_delay_local[], + uint16_t o_link_delay_remote[], + uint8_t o_link_number_remote[]) +{ + FAPI_DBG("OBUS: Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> l_scomData; + + // Link delay values + fapi2::buffer<uint64_t> pu_ioe_olink_0123_delay; + fapi2::buffer<uint64_t> pu_ioe_olink_4567_delay; + fapi2::buffer<uint64_t> l_temp; + + // Read PB Link Mode registers on local chip + FAPI_TRY(fapi2::getScom(i_smp_chip.chip->this_chip, + PU_IOE_PB_OLINK_DLY_0123_REG, + pu_ioe_olink_0123_delay), + "OBUS: getScom error on addr 0x%.16llX", PU_IOE_PB_OLINK_DLY_0123_REG); + + FAPI_TRY(fapi2::getScom(i_smp_chip.chip->this_chip, + PU_IOE_PB_OLINK_DLY_4567_REG, + pu_ioe_olink_4567_delay), + "OBUS: getScom error on addr 0x%.16llX", PU_IOE_PB_OLINK_DLY_4567_REG); + + // TODO: RTC 147511 - Update link delay calculation methods + // Per Joe, we want to compute the link delay as the average of the + // even/odd numbers (same for X link) + + // Extract & return link training delays + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + if (!i_link_en[ll]) + { + o_link_delay_local[ll] = 0xFF; // Even + } + else + { + // Select data buffer to get delay values from + if (ll < 2) + { + l_temp = pu_ioe_olink_0123_delay; + } + else + { + l_temp = pu_ioe_olink_4567_delay; + } + + // Even + FAPI_TRY( l_temp.extractToRight(o_link_delay_local[ll], + OPTIC_EVEN_LINK_DELAY_START_BIT[ll], + LINK_DELAY_BIT_LEN), + "OBUS: l_temp.extractToRight() - OBUS/Even returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + // Process remote links + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + if (!i_link_en[ll]) + { + o_link_delay_remote[ll] = 0xFF; + } + else + { + uint8_t remote_link_number = 0x0; + + // Determine link number on remote end (equivalent to chiplet #) + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_link_target[ll], + remote_link_number), + "OBUS: Error querying ATTR_CHIP_UNIT_POS, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + o_link_number_remote[ll] = remote_link_number; + + // Obtain parent chip target + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procChip; + l_procChip = + i_link_target[ll].getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + // Read PB Link Mode registers on remote chip + FAPI_TRY(fapi2::getScom(l_procChip, + PU_IOE_PB_OLINK_DLY_0123_REG, + pu_ioe_olink_0123_delay), + "OBUS: getScom error on addr 0x%.16llX", PU_IOE_PB_OLINK_DLY_0123_REG); + + FAPI_TRY(fapi2::getScom(l_procChip, + PU_IOE_PB_OLINK_DLY_4567_REG, + pu_ioe_olink_4567_delay), + "OBUS: getScom error on addr 0x%.16llX", PU_IOE_PB_OLINK_DLY_4567_REG); + + // Select data buffer to get delay values from + if (remote_link_number < 2) + { + l_temp = pu_ioe_olink_0123_delay; + } + else + { + l_temp = pu_ioe_olink_4567_delay; + } + + // Even + FAPI_TRY( l_temp.extractToRight( + o_link_delay_remote[ll], + OPTIC_EVEN_LINK_DELAY_START_BIT[ll], + LINK_DELAY_BIT_LEN), + "OBUS: l_temp.extractToRight() - OBUS/Even/Remote returns an error, " + "l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + } + +fapi_try_exit: + FAPI_DBG("OBUS: End"); + return fapi2::current_err; +} + +// Specialization for XBUS +template<> +fapi2::ReturnCode p9_build_smp_get_link_delays( + const p9_build_smp_chip& i_smp_chip, + const bool i_link_en[], + fapi2::Target<fapi2::TARGET_TYPE_XBUS> i_link_target[], + uint16_t o_link_delay_local[], + uint16_t o_link_delay_remote[], + uint8_t o_link_number_remote[]) +{ + FAPI_DBG("XBUS: Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> l_scomData; + + // Link delay values + fapi2::buffer<uint64_t> pu_elink_0123_delay; + fapi2::buffer<uint64_t> pu_elink_45_delay; + fapi2::buffer<uint64_t> l_temp; + + // Read PB Link Mode registers on local chip + FAPI_TRY(fapi2::getScom(i_smp_chip.chip->this_chip, + PU_PB_ELINK_DLY_0123_REG, + pu_elink_0123_delay), + "XBUS: getScom error on addr 0x%.16llX", PU_PB_ELINK_DLY_0123_REG); + + FAPI_TRY(fapi2::getScom(i_smp_chip.chip->this_chip, + PU_PB_ELINK_DLY_45_REG, + pu_elink_45_delay), + "XBUS: getScom error on addr 0x%.16llX", PU_PB_ELINK_DLY_45_REG); + + // TODO: RTC 147511 - Update link delay calculation methods + // Per Joe, we want to compute the link delay as the average of the + // even/odd numbers (same for X link) + + // Extract & return link training delays + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + if (!i_link_en[ll]) + { + o_link_delay_local[ll] = 0xFF; // Even + } + else + { + // Select data buffer to get delay values from + if (ll < 2) + { + l_temp = pu_elink_0123_delay; + } + else + { + l_temp = pu_elink_45_delay; + } + + // Even + FAPI_TRY( l_temp.extractToRight(o_link_delay_local[ll], + X_EVEN_LINK_DELAY_START_BIT[ll], + LINK_DELAY_BIT_LEN), + "XBUS: l_temp.extractToRight() - XBUS/Even returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + // Process remote links + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + if (!i_link_en[ll]) + { + o_link_delay_remote[ll] = 0xFF; + } + else + { + uint8_t remote_link_number = 0x0; + + // Determine link number on remote end (equivalent to chiplet #) + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_link_target[ll], + remote_link_number), + "XBUS: Error querying ATTR_CHIP_UNIT_POS, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + o_link_number_remote[ll] = remote_link_number; + + // Obtain parent chip target + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procChip; + l_procChip = + i_link_target[ll].getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + // Read PB Link Mode registers on remote chip + FAPI_TRY(fapi2::getScom(l_procChip, + PU_PB_ELINK_DLY_0123_REG, + pu_elink_0123_delay), + "XBUS: getScom error on addr 0x%.16llX", PU_PB_ELINK_DLY_0123_REG); + + FAPI_TRY(fapi2::getScom(l_procChip, + PU_PB_ELINK_DLY_45_REG, + pu_elink_45_delay), + "OBUS: getScom error on addr 0x%.16llX", PU_PB_ELINK_DLY_45_REG); + + // Select data buffer to get delay values from + if (remote_link_number < 2) + { + l_temp = pu_elink_0123_delay; + } + else + { + l_temp = pu_elink_45_delay; + } + + // Even + FAPI_TRY( l_temp.extractToRight( + o_link_delay_remote[ll], + X_EVEN_LINK_DELAY_START_BIT[ll], + LINK_DELAY_BIT_LEN), + "XBUS: l_temp.extractToRight() - XBUS/Even/Remote returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + +fapi_try_exit: + FAPI_DBG("XBUS: End"); + return fapi2::current_err; +} + +/// +/// @brief Determine link address/data +/// +/// @tparam T template parameter, passed in target. +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_link_en Per-link enable values +/// @param[in] i_link_id Per-link destination chip/node ID values +/// @param[in] i_link_target Per-link destination targets +/// @param[out] o_link_addr_dis Per-link address disable values +/// (true=address only, false=address/data) +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// +template<fapi2::TargetType T> +fapi2::ReturnCode p9_build_smp_calc_link_setup( + const p9_build_smp_chip& i_smp_chip, + const bool i_link_en[], + const uint8_t i_link_id[], + fapi2::Target<T> i_link_target[], + bool o_link_addr_dis[]); + +// Specialization for OBUS +template<> +fapi2::ReturnCode p9_build_smp_calc_link_setup( + const p9_build_smp_chip& i_smp_chip, + const bool i_link_en[], + const uint8_t i_link_id[], + fapi2::Target<fapi2::TARGET_TYPE_OBUS> i_link_target[], + bool o_link_addr_dis[]) +{ + FAPI_DBG("OBUS: Start"); + fapi2::ReturnCode l_rc; + uint8_t l_idLocal = 0; + + // Mark number of links targeting each ID + uint8_t l_idActiveCount[P9_FAB_SMP_NUM_NODE_IDS]; + + // Link round trip delay values + uint16_t link_delay_local[P9_FAB_SMP_NUM_OPTIC_LINKS]; + uint16_t link_delay_remote[P9_FAB_SMP_NUM_OPTIC_LINKS]; + uint8_t link_number_remote[P9_FAB_SMP_NUM_OPTIC_LINKS]; + + // Init local arrays + for (uint8_t id = 0; id < P9_FAB_SMP_NUM_CHIP_IDS; id++) + { + l_idActiveCount[id] = 0; + } + + // Process all links + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + // Mark link ID + if (i_link_en[ll]) + { + l_idActiveCount[i_link_id[ll]]++; + } + + // Set default value for link address disable (enable coherency) + o_link_addr_dis[ll] = false; + } + + // Figure out if link is to carry data only (Address disabled) + for (uint8_t l_id = 0; l_id < P9_FAB_SMP_NUM_NODE_IDS; l_id++) + { + // Skip if not active + if (!l_idActiveCount[l_id]) + { + continue; + } + + // Flip default value for link address disable + // (disable coherency) + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + if (i_link_en[ll]) + { + o_link_addr_dis[ll] = true; + } + } + + // Select link with the lowest round trip latency value + // to carry coherency + FAPI_TRY(p9_build_smp_get_link_delays(i_smp_chip, + i_link_en, + i_link_target, + link_delay_local, + link_delay_remote, + link_number_remote), + "p9_build_smp_get_link_delays() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Debug trace + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + FAPI_DBG("Link[%d]):"); + FAPI_DBG(" link_delay_local: %d, link_delay_remote: %d, " + "link_number_remote: %d", ll, link_delay_local[ll], + link_delay_remote[ll], link_number_remote[ll]); + } + + // Sum local/remote delay factors & scan for smallest value + uint32_t link_delay_total[P9_FAB_SMP_NUM_OPTIC_LINKS]; + uint8_t coherent_link_index = 0xFF; + uint32_t coherent_link_delay = 0xFFFFFFFF; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + link_delay_total[ll] = link_delay_local[ll] + link_delay_remote[ll]; + + if ( i_link_en[ll] && + (link_delay_total[ll] < coherent_link_delay) ) + { + coherent_link_delay = link_delay_total[ll]; + FAPI_DBG("Setting coherent_link_delay = %d", coherent_link_delay); + } + } + + // Ties must be broken consistently on both connected chips + // search if a tie has occurred + uint8_t matches = 0; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + if (i_link_en[ll] && + (link_delay_total[ll] == coherent_link_delay)) + { + matches++; + coherent_link_index = ll; + } + } + + // If no ties, we're done + // else, break tie + + // Select link with lowest link number on chip with smaller ID + // (chip ID if X links, node ID if A links) + l_idLocal = i_smp_chip.node_id; + + if (matches != 1) + { + FAPI_DBG("Breaking tie"); + + if (l_idLocal < l_id) + { + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + if (i_link_en[ll] && + (link_delay_total[ll] == coherent_link_delay)) + { + coherent_link_index = ll; + break; + } + } + + FAPI_DBG("Selecting coherent link = link %d based on this chip (%d)", + coherent_link_index, l_idLocal); + } + else + { + uint8_t lowest_remote_link_number = 0xFF; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + if ((i_link_en[ll]) && + (link_delay_total[ll] == coherent_link_delay) && + (link_number_remote[ll] < lowest_remote_link_number)) + { + lowest_remote_link_number = link_number_remote[ll]; + coherent_link_index = ll; + } + } + + FAPI_DBG("Selecting coherent link = linkd %d based on remote chip ID (%d)", + coherent_link_index, l_id); + } + } + + o_link_addr_dis[coherent_link_index] = false; + } + +fapi_try_exit: + FAPI_DBG("OBUS: End"); + return fapi2::current_err; +} + +// Specialization for XBUS +template<> +fapi2::ReturnCode p9_build_smp_calc_link_setup( + const p9_build_smp_chip& i_smp_chip, + const bool i_link_en[], + const uint8_t i_link_id[], + fapi2::Target<fapi2::TARGET_TYPE_XBUS> i_link_target[], + bool o_link_addr_dis[]) +{ + FAPI_DBG("XBUS: Start"); + fapi2::ReturnCode l_rc; + uint8_t l_idLocal = 0; + + // Mark number of links targeting each ID + uint8_t l_idActiveCount[P9_FAB_SMP_NUM_CHIP_IDS]; + + // Link round trip delay values + uint16_t link_delay_local[P9_FAB_SMP_NUM_X_LINKS]; + uint16_t link_delay_remote[P9_FAB_SMP_NUM_X_LINKS]; + uint8_t link_number_remote[P9_FAB_SMP_NUM_X_LINKS]; + + // Init local arrays + for (uint8_t id = 0; id < P9_FAB_SMP_NUM_X_LINKS; id++) + { + l_idActiveCount[id] = 0; + } + + // Process all links + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + // Mark link ID + if (i_link_en[ll]) + { + l_idActiveCount[i_link_id[ll]]++; + } + + // Set default value for link address disable (enable coherency) + o_link_addr_dis[ll] = false; + } + + // Figure out if link is to carry data only (ADDR_DIS) + for (uint8_t l_id = 0; l_id < P9_FAB_SMP_NUM_CHIP_IDS; l_id++) + { + // Skip if not active + if (!l_idActiveCount[l_id]) + { + continue; + } + + // Flip default value for link address disable + // (disable coherency) + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + if (i_link_en[ll]) + { + o_link_addr_dis[ll] = true; + } + } + + // Select link with the lowest round trip latency value + // to carry coherency + FAPI_TRY(p9_build_smp_get_link_delays(i_smp_chip, + i_link_en, + i_link_target, + link_delay_local, + link_delay_remote, + link_number_remote), + "p9_build_smp_get_link_delays() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Debug trace + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + FAPI_DBG("Link[%d]):"); + FAPI_DBG(" link_delay_local: %d, link_delay_remote: %d, " + "link_number_remote: %d", ll, link_delay_local[ll], + link_delay_remote[ll], link_number_remote[ll]); + } + + // Sum local/remote delay factors & scan for smallest value + uint32_t link_delay_total[P9_FAB_SMP_NUM_X_LINKS]; + uint8_t coherent_link_index = 0xFF; + uint32_t coherent_link_delay = 0xFFFFFFFF; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + link_delay_total[ll] = link_delay_local[ll] + link_delay_remote[ll]; + + if ( i_link_en[ll] && + (link_delay_total[ll] < coherent_link_delay) ) + { + coherent_link_delay = link_delay_total[ll]; + FAPI_DBG("Setting coherent_link_delay = %d", coherent_link_delay); + } + } + + // Ties must be broken consistently on both connected chips + // search if a tie has occurred + uint8_t matches = 0; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + if (i_link_en[ll] && + (link_delay_total[ll] == coherent_link_delay)) + { + matches++; + coherent_link_index = ll; + } + } + + // If no ties, we're done + // else, break tie + + // Select link with lowest link number on chip with smaller ID + // (chip ID if X links, node ID if A links) + l_idLocal = i_smp_chip.chip_id; + + if (matches != 1) + { + FAPI_DBG("Breaking tie"); + + if (l_idLocal < l_id) + { + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + if (i_link_en[ll] && + (link_delay_total[ll] == coherent_link_delay)) + { + coherent_link_index = ll; + break; + } + } + + FAPI_DBG("Selecting coherent link = link %d based on this chip (%d)", + coherent_link_index, l_idLocal); + } + else + { + uint8_t lowest_remote_link_number = 0xFF; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + if ((i_link_en[ll]) && + (link_delay_total[ll] == coherent_link_delay) && + (link_number_remote[ll] < lowest_remote_link_number)) + { + lowest_remote_link_number = link_number_remote[ll]; + coherent_link_index = ll; + } + } + + FAPI_DBG("Selecting coherent link = linkd %d based on remote chip ID (%d)", + coherent_link_index, l_id); + } + } + + o_link_addr_dis[coherent_link_index] = false; + } + +fapi_try_exit: + FAPI_DBG("XBUS: End"); + return fapi2::current_err; +} + +extern "C" { + +// See doxygen in header file + fapi2::ReturnCode p9_build_smp_get_hotplug_curr_reg( + const p9_build_smp_chip& i_smp_chip, + const bool i_hp_not_hpx, + fapi2::buffer<uint64_t>& o_data) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> l_scomData; + + // Check consistency of west/center/east register copies + for (uint8_t rr = 0; rr < P9_BUILD_SMP_NUM_SHADOWS; rr++) + { + // Get current (working) register + uint64_t l_reg = i_hp_not_hpx ? PB_HP_MODE_CURR_SHADOWS[rr] : + PB_HPX_MODE_CURR_SHADOWS[rr]; + + FAPI_TRY(fapi2::getScom(i_smp_chip.chip->this_chip, l_reg, l_scomData), + "getScom returns error: Addr 0x%016llX, l_rc 0x%.8X", + l_reg, (uint64_t)fapi2::current_err); + + // Raise error if shadow copies aren't equal + FAPI_ASSERT( (rr == 0) || (l_scomData == o_data), + fapi2::PROC_BUILD_SMP_HOTPLUG_SHADOW_ERR() + .set_ADDRESS0((i_hp_not_hpx) ? (PB_HP_MODE_CURR_SHADOWS[rr - 1]) : + (PB_HPX_MODE_CURR_SHADOWS[rr - 1]) + ) + .set_ADDRESS1(l_reg) + .set_DATA0(o_data) + .set_DATA1(l_scomData), + "Shadow copies are not equivalent"); + + // Set output (will be used to compare with next HW read) + o_data = l_scomData; + } + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Program PB Hotplug Mode register +/// +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_smp Structure encapsulating SMP topology +/// @param[in] i_set_curr Set CURR register set? +/// @param[in] i_set_next Set NEXT register set? +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_set_pb_hp_mode( + const p9_build_smp_chip& i_smp_chip, + const p9_build_smp_system& i_smp, + const bool i_set_curr, + const bool i_set_next) + { + + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> l_scomData; + + // Set of per-link destination chip targets + fapi2::Target<fapi2::TARGET_TYPE_OBUS> o_target[P9_FAB_SMP_NUM_OPTIC_LINKS]; + // Per-link enables + bool o_en[P9_FAB_SMP_NUM_OPTIC_LINKS]; + // Per-link destination IDs + uint8_t o_id[P9_FAB_SMP_NUM_OPTIC_LINKS]; + // Per-link address disable values + bool o_addr_dis[P9_FAB_SMP_NUM_OPTIC_LINKS]; + + // TODO: RTC 147511 - Need to handle PCIE link + + // Process all optic links + o_target[0] = i_smp_chip.chip->o0_chip; + o_target[1] = i_smp_chip.chip->o1_chip; + o_target[2] = i_smp_chip.chip->o2_chip; + o_target[3] = i_smp_chip.chip->o2_chip; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_OPTIC_LINKS; ll++) + { + // Determine link enable/ID + p9_fab_smp_node_id dest_node_id; + p9_fab_smp_chip_id dest_chip_id; + FAPI_TRY(p9_build_smp_query_link_state(i_smp_chip, + ll, + o_target[ll], + o_en[ll], + dest_node_id, + dest_chip_id), + "p9_build_smp_query_link_state() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + o_id[ll] = (uint8_t) dest_node_id; + } + + // Determine address/data assignents + // link command rates (A) + if (i_smp_chip.o_enabled) + { + FAPI_TRY(p9_build_smp_calc_link_setup(i_smp_chip, + o_en, + o_id, + o_target, + o_addr_dis), + "p9_build_smp_calc_link_setup() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + // Set attributes + if (i_smp_chip.smpOpticsMode == + fapi2::ENUM_ATTR_PROC_FABRIC_SMP_OPTICS_MODE_OPTICS_IS_X_BUS) + { + uint8_t l_x_address_dis[P9_FAB_SMP_NUM_X_LINKS + + P9_FAB_SMP_NUM_OPTIC_LINKS]; + + // Optic is XBUS, write to X-LINK attribute + + // Read current values to preserve the first 3 values from XBUS + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_X_ADDR_DIS, + i_smp_chip.chip->this_chip, + l_x_address_dis), + "Error getting ATTR_PROC_FABRIC_X_ADDR_DIS, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Store optic addr_dis starting at index 3 + for (uint8_t ii = 0; ii < P9_FAB_SMP_NUM_OPTIC_LINKS; ii++) + { + l_x_address_dis[ii + P9_FAB_SMP_NUM_X_LINKS] = + o_addr_dis[ii] ? 1 : 0; + } + + // Write attribute back + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PROC_FABRIC_X_ADDR_DIS, + i_smp_chip.chip->this_chip, + l_x_address_dis), + "Error setting ATTR_PROC_FABRIC_X_ADDR_DIS, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + else + { + uint8_t l_a_address_dis[P9_FAB_SMP_NUM_OPTIC_LINKS]; + + for (uint8_t ii = 0; ii < P9_FAB_SMP_NUM_OPTIC_LINKS; ii++) + { + l_a_address_dis[ii] = o_addr_dis[ii] ? 1 : 0; + } + + // Optic is ABUS, write to A-LINK attribute + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PROC_FABRIC_A_ADDR_DIS, + i_smp_chip.chip->this_chip, + l_a_address_dis), + "Error setting ATTR_PROC_FABRIC_A_ADDR_DIS, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + // TODO: RTC 147511 - Call initfile + // Call initfile when available to re-program slave fabrics +#if 0 + + // Run initfile to set CURR (OBUS) + if (i_set_curr) + { + FAPI_TRY(p9_set_curr_initfile(), + "p9_set_curr_initfile() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + // Run initfile to set NEXT (OBUS) + if (i_set_next) + { + FAPI_TRY(p9_set_next_initfile(), + "p9_set_next_initfile() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + +#endif + + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Program PB Hotplug Extension Mode register +/// +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_smp Structure encapsulating SMP topology +/// @param[in] i_set_curr Set CURR register set? +/// @param[in] i_set_next Set NEXT register set? +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_set_pb_hpx_mode( + const p9_build_smp_chip& i_smp_chip, + const p9_build_smp_system& i_smp, + const bool i_set_curr, + const bool i_set_next) + { + + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> l_scomData; + + // set of per-link destination chip targets + fapi2::Target<fapi2::TARGET_TYPE_XBUS> x_target[P9_FAB_SMP_NUM_X_LINKS]; + // Per-link enables + bool x_en[P9_FAB_SMP_NUM_X_LINKS]; + // Per-link destination IDs + uint8_t x_id[P9_FAB_SMP_NUM_X_LINKS]; + // Per-link address disable values + bool x_addr_dis[P9_FAB_SMP_NUM_X_LINKS]; + + // Process all links + x_target[0] = i_smp_chip.chip->x0_chip; + x_target[1] = i_smp_chip.chip->x1_chip; + x_target[2] = i_smp_chip.chip->x2_chip; + + for (uint8_t ll = 0; ll < P9_FAB_SMP_NUM_X_LINKS; ll++) + { + // Determine link enable/ID + p9_fab_smp_node_id dest_node_id; + p9_fab_smp_chip_id dest_chip_id; + FAPI_TRY(p9_build_smp_query_link_state(i_smp_chip, + ll, + x_target[ll], + x_en[ll], + dest_node_id, + dest_chip_id), + "p9_build_smp_query_link_state() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + x_id[ll] = (uint8_t) dest_chip_id; + } + + // Determine address/data assignents + if (i_smp_chip.x_enabled) + { + FAPI_TRY(p9_build_smp_calc_link_setup(i_smp_chip, + x_en, + x_id, + x_target, + x_addr_dis), + "p9_build_smp_calc_link_setup() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + // Set attributes + uint8_t l_x_address_dis[P9_FAB_SMP_NUM_X_LINKS + + P9_FAB_SMP_NUM_OPTIC_LINKS]; + + // Read current values to preserve the settings for OBUS + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_X_ADDR_DIS, + i_smp_chip.chip->this_chip, + l_x_address_dis), + "Error getting ATTR_PROC_FABRIC_X_ADDR_DIS, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Store at first 3 indexes for XBUS targets + for (uint8_t ii = 0; ii < P9_FAB_SMP_NUM_X_LINKS; ii++) + { + l_x_address_dis[ii] = x_addr_dis[ii] ? 1 : 0; + } + + // Write attribute back + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PROC_FABRIC_X_ADDR_DIS, + i_smp_chip.chip->this_chip, + l_x_address_dis), + "Error setting ATTR_PROC_FABRIC_X_ADDR_DIS, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // TODO: RTC 147511 - Call initfile + // Call initfile when available to re-program slave fabrics +#if 0 + + // Run initfile to set CURR (XBUS) + if (i_set_curr) + { + FAPI_TRY(p9_set_curr_initfile(), + "p9_build_smp_set_pb_hp_mode: p9_set_curr_initfile() " + "returns an error, l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + + // Run initfile to set NEXT (XBUS) + if (i_set_next) + { + FAPI_TRY(p9_set_next_initfile(), + "p9_build_smp_set_pb_hp_mode: p9_set_next_initfile() " + "returns an error, l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + +#endif + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + + +/// +/// @brief Utility function to program set of PB hotplug registers +/// +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_curr_not_next Choose CURR/NEXT register set (true=CURR, +/// false=NEXT) +/// @param[in] i_hp_not_hpx Structure encapsulating SMP topology +/// @param[in] i_set_curr Choose HP/HPX register set (true=HP, +/// false=HPX) +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_set_hotplug_reg( + const p9_build_smp_chip& i_smp_chip, + const bool i_curr_not_next, + const bool i_hp_not_hpx, + const fapi2::buffer<uint64_t> i_data) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + uint64_t l_scomAddr; + + // write west/center/east register copies + for (uint8_t rr = 0; rr < P9_BUILD_SMP_NUM_SHADOWS; rr++) + { + // Set target scom address based on input parameters + if (i_curr_not_next) + { + if (i_hp_not_hpx) + { + l_scomAddr = PB_HP_MODE_CURR_SHADOWS[rr]; + } + else + { + l_scomAddr = PB_HPX_MODE_CURR_SHADOWS[rr]; + } + } + else + { + if (i_hp_not_hpx) + { + l_scomAddr = PB_HP_MODE_NEXT_SHADOWS[rr]; + } + else + { + l_scomAddr = PB_HPX_MODE_NEXT_SHADOWS[rr]; + } + } + + // Write register + FAPI_TRY(fapi2::putScom(i_smp_chip.chip->this_chip, l_scomAddr, i_data), + "putScom error, addr 0x%.16llX", l_scomAddr); + } + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Reset (copy CURR->NEXT) PB Hotplug Mode/Mode Extension register +/// +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_hp_not_hpx Structure encapsulating SMP topology +/// @param[in] i_set_curr Choose HP/HPX register set (true=HP, +/// false=HPX) +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_reset_hotplug_next_reg( + const p9_build_smp_chip& i_smp_chip, + const bool i_hp_not_hpx) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> l_scomData; + + // Read CURR state + FAPI_TRY(p9_build_smp_get_hotplug_curr_reg(i_smp_chip, + i_hp_not_hpx, + l_scomData), + "p9_build_smp_get_hotplug_curr_reg() Returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Write NEXT state + FAPI_TRY(p9_build_smp_set_hotplug_reg(i_smp_chip, + false, + i_hp_not_hpx, + l_scomData), + "p9_build_smp_set_hotplug_reg() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +// NOTE: see comments above function prototype in header + fapi2::ReturnCode p9_build_smp_set_fbc_ab(p9_build_smp_system& i_smp, + const p9_build_smp_operation i_op) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + // Chip/Node map iterators + std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator n_iter; + std::map<p9_fab_smp_chip_id, p9_build_smp_chip>::iterator p_iter; + + // Quiesce 'slave' fabrics in preparation for joining + // PHASE1 -> quiesce all chips except the chip which is the new fabric master + // PHASE2 -> quiesce all drawers except the drawer containing the new fabric master + FAPI_TRY(p9_build_smp_quiesce_pb(i_smp, i_op), + "p9_build_smp_quiesce_pb() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Program CURR register set only for chips which were just quiesced + // Program NEXT register set for all chips + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + FAPI_TRY(p9_build_smp_set_pb_hp_mode( + p_iter->second, i_smp, + p_iter->second.quiesced_next, // Set CURR + true), // Set NEXT + "p9_build_smp_set_pb_hp_mode() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + FAPI_TRY(p9_build_smp_set_pb_hpx_mode( + p_iter->second, i_smp, + p_iter->second.quiesced_next, // Set CURR + true), // Set NEXT + "p9_build_smp_set_pb_hpx_mode() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + // Issue switch AB reconfiguration from chip designated as new master + // (which is guaranteed to be a master now) + FAPI_TRY(p9_build_smp_switch_ab(i_smp, i_op), + "p9_build_smp_switch_ab() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Reset NEXT register set (copy CURR->NEXT) for all chips + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + + FAPI_TRY(p9_build_smp_reset_hotplug_next_reg(p_iter->second, true), + "p9_build_smp_reset_hotplug_next_reg(true) returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + FAPI_TRY(p9_build_smp_reset_hotplug_next_reg(p_iter->second, false), + "p9_build_smp_reset_hotplug_next_reg(false) returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + + +} // extern "C" diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.H b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.H new file mode 100644 index 000000000..3e74d663c --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.H @@ -0,0 +1,152 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/hwp/nest/p9_build_smp_fbc_ab.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2015,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file p9_build_smp_fbc_ab.H +/// @brief Fabric configuration (hotplug, AB) functions. +/// +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// *HWP Consumed by: HB,FSP +/// + +#ifndef _P9_BUILD_SMP_FBC_AB_H_ +#define _P9_BUILD_SMP_FBC_AB_H_ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <p9_build_smp.H> + +//------------------------------------------------------------------------------ +// Constant definitions +//------------------------------------------------------------------------------ +// PB Hotplug Mode register field/bit definitions +const uint32_t PB_HP_MODE_MASTER_CHIP_BIT = 0; +const uint32_t PB_HP_MODE_CHG_RATE_GP_MASTER_BIT = 2; + +// TODO: RTC 147511 - Use SCOM register names from p9_misc_scom_addresses.H +// Remove the reg addresses defined below and use the ones in +// p9_misc_scom_addresses.H when available. + +// HP +const uint64_t PB_HP_MODE_CURR_WEST = 0x0501180C; +const uint64_t PB_HP_MODE_CURR_CENT = 0x05011C0C; +const uint64_t PB_HP_MODE_CURR_EAST = 0x0501200C; +const uint64_t PB_HP_MODE_CURR_SHADOWS[P9_BUILD_SMP_NUM_SHADOWS] = +{ + PB_HP_MODE_CURR_WEST, + PB_HP_MODE_CURR_CENT, + PB_HP_MODE_CURR_EAST +}; + +const uint64_t PB_HP_MODE_NEXT_WEST = 0x0501180B; +const uint64_t PB_HP_MODE_NEXT_CENT = 0x05011C0B; +const uint64_t PB_HP_MODE_NEXT_EAST = 0x0501200B; +const uint32_t PB_HP_MODE_NEXT_SHADOWS[P9_BUILD_SMP_NUM_SHADOWS] = +{ + PB_HP_MODE_NEXT_WEST, + PB_HP_MODE_NEXT_CENT, + PB_HP_MODE_NEXT_EAST +}; + +// HPX +const uint64_t PB_HPX_MODE_CURR_WEST = 0x05011810; +const uint64_t PB_HPX_MODE_CURR_CENT = 0x05011C10; +const uint64_t PB_HPX_MODE_CURR_EAST = 0x05012010; +const uint32_t PB_HPX_MODE_CURR_SHADOWS[P9_BUILD_SMP_NUM_SHADOWS] = +{ + PB_HPX_MODE_CURR_WEST, + PB_HPX_MODE_CURR_CENT, + PB_HPX_MODE_CURR_EAST +}; + +const uint64_t PB_HPX_MODE_NEXT_WEST = 0x0501180F; +const uint64_t PB_HPX_MODE_NEXT_CENT = 0x05011C0F; +const uint64_t PB_HPX_MODE_NEXT_EAST = 0x0501200F; +const uint32_t PB_HPX_MODE_NEXT_SHADOWS[P9_BUILD_SMP_NUM_SHADOWS] = +{ + PB_HPX_MODE_NEXT_WEST, + PB_HPX_MODE_NEXT_CENT, + PB_HPX_MODE_NEXT_EAST +}; + +//------------------------------------------------------------------------------ +// Function definitions +//------------------------------------------------------------------------------ +/// +/// @brief Determine parameters of link/destination chip +/// +/// @tparam T template parameter, passed in target. +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_source_link_id Link identifier for FFDC +/// @param[in] i_dest_target Destination link endpoint target +/// @param[out] o_link_is_enabled true=link enabled, false=link disabled +/// @param[out] o_dest_target_node_id Node ID of destination chip +/// @param[out] o_dest_target_chip_id Chip ID of destination chip +/// +/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// +template<fapi2::TargetType T> +fapi2::ReturnCode p9_build_smp_query_link_state( + const p9_build_smp_chip& i_smp_chip, + const uint8_t i_source_link_id, + const fapi2::Target<T>& i_dest_target, + bool& o_link_is_enabled, + p9_fab_smp_node_id& o_dest_target_node_id, + p9_fab_smp_chip_id& o_dest_target_chip_id); + +extern "C" +{ + +//------------------------------------------------------------------------------ +// Function prototypes +//------------------------------------------------------------------------------ + +/// +/// @brief Utility function to read set of PB CURR hotplug registers +/// +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// topology +/// @param[in] i_hp_not_hpx Choose HP/HPX register set (true=HP, false=HPX) +/// @param[out] o_data Data buffer containing read data +/// +/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_get_hotplug_curr_reg( + const p9_build_smp_chip& i_smp_chip, + const bool i_hp_not_hpx, + fapi2::buffer<uint64_t>& o_data); + + +/// +/// @brief Program fabric configuration register (hotplug, A/B set) +/// +/// @param[in] i_smp Structure encapsulating SMP topology +/// @param[in] i_op Enumerated type representing SMP build phase +/// +/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_set_fbc_ab(p9_build_smp_system& i_smp, + const p9_build_smp_operation i_op); + +} // extern "C" + +#endif // _P9_BUILD_SMP_FBC_AB_H_ diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.C b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.C new file mode 100644 index 000000000..d6f88053f --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.C @@ -0,0 +1,103 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2015,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file p9_build_smp_fbc_cd.C +/// @brief Fabric configuration (hotplug, CD) functions +/// +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <p9_build_smp_fbc_cd.H> +#include <p9_build_smp_adu.H> + +extern "C" { + + +//------------------------------------------------------------------------------ +// Structure definitions +//------------------------------------------------------------------------------ + +// structure encapsulating serial configuration load programming + struct p9_build_smp_sconfig_def + { + uint8_t select; // ID/select for chain + uint8_t length; // number of bits to load + bool use_slow_clock; // use 16:1 slow clock? (EX) + bool use_shadow[P9_BUILD_SMP_NUM_SHADOWS]; // define which shadows to set + }; + + +//------------------------------------------------------------------------------ +// Constant definitions +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Function definitions +//------------------------------------------------------------------------------ + +// NOTE: see comments above function prototype in header + fapi2::ReturnCode p9_build_smp_set_fbc_cd(p9_build_smp_system& i_smp) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + // Chip/Node map iterators + std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator n_iter; + std::map<p9_fab_smp_chip_id, p9_build_smp_chip>::iterator p_iter; + + for (n_iter = i_smp.nodes.begin(); + n_iter != i_smp.nodes.end(); + ++n_iter) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + ++p_iter) + { + + // TODO: RTC 147511 - Call initfile + // Call initfile when available to program center/east/west chains + FAPI_DBG("Invoking initfile %s", + "TODO RTC 147511 - Replace with initfile name here"); +#if 0 + // Run initfile to program chains + FAPI_TRY(p9_build_smp_set_sconfig(p_iter->second), + "p9_build_smp_set_sconfig() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); +#endif + + // Issue single switch CD to force all updates to occur + FAPI_TRY(p9_build_smp_switch_cd(p_iter->second, i_smp), + "p9_build_smp_switch_cd returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + fapi_try_exit: + FAPI_INF("End"); + return fapi2::current_err; + } + +} // extern "C" diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.H b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.H new file mode 100644 index 000000000..d1d2ab054 --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.H @@ -0,0 +1,66 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: chips/p9/procedures/hwp/nest/p9_build_smp_fbc_cd.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* EKB Project */ +/* */ +/* COPYRIGHT 2015,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/// +/// @file p9_build_smp_fbc_cd.H +/// @brief Fabric configuration (hotplug, CD) functions +/// +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// + +#ifndef _P9_BUILD_SMP_FBC_CD_H_ +#define _P9_BUILD_SMP_FBC_CD_H_ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include <p9_build_smp.H> + +//------------------------------------------------------------------------------ +// Constant definitions +//------------------------------------------------------------------------------ + +// TODO: RTC 147511 - Use SCOM register names from p9_misc_scom_addresses.H +// Remove the reg addresses defined below and use the ones in +// p9_misc_scom_addresses.H when available. +const uint64_t PB_SCONFIG_LOAD_WEST = 0x05011811; +const uint64_t PB_SCONFIG_LOAD_CENT = 0x05011C11; +const uint64_t PB_SCONFIG_LOAD_EAST = 0x05012011; + +extern "C" +{ + +//------------------------------------------------------------------------------ +// Function prototypes +//------------------------------------------------------------------------------ + +/// +/// @brief Program fabric configuration register (hotplug, C/D set) +/// @param[in] i_smp Structure encapsulating SMP topology +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_set_fbc_cd(p9_build_smp_system& i_smp); + + +} // extern "C" + +#endif // _P9_BUILD_SMP_FBC_CD_H_ diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_build_smp_errors.xml b/src/import/chips/p9/procedures/xml/error_info/p9_build_smp_errors.xml new file mode 100644 index 000000000..ee1472c6d --- /dev/null +++ b/src/import/chips/p9/procedures/xml/error_info/p9_build_smp_errors.xml @@ -0,0 +1,233 @@ +<!-- IBM_PROLOG_BEGIN_TAG --> +<!-- This is an automatically generated prolog. --> +<!-- --> +<!-- $Source: chips/p9/procedures/xml/error_info/p9_build_smp_errors.xml $ --> +<!-- --> +<!-- IBM CONFIDENTIAL --> +<!-- --> +<!-- EKB Project --> +<!-- --> +<!-- COPYRIGHT 2015,2016 --> +<!-- [+] International Business Machines Corp. --> +<!-- --> +<!-- --> +<!-- The source code for this program is not published or otherwise --> +<!-- divested of its trade secrets, irrespective of what has been --> +<!-- deposited with the U.S. Copyright Office. --> +<!-- --> +<!-- IBM_PROLOG_END_TAG --> +<!-- File: p9_build_smp_errors.xml. --> +<!-- Error definitions for p9_build_smp HWP. --> + +<hwpErrors> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_CORE_FREQ_RANGE_ERR</rc> + <description>Invalid relationship between ceiling/nominal/floor core frequency attributes.</description> + <ffdc>FREQ_CORE_CEILING</ffdc> + <ffdc>FREQ_CORE_NOM</ffdc> + <ffdc>FREQ_CORE_FLOOR</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_P9_FAB_SMP_PUMP_MODE_ATTR_ERR</rc> + <description>Invalid definition for fabric pump mode attribute value.</description> + <ffdc>ATTR_DATA</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_P9_FAB_SMP_EPSILON_TABLE_TYPE_ATTR_ERR</rc> + <description>Invalid definition for epsilon table type attribute value.</description> + <ffdc>ATTR_DATA</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_CORE_FLOOR_FREQ_RATIO_ERR</rc> + <description>Unsupported core floor to PB frequency ratio.</description> + <ffdc>FREQ_PB</ffdc> + <ffdc>FREQ_CORE_FLOOR</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_CORE_CEILING_FREQ_RATIO_ERR</rc> + <description>Unsupported core ceiling to PB frequency ratio.</description> + <ffdc>FREQ_PB</ffdc> + <ffdc>FREQ_CORE_CEILING</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_FAB_SMP_FABRIC_GROUP_ID_ATTR_ERR</rc> + <description>Invalid definition for fabric group ID attribute value.</description> + <ffdc>TARGET</ffdc> + <ffdc>ATTR_DATA</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_FAB_SMP_FABRIC_CHIP_ID_ATTR_ERR</rc> + <description>Invalid definition for fabric chip ID attribute value.</description> + <ffdc>TARGET</ffdc> + <ffdc>ATTR_DATA</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_NODE_ADD_INTERNAL_ERR</rc> + <description>Internal Error. Error encountered adding node to SMP structure.</description> + <ffdc>TARGET</ffdc> + <ffdc>NODE_ID</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_DUPLICATE_FABRIC_ID_ERR</rc> + <description>Multiple chips found with identifcal fabric node/chip ID attribute values.</description> + <ffdc>TARGET1</ffdc> + <ffdc>TARGET2</ffdc> + <ffdc>NODE_ID</ffdc> + <ffdc>CHIP_ID</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_HOTPLUG_SHADOW_ERR</rc> + <description>Inconsistent state in hotplug (CURR) shadow copies.</description> + <ffdc>ADDRESS0</ffdc> + <ffdc>ADDRESS1</ffdc> + <ffdc>DATA0</ffdc> + <ffdc>DATA1</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_INVALID_OPERATION_ERR</rc> + <description>Unsupported SMP build operation presented.</description> + <ffdc>OP</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_MASTER_DESIGNATION_ERR</rc> + <description>Node or system master chip designation error.</description> + <ffdc>TARGET</ffdc> + <ffdc>OP</ffdc> + <ffdc>MASTER_CHIP_SYS_CURR</ffdc> + <ffdc>MASTER_CHIP_NODE_CURR</ffdc> + <ffdc>MASTER_CHIP_SYS_NEXT</ffdc> + <ffdc>MASTER_CHIP_NODE_NEXT</ffdc> + <ffdc>SYS_RECONFIG_MASTER_SET</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_NO_MASTER_SPECIFIED_ERR</rc> + <description>Input parameters do not specify a new fabric system master.</description> + <ffdc>OP</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_INVALID_TOPOLOGY</rc> + <description>Invalid fabric topology specified by input parameters.</description> + <ffdc>TARGET</ffdc> + <ffdc>A_CONNECTIONS_OK</ffdc> + <ffdc>A_CONNECTED_NODE_IDS</ffdc> + <ffdc>X_CONNECTIONS_OK</ffdc> + <ffdc>X_CONNECTED_CHIP_IDS</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_EPSILON_INVALID_TABLE_ERR</rc> + <description>Invalid epsilon table type or content detected.</description> + <ffdc>TABLE_TYPE</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_EPSILON_RANGE_ERR</rc> + <description>Target epsilon value exceeds maximum value supported by HW capabilities.</description> + <ffdc>VALUE</ffdc> + <ffdc>MAX_HW_VALUE</ffdc> + <ffdc>UNIT</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_PACING_RATE_TABLE_ERR</rc> + <description>Command rate pacing table lookup error.</description> + <ffdc>TARGET</ffdc> + <ffdc>GROUP_SIZE</ffdc> + <ffdc>NODE_ID</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PROC_BUILD_SMP_INVALID_GROUP_SIZE_ERR</rc> + <description>Invalid chips per group configuration detected.</description> + <ffdc>TARGET</ffdc> + <ffdc>GROUP_SIZE</ffdc> + <ffdc>NODE_ID</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>HIGH</priority> + </callout> + </hwpError> + +</hwpErrors> |