diff options
author | Christian Geddes <crgeddes@us.ibm.com> | 2019-01-15 09:47:31 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2019-02-13 14:41:48 -0600 |
commit | aa18e987116a8e03391473c488d0ddb1d5ea8eb5 (patch) | |
tree | c03228ca69f31fcdf26a84f4cf15e1eb736b5164 | |
parent | b9678e8f9164c44361614e50cf02b6e31c860303 (diff) | |
download | blackbird-hostboot-aa18e987116a8e03391473c488d0ddb1d5ea8eb5.tar.gz blackbird-hostboot-aa18e987116a8e03391473c488d0ddb1d5ea8eb5.zip |
Add EEPROM caching device op
This commit introduces a new EEPROM_CACHE deviceOp and registers
the OCMB_CHIP, PROC, and DIMM targets to it. This is part of the
larger effort to transition for a "VPD" cache to an "EEPROM" cache
in pnor. The deviceOp is currently called in hwasPlat's
platPresenceDetect if the target in question has a
ATTR_EEPROM_VPD_PRIMARY_INFO associated with it. The layout for the
new EECACHE section in pnor is defined in eepromCache_const.H.
Essentially it is a header that contains an array of record headers
that tell where in the EECACHE pnor section a given cached EEPROM
can be found. All EEPROM targets will be allocated space in the
EECACHE section but only present targets will have their cache
filled in.
RTC: 196805
Change-Id: I49c341c9784be04ddf0259bd444f06c9baf8c6f1
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/70520
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Matt Derksen <mderkse1@us.ibm.com>
Reviewed-by: Roland Veloz <rveloz@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r-- | src/HBconfig | 7 | ||||
-rw-r--r-- | src/build/configs/simics_axone.config | 4 | ||||
-rw-r--r-- | src/include/usr/devicefw/userif.H | 56 | ||||
-rw-r--r-- | src/include/usr/i2c/eepromCache_const.H | 73 | ||||
-rw-r--r-- | src/include/usr/i2c/i2creasoncodes.H | 8 | ||||
-rw-r--r-- | src/usr/hwas/hwasPlat.C | 17 | ||||
-rw-r--r-- | src/usr/i2c/eepromCache.C | 540 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 245 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.H | 6 | ||||
-rw-r--r-- | src/usr/i2c/errlud_i2c.C | 2 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.H | 1 | ||||
-rw-r--r-- | src/usr/i2c/makefile | 1 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/simics_AXONE.system.xml | 208 |
13 files changed, 994 insertions, 174 deletions
diff --git a/src/HBconfig b/src/HBconfig index 72a4c0a45..8b2c5e407 100644 --- a/src/HBconfig +++ b/src/HBconfig @@ -54,7 +54,14 @@ config SUPPORT_PARTIAL_CACHE Support chips that do not have full cache -- intended for early bringup of hardware + config AXONE_BRING_UP default n help Only enable for Axone bringup, will be removed eventually + +config SUPPORT_EEPROM_CACHING + default n + help + If enabled will read data off eeproms and cache in PNOR's + EECACHE section.
\ No newline at end of file diff --git a/src/build/configs/simics_axone.config b/src/build/configs/simics_axone.config index 206d65e49..1a9ff72b6 100644 --- a/src/build/configs/simics_axone.config +++ b/src/build/configs/simics_axone.config @@ -6,4 +6,6 @@ unset IPLTIME_CHECKSTOP_ANALYSIS #Try to keep a list of things this does # - skipping setting voltages in istep 8.12, nothing on other side of AVSbus # in simics currently. -set AXONE_BRING_UP
\ No newline at end of file +set AXONE_BRING_UP + +set SUPPORT_EEPROM_CACHING
\ No newline at end of file diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H index cf00cfee1..523537cfb 100644 --- a/src/include/usr/devicefw/userif.H +++ b/src/include/usr/devicefw/userif.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -49,29 +49,30 @@ namespace DeviceFW enum AccessType { - SCOM = 0, // SCOM registers - PNOR, // PNOR flash - MAILBOX, // FSP mailbox - PRESENT, // Presence detection - FSI, // FSI/CFAM registers - SPD, // Serial Presence Detect Data for JEDEC DIMMs - MVPD, // Module (processor) VPD - CVPD, // Centaur (memory buffer) VPD - SCAN, // Scan rings - EEPROM, // Standard EEPROM/SEEPROM over i2c - GPIO, // GPIO registers - LPC, // Low Pin Count bus - IPMIBT, // As opposed to other phy's - PVPD, // Planar VPD - TPM, // Trusted Platform Module - SIO, // BMC Super I/O registers - AHB_SIO, // AST Hostbridge via SIO - DVPD, // Direct access memory VPD - NODECOMM, // Internode communication - NVDIMM, // Non-volatile DIMM controller access - FAPI_I2C, // FAPI2-triggered i2c accesses - MMIO, // Memory Mapped I/O - IDEC, // Read and set EC and CHIPID values + SCOM = 0, // SCOM registers + PNOR, // PNOR flash + MAILBOX, // FSP mailbox + PRESENT, // Presence detection + FSI, // FSI/CFAM registers + SPD, // Serial Presence Detect Data for JEDEC DIMMs + MVPD, // Module (processor) VPD + CVPD, // Centaur (memory buffer) VPD + SCAN, // Scan rings + EEPROM, // Standard EEPROM/SEEPROM over i2c + GPIO, // GPIO registers + LPC, // Low Pin Count bus + IPMIBT, // As opposed to other phy's + PVPD, // Planar VPD + TPM, // Trusted Platform Module + SIO, // BMC Super I/O registers + AHB_SIO, // AST Hostbridge via SIO + DVPD, // Direct access memory VPD + NODECOMM, // Internode communication + NVDIMM, // Non-volatile DIMM controller access + FAPI_I2C, // FAPI2-triggered i2c accesses + MMIO, // Memory Mapped I/O + IDEC, // Read and set EC and CHIPID values + EEPROM_CACHE, // Read EEPROM over I2C and write to PNOR LAST_ACCESS_TYPE, }; @@ -124,6 +125,13 @@ namespace DeviceFW #define DEVICE_PRESENT_ADDRESS() \ DeviceFW::PRESENT + /** Construct the device addressing parameters for the EEPROM_CACHE device ops. + * @param[in] i_present indicates if target is present or not. + * @param[in] i_eepromType indicates which EEPROM we wish to cache (PRIMARY/BACKUP etc) + */ + #define DEVICE_CACHE_EEPROM_ADDRESS(i_present, i_eepromType) \ + DeviceFW::EEPROM_CACHE, static_cast<uint64_t>((i_present)), static_cast<uint64_t>((i_eepromType)) + /** * Construct a PNOR DD address * address = 0000_0000_0000_000c_aaaa_aaaa_aaaa_aaaa diff --git a/src/include/usr/i2c/eepromCache_const.H b/src/include/usr/i2c/eepromCache_const.H new file mode 100644 index 000000000..e94798b79 --- /dev/null +++ b/src/include/usr/i2c/eepromCache_const.H @@ -0,0 +1,73 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/i2c/eepromCache_const.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2019 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef EEPROM_CACHE_CONST_H +#define __EEPROM_CACHE_CONST_H + +constexpr uint8_t MAX_EEPROMS_VERSION_1 = 50; +constexpr uint8_t INVALID_EEPROM_INDEX = 0xFF; +constexpr uint32_t UNSET_INTERNAL_OFFSET_VALUE = 0xFFFFFFFF; +constexpr uint32_t UNSET_END_OF_CACHE_VALUE = UNSET_INTERNAL_OFFSET_VALUE; + +enum EECACHE_VERSION +{ + EECACHE_VERSION_UNSET = 0xFF, + EECACHE_VERSION_1 = 0x01, + EECACHE_VERSION_LATEST = EECACHE_VERSION_1, +}; + +enum EEPROM_ATTRIBUTE_MASK : uint8_t +{ + HAS_EEPROM_NV_INFO = 0x01, + HAS_EEPROM_SBE_BACKUP_INFO = 0x02, + HAS_EEPROM_SBE_PRIMARY_INFO = 0x04, + HAS_EEPROM_VPD_BACKUP_INFO = 0x08, + HAS_EEPROM_VPD_PRIMARY_INFO = 0x10, +}; + + +struct eepromRecordHeader +{ + uint32_t target_huid; + uint8_t port; + uint8_t engine; + uint8_t devAddr; + uint32_t mux_huid; + uint8_t mux_select; + uint32_t record_size; + uint32_t internal_offset; + uint8_t record_valid; +} PACKED ; + //record_size // internal_offset //record_valid +constexpr size_t RECORD_COMPARE_SIZE = sizeof(eepromRecordHeader) - sizeof(uint32_t) - sizeof(uint32_t) - sizeof(uint8_t); + +struct eecacheSectionHeader +{ + uint8_t version; + uint32_t end_of_cache; + eepromRecordHeader recordHeaders[MAX_EEPROMS_VERSION_1]; +} PACKED ; + + +#endif
\ No newline at end of file diff --git a/src/include/usr/i2c/i2creasoncodes.H b/src/include/usr/i2c/i2creasoncodes.H index 6b08aefc2..a723e4ec8 100644 --- a/src/include/usr/i2c/i2creasoncodes.H +++ b/src/include/usr/i2c/i2creasoncodes.H @@ -66,6 +66,8 @@ enum i2cModuleId READ_I2C_ATTRIBUTES = 0x10, I2C_ACCESS_MUX = 0x11, I2C_GENERIC_PRES_DETECT = 0x12, + I2C_CACHE_EEPROM = 0x13, + I2C_CLEAR_EECACHE = 0x14, }; @@ -101,7 +103,11 @@ enum i2cReasonCode I2C_MUX_TARGET_NON_FUNCTIONAL = I2C_COMP_ID | 0x15, // The MUX target is non functional I2C_INVALID_LENGTH = I2C_COMP_ID | 0x16, // Invalid data buffer length passed to function I2C_NULL_MASTER_TARGET = I2C_COMP_ID | 0x17, // Target Service's toPath() returned nullptr for target -}; + I2C_FAILED_TO_FLUSH_CONTENTS = I2C_COMP_ID | 0x18, // Error occured while trying to flush the mmio pages out + // containing contents of an EEPROM's cached data in the EECACHE + // PNOR section + I2C_FAILED_TO_FLUSH_HEADER = I2C_COMP_ID | 0x19, // Error occured while trying to flush the mmio page out +}; // containing EECACHE header the to pnor enum UserDetailsTypes diff --git a/src/usr/hwas/hwasPlat.C b/src/usr/hwas/hwasPlat.C index 35e9588e0..e72d5109e 100644 --- a/src/usr/hwas/hwasPlat.C +++ b/src/usr/hwas/hwasPlat.C @@ -48,9 +48,12 @@ #include <fsi/fsiif.H> #include <config.h> #include <targeting/common/targetservice.H> - #include <chipids.H> +#ifdef CONFIG_SUPPORT_EEPROM_CACHING +#include <i2c/eepromif.H> +#endif + namespace HWAS { @@ -615,6 +618,18 @@ errlHndl_t platPresenceDetect(TargetHandleList &io_targets) // erase this target, and 'increment' to next pTarget_it = io_targets.erase(pTarget_it); } +#ifdef CONFIG_SUPPORT_EEPROM_CACHING + TARGETING::EepromVpdPrimaryInfo eepromData; + if (pTarget->tryGetAttr<ATTR_EEPROM_VPD_PRIMARY_INFO>(eepromData)) + { + HWAS_INF( "Reading EEPROMs for target, eeprom type = %d , target present = %d , eeprom type = %d", + DEVICE_CACHE_EEPROM_ADDRESS(present, EEPROM::VPD_PRIMARY)); + errl = deviceRead(pTarget, &present, presentSize, + DEVICE_CACHE_EEPROM_ADDRESS(present, EEPROM::VPD_PRIMARY)); + errlCommit(errl, HWAS_COMP_ID); + // errl is now null, move on to next target + } +#endif } // for pTarget_it return errl; diff --git a/src/usr/i2c/eepromCache.C b/src/usr/i2c/eepromCache.C new file mode 100644 index 000000000..72541df33 --- /dev/null +++ b/src/usr/i2c/eepromCache.C @@ -0,0 +1,540 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/i2c/eepromCache.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <builtins.h> +#include <devicefw/driverif.H> +#include "eepromdd.H" +#include <errl/errlmanager.H> +#include <fsi/fsiif.H> +#include "i2c.H" +#include <i2c/i2cif.H> +#include <i2c/eepromif.H> +#include <i2c/i2creasoncodes.H> +#include <i2c/eepromCache_const.H> +#include <initservice/initserviceif.H> +#include <initservice/initsvcreasoncodes.H> +#include <sys/mm.h> +#include <limits.h> +#include <pnor/pnorif.H> +#include <stdarg.h> +#include <vpd/vpd_if.H> + +extern trace_desc_t* g_trac_i2c; + +// #define TRACSSCOMP(args...) TRACFCOMP(args) +#define TRACSSCOMP(args...) + +namespace I2C +{ + +uint64_t g_eecachePnorVaddr; +uint64_t g_eecachePnorSize; + +mutex_t g_eecacheMutex = MUTEX_INITIALIZER; + +/** + * @brief Write all 0xFFs to the EECACHE section in pnor to clear out the + * eeprom cache information. + * @return errlHndl_t + */ +errlHndl_t clearEEcache() +{ + errlHndl_t l_errl = nullptr; + + memset(reinterpret_cast<void *>(g_eecachePnorVaddr), 0xFF, g_eecachePnorSize); + + // Flush the page to make sure it gets to the PNOR + int rc = mm_remove_pages( FLUSH, reinterpret_cast<void *>(g_eecachePnorVaddr), g_eecachePnorSize ); + + + if( rc ) + { + TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush contents write to pnor! rc=%d",rc); + /*@ + * @errortype + * @moduleid I2C_CLEAR_EECACHE + * @reasoncode I2C_FAILED_TO_FLUSH_CONTENTS + * @userdata1 Requested Address + * @userdata2 rc from mm_remove_pages + * @devdesc clearEEcache mm_remove_pages FLUSH failed + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + I2C_CLEAR_EECACHE, + I2C_FAILED_TO_FLUSH_CONTENTS, + (uint64_t)g_eecachePnorVaddr, + TO_UINT64(rc), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + l_errl->collectTrace(I2C_COMP_NAME); + } + return l_errl; +} + +/** + * @brief Lookup I2C information for given eeprom, check if eeprom exists in cache. + * If it exists already determine if any updates are required. If it is not + * in the cache yet, add it to the cache. + * + * @param[in] i_target Presence detect target + * @param[in] i_present Describes whether or not target is present + * ( CANNOT RELY ON HWAS_STATE!! ) + * @param[in] i_eepromType Describes which EEPROM associated to the target + * that is being requested to cache. (PRIMARY/BACKUP etc) + * @return errlHndl_t + */ +errlHndl_t cacheEeprom(TARGETING::Target* i_target, + bool i_present, + EEPROM::eeprom_chip_types_t i_eepromType) +{ + TRACSSCOMP( g_trac_i2c, "cacheEeprom() ENTER Target HUID 0x%.08X ", TARGETING::get_huid(i_target)); + errlHndl_t l_errl = nullptr; + TARGETING::Target * l_muxTarget = nullptr; + TARGETING::Target * l_i2cMasterTarget = nullptr; + TARGETING::TargetService& l_targetService = TARGETING::targetService(); + + EEPROM::eeprom_addr_t l_eepromInfo; + eecacheSectionHeader * l_eecacheSectionHeaderPtr; + + // Initially assume we will want to update both the entry in the header + // as well as the contents in the body of the EECACHE section + bool l_updateHeader = true; + bool l_updateContents = true; + + do{ + // eepromReadAttributes keys off the eepromRole value + // to determine what attribute to lookup to get eeprom info + l_eepromInfo.eepromRole = i_eepromType; + + l_errl = eepromReadAttributes(i_target, l_eepromInfo); + if(l_errl) + { + TRACFCOMP( g_trac_i2c, + "cacheEeprom() error occured reading eeprom attributes for eepromType %d, target 0x%.08X, returning!!", + i_eepromType, + TARGETING::get_huid(i_target)); + l_errl->collectTrace(I2C_COMP_NAME); + break; + } + + // Grab the I2C mux target so we can read the HUID, if the target is NULL we will not be able + // to lookup attribute to uniquely ID this eeprom so we will not cache it + l_muxTarget = l_targetService.toTarget( l_eepromInfo.i2cMuxPath); + if(l_muxTarget == nullptr) + { + TRACFCOMP( g_trac_i2c, + "cacheEeprom() Mux target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache", + TARGETING::get_huid(i_target), + i_eepromType); + /*@ + * @errortype + * @moduleid I2C_CACHE_EEPROM + * @reasoncode I2C_MUX_TARGET_NOT_FOUND + * @userdata1 HUID of target we want to cache + * @userdata2[0:31] Type of EEPROM we are caching + * @userdata2[32:63] Boolean is target present or not + * @devdesc cacheEeprom invalid mux target + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + I2C_CACHE_EEPROM, + I2C_MUX_TARGET_NOT_FOUND, + TARGETING::get_huid(i_target), + TWO_UINT32_TO_UINT64(i_eepromType, i_present), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + l_errl->collectTrace(I2C_COMP_NAME); + break; + } + + // Grab the I2C master target so we can read the HUID, if the target is NULL we will not be able + // to lookup attribute to uniquely ID this eeprom so we will not cache it + l_i2cMasterTarget = l_targetService.toTarget( l_eepromInfo.i2cMasterPath ); + if(l_i2cMasterTarget == nullptr) + { + TRACFCOMP( g_trac_i2c, + "cacheEeprom() I2C Master target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache ", + TARGETING::get_huid(i_target), + i_eepromType); + /*@ + * @errortype + * @moduleid I2C_CACHE_EEPROM + * @reasoncode INVALID_MASTER_TARGET + * @userdata1 HUID of target we want to cache + * @userdata2[0:31] Type of EEPROM we are caching + * @userdata2[32:63] Boolean is target present or not + * @devdesc cacheEeprom invalid master target + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + I2C_CACHE_EEPROM, + INVALID_MASTER_TARGET, + TARGETING::get_huid(i_target), + TWO_UINT32_TO_UINT64(i_eepromType, i_present), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + l_errl->collectTrace(I2C_COMP_NAME); + break; + } + + // if g_eecachePnorVaddr == 0 this indicates we have not yet looked up + // the virtual address for the start of the EECACHE pnor section so we must look + // it up. We can then store it in this global var for later use + if(g_eecachePnorVaddr == 0 || g_eecachePnorSize == 0) + { + PNOR::SectionInfo_t l_sectionInfo; + l_errl = PNOR::getSectionInfo(PNOR::EECACHE, l_sectionInfo); + + if(l_errl) + { + TRACFCOMP( g_trac_i2c, "cacheEeprom() Failed while looking up the EECACHE section in PNOR!!"); + break; + } + + mutex_lock(&g_eecacheMutex); + g_eecachePnorVaddr = l_sectionInfo.vaddr; + g_eecachePnorSize = l_sectionInfo.size; + TRACFCOMP( g_trac_i2c, "cacheEeprom() vaddr for EECACHE start = 0x%lx , size = 0x%lx!!", + g_eecachePnorVaddr, g_eecachePnorSize); + mutex_unlock(&g_eecacheMutex); + } + + // The start of the EECACHE pnor section follows the order of the eecacheSectionHeader struct + // that is defined in eepromCache_const.H. This should be the version, followed by the current + // end of the cache, followed by a list of EEPROM entries that combines huid of mux target, huid + // of master target, port of eeprom, and devAddr of eeprom to come up with a unqiue identifier + // for a given eeprom. + l_eecacheSectionHeaderPtr = reinterpret_cast<eecacheSectionHeader*>(g_eecachePnorVaddr); + + if(l_eecacheSectionHeaderPtr->version == EECACHE_VERSION_UNSET) + { + // If version == 0xFF then nothing has been cached before, + // if nothing has been cached before then version should + // be set to be the latest version of the struct available + l_eecacheSectionHeaderPtr->version = EECACHE_VERSION_LATEST; + TRACFCOMP( g_trac_i2c, + "cacheEeprom() Found Empty Cache, set version of cache structure to be 0x%.02x", + EECACHE_VERSION_1); + } + + if(l_eecacheSectionHeaderPtr->end_of_cache == UNSET_END_OF_CACHE_VALUE) + { + // If end_of_cache == 0xFFFFFFFF then we will assume the cache is empty. + // In this case, we must set end_of_cache to be the end of the header. + // This means the start of first eeprom's cached data will be immediately + // following the end of the EECACHE header. + l_eecacheSectionHeaderPtr->end_of_cache = sizeof(eecacheSectionHeader); + TRACFCOMP( g_trac_i2c, + "cacheEeprom() Found Empty Cache, set end of cache to be 0x%.04x (End of ToC)", + sizeof(eecacheSectionHeader)); + } + + // This is what we will compare w/ when we are going through the existing + // caches in the eeprom to see if we have already cached something + // Or if no matches are found we will copy this into the header + eepromRecordHeader l_eepromRecord = {l_i2cMasterTarget->getAttr<TARGETING::ATTR_HUID>(), + (uint8_t)l_eepromInfo.port, + (uint8_t)l_eepromInfo.engine, + (uint8_t)l_eepromInfo.devAddr, + l_muxTarget->getAttr<TARGETING::ATTR_HUID>(), + l_eepromInfo.i2cMuxBusSelector, + (uint8_t)l_eepromInfo.devSize_KB, + 0, // Default internal offset to be 0 + i_present}; + + size_t l_eepromLen = l_eepromInfo.devSize_KB * KILOBYTE; + + // Parse through PNOR section header to determine if a copy of this + // eeprom already exists, or if we need to add it, and where we should add it + // if we need to. + eepromRecordHeader * l_recordHeaderToUpdate; + + // Initialize this to an INVALID value. This way we catch the case where + // cache has 50 records and we cannot add anymore. In that case l_recordHeaderToUpdateIndex + // would not get set in the loop below. + uint8_t l_recordHeaderToUpdateIndex = INVALID_EEPROM_INDEX; + + for(uint8_t i = 0; i < MAX_EEPROMS_VERSION_1; i++) + { + // Keep track of current record so we can use outside for loop + l_recordHeaderToUpdate = &l_eecacheSectionHeaderPtr->recordHeaders[i]; + + // If internal_offset is non-zero then we will assume this address has been filled + if(l_recordHeaderToUpdate->internal_offset != UNSET_INTERNAL_OFFSET_VALUE) + { + // Compare the eeprom record we are checking against the eeprom records we are iterating through + // but ignore the last 9 bytes which have chip size, the offset into this pnor section where the + // record exists, and a byte that tells us if its valid or not + if( memcmp(l_recordHeaderToUpdate, &l_eepromRecord, RECORD_COMPARE_SIZE ) == 0 ) + { + l_recordHeaderToUpdateIndex = i; + if( l_recordHeaderToUpdate->record_size != l_eepromRecord.record_size) + { + // This indicates that a part size has changed , caching + // algorithm cannot account for size changes. + // Invalidate entire cache and TI to trigger re-ipl + l_errl = clearEEcache(); + + // If there was an error clearing the cache commit is because we are TIing + if(l_errl) + { + errlCommit(l_errl, I2C_COMP_ID); + } + + INITSERVICE::doShutdown(INITSERVICE::SHUTDOWN_DO_RECONFIG_LOOP); + } + + if(l_recordHeaderToUpdate->record_valid) + { + // If the existing eeprom record is valid, then only update the + // contents if the SN/PN for current HW do not match the eeprom + // record. (target must be present to cache) + + // TODO RTC:203788 add lookup for PN and SN matches + //if( !i_present || PNandSNMatch ) + { + l_updateContents = false; + } + + // If target is present there is nothing in the + // header to update + if( i_present ) + { + l_updateHeader = false; + } + } + else if(!i_present) + { + // If the target is not present, then do not update contents or header + l_updateContents = false; + l_updateHeader = false; + } + + TRACSSCOMP( g_trac_i2c, "cacheEeprom() already found copy for eeprom role %d for target w/ HUID 0x.%08X", + i_eepromType , TARGETING::get_huid(i_target)); + break; + } + } + else + { + assert((l_eecacheSectionHeaderPtr->end_of_cache + l_eepromLen) < g_eecachePnorSize, + "Sum of system EEPROMs is larger than space allocated for EECACHE pnor section"); + + l_recordHeaderToUpdateIndex = i; + // Set this new eepromRecord's offset within the EECACHE PNOR section + // to be the current "end of cache" offset in the toc. + l_eepromRecord.internal_offset = l_eecacheSectionHeaderPtr->end_of_cache; + l_eecacheSectionHeaderPtr->end_of_cache += l_eepromLen; + l_updateContents = i_present; + break; + } + } + + + // Above we have determined whether the contents of the eeprom at + // hand need to have their contents updated. Only do the following + // steps that update the eeprom's cached data if we were told to do so. + if(l_updateContents ) + { + assert(l_recordHeaderToUpdateIndex != INVALID_EEPROM_INDEX, + "More than MAX_EEPROMS_VERSION_1 in system XML"); + + void * l_tmpBuffer; + + l_tmpBuffer = malloc(l_eepromLen); + + void * l_internalSectionAddr = + reinterpret_cast<uint8_t *>(l_eecacheSectionHeaderPtr) + l_eepromRecord.internal_offset; + + TRACSSCOMP( g_trac_i2c, "cacheEeprom() passing the following into deviceOp eeprom address : huid 0x%.08X length 0x%.08X" , + get_huid(i_target), l_eepromLen); + + // Copy vpd contents to cache + l_errl = deviceOp(DeviceFW::READ, + i_target, + l_tmpBuffer, + l_eepromLen, + DEVICE_EEPROM_ADDRESS(i_eepromType, 0)); + + // If an error occurred during the eeprom read then free the tmp buffer and break out + if( l_errl) + { + TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error occured reading from EEPROM type %d for HUID 0x%.08X!", + i_eepromType,get_huid(i_target)); + free(l_tmpBuffer); + break; + } + + // Copy from tmp buffer into vaddr of internal section offset + memcpy(l_internalSectionAddr, l_tmpBuffer, l_eepromLen); + + // Flush the page to make sure it gets to the PNOR + int rc = mm_remove_pages( FLUSH, l_internalSectionAddr, l_eepromLen ); + if( rc ) + { + TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush contents write to pnor! rc=%d",rc); + /*@ + * @errortype + * @moduleid I2C_CACHE_EEPROM + * @reasoncode I2C_FAILED_TO_FLUSH_CONTENTS + * @userdata1 Requested Address + * @userdata2 rc from mm_remove_pages + * @devdesc cacheEeprom mm_remove_pages FLUSH failed + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + I2C_CACHE_EEPROM, + I2C_FAILED_TO_FLUSH_CONTENTS, + (uint64_t)l_internalSectionAddr, + TO_UINT64(rc), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + } + else + { + TRACSSCOMP( g_trac_i2c, "cacheEeprom() %.08X bytes of eeprom data related to %.08X have been written to %p" , + l_eepromLen, get_huid(i_target), l_internalSectionAddr); + } + + // regardless of success always free tmp buffer we allocated + free(l_tmpBuffer); + + if(l_errl) + { + break; + } + + } + + // Above we have determined whether the header entry for the eeprom at + // hand needs to be updated. Only do the following steps that update + // the eeprom's header entry if we were told to do so. + if(l_updateHeader) + { + // Copy the local eepromRecord header struct with the info about the + // new eeprom we want to add to the cache to the open slot we found + memcpy(l_recordHeaderToUpdate , &l_eepromRecord, sizeof(eepromRecordHeader)); + + // Flush the page to make sure it gets to the PNOR + int rc = mm_remove_pages( FLUSH, l_recordHeaderToUpdate, sizeof(eepromRecordHeader) ); + if( rc ) + { + TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush header write to pnor, rc=%d",rc); + /*@ + * @errortype + * @moduleid I2C_CACHE_EEPROM + * @reasoncode I2C_FAILED_TO_FLUSH_HEADER + * @userdata1 Requested Address + * @userdata2 rc from mm_remove_pages + * @devdesc cacheEeprom mm_remove_pages FLUSH failed + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + I2C_CACHE_EEPROM, + I2C_FAILED_TO_FLUSH_HEADER, + (uint64_t)l_recordHeaderToUpdate, + TO_UINT64(rc), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + break; + } + } + + TRACDBIN( g_trac_i2c, "cacheEeprom: l_eecacheSectionHeaderPtr currently ", + l_eecacheSectionHeaderPtr, + sizeof(eecacheSectionHeader)); + }while(0); + + TRACSSCOMP( g_trac_i2c, "cacheEeprom() EXIT Target HUID 0x%.08X ", TARGETING::get_huid(i_target)); + + return l_errl; +} + +/** + * @brief Generic deviceOp that will lookup the PRIMARY_VPD eeprom associated + * with a given target and cache the data from the eeprom into the + * EECACHE section in PNOR for later use + * + * @param[in] i_opType Operation type, see DeviceFW::OperationType + * in driverif.H + * @param[in] i_target Target whose Eeprom we will try to cache + * @param[in/out] io_buffer Read: Pointer to output data storage + * Write: Pointer to input data storage + * @param[in/out] io_buflen Input: size of io_buffer (in bytes, always 1) + * Output: Success = 1, Failure = 0 + * @param[in] i_accessType DeviceFW::AccessType enum (userif.H) + * @param[in] i_args This is an argument list for DD framework. + * In this function, there are no arguments. + * @return errlHndl_t + */ +errlHndl_t genericI2CEepromCache(DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + int64_t i_accessType, + va_list i_args) +{ + errlHndl_t l_errl = nullptr; + + // First param is a uint64_t representing if the target is present or not + bool l_present = (bool)va_arg(i_args,uint64_t); + + // second param is the type of EEPROM type we wish to cache (PRIMARY vs BACKUP etc) + EEPROM::eeprom_chip_types_t l_eepromType = (EEPROM::eeprom_chip_types_t)va_arg(i_args,uint64_t); + + TRACSSCOMP( g_trac_i2c, ENTER_MRK"genericI2CEepromCache() " + "Target HUID 0x%.08X Enter", TARGETING::get_huid(i_target)); + + do{ + // Run the cache eerpom function on the target passed in + l_errl = cacheEeprom(i_target, l_present, l_eepromType); + if(l_errl) + { + TRACFCOMP(g_trac_i2c, + ERR_MRK"cacheEeprom: An error occured while attempting to cache eeprom for 0x%.08X", + TARGETING::get_huid(i_target)); + break; + } + + }while(0); + + TRACSSCOMP( g_trac_i2c, EXIT_MRK"genericI2CEepromCache() " + "Target HUID 0x%.08X EXIT", TARGETING::get_huid(i_target)); + + return l_errl; +} + +DEVICE_REGISTER_ROUTE( DeviceFW::READ, + DeviceFW::EEPROM_CACHE, + TARGETING::TYPE_OCMB_CHIP, + genericI2CEepromCache); + +DEVICE_REGISTER_ROUTE( DeviceFW::READ, + DeviceFW::EEPROM_CACHE, + TARGETING::TYPE_PROC, + genericI2CEepromCache ); + +DEVICE_REGISTER_ROUTE( DeviceFW::READ, + DeviceFW::EEPROM_CACHE, + TARGETING::TYPE_DIMM, + genericI2CEepromCache ); + +}
\ No newline at end of file diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index 048cd731a..c14180a3a 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -119,11 +119,18 @@ DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, TARGETING::TYPE_NODE, eepromPerformOp ); +// Register the perform Op with the routing code for MCS chiplets. DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, DeviceFW::EEPROM, TARGETING::TYPE_MCS, eepromPerformOp ); +// Register the perform Op with the routing code for Open-Capi Memory Buffer Chips. +DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, + DeviceFW::EEPROM, + TARGETING::TYPE_OCMB_CHIP, + eepromPerformOp ); + /** * @@ -197,7 +204,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, TARGETING::Target * i2cMasterTarget = NULL; eeprom_addr_t i2cInfo; - i2cInfo.chip = va_arg( i_args, uint64_t ); + i2cInfo.eepromRole = va_arg( i_args, uint64_t ); i2cInfo.offset = va_arg( i_args, uint64_t ); TRACDCOMP( g_trac_eeprom, @@ -205,7 +212,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, TRACUCOMP (g_trac_eeprom, ENTER_MRK"eepromPerformOp(): " "i_opType=%d, chip=%d, offset=%x, len=%d", - (uint64_t) i_opType, i2cInfo.chip, i2cInfo.offset, io_buflen); + (uint64_t) i_opType, i2cInfo.eepromRole, i2cInfo.offset, io_buflen); #ifdef __HOSTBOOT_RUNTIME // At runtime the OCC sensor cache will need to be diabled to avoid I2C @@ -250,7 +257,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, TRACFCOMP( g_trac_eeprom, ERR_MRK"eepromPerformOp(): Device Overflow! " "C-e/p/dA=%d-%d/%d/0x%X, offset=0x%X, len=0x%X " - "devSizeKB=0x%X", i2cInfo.chip, i2cInfo.engine, + "devSizeKB=0x%X", i2cInfo.eepromRole, i2cInfo.engine, i2cInfo.port, i2cInfo.devAddr, i2cInfo.offset, io_buflen, i2cInfo.devSize_KB); @@ -296,11 +303,13 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, TRACFCOMP( g_trac_eeprom, "eepromPerformOp(): i_opType=%d " - "C-e/p/dA=%d-%d/%d/0x%X, offset=0x%X, len=0x%X, " - "snglChipKB=0x%X, chipCount=0x%X, devSizeKB=0x%X", i_opType, - i2cInfo.chip, i2cInfo.engine, i2cInfo.port, i2cInfo.devAddr, - i2cInfo.offset, io_buflen, l_snglChipSize, - i2cInfo.chipCount, i2cInfo.devSize_KB); + "C-e/p/dA=%d-%d/%d/0x%X, offset=0x%X, len=0x%X, ", + i_opType, i2cInfo.eepromRole, i2cInfo.engine, + i2cInfo.port, i2cInfo.devAddr, i2cInfo.offset, io_buflen) + + TRACFCOMP (g_trac_eeprom, + "eepromPerformOp(): snglChipKB=0x%X, chipCount=0x%X, devSizeKB=0x%X", + l_snglChipSize, i2cInfo.chipCount, i2cInfo.devSize_KB); // Printing mux info separately, if combined, nothing is displayed char* l_muxPath = i2cInfo.i2cMuxPath.toString(); @@ -360,7 +369,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, EEPROM_PERFORM_OP, EEPROM_INVALID_OPERATION, i_opType, - i2cInfo.chip, + i2cInfo.eepromRole, true /*Add HB SW Callout*/ ); err->collectTrace( EEPROM_COMP_NAME ); @@ -453,7 +462,7 @@ bool eepromPresence ( TARGETING::Target * i_target ) eeprom_addr_t i2cInfo; - i2cInfo.chip = EEPROM::VPD_PRIMARY; + i2cInfo.eepromRole = EEPROM::VPD_PRIMARY; i2cInfo.offset = 0; do { @@ -657,88 +666,49 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target, "EEPROM READ START : Chip: %02d : Offset %.2X : Len %d", i_i2cInfo.chip, i_i2cInfo.offset, i_buflen ); - - // Check to see if the Read operation straddles the EEPROM page - //boundary - l_boundaryCrossed = crossesEepromPageBoundary( i_i2cInfo.offset, - i_buflen, - l_readBuflen, - l_pageTwoBuflen, - i_i2cInfo ); - - // Set addressing parameters - err = eepromPrepareAddress( i_target, - &byteAddr, - byteAddrSize, - l_desiredPage, - i_i2cInfo); - - if( err ) - { - TRACFCOMP(g_trac_eeprom, - ERR_MRK"eepromRead()::eepromPrepareAddress()"); - break; - } - - - // Attempt to lock page mutex - bool l_switchPage = true; - bool l_lockMutex = true; - err = eepromPageOp( i_target, - l_switchPage, - l_lockMutex, - l_pageLocked, - l_desiredPage, - i_i2cInfo ); - - if( err ) - { - TRACFCOMP(g_trac_eeprom, - "eepromRead()::eepromPageOp()::failed locking page"); - break; - } + // At maximum we want to do 1 KB reads at a time. The largest that + // the scom byte range will support is 64 KB - 1 but we will do 1 + // KB at a time to catch fails faster. This is useful when we do big + // reads when caching the eeprom to pnor. + size_t l_readLenRemaining = i_buflen; + size_t l_currentReadLen; // Lock to sequence operations mutex_lock( &g_eepromMutex ); - - // First Read. If Second read is necessary, this call will read - // everything from the original offset up to the 256th byte - err = eepromReadData( i_target, - o_buffer, - l_readBuflen, - &byteAddr, - byteAddrSize, - i_i2cInfo ); - if( err ) - { - TRACFCOMP(g_trac_eeprom, - "Failed reading data: original read"); - break; - } - - - // Perform the second Read if necessary. Read starts at - // begining of EEPROM page 1 (offset=0x100) and reads the - // rest of the required data. - if( l_boundaryCrossed ) + + while( l_readLenRemaining > 0 ) { - //Prepare the address to read at the start of EEPROM page one - i_i2cInfo.offset = EEPROM_PAGE_SIZE; // 0x100 + l_currentReadLen = l_readLenRemaining < KILOBYTE ? l_readLenRemaining : KILOBYTE; + + // Check to see if the Read operation straddles the EEPROM page + // boundary.Note this is only required for systems w/ DDR4 industry + // standard dimms. DDR4 ISDIMMS have a max of 512 bytes so we will + // never loop through this multiple times on those systems + l_boundaryCrossed = crossesEepromPageBoundary( i_i2cInfo.offset, + l_currentReadLen, + l_readBuflen, + l_pageTwoBuflen, + i_i2cInfo ); + + // Set addressing parameters err = eepromPrepareAddress( i_target, &byteAddr, byteAddrSize, l_desiredPage, - i_i2cInfo ); + i_i2cInfo); + if( err ) { TRACFCOMP(g_trac_eeprom, - "Error preparing address: second eeprom read"); + ERR_MRK"eepromRead()::eepromPrepareAddress()"); break; } - // Switch to the second EEPROM page - l_switchPage = true; - l_lockMutex = false; + + // Attempt to lock page mutex + // (only important in DDR4 IS-DIMM systems) + bool l_switchPage = true; + bool l_lockMutex = true; err = eepromPageOp( i_target, l_switchPage, l_lockMutex, @@ -748,32 +718,89 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target, if( err ) { - TRACFCOMP( g_trac_eeprom, - "Failed switching to EEPROM page 1 for second read op"); + TRACFCOMP(g_trac_eeprom, + "eepromRead()::eepromPageOp()::failed locking page"); break; } - // Perform the second read operation - err = eepromReadData( - i_target, - &(reinterpret_cast<uint8_t*>(o_buffer)[l_readBuflen]), - l_pageTwoBuflen, - &byteAddr, - byteAddrSize, - i_i2cInfo ); + // First Read. If Second read is necessary, this call will read + // everything from the original offset up to the 256th byte + err = eepromReadData( i_target, + &(reinterpret_cast<uint8_t*>(o_buffer)[i_buflen - l_readLenRemaining]), + l_readBuflen, + &byteAddr, + byteAddrSize, + i_i2cInfo ); + + i_i2cInfo.offset += l_currentReadLen; + l_readLenRemaining -= l_currentReadLen; if( err ) { - TRACFCOMP( g_trac_eeprom, - "Failed reading data: second read"); + TRACFCOMP(g_trac_eeprom, + "Failed reading data: original read"); break; } + + + // Perform the second Read if necessary. Read starts at + // begining of EEPROM page 1 (offset=0x100) and reads the + // rest of the required data. + if( l_boundaryCrossed ) + { + //Prepare the address to read at the start of EEPROM page one + i_i2cInfo.offset = EEPROM_PAGE_SIZE; // 0x100 + err = eepromPrepareAddress( i_target, + &byteAddr, + byteAddrSize, + l_desiredPage, + i_i2cInfo ); + if( err ) + { + TRACFCOMP(g_trac_eeprom, + "Error preparing address: second eeprom read"); + break; + } + + // Switch to the second EEPROM page + l_switchPage = true; + l_lockMutex = false; + err = eepromPageOp( i_target, + l_switchPage, + l_lockMutex, + l_pageLocked, + l_desiredPage, + i_i2cInfo ); + + if( err ) + { + TRACFCOMP( g_trac_eeprom, + "Failed switching to EEPROM page 1 for second read op"); + break; + } + + // Perform the second read operation + err = eepromReadData( + i_target, + &(reinterpret_cast<uint8_t*>(o_buffer)[l_readBuflen]), + l_pageTwoBuflen, + &byteAddr, + byteAddrSize, + i_i2cInfo ); + + if( err ) + { + TRACFCOMP( g_trac_eeprom, + "Failed reading data: second read"); + break; + } + } } TRACUCOMP( g_trac_eepromr, - "EEPROM READ END : Chip: %02d : Offset %.2X : Len %d : %016llx", - i_i2cInfo.chip, i_i2cInfo.offset, i_buflen, + "EEPROM READ END : Eeprom Role: %02d : Offset %.2X : Len %d : %016llx", + i_i2cInfo.eepromRole, i_i2cInfo.offset, i_buflen, *((uint64_t*)o_buffer) ); } while( 0 ); @@ -1035,8 +1062,8 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, do { TRACUCOMP( g_trac_eeprom, - "EEPROM WRITE START : Chip: %02d : Offset %.2X : Len %d : %016llx", - i_i2cInfo.chip, i_i2cInfo.offset, io_buflen, + "EEPROM WRITE START : Eeprom Role : %02d : Offset %.2X : Len %d : %016llx", + i_i2cInfo.eepromRole, i_i2cInfo.offset, io_buflen, *((uint64_t*)io_buffer) ); @@ -1094,7 +1121,7 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, EEPROM_WRITE, EEPROM_I2C_WRITE_PAGE_SIZE_ZERO, TARGETING::get_huid(i_target), - i_i2cInfo.chip, + i_i2cInfo.eepromRole, true /*Add HB SW Callout*/ ); err->collectTrace( EEPROM_COMP_NAME ); @@ -1237,8 +1264,8 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, TRACSCOMP( g_trac_eepromr, - "EEPROM WRITE END : Chip: %02d : Offset %.2X : Len %d", - i_i2cInfo.chip, i_i2cInfo.offset, io_buflen ); + "EEPROM WRITE END : Eeprom Role : %02d : Offset %.2X : Len %d", + i_i2cInfo.eepromRole, i_i2cInfo.offset, io_buflen ); } while( 0 ); // Free memory @@ -1541,7 +1568,7 @@ errlHndl_t eepromPrepareAddress ( TARGETING::Target * i_target, EEPROM_PREPAREADDRESS, EEPROM_INVALID_DEVICE_TYPE, i_i2cInfo.addrSize, - i_i2cInfo.chip, + i_i2cInfo.eepromRole, true /*Add HB SW Callout*/ ); err->collectTrace( EEPROM_COMP_NAME ); @@ -1579,7 +1606,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, do { - switch (o_i2cInfo.chip ) + switch (o_i2cInfo.eepromRole ) { case VPD_PRIMARY: if( !( i_target-> @@ -1628,7 +1655,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, default: TRACFCOMP( g_trac_eeprom,ERR_MRK"eepromReadAttributes() - " "Invalid chip (%d) to read attributes from!", - o_i2cInfo.chip ); + o_i2cInfo.eepromRole ); /*@ * @errortype @@ -1642,7 +1669,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, EEPROM_READATTRIBUTES, EEPROM_INVALID_CHIP, - o_i2cInfo.chip, + o_i2cInfo.eepromRole, TARGETING::get_huid(i_target), true /*Add HB SW Callout*/ ); @@ -1656,8 +1683,8 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, { TRACFCOMP( g_trac_eeprom, ERR_MRK"eepromReadAttributes() - ERROR reading " - "attributes for chip %d!", - o_i2cInfo.chip ); + "attributes for eeprom role %d!", + o_i2cInfo.eepromRole ); /*@ * @errortype @@ -1673,7 +1700,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, EEPROM_READATTRIBUTES, EEPROM_ATTR_INFO_NOT_FOUND, TARGETING::get_huid(i_target), - o_i2cInfo.chip); + o_i2cInfo.eepromRole); // Could be FSP or HB code's fault err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, @@ -1749,12 +1776,14 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, } while( 0 ); TRACUCOMP(g_trac_eeprom,"eepromReadAttributes() tgt=0x%X, %d/%d/0x%X " - "wpw=0x%X, dsKb=0x%X, chpCnt=%d, aS=%d (%d), wct=%d", + "wpw=0x%X, dsKb=0x%X, chpCnt=%d, aS=%d (%d)", TARGETING::get_huid(i_target), o_i2cInfo.port, o_i2cInfo.engine, o_i2cInfo.devAddr, o_i2cInfo.writePageSize, o_i2cInfo.devSize_KB, o_i2cInfo.chipCount, o_i2cInfo.addrSize, - eepromData.byteAddrOffset, o_i2cInfo.writeCycleTime); + eepromData.byteAddrOffset); + + // Printing mux info separately, if combined, nothing is displayed char* l_muxPath = o_i2cInfo.i2cMuxPath.toString(); @@ -1836,7 +1865,7 @@ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target, EEPROM_GETI2CMASTERTARGET, EEPROM_I2C_MASTER_PATH_ERROR, TWO_UINT32_TO_UINT64( - i_i2cInfo.chip, + i_i2cInfo.eepromRole, TARGETING::get_huid(i_target) ), l_epCompressed, true /*Add HB SW Callout*/ ); @@ -1891,7 +1920,7 @@ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target, EEPROM_GETI2CMASTERTARGET, EEPROM_TARGET_NULL, TWO_UINT32_TO_UINT64( - i_i2cInfo.chip, + i_i2cInfo.eepromRole, TARGETING::get_huid(i_target) ), l_epCompressed, true /*Add HB SW Callout*/ ); diff --git a/src/usr/i2c/eepromdd.H b/src/usr/i2c/eepromdd.H index 1dddb0b0e..8acf7d8f2 100755 --- a/src/usr/i2c/eepromdd.H +++ b/src/usr/i2c/eepromdd.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -62,7 +62,7 @@ struct eeprom_addr_t uint64_t port; uint64_t engine; uint64_t devAddr; - int64_t chip; + int64_t eepromRole; uint64_t offset; eeprom_addr_size_t addrSize; TARGETING::EntityPath i2cMasterPath; @@ -80,7 +80,7 @@ struct eeprom_addr_t : port(0), engine(0), devAddr(0), - chip(0), + eepromRole(0), offset(0), addrSize(LAST_DEVICE_TYPE), i2cMasterPath(), diff --git a/src/usr/i2c/errlud_i2c.C b/src/usr/i2c/errlud_i2c.C index 7c3e00f12..bd27be102 100644 --- a/src/usr/i2c/errlud_i2c.C +++ b/src/usr/i2c/errlud_i2c.C @@ -262,7 +262,7 @@ UdEepromParms::UdEepromParms( uint8_t i_opType, memcpy(l_pBuf, &tmp64, sizeof(tmp64)); l_pBuf += sizeof(tmp64); - tmp64 = i_i2cInfo.chip; + tmp64 = i_i2cInfo.eepromRole; memcpy(l_pBuf, &tmp64, sizeof(tmp64)); l_pBuf += sizeof(tmp64); diff --git a/src/usr/i2c/i2c.H b/src/usr/i2c/i2c.H index 114e5a554..baf95df32 100755 --- a/src/usr/i2c/i2c.H +++ b/src/usr/i2c/i2c.H @@ -959,7 +959,6 @@ void setLogicalFsiEnginePort(size_t &io_logical_engine, void addHwCalloutsI2c(errlHndl_t i_err, TARGETING::Target * i_target, const misc_args_t & i_args); - }; // end I2C namespace #endif // __I2C_H diff --git a/src/usr/i2c/makefile b/src/usr/i2c/makefile index 535484752..10e55c9de 100644 --- a/src/usr/i2c/makefile +++ b/src/usr/i2c/makefile @@ -33,6 +33,7 @@ OBJS += i2c.o OBJS += $(if $(CONFIG_TPMDD),tpmdd.o,) OBJS += fapi_i2c_dd.o OBJS += i2cTargetPres.o +OBJS += $(if $(CONFIG_SUPPORT_EEPROM_CACHING),eepromCache.o) SUBDIRS += test.d SUBDIRS += runtime.d diff --git a/src/usr/targeting/common/xmltohb/simics_AXONE.system.xml b/src/usr/targeting/common/xmltohb/simics_AXONE.system.xml index ef31fc743..e8e4fba40 100644 --- a/src/usr/targeting/common/xmltohb/simics_AXONE.system.xml +++ b/src/usr/targeting/common/xmltohb/simics_AXONE.system.xml @@ -445,12 +445,12 @@ <id>EEPROM_VPD_BACKUP_INFO</id> <default> <field><id>byteAddrOffset</id><value>0x02</value></field> - <field><id>devAddr</id><value>0xA0</value></field> - <field><id>engine</id><value>1</value></field> - <field><id>i2cMasterPath</id><value>physical:sys-0/node-0/proc-0</value></field> <!-- Note: that there is actually two 64KB chips associated with the MVPD SEEPROM but Hostboot should never access the second chip --> <field><id>chipCount</id><value>0x01</value></field> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>1</value></field> + <field><id>i2cMasterPath</id><value>physical:sys-0/node-0/proc-0</value></field> <field><id>maxMemorySizeKB</id><value>0x40</value></field> <field><id>port</id><value>2</value></field> <field><id>writeCycleTime</id><value>0x0A</value></field> @@ -461,12 +461,12 @@ <id>EEPROM_VPD_PRIMARY_INFO</id> <default> <field><id>byteAddrOffset</id><value>0x02</value></field> - <field><id>devAddr</id><value>0xA0</value></field> - <field><id>engine</id><value>1</value></field> - <field><id>i2cMasterPath</id><value>physical:sys-0/node-0/proc-0</value></field> <!-- Note: that there is actually two 64KB chips associated with the MVPD SEEPROM but Hostboot should never access the second chip --> <field><id>chipCount</id><value>0x01</value></field> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>1</value></field> + <field><id>i2cMasterPath</id><value>physical:sys-0/node-0/proc-0</value></field> <field><id>maxMemorySizeKB</id><value>0x40</value></field> <field><id>port</id><value>0</value></field> <field><id>writeCycleTime</id><value>0x0A</value></field> @@ -9151,8 +9151,18 @@ <id>FAPI_POS</id> <default>9</default> </attribute> - <!-- No valid I2C connections to OCMB 9-15 in the Axone simics model - Skip setting EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>2</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -9190,8 +9200,18 @@ <id>FAPI_POS</id> <default>10</default> </attribute> - <!-- No valid I2C connections to OCMB 9-15 in the Axone simics model - Skip setting EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>3</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -9229,8 +9249,18 @@ <id>FAPI_POS</id> <default>11</default> </attribute> - <!-- No valid I2C connections to OCMB 9-15 in the Axone simics model - Skip setting EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>4</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -9268,8 +9298,18 @@ <id>FAPI_POS</id> <default>12</default> </attribute> - <!-- No valid I2C connections to OCMB 9-15 in the Axone simics model - Skip setting EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>5</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -9307,8 +9347,18 @@ <id>FAPI_POS</id> <default>13</default> </attribute> - <!-- No valid I2C connections to OCMB 9-15 in the Axone simics model - Skip setting EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>6</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -9346,8 +9396,18 @@ <id>FAPI_POS</id> <default>14</default> </attribute> - <!-- No valid I2C connections to OCMB 9-15 in the Axone simics model - Skip setting EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>7</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -9385,8 +9445,18 @@ <id>FAPI_POS</id> <default>15</default> </attribute> - <!-- No valid I2C connections to OCMB 9-15 in the Axone simics model - Skip setting EEPROM_VPD_PRIMARY_INFO and FAPI_I2C_CONTROL_INFO--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>8</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <!-- ===================================================================== --> @@ -10254,8 +10324,18 @@ <id>VPD_REC_NUM</id> <default>9</default> </attribute> - <!-- EEPROM_VPD_PRIMARY_INFO does not get set for dimms 9-15 in the axone simics model because - the simics model does not provide i2c address spaces for these targets--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>2</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -10286,8 +10366,18 @@ <id>VPD_REC_NUM</id> <default>10</default> </attribute> - <!-- EEPROM_VPD_PRIMARY_INFO does not get set for dimms 9-15 in the axone simics model because - the simics model does not provide i2c address spaces for these targets--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>3</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -10318,8 +10408,18 @@ <id>VPD_REC_NUM</id> <default>11</default> </attribute> - <!-- EEPROM_VPD_PRIMARY_INFO does not get set for dimms 9-15 in the axone simics model because - the simics model does not provide i2c address spaces for these targets--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>4</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -10350,8 +10450,18 @@ <id>VPD_REC_NUM</id> <default>12</default> </attribute> - <!-- EEPROM_VPD_PRIMARY_INFO does not get set for dimms 9-15 in the axone simics model because - the simics model does not provide i2c address spaces for these targets--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>5</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -10382,8 +10492,18 @@ <id>VPD_REC_NUM</id> <default>13</default> </attribute> - <!-- EEPROM_VPD_PRIMARY_INFO does not get set for dimms 9-15 in the axone simics model because - the simics model does not provide i2c address spaces for these targets--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>6</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -10414,8 +10534,18 @@ <id>VPD_REC_NUM</id> <default>14</default> </attribute> - <!-- EEPROM_VPD_PRIMARY_INFO does not get set for dimms 9-15 in the axone simics model because - the simics model does not provide i2c address spaces for these targets--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>7</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <targetInstance> @@ -10446,8 +10576,18 @@ <id>VPD_REC_NUM</id> <default>15</default> </attribute> - <!-- EEPROM_VPD_PRIMARY_INFO does not get set for dimms 9-15 in the axone simics model because - the simics model does not provide i2c address spaces for these targets--> + <!-- Note that EEPROM_VPD_PRIMARY_INFO attrs for OCMB 9-15 and DIMM 9-15 + are invalid. The port value is invalid, info is just here to fully test + the EEPROM caching code (DIMM X should match OCMB X) --> + <attribute> + <id>EEPROM_VPD_PRIMARY_INFO</id> + <default> + <field><id>devAddr</id><value>0xA0</value></field> + <field><id>engine</id><value>3</value></field> + <field><id>port</id><value>8</value></field> + <field><id>maxMemorySizeKB</id><value>0x4</value></field> + </default> + </attribute> </targetInstance> <!-- ===================================================================== --> |