summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build/configs/fsprelease.config1
-rw-r--r--src/include/usr/isteps/istep13list.H5
-rw-r--r--src/include/usr/isteps/istep14list.H6
-rw-r--r--src/include/usr/isteps/istep21list.H5
-rw-r--r--src/include/usr/isteps/nvdimm/nvdimm.H20
-rw-r--r--src/include/usr/vpd/spdenums.H5
-rw-r--r--src/usr/isteps/istep13/call_mss_draminit.C20
-rw-r--r--src/usr/isteps/istep14/call_mss_power_cleanup.C198
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.C568
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.H300
-rw-r--r--src/usr/isteps/nvdimm/runtime/nvdimm_rt.C136
-rw-r--r--src/usr/isteps/pm/runtime/rt_pm.C2
-rwxr-xr-xsrc/usr/vpd/spdDDR4.H3
13 files changed, 881 insertions, 388 deletions
diff --git a/src/build/configs/fsprelease.config b/src/build/configs/fsprelease.config
index 16310594c..ebebfdf50 100644
--- a/src/build/configs/fsprelease.config
+++ b/src/build/configs/fsprelease.config
@@ -12,6 +12,7 @@ unset NO_SBE_UPDATES
unset BMC_BT_LPC_IPMI
unset HTMGT
set FSP_BUILD
+set NVDIMM
set CONFIG_NVDIMM
diff --git a/src/include/usr/isteps/istep13list.H b/src/include/usr/isteps/istep13list.H
index fd0430c6c..d4788913d 100644
--- a/src/include/usr/isteps/istep13list.H
+++ b/src/include/usr/isteps/istep13list.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2017 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -296,6 +296,9 @@ const DepModInfo g_istep13Dependancies = {
DEP_LIB(libistep13.so),
DEP_LIB(libisteps_mss.so),
DEP_LIB(libcen.so),
+#ifdef CONFIG_NVDIMM
+ DEP_LIB(libnvdimm.so),
+#endif
NULL
}
};
diff --git a/src/include/usr/isteps/istep14list.H b/src/include/usr/isteps/istep14list.H
index 1a2058167..bf5b00453 100644
--- a/src/include/usr/isteps/istep14list.H
+++ b/src/include/usr/isteps/istep14list.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2018 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -169,7 +169,11 @@ namespace INITSERVICE
{
ISTEPNAME(14,04,"mss_power_cleanup"),
ISTEP_14::call_mss_power_cleanup,
+#ifdef CONFIG_NVDIMM
+ { START_FN, EXT_IMAGE, MPIPL_OP | NORMAL_IPL_OP, true }
+#else
{ START_FN, EXT_IMAGE, NORMAL_IPL_OP, true }
+#endif
},
{
ISTEPNAME(14,05,"proc_setup_bars"),
diff --git a/src/include/usr/isteps/istep21list.H b/src/include/usr/isteps/istep21list.H
index 582ecf292..fabfc4be6 100644
--- a/src/include/usr/isteps/istep21list.H
+++ b/src/include/usr/isteps/istep21list.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2018 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -132,6 +132,9 @@ const DepModInfo g_istep21Dependancies = {
#ifndef CONFIG_FSP_BUILD
DEP_LIB(libnvram.so),
#endif
+#ifdef CONFIG_NVDIMM
+ DEP_LIB(libnvdimm.so),
+#endif
NULL
}
};
diff --git a/src/include/usr/isteps/nvdimm/nvdimm.H b/src/include/usr/isteps/nvdimm/nvdimm.H
index c1df3033e..6f6b46541 100644
--- a/src/include/usr/isteps/nvdimm/nvdimm.H
+++ b/src/include/usr/isteps/nvdimm/nvdimm.H
@@ -29,7 +29,7 @@
namespace NVDIMM
{
-enum
+enum nvdimm_err_status
{
NSTD_VAL_NOPRSV = 0x08, // memory valid, contents not preserved (genesis)
NSTD_VAL_NOPRSV_MASK = 0xF7,
@@ -41,6 +41,7 @@ enum
NSTD_ERR_NOBKUP_MASK = 0xFE,
NSTD_ERR = 0x03, // NSTD_ERR_NOPRSV+NSTD_ERR_NOBKUP
};
+
#ifndef __HOSTBOOT_RUNTIME
/**
* @brief Entry function to NVDIMM management
@@ -76,7 +77,6 @@ errlHndl_t nvdimmEraseNF(TARGETING::Target *i_nvdimm);
*/
void nvdimmSetStatusFlag(TARGETING::Target *i_nvdimm, const uint8_t i_status_flag);
-
#ifdef __HOSTBOOT_RUNTIME
/**
@@ -89,15 +89,16 @@ void nvdimmSetStatusFlag(TARGETING::Target *i_nvdimm, const uint8_t i_status_fla
bool nvdimmInErrorState(TARGETING::Target *i_nvdimm);
/**
- * @brief This function arms the trigger to enable backup in the event
- * of power loss (DDR Reset_n goes low)
+ * @brief This function arms/disarms the trigger based on i_state
*
* @param[in] i_nvdimm - nvdimm target with NV controller
*
+ * @param[in] i_state - true to arm, false to disarm
+ *
* @return errlHndl_t - Null if successful, otherwise a pointer to
* the error log.
*/
-errlHndl_t nvdimmArmResetN(TARGETING::Target *i_nvdimm);
+errlHndl_t nvdimmChangeArmState(TARGETING::Target *i_nvdimm, bool i_state);
/**
* @brief Arms the trigger to enable backup in the event of a power loss
@@ -113,7 +114,6 @@ errlHndl_t nvdimmArmResetN(TARGETING::Target *i_nvdimm);
*/
bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList);
-
/**
* @brief NVDIMM protection state
*
@@ -139,6 +139,14 @@ enum nvdimm_protection_t
errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target,
const nvdimm_protection_t i_state);
#endif
+/**
+ * @brief Entry function to NVDIMM initialization
+ * - Checks for ready state
+ * - Waits for the ongoing backup to complete
+ * - Disarms the trigger for draminit
+ * @param i_target nvdimm target
+ */
+void nvdimm_init(TARGETING::Target *i_nvdimm);
}
diff --git a/src/include/usr/vpd/spdenums.H b/src/include/usr/vpd/spdenums.H
index 9decbe862..bd6418d5e 100644
--- a/src/include/usr/vpd/spdenums.H
+++ b/src/include/usr/vpd/spdenums.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2016 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -142,7 +142,8 @@ enum
MODULE_REVISION_CODE_DDR4 = MODULE_REVISION_CODE,
DRAM_STEPPING = SPD_FIRST_NORM_KEYWORD | 0x57,
MANUFACTURING_SECTION_CRC = SPD_FIRST_NORM_KEYWORD | 0x58,
- SPD_LAST_NORM_KEYWORD = SPD_FIRST_NORM_KEYWORD | 0x58,
+ NVM_INIT_TIME = SPD_FIRST_NORM_KEYWORD | 0x59,
+ SPD_LAST_NORM_KEYWORD = SPD_FIRST_NORM_KEYWORD | 0x59,
// ==============================================================
// Module Specific Keywords (Available for both DDR3 and DDR4 DIMMs)
diff --git a/src/usr/isteps/istep13/call_mss_draminit.C b/src/usr/isteps/istep13/call_mss_draminit.C
index 00d69f5f3..915bc992b 100644
--- a/src/usr/isteps/istep13/call_mss_draminit.C
+++ b/src/usr/isteps/istep13/call_mss_draminit.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -50,6 +50,11 @@
#include <p9_mss_draminit.H>
#include <p9c_mss_draminit.H>
+#ifdef CONFIG_NVDIMM
+// NVDIMM support
+#include <isteps/nvdimm/nvdimm.H>
+#endif
+
using namespace ERRORLOG;
using namespace ISTEP;
using namespace ISTEP_ERROR;
@@ -161,6 +166,19 @@ void* call_mss_draminit (void *io_pArgs)
fapi2::Target<fapi2::TARGET_TYPE_MCBIST> l_fapi_mcbist_target
(l_mcbist_target);
+ // Initialize the NVDIMMs before hitting draminit
+#ifdef CONFIG_NVDIMM
+ TARGETING::TargetHandleList l_dimmTargetList;
+ getChildAffinityTargets(l_dimmTargetList, l_mcbist_target, CLASS_NA, TYPE_DIMM);
+
+ for (const auto & l_dimm : l_dimmTargetList)
+ {
+ if (isNVDIMM(l_dimm))
+ {
+ NVDIMM::nvdimm_init(l_dimm);
+ }
+ }
+#endif
FAPI_INVOKE_HWP(l_err, p9_mss_draminit, l_fapi_mcbist_target);
if (l_err)
diff --git a/src/usr/isteps/istep14/call_mss_power_cleanup.C b/src/usr/isteps/istep14/call_mss_power_cleanup.C
index 5c27dcc67..3ca963678 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,2018 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -60,43 +60,50 @@ void* call_mss_power_cleanup (void *io_pArgs)
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"call_mss_power_cleanup entry" );
- TARGETING::TargetHandleList l_mcbistTargetList;
- getAllChiplets(l_mcbistTargetList, TYPE_MCBIST);
-
- for (const auto & l_target : l_mcbistTargetList)
+ TARGETING::Target* l_sys = nullptr;
+ TARGETING::targetService().getTopLevelTarget( l_sys );
+ assert(l_sys, "call_mss_power_cleanup: no TopLevelTarget");
+ uint8_t l_mpipl = l_sys->getAttr<ATTR_IS_MPIPL_HB>();
+ if (!l_mpipl)
{
- // Dump current run on target
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "Running mss_power_cleanup HWP on "
- "target HUID %.8X",
- TARGETING::get_huid(l_target));
+ TARGETING::TargetHandleList l_mcbistTargetList;
+ getAllChiplets(l_mcbistTargetList, TYPE_MCBIST);
- fapi2::Target <fapi2::TARGET_TYPE_MCBIST> l_fapi_target
- (l_target);
+ for (const auto & l_target : l_mcbistTargetList)
+ {
+ // Dump current run on target
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "Running mss_power_cleanup HWP on "
+ "target HUID %.8X",
+ TARGETING::get_huid(l_target));
- // call the HWP with each fapi2::Target
- FAPI_INVOKE_HWP(l_err, p9_mss_power_cleanup, l_fapi_target);
+ fapi2::Target <fapi2::TARGET_TYPE_MCBIST> l_fapi_target
+ (l_target);
- if (l_err)
- {
- TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "ERROR 0x%.8X: mss_power_cleanup HWP returns error",
- l_err->reasonCode());
+ // call the HWP with each fapi2::Target
+ FAPI_INVOKE_HWP(l_err, p9_mss_power_cleanup, l_fapi_target);
- // capture the target data in the elog
- ErrlUserDetailsTarget(l_target).addToLog(l_err);
+ if (l_err)
+ {
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "ERROR 0x%.8X: mss_power_cleanup HWP returns error",
+ l_err->reasonCode());
- // Create IStep error log and cross reference to error that
- // occurred
- l_stepError.addErrorDetails( l_err );
+ // capture the target data in the elog
+ ErrlUserDetailsTarget(l_target).addToLog(l_err);
- // Commit Error
- errlCommit( l_err, HWPF_COMP_ID );
- }
- else
- {
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "SUCCESS : mss_power_cleanup HWP( )" );
+ // Create IStep error log and cross reference to error that
+ // occurred
+ l_stepError.addErrorDetails( l_err );
+
+ // Commit Error
+ errlCommit( l_err, HWPF_COMP_ID );
+ }
+ else
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "SUCCESS : mss_power_cleanup HWP( )" );
+ }
}
}
@@ -131,76 +138,79 @@ void* call_mss_power_cleanup (void *io_pArgs)
// -- Cumulus only
// Get a list of all present Centaurs
- TargetHandleList l_presCentaurs;
- getAllChips(l_presCentaurs, TYPE_MEMBUF);
- // For each present Centaur
- for (TargetHandleList::const_iterator
- l_cenIter = l_presCentaurs.begin();
- l_cenIter != l_presCentaurs.end();
- ++l_cenIter)
+ if (!l_mpipl)
{
- // Make a local copy of the target for ease of use
- TARGETING::Target * l_pCentaur = *l_cenIter;
- // Retrieve HUID of current Centaur
- TARGETING::ATTR_HUID_type l_currCentaurHuid =
- TARGETING::get_huid(l_pCentaur);
-
- // Find all present MBAs associated with this Centaur
- TARGETING::TargetHandleList l_presMbas;
- getChildChiplets(l_presMbas, l_pCentaur,TYPE_MBA);
-
- // If not at least two MBAs found
- if (l_presMbas.size() < 2)
+ TargetHandleList l_presCentaurs;
+ getAllChips(l_presCentaurs, TYPE_MEMBUF);
+ // For each present Centaur
+ for (TargetHandleList::const_iterator
+ l_cenIter = l_presCentaurs.begin();
+ l_cenIter != l_presCentaurs.end();
+ ++l_cenIter)
{
- TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "Not enough MBAs found for Centaur target HUID %.8X, "
- "skipping this Centaur.",
- l_currCentaurHuid);
- continue;
- }
-
- // Cache current MBA HUIDs for tracing
- TARGETING::ATTR_HUID_type l_currMBA0Huid =
- TARGETING::get_huid(l_presMbas[0]);
- TARGETING::ATTR_HUID_type l_currMBA1Huid =
- TARGETING::get_huid(l_presMbas[1]);
-
- TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "Running mss_power_cleanup HWP on "
- "Centaur HUID %.8X, MBA0 HUID %.8X, "
- "MBA1 HUID %.8X, ", l_currCentaurHuid,
- l_currMBA0Huid, l_currMBA1Huid);
-
- // Create FAPI Targets.
- fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> l_fapiCentaurTarget( l_pCentaur );
- fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET> l_fapiMba0Target( l_presMbas[0] );
- fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET> l_fapiMba1Target( l_presMbas[1] );
+ // Make a local copy of the target for ease of use
+ TARGETING::Target * l_pCentaur = *l_cenIter;
+ // Retrieve HUID of current Centaur
+ TARGETING::ATTR_HUID_type l_currCentaurHuid =
+ TARGETING::get_huid(l_pCentaur);
+
+ // Find all present MBAs associated with this Centaur
+ TARGETING::TargetHandleList l_presMbas;
+ getChildChiplets(l_presMbas, l_pCentaur,TYPE_MBA);
+
+ // If not at least two MBAs found
+ if (l_presMbas.size() < 2)
+ {
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "Not enough MBAs found for Centaur target HUID %.8X, "
+ "skipping this Centaur.",
+ l_currCentaurHuid);
+ continue;
+ }
- // Call the HWP with each fapi::Target
- FAPI_INVOKE_HWP(l_err, p9c_mss_power_cleanup, l_fapiCentaurTarget,
- l_fapiMba0Target, l_fapiMba1Target);
+ // Cache current MBA HUIDs for tracing
+ TARGETING::ATTR_HUID_type l_currMBA0Huid =
+ TARGETING::get_huid(l_presMbas[0]);
+ TARGETING::ATTR_HUID_type l_currMBA1Huid =
+ TARGETING::get_huid(l_presMbas[1]);
- if (l_err)
- {
- TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "mss_power_cleanup HWP failed to perform"
- " cleanup on centaur: 0x%.8X HWP_ERROR: 0x%.8X",
- l_currCentaurHuid,l_err->reasonCode());
- // Capture the target data in the error log
- ErrlUserDetailsTarget(l_pCentaur).addToLog(l_err);
- // Create IStep error log and cross reference error that occurred
- l_stepError.addErrorDetails(l_err);
- // Commit error
- errlCommit(l_err, HWPF_COMP_ID);
- }
- else
- {
- // Success
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "Successfully ran mss_power_cleanup HWP on "
+ "Running mss_power_cleanup HWP on "
"Centaur HUID %.8X, MBA0 HUID %.8X, "
"MBA1 HUID %.8X, ", l_currCentaurHuid,
- l_currMBA0Huid, l_currMBA1Huid);
+ l_currMBA0Huid, l_currMBA1Huid);
+
+ // Create FAPI Targets.
+ fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> l_fapiCentaurTarget( l_pCentaur );
+ fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET> l_fapiMba0Target( l_presMbas[0] );
+ fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET> l_fapiMba1Target( l_presMbas[1] );
+
+ // Call the HWP with each fapi::Target
+ FAPI_INVOKE_HWP(l_err, p9c_mss_power_cleanup, l_fapiCentaurTarget,
+ l_fapiMba0Target, l_fapiMba1Target);
+
+ if (l_err)
+ {
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "mss_power_cleanup HWP failed to perform"
+ " cleanup on centaur: 0x%.8X HWP_ERROR: 0x%.8X",
+ l_currCentaurHuid,l_err->reasonCode());
+ // Capture the target data in the error log
+ ErrlUserDetailsTarget(l_pCentaur).addToLog(l_err);
+ // Create IStep error log and cross reference error that occurred
+ l_stepError.addErrorDetails(l_err);
+ // Commit error
+ errlCommit(l_err, HWPF_COMP_ID);
+ }
+ else
+ {
+ // Success
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "Successfully ran mss_power_cleanup HWP on "
+ "Centaur HUID %.8X, MBA0 HUID %.8X, "
+ "MBA1 HUID %.8X, ", l_currCentaurHuid,
+ l_currMBA0Huid, l_currMBA1Huid);
+ }
}
}
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C
index fdc0240a9..b472896e5 100644
--- a/src/usr/isteps/nvdimm/nvdimm.C
+++ b/src/usr/isteps/nvdimm/nvdimm.C
@@ -39,6 +39,7 @@
#include <lib/mc/port.H>
#include <isteps/nvdimm/nvdimmreasoncodes.H>
#include <isteps/nvdimm/nvdimm.H>
+#include <vpd/spdenums.H>
using namespace TARGETING;
using namespace DeviceFW;
@@ -48,8 +49,8 @@ trace_desc_t* g_trac_nvdimm = NULL;
TRAC_INIT(&g_trac_nvdimm, NVDIMM_COMP_NAME, 2*KILOBYTE);
// Easy macro replace for unit testing
-// #define TRACUCOMP(args...) TRACFCOMP(args)
-#define TRACUCOMP(args...)
+#define TRACUCOMP(args...) TRACFCOMP(args)
+//#define TRACUCOMP(args...)
namespace NVDIMM
@@ -61,29 +62,29 @@ namespace NVDIMM
#define NVDIMM_SET_USER_DATA_2_TIMEOUT(left_32_polled, right_32_timeout) \
NVDIMM_SET_USER_DATA_1(left_32_polled, right_32_timeout)
+#define ADDRESS(uint16_address) \
+ uint16_address & 0x00FF
+
+#define PAGE(uint16_address) \
+ (uint16_address >> 8) & 0x000F
+
typedef struct ops_timeoutInfo{
const char * desc;
- uint8_t page;
- uint8_t offset[2];
+ uint16_t offset[2];
uint8_t idx;
- uint8_t status_reg_offset;
+ uint16_t status_reg_offset;
uint8_t status_progress;
} ops_timeoutInfo_t;
-#ifndef __HOSTBOOT_RUNTIME
-// Init flag to be used upon initial entry to initialize NV_OPS_TIMEOUT_MSEC
-static bool init_nv_timeout = true;
-#endif
-
// 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},
+ {"SAVE", {CSAVE_TIMEOUT1, CSAVE_TIMEOUT0}, SAVE , NVDIMM_CMD_STATUS0, SAVE_IN_PROGRESS},
+ {"RESTORE", {RESTORE_TIMEOUT1, RESTORE_TIMEOUT0}, RESTORE , NVDIMM_CMD_STATUS0, RSTR_IN_PROGRESS},
+ {"ERASE", {ERASE_TIMEOUT1, ERASE_TIMEOUT0}, ERASE , NVDIMM_CMD_STATUS0, ERASE_IN_PROGRESS},
+ {"ARM", {ARM_TIMEOUT1, ARM_TIMEOUT0}, ARM , NVDIMM_CMD_STATUS0, ARM_IN_PROGRESS},
+ {"PAGE_SWITCH", {PAGE_SWITCH_LATENCY1, PAGE_SWITCH_LATENCY0}, PAGE_SWITCH, 0xff, 0xff},
+ {"CHARGE", {ES_CHARGE_TIMEOUT1, ES_CHARGE_TIMEOUT0}, CHARGE , MODULE_HEALTH_STATUS1, CHARGE_IN_PROGRESS},
};
/**
@@ -95,27 +96,63 @@ constexpr ops_timeoutInfo_t timeoutInfoTable[] =
*
* @param[out] o_data - returned data from read
*
+ * @param[in] page_verify - read and verify the page associated to the given address.
+ * Change if needed. Default to true
+ *
* @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 )
+ uint16_t i_addr,
+ uint8_t & o_data,
+ const bool page_verify)
{
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;
+ uint8_t l_reg_addr = ADDRESS(i_addr);
+ uint8_t l_reg_page = PAGE(i_addr);
+
+ do
+ {
+ // If page_verify is true, make sure the current page is set to the page
+ // where i_addr is in and change if needed
+ if (page_verify)
+ {
+ uint8_t l_data = 0;
+ l_err = nvdimmReadReg(i_nvdimm, OPEN_PAGE, l_data, NO_PAGE_VERIFY);
- l_err = DeviceFW::deviceOp( DeviceFW::READ,
- i_nvdimm,
- &o_data,
- l_numBytes,
- DEVICE_NVDIMM_ADDRESS(i_addr));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReadReg() nvdimm[%X] - failed to read the current page",
+ TARGETING::get_huid(i_nvdimm));
+ break;
+ }
- TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Read HUID %X, addr 0x%X = %X",
- TARGETING::get_huid(i_nvdimm), i_addr, o_data);
+ if (l_data != l_reg_page)
+ {
+ l_err = nvdimmOpenPage(i_nvdimm, l_reg_page);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReadReg() nvdimm[%X] - failed to verify page",
+ TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+ }
+ }
+
+ l_err = DeviceFW::deviceOp( DeviceFW::READ,
+ i_nvdimm,
+ &o_data,
+ l_numBytes,
+ DEVICE_NVDIMM_ADDRESS(l_reg_addr));
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Read HUID %X, page 0x%X, addr 0x%X = %X",
+ TARGETING::get_huid(i_nvdimm), l_reg_page, l_reg_addr, o_data);
return l_err;
}
@@ -129,28 +166,63 @@ errlHndl_t nvdimmReadReg(Target* i_nvdimm,
*
* @param[in] i_data - data to be written to register @ i_addr
*
+ * @param[in] page_verify - read and verify the page associated to the given address.
+ * Change if needed. Default to true
+ *
* @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 )
+ uint16_t i_addr,
+ uint8_t i_data,
+ const bool page_verify)
{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Write HUID %X, addr 0x%X = %X",
+ TARGETING::get_huid(i_nvdimm), i_addr, i_data);
+
errlHndl_t l_err = nullptr;
size_t l_numBytes = 1;
+ uint8_t l_reg_addr = ADDRESS(i_addr);
+ uint8_t l_reg_page = PAGE(i_addr);
- TRACUCOMP(g_trac_nvdimm, ENTER_MRK"NVDIMM Write HUID %X, addr 0x%X = %X",
- TARGETING::get_huid(i_nvdimm), i_addr, i_data);
+ do
+ {
+ // If page_verify is true, make sure the current page is set to the page
+ // where i_addr is in and change if needed
+ if (page_verify)
+ {
+ uint8_t l_data = 0;
+ l_err = nvdimmReadReg(i_nvdimm, OPEN_PAGE, l_data, NO_PAGE_VERIFY);
- // 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));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmWriteReg() nvdimm[%X] - failed to read the current page",
+ TARGETING::get_huid(i_nvdimm));
+ break;
+ }
- TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Write HUID %X, addr 0x%X = %X",
- TARGETING::get_huid(i_nvdimm), i_addr, i_data);
+ if (l_data != l_reg_page)
+ {
+ l_err = nvdimmOpenPage(i_nvdimm, l_reg_page);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmWriteReg() nvdimm[%X] - failed to verify page",
+ TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+ }
+ }
+
+ l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
+ i_nvdimm,
+ &i_data,
+ l_numBytes,
+ DEVICE_NVDIMM_ADDRESS(l_reg_addr));
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"NVDIMM Write HUID %X, page = 0x%X, addr 0x%X = %X",
+ TARGETING::get_huid(i_nvdimm), l_reg_page, l_reg_addr, i_data);
return l_err;
}
@@ -220,42 +292,82 @@ errlHndl_t nvdimmReady(Target *i_nvdimm)
errlHndl_t l_err = nullptr;
uint8_t l_data = 0x0;
+ uint8_t l_nvm_init_time = 0;
+ size_t l_numBytes = 1;
- 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)
+ do
{
- 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 );
+ // Read the maximum NVM init time in seconds from the SPD
+ l_err = deviceRead(i_nvdimm,
+ &l_nvm_init_time,
+ l_numBytes,
+ DEVICE_SPD_ADDRESS(SPD::NVM_INIT_TIME));
- 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, "nvdimmReady() HUID[%X] l_nvm_init_time = %u",
+ TARGETING::get_huid(i_nvdimm), l_nvm_init_time);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReady() nvdimm[%X] - failed to retrieve NVM_INIT_TIME from SPD",
+ TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+
+ // Convert to ms for polling
+ uint32_t l_nvm_init_time_ms = l_nvm_init_time * MS_PER_SEC;
+ uint32_t l_poll = 0;
+
+ do
+ {
+ 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);
+ break;
+ }
+
+ if (l_data == NV_READY)
+ {
+ break;
+ }
+
+ nanosleep(0, NV_READY_POLL_TIME_MS*NS_PER_MSEC);
+ l_poll += NV_READY_POLL_TIME_MS;
+
+ }while(l_poll < l_nvm_init_time_ms);
+
+ if ((l_data != NV_READY) && !l_err)
+ {
+ 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_UNRECOVERABLE,
+ NVDIMM_CHECK_READY,
+ NVDIMM_NOT_READY,
+ NVDIMM_SET_USER_DATA_1(l_data, TARGETING::get_huid(i_nvdimm)),
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024 );
+ //@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
+ }
+
+ }while(0);
TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmReady() HUID[%X] ready[%X]",
TARGETING::get_huid(i_nvdimm), l_data);
@@ -264,6 +376,46 @@ errlHndl_t nvdimmReady(Target *i_nvdimm)
}
/**
+ * @brief Reset the NV controller. This operation does not interfere
+ * with the DRAM operation but will introduce loss of protection
+ * if NVDIMM was armed
+ *
+ * @param[in] i_nvdimm - nvdimm target
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmResetController(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmResetController() HUID[%X]",TARGETING::get_huid(i_nvdimm));
+ errlHndl_t l_err = nullptr;
+
+ do
+ {
+
+ l_err = nvdimmWriteReg(i_nvdimm, NVDIMM_MGT_CMD0, RESET_CONTROLLER);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmResetController() nvdimm[%X] - error reseting the controller",
+ TARGETING::get_huid(i_nvdimm));
+ break;
+ }
+
+ l_err = nvdimmReady(i_nvdimm);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmResetController() nvdimm[%X] - not ready after reset.",
+ TARGETING::get_huid(i_nvdimm));
+ }
+
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmResetController() HUID[%X]",TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
* @brief This function polls the status register for the given ops_id
*
* @param[in] i_nvdimm - nvdimm target with NV controller
@@ -336,7 +488,7 @@ errlHndl_t nvdimmPollStatus ( Target *i_nvdimm,
NVDIMM_SET_USER_DATA_2_TIMEOUT(o_poll, l_timeout),
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
- l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024 );
//@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
@@ -552,7 +704,7 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm)
0x0,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
- l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024 );
//@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
@@ -565,8 +717,40 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm)
return l_err;
}
+/**
+ * @brief This function arms/disarms the trigger based on i_state
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_state - true to arm, false to disarm
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmChangeArmState(Target *i_nvdimm, bool i_state)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmChangeArmState() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+ errlHndl_t l_err = nullptr;
+ // If i_state is true, arm the nvdimm in conjunction with ATOMIC_SAVE_AND_ERASE
+ // feature. A separate erase command is not requred as the image will get erased
+ // before backup on the next catastrophic event
+ uint8_t l_data = i_state ? ARM_RESETN_AND_ATOMIC_SAVE_AND_ERASE : DISARM_RESETN;
+
+ l_err = nvdimmWriteReg(i_nvdimm, ARM_CMD, l_data);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmChangeArmState() nvdimm[%X] error %s nvdimm!!",
+ TARGETING::get_huid(i_nvdimm), i_state? "arming" : "disarming");
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmChangeArmState() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+ return l_err;
+}
/**
* @brief This function checks for valid image on the given target
@@ -612,17 +796,17 @@ errlHndl_t nvdimmValidImage(Target *i_nvdimm, bool &o_imgValid)
*
* @param[in] i_nvdimmList - list of nvdimms
*
+ * @param[in] i_mpipl - MPIPL mode
+ *
* @return errlHndl_t - Null if successful, otherwise a pointer to
* the error log.
*/
-errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList)
+errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList, uint8_t &i_mpipl)
{
errlHndl_t l_err = nullptr;
bool l_imgValid;
uint8_t l_rstrValid;
uint32_t l_poll = 0;
- TARGETING::Target* l_sys = NULL;
- targetService().getTopLevelTarget(l_sys);
do
{
@@ -653,6 +837,25 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList)
fapi2::Target<fapi2::TARGET_TYPE_MCA> l_fapi_mca(l_mcaList[0]);
+ // Before we do anything, check if we are in mpipl. If we are, make sure ddr_resetn
+ // is de-asserted before kicking off the restore
+ if (i_mpipl)
+ {
+ FAPI_INVOKE_HWP(l_err, mss::ddr_resetn, l_fapi_mca, HIGH);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmRestore() HUID[%X] i_mpipl[%u] failed to de-assert resetn!",
+ TARGETING::get_huid(*it), i_mpipl);
+
+ nvdimmSetStatusFlag(*it, NSTD_ERR_NOPRSV);
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //If we failed to de-assert reset_n, the dimm is pretty much useless.
+ //Let's not restore if that happens
+ break;
+ }
+ }
+
// Self-refresh is done at the port level
FAPI_INVOKE_HWP(l_err, mss::nvdimm::self_refresh_entry, l_fapi_mca);
@@ -761,7 +964,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList)
0x0,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT);
- l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024 );
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
@@ -861,7 +1064,7 @@ errlHndl_t nvdimmCheckEraseSuccess(Target *i_nvdimm)
0x0,
ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
- l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024 );
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
@@ -936,7 +1139,6 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm,
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));
@@ -946,7 +1148,8 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm,
do
{
- l_err = nvdimmWriteReg(i_nvdimm, OPEN_PAGE, i_page);
+ // Open page reg is at the same address of every page
+ l_err = nvdimmWriteReg(i_nvdimm, OPEN_PAGE, i_page, NO_PAGE_VERIFY);
if (l_err)
{
@@ -960,7 +1163,7 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm,
// Not using the nvdimmPollStatus since this is polled differently
do
{
- l_err = nvdimmReadReg(i_nvdimm, OPEN_PAGE, l_data);
+ l_err = nvdimmReadReg(i_nvdimm, OPEN_PAGE, l_data, NO_PAGE_VERIFY);
if (l_err){
break;
}
@@ -989,7 +1192,7 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm,
/*@
*@errortype
*@reasoncode NVDIMM_OPEN_PAGE_TIMEOUT
- *@severity ERRORLOG_SEV_PREDICTIVE
+ *@severity ERRORLOG_SEV_UNRECOVERABLE
*@moduleid NVDIMM_OPEN_PAGE
*@userdata1[0:31] Related ops (0xff = NA)
*@userdata1[32:63] Target Huid
@@ -999,7 +1202,7 @@ errlHndl_t nvdimmOpenPage(Target *i_nvdimm,
*@custdesc Encountered error performing internal operaiton
* on NVDIMM
*/
- l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
NVDIMM_POLL_STATUS,
NVDIMM_STATUS_TIMEOUT,
NVDIMM_SET_USER_DATA_1(PAGE_SWITCH, TARGETING::get_huid(i_nvdimm)),
@@ -1039,17 +1242,8 @@ errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm)
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;
- }
-
+ for (uint8_t i = SAVE; i <= CHARGE; i++)
+ {
// 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
@@ -1083,7 +1277,7 @@ errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm)
timeout_map[i] = timeout_map[i] * MS_PER_SEC;
}
- TRACFCOMP(g_trac_nvdimm, "nvdimmGetTimeoutVal() HUID[%X], timeout_idx[%d], timeout_ms[%d]"
+ TRACUCOMP(g_trac_nvdimm, "nvdimmGetTimeoutVal() HUID[%X], timeout_idx[%d], timeout_ms[%d]"
,TARGETING::get_huid(i_nvdimm), timeoutInfoTable[i].idx, timeout_map[i]);
}
@@ -1100,73 +1294,27 @@ errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm)
#ifndef __HOSTBOOT_RUNTIME
/**
- * @brief Entry function to NVDIMM management
+ * @brief Entry function to NVDIMM restore
* - Restore image from NVDIMM NAND flash to DRAM
- * - Arms the backup trigger to ddr_reset_n once the restore
- * is completed
- * - Erase image
+ * - Set up the ES policy
*
* @param[in] i_nvdimmList - list of nvdimm targets
*
*/
void nvdimm_restore(TargetHandleList &i_nvdimmList)
{
- TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_restore()");
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_restore()");
errlHndl_t l_err = nullptr;
+ TARGETING::Target* l_sys = nullptr;
+ TARGETING::targetService().getTopLevelTarget( l_sys );
+ assert(l_sys, "nvdimm_restore: no TopLevelTarget");
+ uint8_t l_mpipl = l_sys->getAttr<ATTR_IS_MPIPL_HB>();
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)
- {
- // @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");
- errlCommit( l_err, NVDIMM_COMP_ID );
- 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
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmReady()");
- errlCommit(l_err, NVDIMM_COMP_ID);
- 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
+ // but do it anyway to get the charging going
for (const auto & l_nvdimm : i_nvdimmList)
{
l_err = nvdimmSetESPolicy(l_nvdimm);
@@ -1181,73 +1329,133 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList)
}
}
- // Get the timeout values for the major ops at init
- if (init_nv_timeout){
- for (const auto & l_nvdimm : i_nvdimmList){
- l_err = nvdimmGetTimeoutVal(l_nvdimm);
+ if (l_mpipl)
+ {
+ // During MPIPL, make sure any in-progress save is completed before proceeding
+ uint32_t l_poll = 0;
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ //Check save progress
+ l_err = nvdimmPollBackupDone(l_nvdimm, l_poll);
+
if (l_err)
{
- nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR);
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //Backup is taking longer than the allotted time here.
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() nvdimm[%X], error backing up the DRAM!",
+ TARGETING::get_huid(l_nvdimm));
+ errlCommit(l_err, NVDIMM_COMP_ID);
break;
}
}
- init_nv_timeout = false;
}
+ // Start the restore
+ l_err = nvdimmRestore(i_nvdimmList, l_mpipl);
+
if (l_err)
{
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmGetTimeoutVal()");
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmRestore()");
errlCommit( l_err, NVDIMM_COMP_ID );
break;
}
- // Change back to page 0 just in case, as all of the remaining
- // operations will be using offsets in page 0
+ // 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 = nvdimmOpenPage(l_nvdimm, ZERO);
- if (l_err)
- {
- nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR);
- break;
- }
+ l_err = nvdimmPollESChargeStatus(l_nvdimm, l_poll);
+ if (l_err){
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ }
}
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_restore()");
+}
+
+/**
+ * @brief NVDIMM initialization
+ * - Checks for ready state
+ * - Gathers timeout values
+ * - Waits for the ongoing backup to complete
+ * - Disarms the trigger for draminit
+ *
+ * @param[in] i_nvdimm - nvdimm target
+ *
+ */
+void nvdimm_init(Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_init() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ do
+ {
+ l_err = nvdimmReady(i_nvdimm);
+
if (l_err)
{
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing open page");
- errlCommit( l_err, NVDIMM_COMP_ID );
+ nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], controller not ready",
+ TARGETING::get_huid(i_nvdimm));
+ errlCommit(l_err, NVDIMM_COMP_ID);
break;
}
- // Start the restore
- l_err = nvdimmRestore(i_nvdimmList);
-
+ // Get the timeout values for the major ops at init
+ l_err = nvdimmGetTimeoutVal(i_nvdimm);
if (l_err)
{
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmRestore()");
- errlCommit( l_err, NVDIMM_COMP_ID );
+ nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error retrieving timeout values",
+ TARGETING::get_huid(i_nvdimm));
+ errlCommit(l_err, NVDIMM_COMP_ID);
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
+ //Check save progress
uint32_t l_poll = 0;
- for (const auto & l_nvdimm : i_nvdimmList)
+ l_err = nvdimmPollBackupDone(i_nvdimm, l_poll);
+
+ if (l_err)
{
- l_err = nvdimmPollESChargeStatus(l_nvdimm, l_poll);
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //Backup is taking longer than the allotted time here.
+ nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOPRSV);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error backing up the DRAM!",
+ TARGETING::get_huid(i_nvdimm));
+ errlCommit(l_err, NVDIMM_COMP_ID);
+ break;
+ }
- if (l_err){
- nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP);
- errlCommit( l_err, NVDIMM_COMP_ID );
- }
+ // Disarm the ddr_resetn here in case it came in armed. When the nvdimm is
+ // armed the reset_n is masked off from the host, meaning the drams won't
+ // be able to get reset properly later, causing training to fail.
+ l_err = nvdimmChangeArmState(i_nvdimm, DISARM_TRIGGER);
+
+ if (l_err)
+ {
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //Failed to disarm the reset_n trigger
+ nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOPRSV);
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_init() nvdimm[%X], error disarming the nvdimm!",
+ TARGETING::get_huid(i_nvdimm));
+ errlCommit(l_err, NVDIMM_COMP_ID);
+ break;
}
}while(0);
- TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_restore()");
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_init() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
}
#endif
diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H
index 9e60d3224..4457424cb 100644
--- a/src/usr/isteps/nvdimm/nvdimm.H
+++ b/src/usr/isteps/nvdimm/nvdimm.H
@@ -41,27 +41,239 @@ extern trace_desc_t* g_trac_nvdimm;
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
+// I2C registers for page 0-3, extracted from JEDEC BAEBI spec
+// Refer to BAEBI spec for details
+// https://www.jedec.org/standards-documents/docs/jesd245a
+// The 2 least significant nibbles indicate the register address.
+// The most significant nibble indicates the page number where the
+// register belongs.
+// e.g. for 0x00A, 0x0 = page number, 0x0A = register address
+enum i2cReg : uint16_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,
+ OPEN_PAGE = 0x000,
+ STD_NUM_PAGES = 0x001,
+ VENDOR_START_PAGES = 0x002,
+ VENDOR_NUM_PAGES = 0x003,
+ HWREV = 0x004,
+ SPECREV = 0x006,
+ SLOT0_FWREV0 = 0x007,
+ SLOT0_FWREV1 = 0x008,
+ SLOT1_FWREV0 = 0x009,
+ SLOT1_FWREV1 = 0x00A,
+ SLOT0_SUBFWREV = 0x00B,
+ SLOT1_SUBFWREV = 0x00C,
+ CAPABILITIES0 = 0x010,
+ CAPABILITIES1 = 0x011,
+ ENERGY_SOURCE_POLICY = 0x014,
+ HOST_MAX_OPERATION_RETRY = 0x015,
+ CSAVE_TRIGGER_SUPPORT = 0x016,
+ EVENT_NOTIFICATION_SUPPORT = 0x017,
+ CSAVE_TIMEOUT0 = 0x018,
+ CSAVE_TIMEOUT1 = 0x019,
+ PAGE_SWITCH_LATENCY0 = 0x01A,
+ PAGE_SWITCH_LATENCY1 = 0x01B,
+ RESTORE_TIMEOUT0 = 0x01C,
+ RESTORE_TIMEOUT1 = 0x01D,
+ ERASE_TIMEOUT0 = 0x01E,
+ ERASE_TIMEOUT1 = 0x01F,
+ ARM_TIMEOUT0 = 0x020,
+ ARM_TIMEOUT1 = 0x021,
+ FIRMWARE_OPS_TIMEOUT0 = 0x022,
+ FIRMWARE_OPS_TIMEOUT1 = 0x023,
+ ABORT_CMD_TIMEOUT = 0x024,
+ MAX_RUNTIME_POWER0 = 0x027,
+ MAX_RUNTIME_POWER1 = 0x028,
+ CSAVE_POWER_REQ0 = 0x029,
+ CSAVE_POWER_REQ1 = 0x02A,
+ CSAVE_IDLE_POWER_REQ0 = 0x02B,
+ CSAVE_IDLE_POWER_REQ1 = 0x02C,
+ CSAVE_MIN_VOLT_REQ0 = 0x02D,
+ CSAVE_MIN_VOLT_REQ1 = 0x02E,
+ CSAVE_MAX_VOLT_REQ0 = 0x02F,
+ CSAVE_MAX_VOLT_REQ1 = 0x030,
+ VENDOR_LOG_PAGE_SIZE = 0x031,
+ REGION_BLOCK_SIZE = 0x032,
+ OPERATIONAL_UNIT_OPS_TIMEOUT0 = 0x033,
+ OPERATIONAL_UNIT_OPS_TIMEOUT1 = 0x034,
+ FACTORY_DEFAULT_TIMEOUT0 = 0x035,
+ FACTORY_DEFAULT_TIMEOUT1 = 0x036,
+ MIN_OPERATING_TEMP0 = 0x038,
+ MIN_OPERATING_TEMP1 = 0x039,
+ MAX_OPERATING_TEMP0 = 0x03A,
+ MAX_OPERATING_TEMP1 = 0x03B,
+ NVDIMM_MGT_CMD0 = 0x040,
+ NVDIMM_MGT_CMD1 = 0x041,
+ NVDIMM_FUNC_CMD = 0x043,
+ ARM_CMD = 0x045,
+ SET_EVENT_NOTIFICATION_CMD = 0x047,
+ SET_ES_POLICY_CMD = 0x049,
+ FIRMWARE_OPS_CMD = 0x04A,
+ OPERATIONAL_UNIT_OPS_CMD = 0x04B,
+ NVDIMM_READY = 0x060,
+ NVDIMM_CMD_STATUS0 = 0x061,
+ NVDIMM_CMD_STATUS1 = 0x062,
+ CSAVE_STATUS = 0x064,
+ RESTORE_STATUS = 0x066,
+ ERASE_STATUS = 0x068,
+ ARM_STATUS = 0x06A,
+ FACTORY_DEFAULT_STATUS = 0x06C,
+ SET_EVENT_NOTIFICATION_STATUS = 0x06E,
+ SET_ES_POLICY_STATUS = 0x070,
+ FIRMWARE_OPS_STATUS = 0x071,
+ OPERATIONAL_UNIT_OPS_STATUS = 0x072,
+ RESTORE_FAIL_INFO = 0x088,
+ OPERATIONAL_UNIT_FAIL_INFO = 0x08F,
+ CSAVE_INFO = 0x080,
+ CSAVE_FAIL_INFO0 = 0x084,
+ CSAVE_FAIL_INFO1 = 0x085,
+ NVM_LIFETIME_ERROR_THRESHOLD = 0x090,
+ ES_LIFETIME_ERROR_THRESHOLD = 0x091,
+ ES_TEMP_ERROR_HIGH_THRESHOLD0 = 0x094,
+ ES_TEMP_ERROR_HIGH_THRESHOLD1 = 0x095,
+ ES_TEMP_ERROR_LOW_THRESHOLD0 = 0x096,
+ ES_TEMP_ERROR_LOW_THRESHOLD1 = 0x097,
+ NVM_LIFETIME_WARNING_THRESHOLD = 0x098,
+ ES_LIFETIME_WARNING_THRESHOLD = 0x099,
+ ES_TEMP_WARNING_HIGH_THRESHOLD0 = 0x09C,
+ ES_TEMP_WARNING_HIGH_THRESHOLD1 = 0x09D,
+ ES_TEMP_WARNING_LOW_THRESHOLD0 = 0x09E,
+ ES_TEMP_WARNING_LOW_THRESHOLD1 = 0x09F,
+ MODULE_HEALTH = 0x0A0,
+ MODULE_HEALTH_STATUS0 = 0x0A1,
+ MODULE_HEALTH_STATUS1 = 0x0A2,
+ ERROR_THRESHOLD_STATUS = 0x0A5,
+ WARNING_THRESHOLD_STATUS = 0x0A7,
+ AUTO_ES_HEALTH_FREQUENCY = 0x0A9,
+ MODULE_OPS_CONFIG = 0x0AA,
+ NVM_LIFETIME = 0x0C0,
+ ES_HWREV = 0x104,
+ ES_FWREV0 = 0x106,
+ ES_FWREV1 = 0x107,
+ SLOT0_ES_FWREV0 = 0x108,
+ SLOT0_ES_FWREV1 = 0x109,
+ SLOT1_ES_FWREV0 = 0x10A,
+ SLOT1_ES_FWREV1 = 0x10B,
+ ES_CHARGE_TIMEOUT0 = 0x110,
+ ES_CHARGE_TIMEOUT1 = 0x111,
+ ES_ATTRIBUTES = 0x114,
+ ES_TECH = 0x115,
+ MIN_ES_OPERATING_TEMP0 = 0x116,
+ MIN_ES_OPERATING_TEMP1 = 0x117,
+ MAX_ES_OPERATING_TEMP0 = 0x118,
+ MAX_ES_OPERATING_TEMP1 = 0x119,
+ ES_FUNC_CMD0 = 0x130,
+ ES_CMD_STATUS0 = 0x150,
+ ES_LIFETIME = 0x170,
+ ES_TEMP0 = 0x171,
+ ES_TEMP1 = 0x172,
+ ES_RUNTIME0 = 0x173,
+ ES_RUNTIME1 = 0x174,
+ LAST_CSAVE_DURATION0 = 0x204,
+ LAST_CSAVE_DURATION1 = 0x205,
+ LAST_RESTORE_DURATION0 = 0x206,
+ LAST_RESTORE_DURATION1 = 0x207,
+ LAST_ERASE_DURATION0 = 0x208,
+ LAST_ERASE_DURATION1 = 0x209,
+ CSAVE_SUCCESS_COUNT0 = 0x20A,
+ CSAVE_SUCCESS_COUNT1 = 0x20B,
+ RESTORE_SUCCESS_COUNT0 = 0x20C,
+ RESTORE_SUCCESS_COUNT1 = 0x20D,
+ ERASE_SUCCESS_COUNT0 = 0x20E,
+ ERASE_SUCCESS_COUNT1 = 0x20F,
+ POWER_CYCLE_COUNT0 = 0x210,
+ POWER_CYCLE_COUNT1 = 0x211,
+ CSAVE_FAILURE_COUNT0 = 0x212,
+ CSAVE_FAILURE_COUNT1 = 0x213,
+ RESTORE_FAILURE_COUNT0 = 0x214,
+ RESTORE_FAILURE_COUNT1 = 0x215,
+ ERASE_FAILURE_COUNT0 = 0x216,
+ ERASE_FAILURE_COUNT1 = 0x217,
+ LAST_ARM_DURATION0 = 0x218,
+ LAST_ARM_DURATION1 = 0x219,
+ LAST_FACTORY_DEFAULT_DURATION0 = 0x21A,
+ LAST_FACTORY_DEFAULT_DURATION1 = 0x21B,
+ LAST_FIRMWARE_OPS_DURATION0 = 0x21C,
+ LAST_FIRMWARE_OPS_DURATION1 = 0x21D,
+ LAST_OPERATIONAL_UNIT_OPS_DURATION0 = 0x21E,
+ LAST_OPERATIONAL_UNIT_OPS_DURATION1 = 0x21F,
+ ARM_SUCCESS_COUNT0 = 0x220,
+ ARM_SUCCESS_COUNT1 = 0x221,
+ FACTORY_DEFAULT_SUCCESS_COUNT0 = 0x222,
+ FACTORY_DEFAULT_SUCCESS_COUNT1 = 0x223,
+ FIRMWARE_SUCCESS_COUNT0 = 0x224,
+ FIRMWARE_SUCCESS_COUNT1 = 0x225,
+ OPERATIONAL_UNIT_SUCCESS_COUNT0 = 0x226,
+ OPERATIONAL_UNIT_SUCCESS_COUNT1 = 0x227,
+ ARM_FAILURE_COUNT0 = 0x228,
+ ARM_FAILURE_COUNT1 = 0x229,
+ FACTORY_DEFAULT_FAILURE_COUNT0 = 0x22A,
+ FACTORY_DEFAULT_FAILURE_COUNT1 = 0x22B,
+ FIRMWARE_FAILURE_COUNT0 = 0x22C,
+ FIRMWARE_FAILURE_COUNT1 = 0x22D,
+ OPERATIONAL_UNIT_FAILURE_COUNT0 = 0x22E,
+ OPERATIONAL_UNIT_FAILURE_COUNT1 = 0x22F,
+ INJECT_OPS_FAILURES0 = 0x260,
+ INJECT_OPS_FAILURES1 = 0x261,
+ INJECT_ES_FAILURES = 0x264,
+ INJECT_FW_FAILURES = 0x265,
+ INJECT_BAD_BLOCK_CAP = 0x267,
+ INJECT_ERROR_TYPE = 0x268,
+ DRAM_ECC_ERROR_COUNT = 0x280,
+ DRAM_THRESHOLD_ECC_COUNT = 0x281,
+ HOST_MANAGED_ES_ATTRIBUTES = 0x282,
+ HOST_CSAVE_FAIL = 0x283,
+ HOST_CSAVE_WORKFLOW_FAILURE_COUNT0 = 0x284,
+ HOST_CSAVE_WORKFLOW_FAILURE_COUNT1 = 0x285,
+ TYPED_BLOCK_DATA = 0x304,
+ REGION_ID0 = 0x305,
+ REGION_ID1 = 0x306,
+ BLOCK_ID = 0x307,
+ TYPED_BLOCK_DATA_SIZE0 = 0x308,
+ TYPED_BLOCK_DATA_SIZE1 = 0x309,
+ TYPED_BLOCK_DATA_SIZE2 = 0x30A,
+ OPERATIONAL_UNIT_ID0 = 0x30C,
+ OPERATIONAL_UNIT_ID1 = 0x30D,
+ OPERATIONAL_UNIT_SIZE0 = 0x310,
+ OPERATIONAL_UNIT_SIZE1 = 0x311,
+ OPERATIONAL_UNIT_SIZE2 = 0x312,
+ OPERATIONAL_UNIT_CRC0 = 0x314,
+ OPERATIONAL_UNIT_CRC1 = 0x315,
+ FW_REGION_CRC0 = 0x340,
+ FW_REGION_CRC1 = 0x341,
+ FW_SLOT_INFO = 0x342,
+ TYPED_BLOCK_DATA_BYTE0 = 0x380,
+ TYPED_BLOCK_DATA_BYTE1 = 0x381,
+ TYPED_BLOCK_DATA_BYTE2 = 0x382,
+ TYPED_BLOCK_DATA_BYTE3 = 0x383,
+ TYPED_BLOCK_DATA_BYTE4 = 0x384,
+ TYPED_BLOCK_DATA_BYTE5 = 0x385,
+ TYPED_BLOCK_DATA_BYTE6 = 0x386,
+ TYPED_BLOCK_DATA_BYTE7 = 0x387,
+ TYPED_BLOCK_DATA_BYTE8 = 0x388,
+ TYPED_BLOCK_DATA_BYTE9 = 0x389,
+ TYPED_BLOCK_DATA_BYTE10 = 0x38A,
+ TYPED_BLOCK_DATA_BYTE11 = 0x38B,
+ TYPED_BLOCK_DATA_BYTE12 = 0x38C,
+ TYPED_BLOCK_DATA_BYTE13 = 0x38D,
+ TYPED_BLOCK_DATA_BYTE14 = 0x38E,
+ TYPED_BLOCK_DATA_BYTE15 = 0x38F,
+ TYPED_BLOCK_DATA_BYTE16 = 0x390,
+ TYPED_BLOCK_DATA_BYTE17 = 0x391,
+ TYPED_BLOCK_DATA_BYTE18 = 0x392,
+ TYPED_BLOCK_DATA_BYTE19 = 0x393,
+ TYPED_BLOCK_DATA_BYTE20 = 0x394,
+ TYPED_BLOCK_DATA_BYTE21 = 0x395,
+ TYPED_BLOCK_DATA_BYTE22 = 0x396,
+ TYPED_BLOCK_DATA_BYTE23 = 0x397,
+ TYPED_BLOCK_DATA_BYTE24 = 0x398,
+ TYPED_BLOCK_DATA_BYTE25 = 0x399,
+ TYPED_BLOCK_DATA_BYTE26 = 0x39A,
+ TYPED_BLOCK_DATA_BYTE27 = 0x39B,
+ TYPED_BLOCK_DATA_BYTE28 = 0x39C,
+ TYPED_BLOCK_DATA_BYTE29 = 0x39D,
+ TYPED_BLOCK_DATA_BYTE30 = 0x39E,
+ TYPED_BLOCK_DATA_BYTE31 = 0x39F,
+ TYPED_BLOCK_DATA_OFFSET = 0x3E0,
};
// Up to 10 pages per BAEBI Spec,
@@ -80,11 +292,13 @@ enum i2c_in_values : uint8_t
{
ARM_RESETN_AND_ATOMIC_SAVE_AND_ERASE = 0x84,
ARM_RESETN = 0x04,
+ DISARM_RESETN = 0x00,
ES_DEV_MANAGE = 0x01, //0x01 for device manage
ERASE_IMAGE = 0x08,
RESTORE_IMAGE = 0x04,
RESET_CTRLR = 0x01,
VALID_IMAGE = 0x01,
+ RESET_CONTROLLER = 0x01,
};
enum i2c_out_values : uint8_t
@@ -107,7 +321,8 @@ enum i2c_out_values : uint8_t
enum timeout : uint32_t
{
OPS_POLL_TIME_MS = 5000,
- PAGE_SWITCH_POLL_TIME_NS = 100,
+ NV_READY_POLL_TIME_MS = 1000,
+ PAGE_SWITCH_POLL_TIME_NS = 100,
};
// Assign an id to each of the 6 major ops
@@ -121,6 +336,16 @@ enum ops_id : uint8_t
CHARGE,
};
+enum misc
+{
+ NO_PAGE_VERIFY = 0,
+ PAGE_VERIFY = 1,
+ ARM_TRIGGER = 1,
+ DISARM_TRIGGER = 0,
+ LOW = 0,
+ HIGH = 1,
+};
+
/**
* @brief Wrapper to call deviceOp to read the NV controller via I2C
*
@@ -130,10 +355,13 @@ enum ops_id : uint8_t
*
* @param[out] o_data - returned data from read
*
+ * @param[in] page_verify - read and verify the page associated to the given address.
+ * Change if needed. Default to true
+ *
* @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 );
+errlHndl_t nvdimmReadReg(TARGETING::Target* i_nvdimm, uint16_t i_addr, uint8_t & o_data, const bool page_verify = PAGE_VERIFY);
/**
* @brief Wrapper to call deviceOp to write the NV controller via I2C
@@ -144,10 +372,36 @@ errlHndl_t nvdimmReadReg(TARGETING::Target* i_nvdimm, uint8_t i_addr, uint8_t &
*
* @param[in] i_data - data to register
*
+ * @param[in] page_verify - read and verify the page associated to the given address.
+ * Change if needed. Default to true
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmWriteReg(TARGETING::Target* i_nvdimm, uint16_t i_addr, uint8_t i_data, const bool page_verify = PAGE_VERIFY);
+
+/**
+ * @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 nvdimmWriteReg(TARGETING::Target* i_nvdimm, uint8_t i_addr, uint8_t i_data );
+errlHndl_t nvdimmReady(TARGETING::Target *i_nvdimm);
+
+/**
+ * @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(TARGETING::Target *i_nvdimm, uint8_t i_page);
/**
* @brief This function polls the status register for the given ops_id
diff --git a/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C
index 9919c9c61..e4040f546 100644
--- a/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C
+++ b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C
@@ -231,50 +231,6 @@ errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target,
return l_err;
}
-
-bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList)
-{
- bool o_arm_successful = true;
-
- TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmArm() %d",
- i_nvdimmTargetList.size());
-
- errlHndl_t l_err = nullptr;
-
- for (auto const l_nvdimm : i_nvdimmTargetList)
- {
- // skip if the nvdimm is in error state
- if (NVDIMM::nvdimmInErrorState(l_nvdimm))
- {
- // error state means arming not successful
- o_arm_successful = false;
- continue;
- }
-
- l_err = NVDIMM::nvdimmArmResetN(l_nvdimm);
- // If we run into any error here we will just
- // commit the error log and move on. Let the
- // system continue to boot and let the user
- // salvage the data
- if (l_err)
- {
- NVDIMM::nvdimmSetStatusFlag(l_nvdimm, NVDIMM::NSTD_ERR_NOBKUP);
- // Committing the error as we don't want this to interrupt
- // the boot. This will notify the user that action is needed
- // on this module
- l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE);
- l_err->collectTrace(NVDIMM_COMP_NAME, 1024);
- errlCommit( l_err, NVDIMM_COMP_ID );
- o_arm_successful = false;
- continue;
- }
- }
-
- TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArm() returning %d",
- o_arm_successful);
- return o_arm_successful;
-}
-
/**
* @brief This function polls the command status register for arm completion
* (does not indicate success or fail)
@@ -364,49 +320,77 @@ errlHndl_t nvdimmCheckArmSuccess(TARGETING::Target *i_nvdimm)
return l_err;
}
-/**
- * @brief This function arms the trigger to enable backup in the event
- * of power loss (DDR Reset_n goes low) in conjunction with
- * ATOMIC_SAVE_AND_ERASE. A separate erase command is not required
- * as the image will get erased immediately before backup on the
- * next catastrophic event.
- *
- * @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(TARGETING::Target *i_nvdimm)
+bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList)
{
- TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmArmResetN() nvdimm[%X]",
- TARGETING::get_huid(i_nvdimm));
+ bool o_arm_successful = true;
- errlHndl_t l_err = nullptr;
+ TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmArm() %d",
+ i_nvdimmTargetList.size());
- // Setting ATOMIC_SAVE_AND_ERASE in conjunction with ARM_RESETN. With this,
- // the content of the persistent data is not erased until immediately after
- // the next catastrophic event has occurred.
- l_err = nvdimmWriteReg(i_nvdimm, ARM_CMD, ARM_RESETN_AND_ATOMIC_SAVE_AND_ERASE);
+ errlHndl_t l_err = nullptr;
- if (l_err)
- {
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmArmResetN() nvdimm[%X] error arming nvdimm!!",
- TARGETING::get_huid(i_nvdimm));
- }
- else
+ for (auto const l_nvdimm : i_nvdimmTargetList)
{
+ // skip if the nvdimm is in error state
+ if (NVDIMM::nvdimmInErrorState(l_nvdimm))
+ {
+ // error state means arming not successful
+ o_arm_successful = false;
+ continue;
+ }
+
+ l_err = NVDIMM::nvdimmChangeArmState(l_nvdimm, ARM_TRIGGER);
+ // If we run into any error here we will just
+ // commit the error log and move on. Let the
+ // system continue to boot and let the user
+ // salvage the data
+ if (l_err)
+ {
+ NVDIMM::nvdimmSetStatusFlag(l_nvdimm, NVDIMM::NSTD_ERR_NOBKUP);
+ // Committing the error as we don't want this to interrupt
+ // the boot. This will notify the user that action is needed
+ // on this module
+ l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE);
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ o_arm_successful = false;
+ continue;
+ }
+
// 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 = nvdimmPollArmDone(l_nvdimm, l_poll);
+ if (l_err)
+ {
+ NVDIMM::nvdimmSetStatusFlag(l_nvdimm, NVDIMM::NSTD_ERR_NOBKUP);
+ // Committing the error as we don't want this to interrupt
+ // the boot. This will notify the user that action is needed
+ // on this module
+ l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE);
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ o_arm_successful = false;
+ continue;
+ }
+
+ l_err = nvdimmCheckArmSuccess(l_nvdimm);
+ if (l_err)
{
- l_err = nvdimmCheckArmSuccess(i_nvdimm);
+ NVDIMM::nvdimmSetStatusFlag(l_nvdimm, NVDIMM::NSTD_ERR_NOBKUP);
+ // Committing the error as we don't want this to interrupt
+ // the boot. This will notify the user that action is needed
+ // on this module
+ l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE);
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ o_arm_successful = false;
+ continue;
}
}
- TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArmResetN() nvdimm[%X]",
- TARGETING::get_huid(i_nvdimm));
- return l_err;
+ TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArm() returning %d",
+ o_arm_successful);
+ return o_arm_successful;
}
/**
diff --git a/src/usr/isteps/pm/runtime/rt_pm.C b/src/usr/isteps/pm/runtime/rt_pm.C
index 9397d0e83..7ee9e0924 100644
--- a/src/usr/isteps/pm/runtime/rt_pm.C
+++ b/src/usr/isteps/pm/runtime/rt_pm.C
@@ -47,8 +47,6 @@
#include <targeting/common/utilFilter.H>
#include <targeting/common/targetservice.H>
-#include <isteps/nvdimm/nvdimm.H>
-
#include <scom/scomif.H>
#include <scom/wakeup.H>
diff --git a/src/usr/vpd/spdDDR4.H b/src/usr/vpd/spdDDR4.H
index d263f9cd4..bf4d0dfc8 100755
--- a/src/usr/vpd/spdDDR4.H
+++ b/src/usr/vpd/spdDDR4.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2016 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -135,6 +135,7 @@ const KeywordData ddr4Data[] =
{ BASE_CONFIG_CRC, 0x7f, 0x02, 0x00, 0x00, true, false, NA },
{ DRAM_STEPPING, 0x160, 0x01, 0x00, 0x00, false, false, NA },
{ MANUFACTURING_SECTION_CRC, 0x17f, 0x02, 0x00, 0x00, true, false, NA },
+ { NVM_INIT_TIME, 0xCB, 0x01, 0x00, 0x00, false, false, NA },
// Module Specific fields supported on both DDR3 and DDR4
{ MODSPEC_COM_NOM_HEIGHT_MAX, 0x80, 0x01, 0x1f, 0x00, false, false, ALL },
{ MODSPEC_COM_MAX_THICK_BACK, 0x81, 0x01, 0xf0, 0x04, false, false, ALL },
OpenPOWER on IntegriCloud