diff options
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/hwas/common/hwas.C | 25 | ||||
-rw-r--r-- | src/usr/hwas/hwasPlat.C | 213 | ||||
-rw-r--r-- | src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C | 31 |
3 files changed, 250 insertions, 19 deletions
diff --git a/src/usr/hwas/common/hwas.C b/src/usr/hwas/common/hwas.C index 45a88cf85..569061814 100644 --- a/src/usr/hwas/common/hwas.C +++ b/src/usr/hwas/common/hwas.C @@ -728,19 +728,23 @@ errlHndl_t discoverTargets() MOD_DISCOVER_TARGETS, RC_PARTIAL_GOOD_INFORMATION); - if( (pTarget->getAttr<ATTR_CLASS>() == CLASS_CHIP) && - (l_targetType != TYPE_TPM) && - (l_targetType != TYPE_SP) && - (l_targetType != TYPE_BMC) && - (l_targetType != TYPE_I2C_MUX)) + if( (pTarget->getAttr<ATTR_CLASS>() == CLASS_CHIP) + && (l_targetType != TYPE_TPM) + && (l_targetType != TYPE_SP) + && (l_targetType != TYPE_BMC) + && (l_targetType != TYPE_I2C_MUX) + && (l_targetType != TYPE_OCMB_CHIP)) { // read Chip ID/EC data from these physical chips errl = platReadIDEC(pTarget); if (errl) - { // read of ID/EC failed even tho we THOUGHT we were present. - HWAS_INF("pTarget %.8X - read IDEC failed (eid 0x%X) - bad", - errl->eid(), pTarget->getAttr<ATTR_HUID>()); + { + // read of ID/EC failed even tho we THOUGHT we were present. + HWAS_INF("pTarget 0x%.8X - read IDEC failed " + "(eid 0x%X) - bad", + get_huid(pTarget), errl->eid()); + // chip NOT present and NOT functional, so that FSP doesn't // include this for HB to process chipPresent = false; @@ -758,8 +762,9 @@ errlHndl_t discoverTargets() if (errl) { // read of PG failed even tho we were present.. - HWAS_INF("pTarget %.8X - read PG failed (eid 0x%X)- bad", - errl->eid(), pTarget->getAttr<ATTR_HUID>()); + HWAS_INF("pTarget 0x%.8X - read PG failed " + "(eid 0x%X) - bad", + get_huid(pTarget), errl->eid()); chipFunctional = false; errlEid = errl->eid(); diff --git a/src/usr/hwas/hwasPlat.C b/src/usr/hwas/hwasPlat.C index bea5b4d8f..543814d82 100644 --- a/src/usr/hwas/hwasPlat.C +++ b/src/usr/hwas/hwasPlat.C @@ -50,6 +50,9 @@ #include <config.h> #include <targeting/common/targetservice.H> #include <chipids.H> +#include <vpd/spdenums.H> + +#include <map> #ifdef CONFIG_SUPPORT_EEPROM_CACHING #include <i2c/eepromif.H> @@ -234,6 +237,28 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WRITE, TARGETING::TYPE_MEMBUF, cfamIDEC); +/* @brief A helper function used to convert the contents of the IDEC register + * to the CFAM ID format. + * + * @param[in] i_idec The contents of the IDEC register + * + * @return uint64_t The converted result. + */ +uint64_t formatOcmbIdecToCfamStandard(const uint64_t i_idec) +{ + uint64_t convertedIdec = 0; + + // Need to convert register contents from Mm0L00CC to MLmCC000 + uint32_t idec = static_cast<uint32_t>(i_idec); + uint32_t major = 0xF0000000 & idec; + uint32_t minor = 0x0F000000 & idec; + uint32_t location = 0x000F0000 & idec; + convertedIdec = (major | (location << 8) | (minor >> 4) + | ((idec & 0x000000FF) << 12)); + + return convertedIdec; +} + errlHndl_t ocmbIDEC(DeviceFW::OperationType i_opType, TARGETING::Target* i_target, void* io_buffer, @@ -241,16 +266,188 @@ errlHndl_t ocmbIDEC(DeviceFW::OperationType i_opType, int64_t i_accessType, va_list i_args) { - // for now just hardcode the answer to something explicitly invalid - uint8_t l_ec = INVALID__ATTR_EC; - i_target->setAttr<TARGETING::ATTR_EC>(l_ec); - i_target->setAttr<TARGETING::ATTR_HDAT_EC>(l_ec); + //@fixme when we know what register to read the IDEC from. + const uint16_t OCMB_IDEC_REGISTER = 0x2134; + + uint64_t idec = 0; + size_t op_size = sizeof(idec); + errlHndl_t error = nullptr; + + // Read the ID/EC + error = DeviceFW::deviceRead(i_target, + &idec, + op_size, + DEVICE_SCOM_ADDRESS(OCMB_IDEC_REGISTER)); + + do { + + if (error != nullptr) + { + HWAS_ERR("ocmbIDEC> OCMB 0x%.8X - failed to read ID/EC", + TARGETING::get_huid(i_target)); + + break; + } + + assert(op_size == sizeof(idec), "ocmbIDEC> Size returned from OCMB " + "IDEC read size %d not the expected size %d", + op_size, sizeof(idec)); + + idec = formatOcmbIdecToCfamStandard(idec); + + uint8_t ec = POWER_CHIPID::extract_ddlevel(idec); + uint32_t id = POWER_CHIPID::extract_chipid16(idec); + + HWAS_DBG("ocmbIDEC> OCMB 0x%.8X - read ID/EC successful. " + "ID = 0x%.4X, EC = 0x%.2X, Full IDEC 0x%x", + TARGETING::get_huid(i_target), + id, + ec, + idec); + + // Verify the OCMB ID is an expected value - // we can assume this is an Explorer chip though - uint32_t l_id = POWER_CHIPID::EXPLORER_16; - i_target->setAttr<TARGETING::ATTR_CHIP_ID>(l_id); + // Allocate buffer to hold SPD and init to 0 + size_t spdBufferSize = SPD::OCMB_SPD_EFD_COMBINED_SIZE; + uint8_t* spdBuffer = new uint8_t[spdBufferSize]; + memset(spdBuffer, 0, spdBufferSize); + + // Read the full SPD. + error = deviceRead(i_target, + spdBuffer, + spdBufferSize, + DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD)); + + // If unable to retrieve the SPD buffer then can't + // extract the IDEC data, so return error. + if (error) + { + HWAS_ERR("ocmbIDEC> Error while trying to read " + "ENTIRE SPD from 0x%.08X ", + TARGETING::get_huid(i_target)); + break; + } + + // Make sure we got back the size we were expecting. + assert(spdBufferSize == SPD::OCMB_SPD_EFD_COMBINED_SIZE, + "ocmbIDEC> OCMB SPD read size %d " + "doesn't match the expected size %d", + spdBufferSize, + SPD::OCMB_SPD_EFD_COMBINED_SIZE); + + // SPD IDEC info is in the following three bytes + const size_t SPD_ID_LEAST_SIGNIFICANT_BYTE_OFFSET = 198; + const size_t SPD_ID_MOST_SIGNIFICANT_BYTE_OFFSET = 199; + const size_t SPD_EC_OFFSET = 200; + + // Get the ID from the SPD and verify that it matches what we read from + // the IDEC register. + uint16_t spdId = 0; + + spdId = TWO_UINT8_TO_UINT16( + *(spdBuffer + SPD_ID_MOST_SIGNIFICANT_BYTE_OFFSET), + *(spdBuffer + SPD_ID_LEAST_SIGNIFICANT_BYTE_OFFSET)); + + uint8_t spdEc = *(spdBuffer + SPD_EC_OFFSET); + + // This map will hold the associated values between what is read from + // the OCMB's IDEC register and the SPD since they use different + // standards and thus cannot be directly compared. + // @TODO RTC 205563 Fix Gemini info when it is known. + const uint32_t GEMINI_ID = 0x20D2; + const uint32_t GEMINI_SPD_ID = 0x80A4; + const uint32_t GEMINI_EC = 0x0000; + const uint32_t GEMINI_SPD_EC = 0x0000; + const uint32_t EXPLORER_SPD_ID = 0x2980; + const uint32_t EXPLORER_EC = 0x0010; + const uint32_t EXPLORER_SPD_EC = 0x0000; + const std::map<uint32_t, uint32_t> OCMB_ID_SPD_ASSOCIATION_MAP + { + {POWER_CHIPID::EXPLORER_16, EXPLORER_SPD_ID}, + {GEMINI_ID, GEMINI_SPD_ID}, + }; + + const std::map<uint32_t, uint32_t> OCMB_EC_SPD_ASSOCIATION_MAP + { + {EXPLORER_EC, EXPLORER_SPD_EC}, + {GEMINI_EC, GEMINI_SPD_EC}, + }; + + auto id_it = OCMB_ID_SPD_ASSOCIATION_MAP.find(id); + auto ec_it = OCMB_EC_SPD_ASSOCIATION_MAP.find(ec); + + if (( id_it == OCMB_ID_SPD_ASSOCIATION_MAP.end()) + || ec_it == OCMB_EC_SPD_ASSOCIATION_MAP.end()) + { + HWAS_ERR("ocmbIDEC> Unexpected ID/EC value."); + + /*@ + * @errortype + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_OCMB_IDEC + * @reasoncode RC_OCMB_UNEXPECTED_IDEC + * @userdata1[00:31] ID (Chip ID) + * @userdata1[32:63] EC (Revision) + * @userdata2 HUID of OCMB target + * @devdesc The IDEC values read from the OCMB did not + * appear in the IDEC to SPD association map. + * Please update the map with new values. + * @custdesc Firmware Error + */ + error = hwasError(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_OCMB_IDEC, + RC_OCMB_UNEXPECTED_IDEC, + TWO_UINT32_TO_UINT64(id, ec), + TARGETING::get_huid(i_target)); + + break; + + } + + if ((id_it->second != spdId) || (ec_it->second != spdEc)) + { + HWAS_ERR("ocmbIDEC> OCMB IDEC and associated SPD IDEC don't match: " + "OCMB ID=0x%.4X, EC=0x%.2X; SPD ID=0x%.4X, EC=0x%.2X; " + "Expected SPD ID=0x%.4X, EC=0x%.2X", + id, ec, spdId, spdEc, id_it->second, ec_it->second); + + uint32_t bothIds = TWO_UINT16_TO_UINT32(id, spdId); + uint32_t bothEcs = TWO_UINT16_TO_UINT32(ec, spdEc); + + /*@ + * @errortype + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_OCMB_IDEC + * @reasoncode RC_OCMB_SPD_IDEC_MISMATCH + * @userdata1[00:15] OCMB ID from device read + * @userdata1[16:31] SPD ID from device read + * @userdata1[32:47] OCMB EC from device read + * @userdata1[48:63] SPD EC from device read + * @userdata2 HUID of OCMB target + * @devdesc The IDEC info read from the OCMB and SPD + * did not match the expected values. + * @custdesc Firmware Error + */ + error = hwasError(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_OCMB_IDEC, + RC_OCMB_SPD_IDEC_MISMATCH, + TWO_UINT32_TO_UINT64(bothIds, bothEcs), + TARGETING::get_huid(i_target)); + + break; + + } + + // set the explorer chip EC attributes. + i_target->setAttr<TARGETING::ATTR_EC>(ec); + i_target->setAttr<TARGETING::ATTR_HDAT_EC>(ec); + + // set the explorer chip id attribute. + i_target->setAttr<TARGETING::ATTR_CHIP_ID>(id); + + } while(0); - return nullptr; + return error; } // Register the presence detect function with the device framework diff --git a/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C b/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C index 67a11b775..627b5803d 100644 --- a/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C +++ b/src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C @@ -1086,8 +1086,37 @@ void* call_proc_cen_ref_clk_enable(void *io_pArgs ) else { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, - "SUCCESS : exp_check_for_ready" + "SUCCESS : exp_check_for_ready " "completed ok"); + + size_t size = 0; + + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "Read IDEC from OCMB 0x%.8X", + TARGETING::get_huid(l_ocmb)); + + // This write gets translated into a read of the explorer chip + // in the device driver. First, a read of the chip's IDEC + // register occurs then ATTR_EC, ATTR_HDAT_EC, and ATTR_CHIP_ID + // are set with the values found in that register. So, this + // deviceWrite functions more as a setter for an OCMB target's + // attributes. + l_errl = DeviceFW::deviceWrite(l_ocmb, + nullptr, + size, + DEVICE_IDEC_ADDRESS()); + if (l_errl) + { + // read of ID/EC failed even though we THOUGHT we were + // present. + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "OCMB 0x%.8X - read IDEC failed (eid 0x%X) - bad", + TARGETING::get_huid(l_ocmb), l_errl->eid()); + + // commit the error but keep going + errlCommit(l_errl, HWAS_COMP_ID); + // l_errl is now nullptr + } } } #endif |