summaryrefslogtreecommitdiffstats
path: root/src/occ_405
diff options
context:
space:
mode:
authorChris Cain <cjcain@us.ibm.com>2015-11-19 12:27:03 -0600
committerWilliam A. Bryan <wilbryan@us.ibm.com>2016-01-27 16:27:07 -0600
commit1cdc7f74cf7303b2d2e7e172b0e269928def09de (patch)
treebc88add88943f8389626a04c5219d0efc3d08f17 /src/occ_405
parent476a284b52f50c1d0f5a8fc637cc28a22c714185 (diff)
downloadtalos-occ-1cdc7f74cf7303b2d2e7e172b0e269928def09de.tar.gz
talos-occ-1cdc7f74cf7303b2d2e7e172b0e269928def09de.zip
Implement code to read DIMM temperatures
Change-Id: I98fc83ab1c78bd40241fe6e47a9ddeae24f78c38 RTC: 140093 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22770 Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Tested-by: FSP CI Jenkins Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: Christopher Cain <cjcain@us.ibm.com>
Diffstat (limited to 'src/occ_405')
-rwxr-xr-xsrc/occ_405/Makefile1
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c48
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_mnfg_intf.c3
-rwxr-xr-xsrc/occ_405/dimm/dimm.c749
-rw-r--r--src/occ_405/dimm/dimm.h69
-rwxr-xr-xsrc/occ_405/dimm/dimm_service_codes.h40
-rw-r--r--src/occ_405/img_defs.mk11
-rwxr-xr-xsrc/occ_405/incl/comp_ids.h4
-rwxr-xr-xsrc/occ_405/main.c1
-rw-r--r--src/occ_405/occLinkInputFile1
-rw-r--r--src/occ_405/occ_service_codes.h7
-rwxr-xr-xsrc/occ_405/occ_sys_config.c7
-rwxr-xr-xsrc/occ_405/occ_sys_config.h7
-rwxr-xr-xsrc/occ_405/rtls/rtls.h14
-rwxr-xr-xsrc/occ_405/rtls/rtls_tables.c27
-rwxr-xr-xsrc/occ_405/state.c32
-rw-r--r--src/occ_405/topfiles.mk1
-rwxr-xr-xsrc/occ_405/trac/trac.h12
18 files changed, 960 insertions, 74 deletions
diff --git a/src/occ_405/Makefile b/src/occ_405/Makefile
index 633b9d1..caae6f7 100755
--- a/src/occ_405/Makefile
+++ b/src/occ_405/Makefile
@@ -54,6 +54,7 @@ LIB_DIRS = -L$(OBJDIR) \
-L$(OBJDIR)/ppc405lib \
-L$(OBJDIR)/cmdh \
-L$(OBJDIR)/dcom \
+ -L$(OBJDIR)/dimm \
-L$(OBJDIR)/errl \
-L$(OBJDIR)/pss \
-L$(OBJDIR)/rtls \
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
index 2abebc0..b2ac116 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -957,7 +957,7 @@ errlHndl_t data_store_apss_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
* @userdata4 OCC_NO_EXTENDED_RC
* @devdesc OCC recieved an invalid data packet from the FSP
*/
- cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
}
else // Version 0x20
{
@@ -1483,7 +1483,6 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
uint8_t l_i2c_port;
uint8_t l_i2c_addr = 0;
uint8_t l_dimm_num = 0;
- uint8_t l_centaur_num = 0;
int i;
do
@@ -1511,7 +1510,7 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
// Store the memory type. Memory must all be the same type, save from first and verify remaining
G_sysConfigData.mem_type = l_cmd_ptr->data_set[0].memory_type;
- if(G_sysConfigData.mem_type == 0xFF) // TODO change to MEM_TYPE_NIMBUS
+ if(G_sysConfigData.mem_type == MEM_TYPE_NIMBUS)
{
// Nimbus type -- dimm_info1 is I2C engine which must be the same
// save from first entry and verify remaining
@@ -1519,8 +1518,28 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
}
else
{
- // Must be cumulus type
- G_sysConfigData.mem_type = 0; // TODO change to MEM_TYPE_CUMULUS
+ // TODO - CUMULUS not supported yet
+ //G_sysConfigData.mem_type = MEM_TYPE_CUMULUS;
+
+ CMDH_TRAC_ERR("data_store_mem_cfg: Invalid mem type 0x%02X in config data packet version[0x%02X] num_data_sets[%u]",
+ l_cmd_ptr->data_set[0].memory_type,
+ l_cmd_ptr->header.version,
+ l_cmd_ptr->header.num_data_sets);
+
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+
+ // Clear all sensor IDs (hw and temperature)
+ memset(G_sysConfigData.dimm_huids, 0, sizeof(G_sysConfigData.dimm_huids));
+ int memctl, dimm;
+ for(memctl=0; memctl < MAX_NUM_MEM_CONTROLLERS; ++memctl)
+ {
+ g_amec->proc[0].memctl[memctl].centaur.temp_sid = 0;
+ for(dimm=0; dimm < NUM_DIMMS_PER_CENTAUR; ++dimm)
+ {
+ g_amec->proc[0].memctl[memctl].centaur.dimm_temps[dimm].temp_sid = 0;
+ }
}
// Store the hardware sensor ID and the temperature sensor ID
@@ -1531,7 +1550,7 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
// Verify matching memory type and process based on memory type
if( (l_data_set->memory_type == G_sysConfigData.mem_type) &&
- (l_data_set->memory_type == 0xFF) ) // TODO change to MEM_TYPE_NIMBUS
+ (l_data_set->memory_type == MEM_TYPE_NIMBUS) )
{
// Nimbus type: dimm info is I2C Engine, I2C Port, I2C Address
l_i2c_engine = l_data_set->dimm_info1;
@@ -1577,7 +1596,7 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
// The location of the HW sensor ID in the 2D dimm_huids array is used to know i2c port
// and i2c address for reading the DIMM. "centaur num" index is port "dimm num" is
// translated from i2c address, we already verified the i2c addr is 0x3z above
- l_dimm_num = (l_i2c_addr & 0x0F) >> 1;
+ l_dimm_num = (l_i2c_addr & 0x0F) >> 1;
// Store the hardware sensor ID
G_sysConfigData.dimm_huids[l_i2c_port][l_dimm_num] = l_data_set->hw_sensor_id;
@@ -1591,8 +1610,16 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
}
else // must be cumulus and the "memory type" byte is the centaur#
{
+ CMDH_TRAC_ERR("data_store_mem_cfg: Invalid mem type 0x%02X in config data packet entry %d (entry 0 type: 0x%02X)",
+ l_data_set->memory_type, i, G_sysConfigData.mem_type);
+
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+
+#if 0
+ // TODO - CUMULUS not supported yet
// per spec for cumulus memory type is the centaur# and dimm info1 is DIMM#
- l_centaur_num = l_data_set->memory_type;
+ uint8_t l_centaur_num = l_data_set->memory_type;
l_dimm_num = l_data_set->dimm_info1;
// Validate the centaur and dimm #'s for this data set
@@ -1629,6 +1656,7 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
l_num_dimms++;
}
+#endif
} // Cumulus
} // for each data set
} // version 0x20
@@ -1645,8 +1673,8 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
{
// If there were no errors, indicate that we got this data
G_data_cnfg->data_mask |= DATA_MASK_MEM_CFG;
- CMDH_TRAC_IMP("data_store_mem_cfg: Got valid mem cfg packet. cent#=%d, dimm#=%d",
- l_num_centaurs, l_num_dimms);
+ CMDH_TRAC_IMP("data_store_mem_cfg: Got valid mem cfg packet. type=0x%02X, #cent=%d, #dimm=%d",
+ G_sysConfigData.mem_type, l_num_centaurs, l_num_dimms);
// No errors so we can enable memory monitoring if the data indicates it should be enabled
if(l_cmd_ptr->header.num_data_sets == 0) // num data sets of 0 indicates memory monitoring disabled
diff --git a/src/occ_405/cmdh/cmdh_mnfg_intf.c b/src/occ_405/cmdh/cmdh_mnfg_intf.c
index a952f1b..8fd8feb 100755
--- a/src/occ_405/cmdh/cmdh_mnfg_intf.c
+++ b/src/occ_405/cmdh/cmdh_mnfg_intf.c
@@ -238,7 +238,8 @@ uint8_t cmdh_mnfg_mem_slew(const cmdh_fsp_cmd_t * i_cmd_ptr,
// If we made it here, that means we are starting up a slew run
TRAC_INFO("cmdh_mnfg_mem_slew: We are about to start auto-slewing function");
-// TEMP -- NOT SUPPORTED YET IN PHASE1
+// TEMP -- NOT SUPPORTED YET IN PHASE1
+// when implementing see dimm/dimm.c - memory_init()
/*
// Force activation of memory monitoring and control
if(!rtl_task_is_runnable(TASK_ID_CENTAUR_CONTROL))
diff --git a/src/occ_405/dimm/dimm.c b/src/occ_405/dimm/dimm.c
new file mode 100755
index 0000000..3008979
--- /dev/null
+++ b/src/occ_405/dimm/dimm.c
@@ -0,0 +1,749 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/dimm/dimm.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* [+] 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 */
+
+//#define DIMM_DEBUG
+
+#include <ssx.h>
+#include <occhw_async.h>
+#include <gpe_export.h>
+
+#include <trac_interface.h>
+#include <trac.h>
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <occ_service_codes.h>
+#include <dimm.h>
+#include <dimm_service_codes.h>
+#include <state.h>
+#include <occ_sys_config.h>
+#include "sensor.h"
+#include "amec_sys.h"
+
+
+extern bool G_mem_monitoring_allowed;
+extern task_t G_task_table[TASK_END];
+
+uint8_t G_dimm_state = DIMM_STATE_INIT; // Curret state of DIMM state machine
+uint8_t G_maxDimmPorts = NUM_DIMM_PORTS;
+
+bool G_dimm_i2c_reset_required = false;
+uint32_t G_dimm_i2c_reset_cause = 0;
+
+#define MAX_CONSECUTIVE_DIMM_RESETS 1
+typedef struct {
+ bool disabled;
+ uint8_t errorCount;
+ uint64_t lastReading;
+} dimmData_t;
+dimmData_t G_dimm[NUM_DIMM_PORTS][NUM_DIMMS_PER_CENTAUR] = {{{false,0}}};
+
+#define DIMM_TICK (CURRENT_TICK % MAX_NUM_TICKS)
+
+// If still no i2c interrupt after MAX_TICK_COUNT_WAIT, then try next operation anyway
+#define MAX_TICK_COUNT_WAIT 2
+
+#define DIMM_AND_PORT ((G_dimm_sm_args.i2cPort<<8) | G_dimm_sm_args.dimm)
+// GPE Requests
+GpeRequest G_dimm_sm_request;
+// GPE arguments
+GPE_BUFFER(dimm_sm_args_t G_dimm_sm_args);
+
+
+// Read OCC_MISC register to see if an I2C interrupt was generated for
+// the specified engine.
+bool check_for_i2c_interrupt(const uint8_t i_engine)
+{
+ bool l_interruptTriggered = false;
+ ocb_occmisc_t occmisc;
+ occmisc.value = in32(OCB_OCCMISC);
+
+ // I2CM_INTR_STATUS has a one bit status for each engine: C, D, and E
+ if (PIB_I2C_ENGINE_E == i_engine)
+ {
+ // Engine E
+ l_interruptTriggered = occmisc.fields.i2cm_intr_status & 0x01;
+ }
+ else if (PIB_I2C_ENGINE_D == i_engine)
+ {
+ // Engine D
+ l_interruptTriggered = occmisc.fields.i2cm_intr_status & 0x02;
+ }
+ else if (PIB_I2C_ENGINE_C == i_engine)
+ {
+ // Engine C
+ l_interruptTriggered = occmisc.fields.i2cm_intr_status & 0x04;
+ }
+ else
+ {
+ // Invalid engine
+ DIMM_DBG("check_for_i2c_interrupt: invalid engine 0x%02X", i_engine);
+ }
+
+ if (!l_interruptTriggered)
+ {
+ DIMM_DBG("check_for_i2c_interrupt: no interrupt for engine 0x%02X", i_engine);
+ }
+
+ return l_interruptTriggered;
+
+} // end check_for_i2c_interrupt()
+
+
+// Determine the I2C address for specified DIMM
+uint8_t get_dimm_addr(uint8_t i_dimm)
+{
+ //if (MEMORY_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ return 0x30 | (i_dimm<<1);
+}
+
+
+// Initialize the memory task data
+void memory_init()
+{
+ if(G_mem_monitoring_allowed)
+ {
+ // Check if memory task is running (default task is for NIMBUS)
+ const task_id_t mem_task = TASK_ID_DIMM_SM;
+ if(!rtl_task_is_runnable(mem_task))
+ {
+ if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ {
+ // Init DIMM state manager IPC request
+ memory_nimbus_init();
+ }
+ else
+ {
+ // TODO CUMULUS NOT SUPPORTED YET IN PHASE1
+#if 0
+ TRAC_INFO("memory_init: calling centaur_init()");
+ centaur_init(); //no rc, handles errors internally
+#endif
+ TRAC_ERR("memory_init: invalid memory type 0x%02X", G_sysConfigData.mem_type);
+ /*
+ * @errortype
+ * @moduleid DIMM_MID_MEMORY_INIT
+ * @reasoncode MEMORY_INIT_FAILED
+ * @userdata1 memory type
+ * @userdata2 0
+ * @devdesc Invalid memory type detected
+ */
+ errlHndl_t err = createErrl(DIMM_MID_MEMORY_INIT,
+ MEMORY_INIT_FAILED,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_sysConfigData.mem_type,
+ 0);
+ REQUEST_RESET(err);
+ }
+
+ // check if the init resulted in a reset
+ if(isSafeStateRequested())
+ {
+ TRAC_ERR("memory_init: OCC is being reset, memory init failed (type=0x%02X)",
+ G_sysConfigData.mem_type);
+ }
+ else
+ {
+ // Initialization was successful. Set task flags to allow memory
+ // tasks to run and also prevent from doing initialization again.
+ G_task_table[mem_task].flags = MEMORY_DATA_RTL_FLAGS;
+ //G_task_table[TASK_ID_CENTAUR_CONTROL].flags = MEMORY_CONTROL_RTL_FLAGS;
+ }
+ }
+ }
+
+} // end memory_init()
+
+
+// Create DIMM state machine IPC request
+void memory_nimbus_init()
+{
+ DIMM_DBG("memory_nimbus_init: Creating request GPE1 DIMM request objects");
+ gpe_request_create(&G_dimm_sm_request,
+ &G_async_gpe_queue1, // queue
+ IPC_ST_DIMM_SM_FUNCID, // entry_point
+ &G_dimm_sm_args, // entry_point arg
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // callback
+ NULL, // callback arg
+ ASYNC_CALLBACK_IMMEDIATE); // options
+}
+
+
+// Scan all of the DIMM temps and keep track of the hottest
+void update_hottest_dimm()
+{
+ // Find/save the hottest DIMM temperature for the last set of readings
+ uint8_t hottest = 0, hottest_loc = 0;
+ int pIndex, dIndex;
+ for (pIndex = 0; pIndex < G_maxDimmPorts; ++pIndex)
+ {
+ for (dIndex = 0; dIndex < NUM_DIMMS_PER_CENTAUR; ++dIndex)
+ {
+ if (g_amec->proc[0].memctl[pIndex].centaur.dimm_temps[dIndex].cur_temp > hottest)
+ {
+ hottest = g_amec->proc[0].memctl[pIndex].centaur.dimm_temps[dIndex].cur_temp;
+ hottest_loc = (pIndex*8) + dIndex;
+ }
+ }
+ }
+
+ DIMM_DBG("update_hottest_dimm: hottest DIMM temp for this sample: %dC (loc=%d)", hottest, hottest_loc);
+ if(hottest > g_amec->proc[0].memctl[0].centaur.tempdimmax.sample_max)
+ {
+ // Save hottest DIMM location ever sampled
+ DIMM_DBG("update_hottest_dimm: Hottest DIMM ever sampled was DIMM%d %dC (prior %dC)",
+ hottest_loc, hottest, g_amec->proc[0].memctl[0].centaur.tempdimmax.sample_max);
+ sensor_update(&g_amec->proc[0].memctl[0].centaur.locdimmax, hottest_loc);
+ }
+ // Nimbus has no Centaurs, but store hottest temp in memctl[0]
+ sensor_update(&g_amec->proc[0].memctl[0].centaur.tempdimmax, hottest);
+}
+
+
+// Update current I2C port/DIMM index to next potential DIMM
+void use_next_dimm(uint8_t * i_port, uint8_t * i_dimm)
+{
+ if (++*i_dimm == NUM_DIMMS_PER_CENTAUR)
+ {
+ // Finished all DIMMs for current port, switch to new port
+ *i_port = 1 - *i_port;
+ *i_dimm = 0;
+ }
+
+ // Check if we are starting a new set of readings and if so, update hottest DIMM
+ if ((*i_port == 0) && (*i_dimm == 0))
+ {
+ update_hottest_dimm();
+ }
+}
+
+
+// Called after a failure to read a DIMM temperature. The error will
+// be counted and if threshold is reached, and error will be created with
+// the DIMM as a callout and then set flag to trigger I2C reset
+void mark_dimm_failed()
+{
+ const uint8_t port = G_dimm_sm_args.i2cPort;
+ const uint8_t dimm = G_dimm_sm_args.dimm;
+ INTR_TRAC_ERR("mark_dimm_failed: DIMM%04X failed in state %d with rc=0x%02X "
+ "(ffdc 0x%08X%08X, err_count=%d, completion_state 0x%02X)",
+ DIMM_AND_PORT, G_dimm_sm_args.state,
+ G_dimm_sm_args.error.rc,
+ WORD_HIGH(G_dimm_sm_args.error.ffdc),
+ WORD_LOW(G_dimm_sm_args.error.ffdc),
+ G_dimm[port][dimm].errorCount,
+ G_dimm_sm_request.request.completion_state);
+
+ if (++G_dimm[port][dimm].errorCount > MAX_CONSECUTIVE_DIMM_RESETS)
+ {
+ // Disable collection on this DIMM, collect FFDC and log error
+ G_dimm[port][dimm].disabled = true;
+ INTR_TRAC_ERR("mark_dimm_failed: disabling DIMM%04X due to %d consecutive errors (state=%d)",
+ DIMM_AND_PORT, G_dimm[port][dimm].errorCount, G_dimm_sm_args.state);
+ errlHndl_t l_err = NULL;
+ /*
+ * @errortype
+ * @moduleid DIMM_MID_MARK_DIMM_FAILED
+ * @reasoncode DIMM_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata4 ERC_DIMM_COMPLETE_FAILURE
+ * @devdesc Failure writing dimm i2c mode register
+ */
+ l_err = createErrl(DIMM_MID_MARK_DIMM_FAILED,
+ DIMM_GPE_FAILURE,
+ ERC_DIMM_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_dimm_sm_args.error.rc,
+ 0);
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_dimm_sm_request.ffdc,
+ sizeof(G_dimm_sm_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.dimm_huids[port][dimm],
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ commitErrl(&l_err);
+ }
+
+ // Reset DIMM I2C engine
+ G_dimm_i2c_reset_required = true;
+ G_dimm_i2c_reset_cause = port<<24 | dimm<<16 | (G_dimm_sm_args.error.rc & 0xFFFF);
+ G_dimm_state = DIMM_STATE_RESET_MASTER;
+
+} // end mark_dimm_failed()
+
+
+// Schedule a GPE request for the specified DIMM state
+bool schedule_dimm_req(uint8_t i_state)
+{
+ bool l_scheduled = false;
+ bool scheduleRequest = true;
+
+ DIMM_DBG("dimm_sm called with state 0x%02X (tick=%d)", i_state, DIMM_TICK);
+
+ if (!async_request_is_idle(&G_dimm_sm_request.request))
+ {
+ INTR_TRAC_ERR("dimm_sm: request is not idle.");
+ }
+ else
+ {
+ switch(i_state)
+ {
+ // Init
+ case DIMM_STATE_INIT:
+ break;
+
+ // Read DIMM temp
+ case DIMM_STATE_WRITE_MODE:
+ case DIMM_STATE_WRITE_ADDR:
+ case DIMM_STATE_INITIATE_READ:
+ case DIMM_STATE_READ_TEMP:
+ break;
+
+ // I2C reset
+ case DIMM_STATE_RESET_MASTER:
+ case DIMM_STATE_RESET_SLAVE_P0:
+ case DIMM_STATE_RESET_SLAVE_P0_COMPLETE:
+ case DIMM_STATE_RESET_SLAVE_P1:
+ case DIMM_STATE_RESET_SLAVE_P1_COMPLETE:
+ break;
+
+ default:
+ INTR_TRAC_ERR("dimm_sm: Invalid state (0x%02X)", i_state);
+ errlHndl_t err = NULL;
+ /*
+ * @errortype
+ * @moduleid DIMM_MID_DIMM_SM
+ * @reasoncode DIMM_INVALID_STATE
+ * @userdata1 DIMM state
+ * @userdata2 0
+ * @devdesc Invalid DIMM I2C state requested
+ */
+ err = createErrl(DIMM_MID_DIMM_SM,
+ DIMM_INVALID_STATE,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ i_state,
+ 0);
+ // Request reset since this should never happen.
+ REQUEST_RESET(err);
+ scheduleRequest = false;
+ break;
+ }
+
+ if (scheduleRequest)
+ {
+ // Clear errors and init common arguments for GPE
+ G_dimm_sm_args.error.error = 0;
+ G_dimm_sm_args.state = i_state;
+
+ DIMM_DBG("dimm_sm: Scheduling GPE1 DIMM I2C state 0x%02X (tick %d)", i_state, DIMM_TICK);
+ int l_rc = gpe_request_schedule(&G_dimm_sm_request);
+ if (0 == l_rc)
+ {
+ l_scheduled = true;
+ }
+ else
+ {
+ errlHndl_t l_err = NULL;
+ INTR_TRAC_ERR("dimm_sm: schedule failed w/rc=0x%08X (%d us)",
+ l_rc, (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+ /*
+ * @errortype
+ * @moduleid DIMM_MID_DIMM_SM
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 state
+ * @devdesc dimm_sm schedule failed
+ */
+ l_err = createErrl(DIMM_MID_DIMM_SM,
+ SSX_GENERIC_FAILURE,
+ ERC_DIMM_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ i_state);
+ // Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ }
+ }
+ }
+
+ return l_scheduled;
+
+} // end schedule_dimm_req()
+
+
+// Check if the last I2C operation completed, and force failure if not
+bool check_for_i2c_failure()
+{
+ bool failed = false;
+
+ if (false == G_dimm_i2c_reset_required)
+ {
+ // Check if I2C operation is complete
+ if (ASYNC_REQUEST_STATE_COMPLETE == G_dimm_sm_request.request.completion_state)
+ {
+ // Check if I2C operation failed
+ if ((GPE_RC_SUCCESS != G_dimm_sm_args.error.rc) &&
+ (GPE_RC_NOT_COMPLETE != G_dimm_sm_args.error.rc))
+ {
+ mark_dimm_failed();
+ failed = true;
+ }
+ }
+ }
+ return failed;
+}
+
+
+// Handle the DIMM reset states
+uint8_t dimm_reset_sm()
+{
+ uint8_t nextState = G_dimm_state;
+
+ switch (G_dimm_state)
+ {
+ case DIMM_STATE_RESET_MASTER:
+ if (DIMM_TICK == 0)
+ {
+ G_dimm_sm_args.i2cEngine = G_sysConfigData.dimm_i2c_engine;
+ if (schedule_dimm_req(DIMM_STATE_RESET_MASTER))
+ {
+ nextState = DIMM_STATE_RESET_SLAVE_P0;
+ }
+ }
+ // else wait for tick 0
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P0:
+ G_dimm_sm_args.i2cPort = 0;
+ if (schedule_dimm_req(DIMM_STATE_RESET_SLAVE_P0))
+ {
+ nextState = DIMM_STATE_RESET_SLAVE_P0_WAIT;
+ }
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P0_WAIT:
+ // Delay to allow reset to complete
+ DIMM_DBG("dimm_reset_sm: waiting during slave port 0 reset");
+ nextState = DIMM_STATE_RESET_SLAVE_P0_COMPLETE;
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P0_COMPLETE:
+ if (schedule_dimm_req(DIMM_STATE_RESET_SLAVE_P0_COMPLETE))
+ {
+ if (G_maxDimmPorts > 1)
+ {
+ nextState = DIMM_STATE_RESET_SLAVE_P1;
+ }
+ else
+ {
+ // If there is only one port, skip slave port 1
+ nextState = DIMM_STATE_INIT;
+ G_dimm_i2c_reset_required = false;
+ TRAC_INFO("dimm_reset_sm: I2C reset completed (1 port)");
+ }
+ }
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P1:
+ G_dimm_sm_args.i2cPort = 1;
+ if (schedule_dimm_req(DIMM_STATE_RESET_SLAVE_P1))
+ {
+ nextState = DIMM_STATE_RESET_SLAVE_P1_WAIT;
+ }
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P1_WAIT:
+ // Delay to allow reset to complete
+ nextState = DIMM_STATE_RESET_SLAVE_P1_COMPLETE;
+ break;
+
+ case DIMM_STATE_RESET_SLAVE_P1_COMPLETE:
+ if (schedule_dimm_req(DIMM_STATE_RESET_SLAVE_P1_COMPLETE))
+ {
+ nextState = DIMM_STATE_INIT;
+ G_dimm_i2c_reset_required = false;
+ TRAC_INFO("dimm_reset_sm: I2C reset completed");
+ }
+ break;
+
+ default:
+ INTR_TRAC_ERR("dimm_reset_sm: INVALID STATE: 0x%02X when reset is required", G_dimm_state);
+ nextState = DIMM_STATE_RESET_MASTER;
+ break;
+ }
+
+ return nextState;
+
+} // end dimm_reset_sm()
+
+
+// Function Specification
+//
+// Name: task_dimm_sm
+//
+// Description: DIMM State Machine - Called every other tick to collect all of
+// the DIMM temperatures.
+//
+// Task Flags: RTL_FLAG_ACTIVE
+//
+// End Function Specification
+void task_dimm_sm(struct task *i_self)
+{
+ static uint8_t L_dimmIndex = 0x00;
+ static uint8_t L_dimmPort = 0x00;
+ static uint8_t L_notReadyCount = 0;
+#define MAX_READ_ATTEMPT 3
+ static uint8_t L_readAttempt = 0;
+ static bool L_readIssued = false;
+
+ if (G_mem_monitoring_allowed)
+ {
+ //DIMM_DBG("task_dimm_sm: request state=0x%02X, completion_state=0x%02X, abort_state=0x%02X",
+ // G_dimm_sm_request.request.state, G_dimm_sm_request.request.completion_state, G_dimm_sm_request.request.abort_state);
+
+ if (check_for_i2c_failure())
+ {
+ // After reset, move on to next DIMM
+ use_next_dimm(&L_dimmPort, &L_dimmIndex);
+ }
+
+ uint8_t nextState = G_dimm_state;
+
+ if (G_dimm_i2c_reset_required)
+ {
+ nextState = dimm_reset_sm();
+ }
+ else if (G_dimm_state == DIMM_STATE_INIT)
+ {
+ // Setup I2C Interrupt Mask Register
+ DIMM_DBG("DIMM_STATE_INIT: (I2C Engine 0x%02X, Memory Type 0x%02X)",
+ G_sysConfigData.dimm_i2c_engine, G_sysConfigData.mem_type);
+ G_dimm_sm_args.i2cEngine = G_sysConfigData.dimm_i2c_engine;
+ if (schedule_dimm_req(DIMM_STATE_INIT))
+ {
+ nextState = DIMM_STATE_WRITE_MODE;
+ }
+ }
+ else
+ {
+ bool intTriggered = check_for_i2c_interrupt(G_sysConfigData.dimm_i2c_engine);
+ if (intTriggered == false)
+ {
+ ++L_notReadyCount;
+ }
+
+ // Check if prior command completed (or timed out waiting for it)
+ if (intTriggered || (L_notReadyCount > MAX_TICK_COUNT_WAIT))
+ {
+ if (ASYNC_REQUEST_STATE_COMPLETE == G_dimm_sm_request.request.completion_state)
+ {
+ // IPC request completed, now check return code
+ if (GPE_RC_SUCCESS == G_dimm_sm_args.error.rc)
+ {
+ // last request completed without error
+ switch (G_dimm_sm_args.state)
+ {
+ case DIMM_STATE_INIT:
+ // Save max I2C ports
+ if (G_maxDimmPorts != G_dimm_sm_args.maxPorts)
+ {
+ G_maxDimmPorts = G_dimm_sm_args.maxPorts;
+ DIMM_DBG("task_dimm_sm: updating DIMM Max I2C Ports to %d", G_maxDimmPorts);
+ }
+ break;
+
+ case DIMM_STATE_READ_TEMP:
+ if (L_readIssued)
+ {
+ const uint8_t port = G_dimm_sm_args.i2cPort;
+ const uint8_t dimm = G_dimm_sm_args.dimm;
+
+ // Last DIMM read completed, update sensor and clear error count
+ DIMM_DBG("task_dimm_sm: Successfully read DIMM%04X temperature: %dC, tick %d",
+ DIMM_AND_PORT, G_dimm_sm_args.temp, DIMM_TICK);
+ g_amec->proc[0].memctl[port].centaur.dimm_temps[dimm].cur_temp = G_dimm_sm_args.temp;
+ G_dimm[port][dimm].lastReading = ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000));
+ G_dimm[port][dimm].errorCount = 0;
+
+ // Move on to next DIMM
+ use_next_dimm(&L_dimmPort, &L_dimmIndex);
+ L_readIssued = false;
+ }
+ break;
+
+ default:
+ // Nothing to do
+ break;
+ }
+ }
+ else
+ {
+ // last request did not return success
+ switch (G_dimm_sm_args.state)
+ {
+ case DIMM_STATE_INITIATE_READ:
+ if (++L_readAttempt < MAX_READ_ATTEMPT)
+ {
+ // The initiate_read didnt complete, retry
+ DIMM_DBG("task_dimm_sm: initiate read didn't start (%d attempts)", L_readAttempt);
+ // Force the read again
+ G_dimm_state = DIMM_STATE_INITIATE_READ;
+ nextState = G_dimm_state;
+ }
+ else
+ {
+ INTR_TRAC_ERR("task_dimm_sm: initiate read didn't start after %d attempts... forcing reset", L_readAttempt);
+ mark_dimm_failed();
+ }
+ break;
+
+ case DIMM_STATE_READ_TEMP:
+ if (L_readIssued)
+ {
+ if (++L_readAttempt < MAX_READ_ATTEMPT)
+ {
+ DIMM_DBG("task_dimm_sm: read didn't complete (%d attempts)", L_readAttempt);
+ // Force the read again
+ G_dimm_state = DIMM_STATE_READ_TEMP;
+ nextState = G_dimm_state;
+ }
+ else
+ {
+ INTR_TRAC_ERR("task_dimm_sm: read did not complete after %d attempts... forcing reset", L_readAttempt);
+ mark_dimm_failed();
+ }
+ }
+ break;
+
+ default:
+ // Nothing to do
+ break;
+ }
+ }
+ }
+ }
+
+ if (false == G_dimm_i2c_reset_required)
+ {
+ // Handle new DIMM state
+ switch (G_dimm_state)
+ {
+ case DIMM_STATE_WRITE_MODE:
+ // Only start a DIMM read on tick 0 or 8
+ if ((DIMM_TICK == 0) || (DIMM_TICK == 8))
+ {
+ // If DIMM has huid/sensor then it should be present
+ if ((0 != G_sysConfigData.dimm_huids[L_dimmPort][L_dimmIndex]) &&
+ (G_dimm[L_dimmPort][L_dimmIndex].disabled == false))
+ {
+ G_dimm_sm_args.i2cPort = L_dimmPort;
+ G_dimm_sm_args.dimm = L_dimmIndex;
+ DIMM_DBG("task_dimm_sm: Starting collection for DIMM%04X at tick %d",
+ DIMM_AND_PORT, DIMM_TICK);
+ if (schedule_dimm_req(DIMM_STATE_WRITE_MODE))
+ {
+ nextState = DIMM_STATE_WRITE_ADDR;
+ }
+ }
+ else
+ {
+ // Skip current DIMM and move on to next one
+ use_next_dimm(&L_dimmPort, &L_dimmIndex);
+ }
+ }
+ break;
+
+ case DIMM_STATE_WRITE_ADDR:
+ if (intTriggered || (L_notReadyCount > MAX_TICK_COUNT_WAIT))
+ {
+ G_dimm_sm_args.dimm = L_dimmIndex;
+ G_dimm_sm_args.i2cAddr = get_dimm_addr(L_dimmIndex);
+ if (schedule_dimm_req(DIMM_STATE_WRITE_ADDR))
+ {
+ nextState = DIMM_STATE_INITIATE_READ;
+ L_readAttempt = 0;
+ L_readIssued = false;
+ }
+ }
+ break;
+
+ case DIMM_STATE_INITIATE_READ:
+ if (intTriggered || (L_notReadyCount > MAX_TICK_COUNT_WAIT))
+ {
+ G_dimm_sm_args.dimm = L_dimmIndex;
+ if (schedule_dimm_req(DIMM_STATE_INITIATE_READ))
+ {
+ nextState = DIMM_STATE_READ_TEMP;
+ }
+ }
+ break;
+
+ case DIMM_STATE_READ_TEMP:
+ if (intTriggered || (L_notReadyCount > MAX_TICK_COUNT_WAIT))
+ {
+ if (schedule_dimm_req(DIMM_STATE_READ_TEMP))
+ {
+ L_readIssued = true;
+ nextState = DIMM_STATE_WRITE_MODE;
+ }
+ }
+ break;
+
+ default:
+ INTR_TRAC_ERR("task_dimm_sm: INVALID STATE: 0x%02X", G_dimm_state);
+ break;
+ }
+ }
+ else
+ {
+ // Previous op triggered reset
+ nextState = dimm_reset_sm();
+ }
+ }
+
+ if (nextState != G_dimm_state)
+ {
+ DIMM_DBG("task_dimm_sm: Updating state to 0x%02X (DIMM%04X) end of tick %d", nextState, (L_dimmPort<<8)|L_dimmIndex, DIMM_TICK);
+ G_dimm_state = nextState;
+ L_notReadyCount = 0;
+ }
+ }
+
+} // end task_dimm_sm()
+
+
diff --git a/src/occ_405/dimm/dimm.h b/src/occ_405/dimm/dimm.h
new file mode 100644
index 0000000..cfbb898
--- /dev/null
+++ b/src/occ_405/dimm/dimm.h
@@ -0,0 +1,69 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/dimm/dimm.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* [+] 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 _DIMM_H
+#define _DIMM_H
+
+#include <occ_common.h>
+#include <trac_interface.h>
+#include <errl.h>
+#include <rtls.h>
+
+#define WORD_HIGH(data) ((uint32_t)(((uint64_t)data)>>32))
+#define WORD_LOW(data) ((uint32_t)(((uint64_t)data)&0xFFFFFFFF))
+
+#define NUM_DIMM_PORTS 2
+
+typedef enum
+{
+ DIMM_READ_SUCCESS = 0x00,
+ DIMM_READ_IN_PROGRESS = 0x01,
+ DIMM_READ_SCHEDULE_FAILED = 0xFA,
+ DIMM_READ_NOT_COMPLETE = 0xFF,
+} readStatus_e;
+
+typedef enum
+{
+ PIB_I2C_ENGINE_C = 0x01,
+ PIB_I2C_ENGINE_D = 0x02,
+ PIB_I2C_ENGINE_E = 0x03,
+} PIB_I2C_ENGINE;
+
+typedef enum
+{
+ MEM_TYPE_CUMULUS = 0x00,
+ MEM_TYPE_NIMBUS = 0xFF
+} MEMORY_TYPE;
+
+// Generic memory initialization to handle init for all memory types
+void memory_init();
+
+// Nimbus specific init
+void memory_nimbus_init();
+
+// DIMM I2C state machine (for NIMBUS)
+void task_dimm_sm(struct task *i_self);
+
+#endif //_DIMM_H
diff --git a/src/occ_405/dimm/dimm_service_codes.h b/src/occ_405/dimm/dimm_service_codes.h
new file mode 100755
index 0000000..9261d04
--- /dev/null
+++ b/src/occ_405/dimm/dimm_service_codes.h
@@ -0,0 +1,40 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/dimm/dimm_service_codes.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* [+] 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 _DIMM_SERVICE_CODES_H_
+#define _DIMM_SERVICE_CODES_H_
+
+#include <comp_ids.h>
+
+enum dimmModuleId
+{
+ DIMM_MID_STATE_MACHINE = DIMM_COMP_ID | 0x00,
+ DIMM_MID_MEMORY_INIT = DIMM_COMP_ID | 0x01,
+ DIMM_MID_NIMBUS_INIT = DIMM_COMP_ID | 0x02,
+ DIMM_MID_DIMM_SM = DIMM_COMP_ID | 0x03,
+ DIMM_MID_MARK_DIMM_FAILED = DIMM_COMP_ID | 0x04,
+};
+
+#endif /* #ifndef _DIMM_SERVICE_CODES_H_ */
diff --git a/src/occ_405/img_defs.mk b/src/occ_405/img_defs.mk
index e3fec37..a2f6d50 100644
--- a/src/occ_405/img_defs.mk
+++ b/src/occ_405/img_defs.mk
@@ -35,10 +35,10 @@
#
# SSX_SRCDIR : Default ..; The path to the SSX source code.
# The default is set for building the SSX
-# subdirectories.
+# subdirectories.
#
# SSX_THREAD_SUPPORT : (0/1, default 1); Compile SSX thread and
-# semaphore suppprt
+# semaphore suppprt
#
# SSX_TIMER_SUPPORT : (0/1, default 1); Compile SSX timer suppprt
#
@@ -58,7 +58,7 @@
# make GCC-O-LEVEL="-Os -fno-branch-count-reg"
#
# GCC-TOOL-PREFIX : The full path (including executable file prefixes) to
-# the GCC cross-development tools to use. The default is
+# the GCC cross-development tools to use. The default is
# "ppcnf-mcp5-"
#
# CTEPATH : This variable defaults to the afs/awd CTE tool
@@ -186,8 +186,8 @@ GCC-DEFS += -DSTRAIGHT_TO_OBS_HACK=1
endif
GCC-DEFS += -DIMAGE_NAME=$(IMAGE_NAME)
-GCC-DEFS += -DSSX_TIMER_SUPPORT=$(SSX_TIMER_SUPPORT)
-GCC-DEFS += -DSSX_THREAD_SUPPORT=$(SSX_THREAD_SUPPORT)
+GCC-DEFS += -DSSX_TIMER_SUPPORT=$(SSX_TIMER_SUPPORT)
+GCC-DEFS += -DSSX_THREAD_SUPPORT=$(SSX_THREAD_SUPPORT)
GCC-DEFS += -DPPC405_MMU_SUPPORT=$(PPC405_MMU_SUPPORT)
GCC-DEFS += -DSSX_TRACE_SUPPORT=$(SSX_TRACE_SUPPORT)
GCC-DEFS += -DSSX_TRACE_HASH_PREFIX=$(SSX_TRACE_HASH_PREFIX)
@@ -212,6 +212,7 @@ APP_INCLUDES = -I$(IMAGE_SRCDIR)/rtls \
-I$(IMAGE_SRCDIR)/amec \
-I$(IMAGE_SRCDIR)/cent \
-I$(IMAGE_SRCDIR)/firdata \
+ -I$(IMAGE_SRCDIR)/dimm \
-I$(IMAGE_SRCDIR)/../occ_gpe0 \
INCLUDES += $(IMG_INCLUDES) $(GLOBAL_INCLUDES) $(APP_INCLUDES) \
diff --git a/src/occ_405/incl/comp_ids.h b/src/occ_405/incl/comp_ids.h
index fb6f5d5..e6ff8b6 100755
--- a/src/occ_405/incl/comp_ids.h
+++ b/src/occ_405/incl/comp_ids.h
@@ -80,5 +80,9 @@
#define CMDH_COMP_ID 0x0E00
#define CMDH_COMP_NAME "CMDH"
+// DIMM State Manager
+#define DIMM_COMP_ID 0x0F00
+#define DIMM_COMP_NAME "DIMM"
+
#endif
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index 2d0c37b..8e77fcf 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -56,6 +56,7 @@
#include "scom.h"
//#include <fir_data_collect.h>
#include <pss_service_codes.h>
+#include <dimm.h>
extern uint32_t __ssx_boot; // Function address is 32 bits
extern uint32_t G_occ_phantom_critical_count;
diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile
index 98bec10..adc8403 100644
--- a/src/occ_405/occLinkInputFile
+++ b/src/occ_405/occLinkInputFile
@@ -20,6 +20,7 @@ INPUT ( amec_data.o
dcomMasterRx.o
dcomSlaveRx.o
dcomSlaveTx.o
+ dimm.o
errl.o
ffdc.o
fir_data_collect.o
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index 65ccde4..e355f28 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -102,6 +102,10 @@ enum occReasonCode
APSS_HARD_FAILURE = 0xC5,
/// Request to read redundant APSS data failed
REDUNDANT_APSS_GPE_FAILURE = 0xCB,
+ /// Request to read DIMM data failed.
+ DIMM_GPE_FAILURE = 0xD0,
+ MEMORY_INIT_FAILED = 0xD1,
+ DIMM_INVALID_STATE = 0xD2,
/// Success!
OCC_SUCCESS_REASON_CODE = 0xFF,
};
@@ -193,6 +197,9 @@ enum occExtReasonCode
ERC_BCE_REQ_SCHED_INPROG_FAILURE = 0x00000073,
ERC_BCE_REQ_CREATE_WRITE_FAILURE = 0x00000074,
ERC_BCE_REQ_SCHED_WRITE_FAILURE = 0x00000075,
+
+ ERC_DIMM_SCHEDULE_FAILURE = 0x00000080,
+ ERC_DIMM_COMPLETE_FAILURE = 0x00000081,
};
// Error log Module Ids
diff --git a/src/occ_405/occ_sys_config.c b/src/occ_405/occ_sys_config.c
index f052fe0..808fce0 100755
--- a/src/occ_405/occ_sys_config.c
+++ b/src/occ_405/occ_sys_config.c
@@ -26,6 +26,7 @@
#include <occ_common.h>
#include <common_types.h>
#include <occ_sys_config.h>
+#include <dimm.h>
// SysConfig Section Defines
#define SYSCFG_DEFAULT_VERSION 0xff
@@ -183,10 +184,12 @@ occSysConfigData_t G_sysConfigData =
.master_ppb_fmax = 0xFFFF,
// -----------------------------------------------------------
- // Centaur/Dimm HUID initializations
+ // Centaur/DIMM Initialization
// -----------------------------------------------------------
.centaur_huids = {0},
- .dimm_huids = {{0},{0},{0},{0},{0},{0},{0},{0}},
+ .dimm_huids = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
+ .mem_type = MEM_TYPE_NIMBUS,
+ .dimm_i2c_engine = PIB_I2C_ENGINE_E,
// -----------------------------------------------------------
// Memory Throttle Limits
diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h
index 91a6369..4d238ee 100755
--- a/src/occ_405/occ_sys_config.h
+++ b/src/occ_405/occ_sys_config.h
@@ -34,6 +34,7 @@
#endif
#include <state.h>
#include <apss.h>
+#include <dimm.h>
#define MAX_NUM_OCC 8
#define MAX_NUM_NODES 4
@@ -332,14 +333,10 @@ typedef struct
uint32_t master_ppb_fmax;
// --------------------------------------
- // Hardware Sensor ID's for centaurs and dimms
+ // Memory Configuration Data
// --------------------------------------
uint32_t centaur_huids[MAX_NUM_CENTAURS];
uint32_t dimm_huids[MAX_NUM_CENTAURS][NUM_DIMMS_PER_CENTAUR];
-
- // --------------------------------------
- // Memory type and dimm i2c engine for nimbus
- // --------------------------------------
uint8_t mem_type;
uint8_t dimm_i2c_engine;
diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h
index 7db2e90..5b95791 100755
--- a/src/occ_405/rtls/rtls.h
+++ b/src/occ_405/rtls/rtls.h
@@ -57,7 +57,7 @@ typedef enum {
// TASK_ID_AMEC_MASTER, // AMEC SMH tasks
// TASK_ID_CORE_DATA_CONTROL,
// TASK_ID_GPU_SM, // GPU State Machine
-// TASK_ID_DIMM_SM, // DIMM State Machine
+ TASK_ID_DIMM_SM, // DIMM State Machine
// TASK_ID_MEM_DEADMAN, // Memory deadman timer
TASK_END // This must always be the last enum in this list,
// so that TASK_END always equals the last task ID + 1.
@@ -97,13 +97,13 @@ typedef struct
RTL_FLAG_NO_APSS | RTL_FLAG_MSTR_READY | RTL_FLAG_STANDBY | \
RTL_FLAG_APSS_NOT_INITD)
-#define CENTAUR_CONTROL_RTL_FLAGS (RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_ACTIVE | \
- RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | \
- RTL_FLAG_APSS_NOT_INITD)
+#define MEMORY_CONTROL_RTL_FLAGS (RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_ACTIVE | \
+ RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | \
+ RTL_FLAG_APSS_NOT_INITD)
-#define CENTAUR_DATA_RTL_FLAGS (RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | \
- RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | \
- RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD)
+#define MEMORY_DATA_RTL_FLAGS (RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | \
+ RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | \
+ RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD)
// Tick Timer definitions
#define MICS_PER_TICK 250 // Number of micro-seconds per tick
diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c
index 69c6219..9d63762 100755
--- a/src/occ_405/rtls/rtls_tables.c
+++ b/src/occ_405/rtls/rtls_tables.c
@@ -33,6 +33,7 @@
#include <centaur_data.h>
#include <centaur_control.h>
#include "amec_master_smh.h"
+#include "dimm.h"
//flags for task table
#define APSS_TASK_FLAGS RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_RUN
@@ -47,9 +48,9 @@
#define FLAGS_LOW_CORES_DATA RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
#define FLAGS_HIGH_CORES_DATA RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
-//Start out with centaur tasks not running.
-#define FLAGS_CENTAUR_DATA RTL_FLAG_NONE
-#define FLAGS_CENTAUR_CONTROL RTL_FLAG_NONE
+// Start out with memory tasks not running, then start during transition to observation in memory_init()
+#define FLAGS_MEMORY_DATA RTL_FLAG_NONE
+#define FLAGS_MEMORY_CONTROL RTL_FLAG_NONE
#define FLAGS_FAST_CORES_DATA RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
@@ -71,7 +72,6 @@
// TEMP/TODO: These are not yet implemented
#define FLAGS_GPU_SM
-#define FLAGS_DIMM_SM
#define FLAGS_MEM_DEADMAN
// Global tick sequences
@@ -121,8 +121,7 @@ task_t G_task_table[TASK_END] = {
// { FLAGS_CORE_DATA_CONTROL, task_core_data_control, NULL }, // TASK_ID_CORE_DATA_CONTROL
// TEMP -- NOT YET IMPLEMENTED
// { FLAGS_GPU_SM, task_gpu_sm, NULL }, // TASK_ID_GPU_SM
-// TEMP -- NOT YET IMPLEMENTED
-// { FLAGS_DIMM_SM, task_dimm_sm, NULL }, // TASK_ID_DIMM_SM
+ { FLAGS_MEMORY_DATA, task_dimm_sm, NULL }, // TASK_ID_DIMM_SM
// TEMP -- NOT YET IMPLEMENTED
// { FLAGS_MEM_DEADMAN, task_mem_deadman, NULL }, // TASK_ID_MEM_DEADMAN
};
@@ -130,7 +129,7 @@ task_t G_task_table[TASK_END] = {
const uint8_t G_tick0_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
@@ -169,7 +168,7 @@ const uint8_t G_tick1_seq[] = {
const uint8_t G_tick2_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
@@ -207,7 +206,7 @@ const uint8_t G_tick3_seq[] = {
const uint8_t G_tick4_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
@@ -246,7 +245,7 @@ const uint8_t G_tick5_seq[] = {
const uint8_t G_tick6_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
@@ -284,7 +283,7 @@ const uint8_t G_tick7_seq[] = {
const uint8_t G_tick8_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
@@ -323,7 +322,7 @@ const uint8_t G_tick9_seq[] = {
const uint8_t G_tick10_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
@@ -361,7 +360,7 @@ const uint8_t G_tick11_seq[] = {
const uint8_t G_tick12_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
@@ -400,7 +399,7 @@ const uint8_t G_tick13_seq[] = {
const uint8_t G_tick14_seq[] = {
TASK_ID_APSS_START,
TASK_ID_CORE_DATA_LOW,
- //TASK_ID_DIMM_SM,
+ TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
diff --git a/src/occ_405/state.c b/src/occ_405/state.c
index 8cb1124..b784fa4 100755
--- a/src/occ_405/state.c
+++ b/src/occ_405/state.c
@@ -40,6 +40,7 @@
//#include "heartbeat.h"
#include "scom.h"
#include <fir_data_collect.h>
+#include <dimm.h>
extern proc_gpsm_dcm_sync_occfw_t G_proc_dcm_sync_state;
extern bool G_mem_monitoring_allowed;
@@ -135,37 +136,8 @@ errlHndl_t SMGR_standby_to_observation()
l_error_logged = FALSE;
TRAC_IMP("SMGR: Standby to Observation Transition Started");
-// TEMP -- NOT SUPPORTED YET IN PHASE1
-/*
- //This flag is set if tmgt sends us at least one data set in the
- //mem config data packet. No data sets will be sent for centaur ec less than 2.0
- //due to an intermittent hw failure that can occur on those chips.
+ memory_init();
- if(G_mem_monitoring_allowed)
- {
- if(!rtl_task_is_runnable(TASK_ID_CENTAUR_DATA))
- {
-
- TRAC_INFO("SMGR_standby_to_observation: calling centaur_init()");
- centaur_init(); //no rc, handles errors internally
-
- //check if centaur_init resulted in a reset
- //since we don't have a return code from centaur_init.
- if(isSafeStateRequested())
- {
- TRAC_ERR("SMGR_standby_to_observation: OCC is being reset, centaur_init failed");
- }
- else
- {
- //initialization was successful.
- //Set task flags to allow centaur control task to run and
- //also to prevent us from doing initialization again.
- G_task_table[TASK_ID_CENTAUR_DATA].flags = CENTAUR_DATA_RTL_FLAGS;
- G_task_table[TASK_ID_CENTAUR_CONTROL].flags = CENTAUR_CONTROL_RTL_FLAGS;
- }
- }
- }
-*/
// Set the RTL Flags to indicate which tasks can run
// - Set OBSERVATION b/c we're in OBSERVATION State
rtl_clr_run_mask_deferred(RTL_FLAG_STANDBY);
diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk
index c13d742..58aa999 100644
--- a/src/occ_405/topfiles.mk
+++ b/src/occ_405/topfiles.mk
@@ -47,6 +47,7 @@ TOP-C-SOURCES = amec/amec_data.c \
dcom/dcomMasterRx.c \
dcom/dcomSlaveRx.c \
dcom/dcomSlaveTx.c \
+ dimm/dimm.c \
errl/errl.c \
firdata/fir_data_collect.c \
homer.c \
diff --git a/src/occ_405/trac/trac.h b/src/occ_405/trac/trac.h
index dad0ad4..92fd9bf 100755
--- a/src/occ_405/trac/trac.h
+++ b/src/occ_405/trac/trac.h
@@ -287,6 +287,16 @@ extern void dumpHexString(const void *i_data, const unsigned int len, const char
#define CNFG_DBG_HEXDUMP(data, len, string)
#endif
+#ifdef DIMM_DEBUG
+ #define DIMM_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define DIMM_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define DIMM_DBG(frmt,args...)
+ #define DIMM_DBG_HEXDUMP(data, len, string)
+#endif
+
#else // NO_TRAC_STRINGS
#define TRAC_ERR(frmt,args...)
@@ -307,6 +317,7 @@ extern void dumpHexString(const void *i_data, const unsigned int len, const char
#define SNSR_DBG(frmt,args...)
#define TMER_DBG(frmt,args...)
#define CNFG_DBG(frmt,args...)
+#define DIMM_DBG(frmt,args...)
#define MAIN_DBG_HEXDUMP(frmt,args...)
#define RTLS_DBG_HEXDUMP(frmt,args...)
@@ -322,6 +333,7 @@ extern void dumpHexString(const void *i_data, const unsigned int len, const char
#define SNSR_DBG_HEXDUMP(frmt,args...)
#define TMER_DBG_HEXDUMP(frmt,args...)
#define CNFG_DBG_HEXDUMP(frmt,args...)
+#define DIMM_DBG_HEXDUMP(frmt,args...)
#endif
OpenPOWER on IntegriCloud