summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/HBconfig7
-rw-r--r--src/build/configs/simics_axone.config4
-rw-r--r--src/include/usr/devicefw/userif.H56
-rw-r--r--src/include/usr/i2c/eepromCache_const.H73
-rw-r--r--src/include/usr/i2c/i2creasoncodes.H8
-rw-r--r--src/usr/hwas/hwasPlat.C17
-rw-r--r--src/usr/i2c/eepromCache.C540
-rwxr-xr-xsrc/usr/i2c/eepromdd.C245
-rwxr-xr-xsrc/usr/i2c/eepromdd.H6
-rw-r--r--src/usr/i2c/errlud_i2c.C2
-rwxr-xr-xsrc/usr/i2c/i2c.H1
-rw-r--r--src/usr/i2c/makefile1
-rw-r--r--src/usr/targeting/common/xmltohb/simics_AXONE.system.xml208
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>
<!-- ===================================================================== -->
OpenPOWER on IntegriCloud