summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/hwas/common/hwas.C25
-rw-r--r--src/usr/hwas/hwasPlat.C213
-rw-r--r--src/usr/isteps/istep10/call_proc_cen_ref_clk_enable.C31
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
OpenPOWER on IntegriCloud