summaryrefslogtreecommitdiffstats
path: root/src/usr/isteps
diff options
context:
space:
mode:
authorTsung Yeung <tyeung@us.ibm.com>2018-08-06 08:51:22 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-10-30 16:50:11 -0500
commit2c1c99f370191e4099870a0699cd6f01510222e7 (patch)
tree52081d13a60adf0cfeea62189e45d48b9cb9203a /src/usr/isteps
parentd9711869369308c99eea851c45022b66f68b12df (diff)
downloadtalos-hostboot-2c1c99f370191e4099870a0699cd6f01510222e7.tar.gz
talos-hostboot-2c1c99f370191e4099870a0699cd6f01510222e7.zip
Adds NVDIMM IPL Support on ZZ
-New NVDIMM functions to support restore and trigger setup -Includes NVDIMM step in call_mss_power_cleanup after mss_power_cleanup HWP -Fixes attribute NV_STATUS_FLAG to match HDAT spec Change-Id: I2d68123ceb0b8e7a33b54f9acad0968670a67ea9 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/63948 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/isteps')
-rw-r--r--src/usr/isteps/HBconfig2
-rw-r--r--src/usr/isteps/istep14/call_mss_power_cleanup.C67
-rw-r--r--src/usr/isteps/istep14/makefile2
-rw-r--r--src/usr/isteps/makefile1
-rw-r--r--src/usr/isteps/nvdimm/makefile53
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.C1435
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.H151
7 files changed, 1709 insertions, 2 deletions
diff --git a/src/usr/isteps/HBconfig b/src/usr/isteps/HBconfig
index ce6573a2e..231464b7e 100644
--- a/src/usr/isteps/HBconfig
+++ b/src/usr/isteps/HBconfig
@@ -32,6 +32,6 @@ config PCA95X_16BIT
Set the PCA95X support to a 16 bit chip.
config PRINT_SYSTEM_INFO
- defaults n
+ default n
help
Enables code that prints out the HWAS information for each target found during discovery
diff --git a/src/usr/isteps/istep14/call_mss_power_cleanup.C b/src/usr/isteps/istep14/call_mss_power_cleanup.C
index ae6a4f42a..861647e09 100644
--- a/src/usr/isteps/istep14/call_mss_power_cleanup.C
+++ b/src/usr/isteps/istep14/call_mss_power_cleanup.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -40,6 +40,11 @@
#include <p9_mss_power_cleanup.H>
#include <p9c_mss_power_cleanup.H>
+#ifdef CONFIG_NVDIMM
+// NVDIMM support
+#include <isteps/nvdimm/nvdimm.H>
+#endif
+
using namespace ISTEP;
using namespace ISTEP_ERROR;
using namespace ERRORLOG;
@@ -95,6 +100,66 @@ void* call_mss_power_cleanup (void *io_pArgs)
}
}
+#ifdef CONFIG_NVDIMM
+ TARGETING::TargetHandleList l_procList;
+ getAllChips(l_procList, TARGETING::TYPE_PROC, false);
+ TARGETING::ATTR_MODEL_type l_chipModel =
+ l_procList[0]->getAttr<TARGETING::ATTR_MODEL>();
+
+ if(l_chipModel == TARGETING::MODEL_NIMBUS)
+ {
+ // Check for any NVDIMMs after the mss_power_cleanup
+ TARGETING::TargetHandleList l_dimmTargetList;
+ TARGETING::TargetHandleList l_nvdimmTargetList;
+ getAllLogicalCards(l_dimmTargetList, TYPE_DIMM);
+
+ // Walk the dimm list and collect all the nvdimm targets
+ for (auto const l_dimm : l_dimmTargetList)
+ {
+ //@TODO replace this with isNVDIMM()
+ // Not the most elegant way of doing it but the hybrid attributes
+ // are at the MCS level. Need to find my way up to MCS and check
+ // if the dimm is hybrid
+ TARGETING::TargetHandleList l_mcaList;
+ getParentAffinityTargets(l_mcaList, l_dimm, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA);
+
+ if (l_mcaList.size())
+ {
+ TARGETING::TargetHandleList l_mcsList;
+ getParentAffinityTargets(l_mcsList, l_mcaList[0], TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS);
+
+ if(l_mcsList.size())
+ {
+ // 2-D array. [MCA][DIMM]
+ TARGETING::ATTR_EFF_HYBRID_type l_hybrid;
+ TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE_type l_hybrid_type;
+
+ if( l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID>(l_hybrid) &&
+ l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE>(l_hybrid_type) )
+ {
+ //Using huid to lookup the hybrid attribute for the current dimm
+ const auto l_dimm_huid = TARGETING::get_huid(l_dimm);
+ const auto l_mca_huid = TARGETING::get_huid(l_mcaList[0]);
+ const uint8_t MCA_PER_MCS = 2;
+ const uint8_t DIMM_PER_MCA = 2;
+
+ if (l_hybrid[l_mca_huid%MCA_PER_MCS][l_dimm_huid%DIMM_PER_MCA] == TARGETING::EFF_HYBRID_IS_HYBRID &&
+ l_hybrid_type[l_mca_huid%MCA_PER_MCS][l_dimm_huid%DIMM_PER_MCA] == TARGETING::EFF_HYBRID_MEMORY_TYPE_NVDIMM )
+ {
+ l_nvdimmTargetList.push_back(l_dimm);
+ }
+ }
+ }
+ }
+ }
+
+ // Run the nvdimm management function if the list is not empty
+ if (!l_nvdimmTargetList.empty()){
+ NVDIMM::nvdimm_restore(l_nvdimmTargetList);
+ }
+ }
+#endif
+
// -- Cumulus only
// Get a list of all present Centaurs
TargetHandleList l_presCentaurs;
diff --git a/src/usr/isteps/istep14/makefile b/src/usr/isteps/istep14/makefile
index 21e1383c0..68156f5b1 100644
--- a/src/usr/isteps/istep14/makefile
+++ b/src/usr/isteps/istep14/makefile
@@ -46,6 +46,7 @@ EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/
EXTRAINCDIR += ${CEN_PROC_PATH}/hwp/memory
EXTRAINCDIR += ${CEN_PROC_PATH}/hwp/memory/lib/shared/
EXTRAINCDIR += ${ROOTPATH}/src/import/chips/centaur/common/include/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/
OBJS += call_mss_memdiag.o
OBJS += call_mss_thermal_init.o
@@ -99,3 +100,4 @@ VPATH += ${PROCEDURE_PATH}/hwp/memory/lib/utils/
VPATH += ${PROCEDURE_PATH}/hwp/memory/lib/mcbist/
VPATH += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/
VPATH += ${CEN_PROC_PATH}/hwp/memory/
+VPATH += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/
diff --git a/src/usr/isteps/makefile b/src/usr/isteps/makefile
index b64adc283..920eae593 100644
--- a/src/usr/isteps/makefile
+++ b/src/usr/isteps/makefile
@@ -50,6 +50,7 @@ SUBDIRS+=tod.d
SUBDIRS+=fab_iovalid.d
SUBDIRS+=nest.d
SUBDIRS+=io.d
+SUBDIRS+=nvdimm.d
#TODO: RTC 176018
EXTRAINCDIR += ${ROOTPATH}/src/import/
diff --git a/src/usr/isteps/nvdimm/makefile b/src/usr/isteps/nvdimm/makefile
new file mode 100644
index 000000000..a39be6f0e
--- /dev/null
+++ b/src/usr/isteps/nvdimm/makefile
@@ -0,0 +1,53 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/isteps/nvdimm/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2012,2018
+# [+] 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
+ROOTPATH = ../../../..
+
+PROCEDURE_PATH = ${ROOTPATH}/src/import/chips/p9/procedures
+
+#Add all the extra include paths
+
+EXTRAINCDIR += ${ROOTPATH}/obj/genfiles/
+EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2
+EXTRAINCDIR += ${ROOTPATH}/src/import/chips/common/utils/imageProcs/
+EXTRAINCDIR += ${ROOTPATH}/src/import/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory
+EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/common/include/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/eff_config/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/mcbist/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/
+EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/ffdc/
+
+MODULE = nvdimm
+
+OBJS += nvdimm.o
+
+include ${ROOTPATH}/config.mk
+
+VPATH += ${PROCEDURE_PATH}/hwp/memory/
+VPATH += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/
diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C
new file mode 100644
index 000000000..d98397edb
--- /dev/null
+++ b/src/usr/isteps/nvdimm/nvdimm.C
@@ -0,0 +1,1435 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/isteps/nvdimm/nvdimm.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2018 */
+/* [+] 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 "nvdimm.H"
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <errl/errludtarget.H>
+#include <i2c/nvdimmddreasoncodes.H>
+#include <targeting/common/commontargeting.H>
+#include <targeting/common/util.H>
+#include <targeting/common/utilFilter.H>
+#include <kernel/timemgr.H>
+#include <sys/time.h>
+#include <usr/devicefw/userif.H>
+#include <fapi2.H>
+#include <fapi2/plat_hwp_invoker.H>
+#include <lib/dimm/ddr4/nvdimm_utils.H>
+#include <isteps/nvdimm/nvdimm.H>
+
+using namespace TARGETING;
+using namespace DeviceFW;
+using namespace EEPROM;
+
+trace_desc_t* g_trac_nvdimm = NULL;
+TRAC_INIT(&g_trac_nvdimm, "NVDIMM", 2*KILOBYTE);
+
+// Easy macro replace for unit testing
+// #define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
+
+namespace NVDIMM
+{
+#define NUM_OFFSET 2
+#define NVDIMM_SET_USER_DATA_1(left_32_ops_id, right_32_huid) \
+ TWO_UINT32_TO_UINT64(left_32_ops_id, right_32_huid)
+
+#define NVDIMM_SET_USER_DATA_2_TIMEOUT(left_32_polled, right_32_timeout) \
+ NVDIMM_SET_USER_DATA_1(left_32_polled, right_32_timeout)
+
+enum
+{
+ NSTD_VAL_NOPRSV = 0x08, // memory valid, contents not preserved (genesis)
+ NSTD_VAL_NOPRSV_MASK = 0xF7,
+ NSTD_VAL_PRSV = 0x04, // memory contents preserved
+ NSTD_VAL_PRSV_MASK = 0xFB,
+ NSTD_ERR_NOPRSV = 0x02, // memory failed to preserve contents
+ NSTD_ERR_NOPRSV_MASK = 0xFD,
+ NSTD_ERR_NOBKUP = 0x01, // memory unable to preserve future content
+ NSTD_ERR_NOBKUP_MASK = 0xFE,
+ NSTD_ERR = 0x03, // NSTD_ERR_NOPRSV+NSTD_ERR_NOBKUP
+};
+
+typedef struct ops_timeoutInfo{
+ const char * desc;
+ uint8_t page;
+ uint8_t offset[2];
+ uint8_t idx;
+ uint8_t status_reg_offset;
+ uint8_t status_progress;
+} ops_timeoutInfo_t;
+
+static bool init = true;
+
+// Table containing register info on the timeout registers for different ops
+constexpr ops_timeoutInfo_t timeoutInfoTable[] =
+{
+ {"SAVE", 0, {0x19, 0x18}, SAVE , NVDIMM_CMD_STATUS0, SAVE_IN_PROGRESS},
+ {"RESTORE", 0, {0x1D, 0x1C}, RESTORE , NVDIMM_CMD_STATUS0, RSTR_IN_PROGRESS},
+ {"ERASE", 0, {0x1F, 0x1E}, ERASE , NVDIMM_CMD_STATUS0, ERASE_IN_PROGRESS},
+ {"ARM", 0, {0x21, 0x20}, ARM , NVDIMM_CMD_STATUS0, ARM_IN_PROGRESS},
+ {"PAGE_SWITCH", 0, {0x1B, 0x1A}, PAGE_SWITCH, 0xff, 0xff},
+ {"CHARGE", 1, {0x11, 0x10}, CHARGE , MODULE_HEALTH_STATUS1, CHARGE_IN_PROGRESS},
+};
+
+/**
+ * @brief Wrapper to call deviceOp to read the NV controller via I2C
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_addr - address/offset for the register to be read
+ *
+ * @param[out] o_data - returned data from read
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmReadReg(Target* i_nvdimm,
+ uint8_t i_addr,
+ uint8_t & o_data )
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Read HUID %X, addr 0x%X",
+ TARGETING::get_huid(i_nvdimm), i_addr);
+
+ errlHndl_t l_err = nullptr;
+ size_t l_numBytes = 1;
+
+ l_err = DeviceFW::deviceOp( DeviceFW::READ,
+ i_nvdimm,
+ &o_data,
+ l_numBytes,
+ DEVICE_NVDIMM_ADDRESS(i_addr));
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Read HUID %X, addr 0x%X = %X",
+ TARGETING::get_huid(i_nvdimm), i_addr, o_data);
+
+ return l_err;
+}
+
+/**
+ * @brief Wrapper to call deviceOp to write the NV controller via I2C
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_addr - address/offset for the register to be written
+ *
+ * @param[in] i_data - data to be written to register @ i_addr
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmWriteReg(Target* i_nvdimm,
+ uint8_t i_addr,
+ uint8_t i_data )
+{
+ errlHndl_t l_err = nullptr;
+ size_t l_numBytes = 1;
+
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Write HUID %X, addr 0x%X = %X",
+ TARGETING::get_huid(i_nvdimm), i_addr, i_data);
+
+ // Need to write directly from target's EEPROM.
+ l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
+ i_nvdimm,
+ &i_data,
+ l_numBytes,
+ DEVICE_NVDIMM_ADDRESS(i_addr));
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Write HUID %X, addr 0x%X = %X",
+ TARGETING::get_huid(i_nvdimm), i_addr, i_data);
+
+ return l_err;
+}
+
+/**
+ * @brief Set the status flag
+ *
+ * @param[in] i_nvdimm - nvdimm target
+ *
+ * @param[in] i_status_flag - status flag to set for each nvdimm
+ *
+ */
+void nvdimmSetStatusFlag(Target *i_nvdimm, const uint8_t i_status_flag)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmSetStatusFlag() HUID[%X], i_status_flag[%X]"
+ ,TARGETING::get_huid(i_nvdimm), i_status_flag);
+
+ auto l_statusFlag = i_nvdimm->getAttr<TARGETING::ATTR_NV_STATUS_FLAG>();
+
+ switch(i_status_flag)
+ {
+ // Make sure NSTD_VAL_PRSV (content preserved) is unset before setting NSTD_VAL_NOPRSV
+ // (data not preserved) or NSTD_ERR_NOPRSV (error preserving data)
+ case NSTD_ERR:
+ case NSTD_VAL_NOPRSV:
+ case NSTD_ERR_NOPRSV:
+ l_statusFlag &= NSTD_VAL_PRSV_MASK;
+ l_statusFlag |= i_status_flag;
+ break;
+
+ // If the content preserved(restore sucessfully), make sure
+ // NSTD_VAL_NOPRSV (not preserved) and NSTD_ERR_NOPRSV (error preserving)
+ // are unset before setting this flag.
+ case NSTD_VAL_PRSV:
+ l_statusFlag &= (NSTD_VAL_NOPRSV_MASK & NSTD_ERR_NOPRSV_MASK);
+ l_statusFlag |= i_status_flag;
+ break;
+
+ case NSTD_ERR_NOBKUP:
+ l_statusFlag |= i_status_flag;
+ break;
+
+ default:
+ assert(0, "nvdimmSetStatusFlag() HUID[%X], i_status_flag[%X] invalid flag!",
+ TARGETING::get_huid(i_nvdimm), i_status_flag);
+ break;
+ }
+
+ i_nvdimm->setAttr<TARGETING::ATTR_NV_STATUS_FLAG>(l_statusFlag);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmSetStatusFlag() HUID[%X], i_status_flag[%X]"
+ ,TARGETING::get_huid(i_nvdimm), i_status_flag);
+}
+
+/**
+ * @brief Check nvdimm error state
+ *
+ * @param[in] i_nvdimm - nvdimm target
+ *
+ * @return bool - true if nvdimm is in any error state, false otherwise
+ */
+bool nvdimmInErrorState(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm));
+
+ uint8_t l_statusFlag = i_nvdimm->getAttr<TARGETING::ATTR_NV_STATUS_FLAG>();
+ bool l_ret = true;
+
+ if ((l_statusFlag & NSTD_ERR) == 0)
+ l_ret = false;
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm));
+ return l_ret;
+}
+
+/**
+ * @brief Check NV controller ready state
+ *
+ * @param[in] i_nvdimm - nvdimm target
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmReady(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmReady() HUID[%X]",TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+ uint8_t l_data = 0x0;
+
+ l_err = nvdimmReadReg(i_nvdimm, NVDIMM_READY, l_data);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReady() nvdimm[%X] - error getting ready status[%d]",
+ TARGETING::get_huid(i_nvdimm), l_data);
+ }
+ else if (l_data != NV_READY)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReady() nvdimm[%X] - nvdimm not ready[%d]",
+ TARGETING::get_huid(i_nvdimm), l_data);
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_NOT_READY
+ *@severity ERRORLOG_SEV_UNRECOVERABLE
+ *@moduleid NVDIMM_CHECK_READY
+ *@userdata1[0:31] Ret value from ready register
+ *@userdata1[32:63] Target Huid
+ *@userdata2 <UNUSED>
+ *@devdesc Failed to read ready status or NVDIMM not ready
+ * for host access. (userdata1 != 0xA5)
+ *@custdesc NVDIMM not ready
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_POLL_STATUS,
+ NVDIMM_STATUS_TIMEOUT,
+ NVDIMM_SET_USER_DATA_1(l_data, TARGETING::get_huid(i_nvdimm)),
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ //@TODO RTC 199645 - add HW callout on dimm target.
+ //if nvdimm is not ready for access by now, this is
+ //a failing indication on the NV controller
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmReady() HUID[%X] ready[%X]",
+ TARGETING::get_huid(i_nvdimm), l_data);
+
+ return l_err;
+}
+
+/**
+ * @brief This function polls the status register for the given ops_id
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_ops_id - id assigned to each operation in nvdimm.H
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollStatus ( Target *i_nvdimm,
+ ops_id i_ops_id,
+ uint32_t &o_poll)
+{
+ errlHndl_t l_err = nullptr;
+ uint8_t l_data = 0x0;
+ uint32_t l_target_timeout_values[6];
+ bool l_done = false;
+
+ // Get the timeout value for ops_id
+ assert(i_nvdimm->tryGetAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(l_target_timeout_values),
+ "nvdimmPollStatus() HUID[%X], failed reading ATTR_NV_OPS_TIMEOUT_MSEC!", TARGETING::get_huid(i_nvdimm));
+ uint32_t l_timeout = l_target_timeout_values[i_ops_id];
+
+ do
+ {
+ l_err = nvdimmReadReg( i_nvdimm,
+ timeoutInfoTable[i_ops_id].status_reg_offset,
+ l_data );
+ if(l_err)
+ {
+ break;
+ }
+
+ if((l_data & timeoutInfoTable[i_ops_id].status_progress) !=
+ timeoutInfoTable[i_ops_id].status_progress) // Done
+ {
+ l_done = true;
+ break;
+ }
+
+ nanosleep( 0, OPS_POLL_TIME_MS*NS_PER_MSEC ); //sleep for POLL ms
+ o_poll += OPS_POLL_TIME_MS;
+
+ } while (o_poll < l_timeout);
+
+ if (!l_done && !l_err)
+ {
+
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmPollStatus() nvdimm[%X] - Status timed out ops_id[%d]",
+ TARGETING::get_huid(i_nvdimm), i_ops_id);
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_STATUS_TIMEOUT
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_POLL_STATUS
+ *@userdata1[0:31] Related ops (0xff = NA)
+ *@userdata1[32:63] Target Huid
+ *@userdata2[0:31] Polled value
+ *@userdata2[32:63] Timeout value
+ *@devdesc Encountered timeout while performing operation on NVDIMM
+ * Refer to userdata1 for which operation it timed out.
+ *@custdesc NVDIMM timed out
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_POLL_STATUS,
+ NVDIMM_STATUS_TIMEOUT,
+ NVDIMM_SET_USER_DATA_1(i_ops_id, TARGETING::get_huid(i_nvdimm)),
+ NVDIMM_SET_USER_DATA_2_TIMEOUT(o_poll, l_timeout),
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ //@TODO RTC 199645 - add HW callout on dimm target.
+ //may have to move the error handling to the caller
+ //as different op could have different error severity
+ }
+
+ return l_err;
+}
+
+/**
+ * @brief This function polls the command status register for backup/CSAVE
+ * completion (does not indicate success or fail)
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollBackupDone(Target* i_nvdimm,
+ uint32_t &o_poll)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollBackupDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmPollStatus ( i_nvdimm, SAVE, o_poll);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollBackupDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief This function polls the command status register for restore
+ * completion (does not indicate success or fail)
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollRestoreDone(Target* i_nvdimm,
+ uint32_t &o_poll)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollRestoreDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmPollStatus ( i_nvdimm, RESTORE, o_poll );
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollRestoreDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief This function polls the command status register for erase
+ * completion (does not indicate success or fail)
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollEraseDone(Target* i_nvdimm,
+ uint32_t &o_poll)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollEraseDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmPollStatus ( i_nvdimm, ERASE, o_poll);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollEraseDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief This function polls the command status register for arm completion
+ * (does not indicate success or fail)
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollArmDone(Target* i_nvdimm,
+ uint32_t &o_poll)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollArmDone() nvdimm[%X]", TARGETING::get_huid(i_nvdimm) );
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmPollStatus ( i_nvdimm, ARM, o_poll);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollArmDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief This function polls the command status register for backup power
+ * charge completion (does not indicate success or fail)
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollESChargeStatus(Target* i_nvdimm,
+ uint32_t &o_poll)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollESChargeDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmPollStatus ( i_nvdimm, CHARGE, o_poll );
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollESChargeDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief This function retrieve the restore status
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_rstrValid - returned data from the restore status register
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmGetRestoreValid(Target* i_nvdimm, uint8_t & o_rstrValid)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmGetRestoreValid() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmReadReg(i_nvdimm, RESTORE_STATUS, o_rstrValid);
+
+ if (l_err){
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X], Error getting restore status!",
+ TARGETING::get_huid(i_nvdimm));
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmGetRestoreValid() nvdimm[%X], restore_status[%x],",
+ TARGETING::get_huid(i_nvdimm), o_rstrValid);
+
+ return l_err;
+}
+
+/**
+ * @brief This function sets the energy supply policy to device-managed
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmSetESPolicy() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+ uint8_t l_data;
+
+ do
+ {
+
+ l_err = nvdimmWriteReg(i_nvdimm, SET_ES_POLICY_CMD, ES_DEV_MANAGE);
+
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOBKUP);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmSetESPolicy() nvdimm[%X]"
+ "failed to write ES register!",TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+
+ // Give it a bit of time (100ms) for the status reg to reflect the change
+ nanosleep( 0, 100*NS_PER_MSEC );
+
+ // Make sure the set was a success
+ l_err = nvdimmReadReg(i_nvdimm, SET_ES_POLICY_STATUS, l_data);
+
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOBKUP);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmSetESPolicy() nvdimm[%X]"
+ "failed to read ES register!",TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+
+ if ((l_data & ES_SUCCESS) != ES_SUCCESS)
+ {
+ TRACFCOMP(g_trac_nvdimm, EXIT_MRK"NDVIMM HUID[%X], nvdimmSetESPolicy() "
+ "failed!",TARGETING::get_huid(i_nvdimm));
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_SET_ES_ERROR
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_SET_ES
+ *@userdata1[0:31] Related ops (0xff = NA)
+ *@userdata1[32:63] Target Huid
+ *@userdata2 <UNUSED>
+ *@devdesc Encountered error setting the energy source policy
+ * Make sure the connection between energy source and
+ * NVDIMM is intact
+ *@custdesc NVDIMM encountered error setting the energy source policy
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_SET_ES,
+ NVDIMM_SET_ES_ERROR,
+ NVDIMM_SET_USER_DATA_1(CHARGE, TARGETING::get_huid(i_nvdimm)),
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ //@TODO RTC 199645 - add procedure callout on backup power source.
+ //Failure setting the energy source policy could mean error on the
+ //battery or even the cabling
+ }
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NDVIMM HUID[%X], nvdimmSetESPolicy(),"
+ ,TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+
+/**
+ * @brief This function checks the arm status register to make sure
+ * the trigger has been armed to ddr_reset_n
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmCheckArmSuccess(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmCheckArmSuccess() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+ uint8_t l_data = 0;
+
+ l_err = nvdimmReadReg(i_nvdimm, ARM_STATUS, l_data);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckArmSuccess() nvdimm[%X]"
+ "failed to read arm status reg!",TARGETING::get_huid(i_nvdimm));
+ }
+ else if ((l_data & ARM_SUCCESS) != ARM_SUCCESS)
+ {
+
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckArmSuccess() nvdimm[%X]"
+ "failed to arm!",TARGETING::get_huid(i_nvdimm));
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_ARM_FAILED
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_SET_ARM
+ *@userdata1[0:31] Related ops (0xff = NA)
+ *@userdata1[32:63] Target Huid
+ *@userdata2 <UNUSED>
+ *@devdesc Encountered error arming the catastrophic save
+ * trigger on NVDIMM. Make sure an energy source
+ * is connected to the NVDIMM and the ES policy
+ * is set properly
+ *@custdesc NVDIMM encountered error arming save trigger
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_SET_ARM,
+ NVDIMM_ARM_FAILED,
+ NVDIMM_SET_USER_DATA_1(ARM, TARGETING::get_huid(i_nvdimm)),
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //failure to arm could mean internal NV controller error or
+ //even error on the battery pack. NVDIMM will lose persistency
+ //if failed to arm trigger
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmCheckArmSuccess() nvdimm[%X] ret[%X]",
+ TARGETING::get_huid(i_nvdimm), l_data);
+
+ return l_err;
+}
+
+/**
+ * @brief This function arms the trigger to enable backup in the event
+ * of power loss (DDR Reset_n goes low)
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmArmResetN(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmArmResetN() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmWriteReg(i_nvdimm, ARM_CMD, ARM_DIMM);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmArmResetN() nvdimm[%X] error arming nvdimm!!",
+ TARGETING::get_huid(i_nvdimm));
+ }
+ else
+ {
+ // Arm happens one module at a time. No need to set any offset on the counter
+ uint32_t l_poll = 0;
+ l_err = nvdimmPollArmDone(i_nvdimm, l_poll);
+ if (!l_err)
+ {
+ l_err = nvdimmCheckArmSuccess(i_nvdimm);
+ }
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArmResetN() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+ return l_err;
+}
+
+/**
+ * @brief This function checks for valid image on the given target
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_imgValid - return true if the target has a valid image
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmValidImage(Target *i_nvdimm, bool &o_imgValid)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmValidImage(): nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+ uint8_t l_data = 0x0;
+ o_imgValid = false;
+
+ l_err = nvdimmReadReg(i_nvdimm, CSAVE_INFO, l_data);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmValidImage() nvdimm[%X]"
+ "failed to for image!",TARGETING::get_huid(i_nvdimm) );
+ }
+ else if(l_data & VALID_IMAGE)
+ {
+ o_imgValid = true;
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmValidImage(): nvdimm[%X] ret[%X]",
+ TARGETING::get_huid(i_nvdimm), l_data);
+
+ return l_err;
+}
+
+/**
+ * @brief This function handles all the restore related operations.
+ * SRE -> restore -> SRX/RCD/MRS
+ *
+ * @param[in] i_nvdimmList - list of nvdimms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList)
+{
+ errlHndl_t l_err = nullptr;
+ bool l_imgValid;
+ uint8_t l_rstrValid;
+ uint32_t l_poll = 0;
+
+ do
+ {
+ // Put NVDIMM into self-refresh
+ for (TargetHandleList::iterator it = i_nvdimmList.begin();
+ it != i_nvdimmList.end();)
+ {
+ l_err = nvdimmValidImage(*it, l_imgValid);
+
+ // No reason to run if we can't figure out
+ // if there is an image or not
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(*it, NSTD_ERR_NOPRSV);
+ break;
+ }
+
+ if (!l_imgValid)
+ {
+ nvdimmSetStatusFlag(*it, NSTD_VAL_NOPRSV);
+ i_nvdimmList.erase(it);
+ continue;
+ }
+
+ TARGETING::TargetHandleList l_mcaList;
+ getParentAffinityTargets(l_mcaList, *it, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA);
+ assert(l_mcaList.size(), "nvdimmRestore() failed to find parent MCA.");
+
+ fapi2::Target<fapi2::TARGET_TYPE_MCA> l_fapi_mca(l_mcaList[0]);
+
+ // Self-refresh is done at the port level
+ FAPI_INVOKE_HWP(l_err, mss::nvdimm::self_refresh_entry, l_fapi_mca);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore() HUID[%X] self_refresh_entry failed!",
+ TARGETING::get_huid(*it));
+
+ nvdimmSetStatusFlag(*it, NSTD_ERR_NOPRSV);
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //Without SRE the data could be not reliably restored
+ break;
+ }
+ it++;
+ }
+
+ if (l_err)
+ {
+ break;
+ }
+
+ // Nothing to do. Move on.
+ if (i_nvdimmList.empty())
+ {
+ break;
+ }
+
+ // Kick off the restore on each nvdimm in the nvdimm list
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ l_err = nvdimmWriteReg(l_nvdimm, NVDIMM_FUNC_CMD, RESTORE_IMAGE);
+ if (l_err)
+ {
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //failing here is likely an NV controller/i2c problem
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X], error initiating restore!!",
+ TARGETING::get_huid(l_nvdimm));
+ break;
+ }
+ }
+
+ if (l_err)
+ {
+ break;
+ }
+
+ // Make sure the restore completed
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ // Since we kicked off the restore on all the modules at once, the restore
+ // should complete on all of the modules in one restore window. Use the
+ // polled time from the previous nvdimm as the offset for the next one.
+ l_err = nvdimmPollRestoreDone(l_nvdimm, l_poll);
+ if (l_err)
+ {
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //Restore is taking longer than the allotted time here.
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV);
+ errlCommit(l_err, NVDIMM_COMP_ID);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X], error restoring!",
+ TARGETING::get_huid(l_nvdimm));
+ break;
+ }
+ }
+
+ if (l_err)
+ {
+ break;
+ }
+
+ // Make sure the restore is valid
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ l_err = nvdimmGetRestoreValid(l_nvdimm, l_rstrValid);
+ if (l_err)
+ {
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //failing here is likely an NV controller/i2c problem
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore Target[%X] error validating restore status!",
+ TARGETING::get_huid(l_nvdimm));
+ break;
+ }
+
+ if ((l_rstrValid & RSTR_SUCCESS) != RSTR_SUCCESS){
+
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X] restoreValid[%d], restore failed!",
+ TARGETING::get_huid(l_nvdimm), l_rstrValid);
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_RESTORE_FAILED
+ *@severity ERRORLOG_SEV_UNRECOVERABLE
+ *@moduleid NVDIMM_RESTORE
+ *@userdata1 Target Huid
+ *@userdata2 <UNUSED>
+ *@devdesc NVDIMM failed to restore data. This is likely
+ * due to failure entering self-refresh and/or
+ * restore timeout (Controller error)
+ *@custdesc NVDIMM failed to restore data
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ NVDIMM_RESTORE,
+ NVDIMM_RESTORE_FAILED,
+ TARGETING::get_huid(l_nvdimm),
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT);
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV);
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //Invalid restore could be due to dram not in self-refresh
+ //or controller issue. Data should not be trusted at this point
+ break;
+ }
+ }
+
+ if (l_err)
+ {
+ break;
+ }
+
+ // Exit self-refresh
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+
+ TARGETING::TargetHandleList l_mcaList;
+ getParentAffinityTargets(l_mcaList, l_nvdimm, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA);
+ assert(l_mcaList.size(), "nvdimmRestore() failed to find parent MCA.");
+
+ fapi2::Target<fapi2::TARGET_TYPE_MCA> l_fapi_mca(l_mcaList[0]);
+
+ // This is done again at the port level
+ // Post restore consists of exiting self-refresh, restoring MRS/RCD, and running ZQCAL
+ FAPI_INVOKE_HWP(l_err, mss::nvdimm::post_restore_transition, l_fapi_mca);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore() HUID[%X] post_restore_transition failed!",
+ TARGETING::get_huid(l_nvdimm));
+
+ // Commit the error from the HWP
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV);
+ break;
+ }
+ else
+ {
+ // Restore success!
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_VAL_PRSV);
+ }
+ }
+
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmRestore() restore completed!!");
+
+ return l_err;
+}
+
+/**
+ * @brief This function checks the erase status register to make sure
+ * the last erase completed witout error
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmCheckEraseSuccess(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmCheckEraseSuccess() : nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ uint8_t l_data = 0;
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmReadReg(i_nvdimm, ERASE_STATUS, l_data);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckEraseSuccess() nvdimm[%X]"
+ "failed to read erase status reg!",TARGETING::get_huid(i_nvdimm));
+ }
+ else if ((l_data & ERASE_SUCCESS) != ERASE_SUCCESS)
+ {
+
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckEraseSuccess() nvdimm[%X]"
+ "failed to erase!",TARGETING::get_huid(i_nvdimm));
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_ERASE_FAILED
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_CHECK_ERASE
+ *@userdata1[0:31] Related ops (0xff = NA)
+ *@userdata1[32:63] Target Huid
+ *@userdata2 <UNUSED>
+ *@devdesc Encountered error erasing previously stored data image
+ * on NVDIMM. Likely due to timeout and/or controller error
+ *@custdesc NVDIMM error erasing data image
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_CHECK_ERASE,
+ NVDIMM_ERASE_FAILED,
+ NVDIMM_SET_USER_DATA_1(ERASE, TARGETING::get_huid(i_nvdimm)),
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ //@TODO RTC 199645 - add HW callout on dimm target.
+ //failure to erase could mean internal NV controller error and/or
+ //HW error on nand flash. NVDIMM will lose persistency if failed to
+ //erase nand flash
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmCheckEraseSuccess(): nvdimm[%X] ret[%X]",
+ TARGETING::get_huid(i_nvdimm), l_data);
+
+ return l_err;
+}
+
+/**
+ * @brief This function erases image on the nvdimm target
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmEraseNF(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmEraseNF() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ do
+ {
+ l_err = nvdimmWriteReg(i_nvdimm, NVDIMM_FUNC_CMD, ERASE_IMAGE);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X] error initiating erase!!",
+ TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+
+ // Erase happens one module at a time. No need to set any offset on the counter
+ uint32_t l_poll = 0;
+ l_err = nvdimmPollEraseDone(i_nvdimm, l_poll);
+ if (!l_err)
+ {
+ l_err = nvdimmCheckEraseSuccess(i_nvdimm);
+ }
+
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmEraseNF() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief This functions opens the NV controller to the specified page
+ * Refer to the BAEBI to see what each page does
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_page - page number to open to
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log
+ */
+errlHndl_t nvdimmOpenPage(Target *i_nvdimm,
+ uint8_t i_page)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmOpenPage nvdimm[%X]", TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+ bool l_success = false;
+ uint8_t l_data;
+ uint32_t l_poll = 0;
+
+ uint32_t l_target_timeout_values[6];
+ assert(i_nvdimm->tryGetAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(l_target_timeout_values),
+ "nvdimmOpenPage() HUID[%X], failed reading ATTR_NV_OPS_TIMEOUT_MSEC!", TARGETING::get_huid(i_nvdimm));
+
+ uint32_t l_timeout = l_target_timeout_values[PAGE_SWITCH];
+
+ do
+ {
+
+ l_err = nvdimmWriteReg(i_nvdimm, OPEN_PAGE, i_page);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmOpenPage nvdimm[%X]"
+ "error writing to page change reg", TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+
+ // This should not take long, but putting a loop here anyway
+ // to make sure it finished within time
+ // Not using the nvdimmPollStatus since this is polled differently
+ do
+ {
+ l_err = nvdimmReadReg(i_nvdimm, OPEN_PAGE, l_data);
+ if (l_err){
+ break;
+ }
+
+ if (l_data == i_page){
+ l_success = true;
+ break;
+ }
+
+ nanosleep(0, PAGE_SWITCH_POLL_TIME_NS);
+ l_poll += PAGE_SWITCH_POLL_TIME_NS;
+
+ }while (l_poll < l_timeout*NS_PER_MSEC);
+
+ if (l_err)
+ {
+ break;
+ }
+
+ //timed out
+ if (!l_success && !l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmOpenPage nvdimm[%X] openpage_success[%d],"
+ "failure to open page!", TARGETING::get_huid(i_nvdimm), static_cast<uint8_t>(l_success));
+
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_OPEN_PAGE_TIMEOUT
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_OPEN_PAGE
+ *@userdata1[0:31] Related ops (0xff = NA)
+ *@userdata1[32:63] Target Huid
+ *@userdata2[0:31] Polled value
+ *@userdata2[32:63] Timeout value
+ *@devdesc NVDIMM OpenPage timed out, likely due to controller error
+ *@custdesc Encountered error performing internal operaiton
+ * on NVDIMM
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_POLL_STATUS,
+ NVDIMM_STATUS_TIMEOUT,
+ NVDIMM_SET_USER_DATA_1(PAGE_SWITCH, TARGETING::get_huid(i_nvdimm)),
+ NVDIMM_SET_USER_DATA_2_TIMEOUT(l_poll, l_timeout),
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ //@TODO RTC 199645 - add HW callout on dimm target.
+ //failure to open page most likely means problem with
+ //the NV controller.
+ }
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmOpenPage nvdimm[%X] nvdimmOpenPage.success[%d],"
+ ,TARGETING::get_huid(i_nvdimm), static_cast<uint8_t>(l_success));
+
+ return l_err;
+}
+
+/**
+ * @brief This function gets the timeout values and fill out
+ * ATTR_NV_OPS_TIMEOUT_MSEC for nvdimm
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmGetTimeoutVal() HUID[%X]"
+ ,TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+ uint8_t l_data = 0;
+ uint32_t timeout_map[6];
+ i_nvdimm->tryGetAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(timeout_map);
+
+ //Get the 6 main timeout values
+ for (uint8_t i = SAVE; i <= CHARGE; i++){
+
+ // Some timeout value maybe in different page
+ l_err = nvdimmOpenPage(i_nvdimm, timeoutInfoTable[i].page);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmGetTimeoutVal() HUID[%X] "
+ "failing on nvdimmOpenPage()",TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+
+ // Need to loop thru both offsets to get the full timeout value
+ // The first offset contains the MSByte of the timeout value
+ // with the MSB indicating ms or sec
+ // The second offset contains the LSByte of the value
+ for (uint8_t j = 0; j < NUM_OFFSET; j++){
+
+ timeout_map[i] = timeout_map[i] << 8;
+
+ l_err = nvdimmReadReg(i_nvdimm, timeoutInfoTable[i].offset[j], l_data);
+
+ if (l_err)
+ {
+ break;
+ }
+
+ timeout_map[i] = timeout_map[i] | static_cast<uint32_t>(l_data);
+
+ }
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmGetTimeoutVal() HUID[%X] "
+ "error reading timeout value for op[%d]!", TARGETING::get_huid(i_nvdimm), i);
+ break;
+ }
+
+ //Converting to msec depending on bit 15. 1 = sec, 0 = msec
+ //except for charge. Charge is only in seconds so convert anyway
+ if (timeout_map[i] >= 0x8000 || i == CHARGE){
+ timeout_map[i] = timeout_map[i] & 0x7FFF;
+ timeout_map[i] = timeout_map[i] * MS_PER_SEC;
+ }
+
+ TRACFCOMP(g_trac_nvdimm, "nvdimmGetTimeoutVal() HUID[%X], timeout_idx[%d], timeout_ms[%d]"
+ ,TARGETING::get_huid(i_nvdimm), timeoutInfoTable[i].idx, timeout_map[i]);
+ }
+
+ if (!l_err)
+ {
+ i_nvdimm->setAttr<TARGETING::ATTR_NV_OPS_TIMEOUT_MSEC>(timeout_map);
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmGetTimeoutVal() HUID[%X]"
+ ,TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief Entry function to NVDIMM management
+ * - Restore image from NVDIMM NAND flash to DRAM
+ * - Arms the backup trigger to ddr_reset_n once the restore
+ * is completed
+ * - Erase image
+ *
+ * @param[in] i_nvdimmList - list of nvdimm targets
+ *
+ */
+void nvdimm_restore(TargetHandleList &i_nvdimmList)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_restore()");
+ errlHndl_t l_err = nullptr;
+
+ do
+ {
+ // Typically during init the NV controller defaults the page
+ // to 0, but it doesn't in warmboot because the controller
+ // doesn't get power cycled. So, let's change it to page 0
+ // anyway right at the beginning.
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ l_err = nvdimmOpenPage(l_nvdimm, ZERO);
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR);
+ break;
+ }
+
+ }
+
+ if (l_err)
+ {
+ errlCommit( l_err, NVDIMM_COMP_ID );
+
+ // @TODO-RTC:200275-Make logic generic for all system configs
+ // Because of interleaving, if one is garded the other one
+ // in the pair should be garded by association. So, let's
+ // move on since there is nothing else to do.
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing open page");
+ break;
+ }
+
+ // Before proceeding, make sure the NV controller
+ // is in ready state.
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ l_err = nvdimmReady(l_nvdimm);
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR);
+ break;
+ }
+ }
+
+ if (l_err)
+ {
+ // If this failing right off the bat,
+ // something isn't quite right with
+ // the module
+ errlCommit(l_err, NVDIMM_COMP_ID);
+
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmReady()");
+ break;
+ }
+
+ // Set the energy policy to device-managed
+ // Don't think this is needed for the supercaps to start charging
+ // but on some devices this is needed to get the charge timeout value
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ l_err = nvdimmSetESPolicy(l_nvdimm);
+ if (l_err)
+ {
+ // Failing this is an indication of power pack issue.
+ // This will prevent future backup, but let's continue
+ // since we can still restore the data if there is any
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmSetESPolicy()");
+ }
+ }
+
+ // Get the timeout values for the major ops at init
+ if (init){
+ for (const auto & l_nvdimm : i_nvdimmList){
+ l_err = nvdimmGetTimeoutVal(l_nvdimm);
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR);
+ break;
+ }
+ }
+ init = false;
+ }
+
+ if (l_err)
+ {
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmGetTimeoutVal()");
+ break;
+ }
+
+ // Change back to page 0 just in case, as all of the remaining
+ // operations will be using offsets in page 0
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ l_err = nvdimmOpenPage(l_nvdimm, ZERO);
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR);
+ break;
+ }
+
+ }
+
+ if (l_err)
+ {
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing open page");
+ break;
+ }
+
+ // Start the restore
+ l_err = nvdimmRestore(i_nvdimmList);
+
+ if (l_err)
+ {
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmRestore()");
+ break;
+ }
+
+ // Make sure the energy source is fully charged before erasing the images
+ // Doing this on all the nvdimms since the ones w/o image will need
+ // to be fully charged before arming the trigger
+ uint32_t l_poll = 0;
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ l_err = nvdimmPollESChargeStatus(l_nvdimm, l_poll);
+
+ if (l_err){
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ }
+ }
+
+ // @TODO move arm and erase to pm_common.C, after occ has started
+
+ // From this point forward, we only want to set up the trigger on the
+ // nvdimm that is not in error state. Any nvdimm in error state will
+ // get to preserve the data previously saved and recover if needed.
+
+ // Arm the nvdimm to trigger save on RESET_n
+ // and erase the image
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ // skip if the nvdimm is in error state
+ if (nvdimmInErrorState(l_nvdimm))
+ {
+ continue;
+ }
+
+ l_err = nvdimmArmResetN(l_nvdimm);
+ if (l_err)
+ {
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ continue;
+ }
+
+ l_err = nvdimmEraseNF(l_nvdimm);
+ if (l_err){
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP);
+ }
+ }
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_restore()");
+}
+
+} // end NVDIMM namespace
diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H
new file mode 100644
index 000000000..12a2ee2aa
--- /dev/null
+++ b/src/usr/isteps/nvdimm/nvdimm.H
@@ -0,0 +1,151 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/isteps/nvdimm/nvdimm.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2018 */
+/* [+] 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 NVDIMM_H__
+#define NVDIMM_H__
+
+#include <usr/errl/errlentry.H>
+#include <targeting/common/commontargeting.H>
+#include <targeting/common/util.H>
+#include <targeting/common/utilFilter.H>
+#include <i2c/eepromif.H>
+#include <map>
+
+using namespace EEPROM;
+
+namespace NVDIMM
+{
+
+//Defining necessary offsets for page0
+//Refer to BAEBI spec for details
+//https://www.jedec.org/standards-documents/docs/jesd245a
+enum i2cReg : uint8_t
+{
+ ARM_CMD = 0x45,
+ ARM_STATUS = 0x6A,
+ NVDIMM_FUNC_CMD = 0x43,
+ NVDIMM_CMD_STATUS0 = 0x61,
+ CSAVE_INFO = 0x80,
+ CSAVE_STATUS = 0x64,
+ RESTORE_STATUS = 0x66,
+ SET_ES_POLICY_CMD = 0x49,
+ SET_ES_POLICY_STATUS = 0x70,
+ NVDIMM_MGT_CMD0 = 0x40,
+ ERASE_STATUS = 0x68,
+ MODULE_HEALTH = 0xA0,
+ MODULE_HEALTH_STATUS0 = 0xA1,
+ MODULE_HEALTH_STATUS1 = 0xA2,
+ OPEN_PAGE = 0x00,
+ NVDIMM_READY = 0x60,
+};
+
+// Up to 10 pages per BAEBI Spec,
+// but use page 0 mostly
+enum page : uint8_t
+{
+ ZERO = 0x00,
+ ONE = 0x01,
+ TWO = 0x02,
+ THREE = 0x03,
+ FOUR = 0x04,
+};
+
+// Enums for inputs/expected output to/from the i2c registers
+enum i2c_in_values : uint8_t
+{
+ ARM_DIMM = 0x04, //0x04 to trigger on RESET_n
+ ES_DEV_MANAGE = 0x01, //0x01 for device manage
+ ERASE_IMAGE = 0x08,
+ RESTORE_IMAGE = 0x04,
+ RESET_CTRLR = 0x01,
+ VALID_IMAGE = 0x01,
+ PAGE_SWITCH_POLL_TIME_NS = 100,
+};
+
+enum i2c_out_values : uint8_t
+{
+ SAVE_IN_PROGRESS = 0x05,
+ RSTR_IN_PROGRESS = 0x09,
+ ERASE_IN_PROGRESS = 0x11,
+ ARM_IN_PROGRESS = 0x41,
+ CHARGE_IN_PROGRESS = 0x41,
+ SAVE_SUCCESS = 0x01,
+ RSTR_SUCCESS = 0X01,
+ ARM_SUCCESS = 0X09,
+ ERASE_SUCCESS = 0X01,
+ ES_SUCCESS = 0x05,
+ CHARGE_SUCCESS = 0x00,
+ NV_READY = 0xA5,
+};
+
+// Timeout-related enum
+enum timeout : uint32_t
+{
+ OPS_POLL_TIME_MS = 5000,
+};
+
+// Assign an id to each of the 6 major ops
+enum ops_id : uint8_t
+{
+ SAVE = 0,
+ RESTORE,
+ ERASE,
+ ARM,
+ PAGE_SWITCH,
+ CHARGE,
+};
+
+/**
+ * @brief Wrapper to call deviceOp to read the NV controller via I2C
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_addr - address/offset for the register to be read
+ *
+ * @param[out] o_data - returned data from read
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmReadReg(TARGETING::Target* i_nvdimm, uint8_t i_addr, uint8_t & o_data );
+
+/**
+ * @brief Wrapper to call deviceOp to write the NV controller via I2C
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_addr - address/offset for the register to be written
+ *
+ * @param[in] i_data - data to register
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmWriteReg(TARGETING::Target* i_nvdimm, uint8_t i_addr, uint8_t i_data );
+
+} //End NVDIMM namespace
+
+
+#endif // NVDIMM_H__
OpenPOWER on IntegriCloud