summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Cain <cjcain@us.ibm.com>2017-01-10 14:32:13 -0600
committerChristopher J. Cain <cjcain@us.ibm.com>2017-01-18 18:40:21 -0500
commit6089fe0e7580b1c5030d1f380b1bc91c293e8bb9 (patch)
tree274c7e5e0c6a3214fd4c792266fbe8a396fa23d8
parent4141b5f5fef2ba4b444aabbda1677e7f583cd4e8 (diff)
downloadtalos-occ-6089fe0e7580b1c5030d1f380b1bc91c293e8bb9.tar.gz
talos-occ-6089fe0e7580b1c5030d1f380b1bc91c293e8bb9.zip
AVS Bus divider, loadline and misc changes
- validate CRC in cmd response - read current / voltage on alternating ticks (commands on both bus for each tick) - calculate chip power (with loadline) and power for each tick - update divider value for bus speed - add error history counters and add them to logs Change-Id: I33bce916dc2dffef6a6d616633a5f1266d7baa7e RTC: 163992 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34947 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
-rwxr-xr-xsrc/occ_405/amec/amec_sensors_power.c213
-rwxr-xr-xsrc/occ_405/amec/amec_sys.h2
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds.c8
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c10
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h4
-rwxr-xr-xsrc/occ_405/dimm/dimm.c9
-rwxr-xr-xsrc/occ_405/errl/errl.c66
-rwxr-xr-xsrc/occ_405/errl/errl.h21
-rwxr-xr-xsrc/occ_405/main.c8
-rw-r--r--src/occ_405/occ_service_codes.h1
-rw-r--r--src/occ_405/pss/avsbus.c290
-rwxr-xr-xsrc/occ_405/pss/avsbus.h11
-rwxr-xr-xsrc/occ_405/sensor/sensor_enum.h3
-rwxr-xr-xsrc/occ_405/sensor/sensor_info.c2
-rwxr-xr-xsrc/occ_405/sensor/sensor_table.c5
15 files changed, 497 insertions, 156 deletions
diff --git a/src/occ_405/amec/amec_sensors_power.c b/src/occ_405/amec/amec_sensors_power.c
index 570ea34..5b98877 100755
--- a/src/occ_405/amec/amec_sensors_power.c
+++ b/src/occ_405/amec/amec_sensors_power.c
@@ -405,78 +405,159 @@ void amec_update_apss_sensors(void)
}
+// Read the current from AVS Bus and update sensors
+void process_avsbus_current()
+{
+ if (G_avsbus_vdd_monitoring)
+ {
+ // Read Vdd current (returns 10mA)
+ uint32_t current = avsbus_read(AVSBUS_VDD, AVSBUS_CURRENT);
+ if (current != 0)
+ {
+ // Current value stored in the sensor should be in 10mA (scale -2)
+ sensor_update(AMECSENSOR_PTR(CURVDD), (uint16_t)current);
+ }
+ }
+ if (G_avsbus_vdn_monitoring)
+ {
+ // Read Vdn current (returns 10mA)
+ uint32_t current = avsbus_read(AVSBUS_VDN, AVSBUS_CURRENT);
+ if (current != 0)
+ {
+ // Current value stored in the sensor should be in 10mA (scale -2)
+ sensor_update(AMECSENSOR_PTR(CURVDN), (uint16_t)current);
+ }
+ }
+}
+
+
+// Read the voltage from AVS Bus and update sensors
+void process_avsbus_voltage()
+{
+ if (G_avsbus_vdd_monitoring)
+ {
+ // Read Vdd voltage (returns mV)
+ uint32_t voltage = avsbus_read(AVSBUS_VDD, AVSBUS_VOLTAGE);
+ if (voltage != 0)
+ {
+ // Voltage value stored in the sensor should be in 100mV (scale -1)
+ voltage /= 100;
+ sensor_update(AMECSENSOR_PTR(VOLTVDD), (uint16_t)voltage);
+ }
+ }
+ if (G_avsbus_vdn_monitoring)
+ {
+ // Read Vdn voltage (returns mV)
+ uint32_t voltage = avsbus_read(AVSBUS_VDN, AVSBUS_VOLTAGE);
+ if (voltage != 0)
+ {
+ // Voltage value stored in the sensor should be in 100mV (scale -1)
+ voltage /= 100;
+ sensor_update(AMECSENSOR_PTR(VOLTVDN), (uint16_t)voltage);
+ }
+ }
+}
+
+
+// Calculate chip voltage and power and update sensors
void update_avsbus_power_sensors(const avsbus_type_e i_type)
{
static bool L_throttle_vdd = FALSE;
static bool L_throttle_vdn = FALSE;
bool * L_throttle = &L_throttle_vdd;
- uint16_t l_loadline = G_sysConfigData.avsbus_vdd.loadline;
- uint32_t l_voltageSensor = VOLTVDD;
+ // TODO: RTC 130216 : read loadline and distloss from Pstate Super Structure
+ uint16_t l_loadline = 0x61AB; // OCCPstateParmBlock.vdd_sysparm.loadline_uohm
+ uint16_t l_distloss = 0x0000; // OCCPstateParmBlock.vdd_sysparm.distloss_uohm
uint32_t l_currentSensor = CURVDD;
+ uint32_t l_voltageSensor = VOLTVDD;
+ uint32_t l_voltageChip = VOLTVDDSENSE;
uint32_t l_powerSensor = PWRVDD;
if (AVSBUS_VDN == i_type)
{
L_throttle = &L_throttle_vdn;
- l_loadline = G_sysConfigData.avsbus_vdn.loadline;
- l_voltageSensor = VOLTVDN;
+ l_loadline = 0x6BA8; // OCCPstateParmBlock.vdn_sysparm.loadline_uohm
+ l_distloss = 0x0000; // OCCPstateParmBlock.vdn_sysparm.distloss_uohm
l_currentSensor = CURVDN;
+ l_voltageSensor = VOLTVDN;
+ l_voltageChip = VOLTVDNSENSE;
l_powerSensor = PWRVDN;
}
- // Read AVS Bus current
- uint32_t l_current_10ma = avsbus_read(i_type, AVSBUS_CURRENT);
- if (l_current_10ma != 0)
+ // Read latest voltage/current sensors
+ const sensor_t *volt = getSensorByGsid(l_voltageSensor);
+ const uint32_t l_voltage_100mv = volt->sample;
+ const sensor_t *curr = getSensorByGsid(l_currentSensor);
+ const uint32_t l_current_10ma = curr->sample;
+
+#ifdef AVSDEBUG
+ // TODO: RTC 130216 : REMOVE AFTER VERIFYING loadline/distlost from Pstate Super Structure
+ static uint8_t L_traceCount = 0;
+ if (L_traceCount < 4)
{
- // Current value stored in the sensor should be in 10mA (scale -2)
- sensor_update(AMECSENSOR_PTR(l_currentSensor), (uint16_t)l_current_10ma);
+ TRAC_INFO("update_avsbus_power_sensors: #%d Vd%c=%dx100mV, I=%dx10mA", L_traceCount, (i_type==AVSBUS_VDD)?'d':'n',
+ l_voltage_100mv, l_current_10ma);
+ TRAC_INFO("update_avsbus_power_sensors: #%d Vd%c Rloadline=%d, Rdistloss=%d", L_traceCount, (i_type==AVSBUS_VDD)?'d':'n',
+ l_loadline, l_distloss);
}
+#endif
- // Read AVS Bus voltage
- uint32_t l_voltage_mv = avsbus_read(i_type, AVSBUS_VOLTAGE);
- if (l_voltage_mv != 0)
+ if ((l_voltage_100mv != 0) && (l_current_10ma != 0))
{
// Calculate voltage on just processor package (need to take load-line into account)
// Voltage value stored in the sensor should be in 100mV (scale -1)
// (current is in 10mA units, and load-line is in tenth of microOhms)
- // v(V) = i(10mA)*(1 A/1000 mA) * r(1/10u Ohm)*(1 Ohm/1,000,000 uOhm)
- // = i * (1 A/100) * r * (1 Ohm/10,000,000)
- // = i * r / 1,000,000,000
+ // v(V) = i(10mA)*(1 A/1000 mA) * r(1 uOhm)*(1 Ohm/1,000,000 uOhm)
+ // = i * (1 A/100) * r * (1 Ohm/1,000,000)
+ // = i * r / 100,000,000
// v(mV) = v(V) * 1,000
// v(100mV) = v(mV) / 100
// = (v(V) * 1,000) / 100 = v(V) * 10
- // = (i * r / 1,000,000,000) * 10 = i * r / 100,000,000
- const uint64_t l_volt_drop_100mv = (l_current_10ma * l_loadline) / 100000000;
- // TODO: RTC163992 - Confirm loadline calculation (chip package load line vs regulator load line)
- // Convert voltage to 100mv units and subtract the drop:
- int32_t l_voltage_100mv = (l_voltage_mv / 100) - l_volt_drop_100mv;
- if ((l_voltage_100mv <= 0) || (l_voltage_100mv > 0xFFFF))
+ // = (i * r / 100,000,000) * 10 = i * r / 10,000,000
+ // NOTE: distloss is the same as Rpath in the WOF algorithm
+ const uint64_t l_volt_drop_100mv = (l_current_10ma * (l_loadline+l_distloss)) / 10000000;
+ // Calculate chip voltage
+ int32_t l_chip_voltage_100mv = l_voltage_100mv - l_volt_drop_100mv;
+ if ((l_chip_voltage_100mv <= 0) || (l_chip_voltage_100mv > 0xFFFF))
{
- // Voltage out of range, write 0
+ // Voltage out of range, do not write sensors
if (!*L_throttle)
{
- TRAC_ERR("update_avsbus_power_sensors: Voltage out of range! %dmV - %d(100mV) = %d(100mV)",
- l_voltage_mv, WORD_LOW(l_volt_drop_100mv), l_voltage_100mv);
+ TRAC_ERR("update_avsbus_power_sensors: chip voltage out of range! %dmV - %d(100mV) = %d(100mV)",
+ l_voltage_100mv, WORD_LOW(l_volt_drop_100mv), l_chip_voltage_100mv);
*L_throttle = TRUE;
}
- l_voltage_100mv = 0;
}
else
{
*L_throttle = FALSE;
- }
- sensor_update(AMECSENSOR_PTR(l_voltageSensor), (uint16_t)l_voltage_100mv);
- if (l_current_10ma != 0)
- {
+ // Update chip voltage (remote sense adjusted for loadline) (100mV units)
+ sensor_update(AMECSENSOR_PTR(l_voltageChip), (uint16_t)l_chip_voltage_100mv);
+
// Power value stored in the sensor should be in W (scale 0)
// p(W) = v(V) * i(A) = v(100mV)*100/1000 * i(10mA)*10/1000
// = v(100mV)/10 * i(10mA)/100
// = v(100mv) * i(10mA) / 1000
- const uint32_t l_power = l_voltage_100mv * l_current_10ma / 1000;
+ const uint32_t l_power = l_chip_voltage_100mv * l_current_10ma / 1000;
sensor_update(AMECSENSOR_PTR(l_powerSensor), (uint16_t)l_power);
}
+
+#ifdef AVSDEBUG
+ // TODO: RTC 130216 : REMOVE AFTER VERIFYING loadline/distlost from Pstate Super Structure
+ if (L_traceCount < 4)
+ {
+ const sensor_t *power = getSensorByGsid(l_powerSensor);
+ TRAC_INFO("update_avsbus_power_sensors: #%d Vd%cs=%dx100mV, P=%dW", L_traceCount, (i_type==AVSBUS_VDD)?'d':'n',
+ l_chip_voltage_100mv, power->sample);
+ }
+#endif
}
+#ifdef AVSDEBUG
+ // TODO: RTC 130216 : REMOVE AFTER VERIFYING loadline/distlost from Pstate Super Structure
+ ++L_traceCount;
+#endif
+
} // end update_avsbus_power_sensors()
@@ -484,34 +565,74 @@ void update_avsbus_power_sensors(const avsbus_type_e i_type)
//
// Name: amec_update_avsbus_sensors
//
-// Description: Read AVS Bus data and update sensors
+// Description: Read AVS Bus data and update sensors (called every tick)
+// The very first tick kicks off a read of the currents for both buses (Vdd/Vdn).
+// The next tick will process the currents and then start a read of the voltages.
+// The next tick will process the voltages and then start a read of the currents.
+// (readings for each bus will essentially be updated every 2 ticks)
//
// Thread: RealTime Loop
//
// End Function Specification
void amec_update_avsbus_sensors(void)
{
- static bool L_vdd_state = TRUE;
- if (L_vdd_state)
+ static enum {
+ AVSBUS_STATE_DISABLED = 0,
+ AVSBUS_STATE_INITIATE_READ = 1,
+ AVSBUS_STATE_PROCESS_CURRENT = 2,
+ AVSBUS_STATE_PROCESS_VOLTAGE = 3
+ } L_avsbus_state = AVSBUS_STATE_INITIATE_READ;
+
+ if (isSafeStateRequested())
{
- // If AVS Bus Vdd config data was received, update sensors
- if (G_avsbus_vdd_monitoring)
- {
- update_avsbus_power_sensors(AVSBUS_VDD);
- }
+ L_avsbus_state = AVSBUS_STATE_DISABLED;
+ G_avsbus_vdd_monitoring = FALSE;
+ G_avsbus_vdn_monitoring = FALSE;
}
- else
+
+ switch (L_avsbus_state)
{
- // If AVS Bus Vdn config data was received, update sensors
- if (G_avsbus_vdn_monitoring)
- {
- update_avsbus_power_sensors(AVSBUS_VDN);
- }
+ case AVSBUS_STATE_INITIATE_READ:
+ // Start first AVS Bus read of current
+ initiate_avsbus_reads(AVSBUS_CURRENT);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_CURRENT;
+ break;
+
+ case AVSBUS_STATE_PROCESS_CURRENT:
+ // Process the current readings
+ process_avsbus_current();
+ // Initiate read of voltages
+ initiate_avsbus_reads(AVSBUS_VOLTAGE);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_VOLTAGE;
+ break;
+
+ case AVSBUS_STATE_PROCESS_VOLTAGE:
+ // Process the voltage readings
+ process_avsbus_voltage();
+ // Initiate read of currents
+ initiate_avsbus_reads(AVSBUS_CURRENT);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_CURRENT;
+ break;
+
+ case AVSBUS_STATE_DISABLED:
+ break;
+
+ default:
+ TRAC_ERR("amec_update_avsbus_sensors: INVALID AVSBUS STATE 0x%02X", L_avsbus_state);
+ L_avsbus_state = AVSBUS_STATE_INITIATE_READ;
+ break;
}
- // Alternate between Vdd/Vdn readings
- L_vdd_state = !L_vdd_state;
+ // Update the chip voltage and power sensors after every reading
+ if (G_avsbus_vdd_monitoring)
+ {
+ update_avsbus_power_sensors(AVSBUS_VDD);
+ }
+ if (G_avsbus_vdn_monitoring)
+ {
+ update_avsbus_power_sensors(AVSBUS_VDN);
+ }
} // end amec_update_avsbus_sensors()
diff --git a/src/occ_405/amec/amec_sys.h b/src/occ_405/amec/amec_sys.h
index f741d53..d298c7f 100755
--- a/src/occ_405/amec/amec_sys.h
+++ b/src/occ_405/amec/amec_sys.h
@@ -79,6 +79,8 @@ typedef struct
sensor_t gpetickdur[NUM_GPE_ENGINES];
sensor_t prcdupdatedur;
sensor_t probe250us[NUM_AMEC_FW_PROBES];
+ sensor_t voltvddsense;
+ sensor_t voltvdnsense;
// DPS update flag
// 8 bit flag: =1, no updating allowed; =0, updating is allowed
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds.c b/src/occ_405/cmdh/cmdh_fsp_cmds.c
index 0f09151..dbdd75a 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds.c
@@ -1160,6 +1160,14 @@ errlHndl_t cmdh_tmgt_setmodestate(const cmdh_fsp_cmd_t * i_cmd_ptr,
break;
}
+ // Verify not in safe state
+ if ((TRUE == isSafeStateRequested()) || (CURRENT_STATE() == OCC_STATE_SAFE))
+ {
+ CMDH_TRAC_ERR("OCC in safe state, rejecting mode change request");
+ l_rc = ERRL_RC_INVALID_STATE;
+ break;
+ }
+
// -------------------------------------------------
// Act on State & Mode Changes
// -------------------------------------------------
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
index b0d4cd2..d3e9a3f 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -1001,9 +1001,8 @@ errlHndl_t data_store_avsbus_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
G_avsbus_vdd_monitoring = TRUE;
G_sysConfigData.avsbus_vdd.bus = l_cmd_ptr->vdd_bus;
G_sysConfigData.avsbus_vdd.rail = l_cmd_ptr->vdd_rail;
- G_sysConfigData.avsbus_vdd.loadline = l_cmd_ptr->vdd_loadline;
- CNFG_DBG("data_store_avsbus_config: Vdd bus[%d] rail[%d] loadline[0x%02X]",
- G_sysConfigData.avsbus_vdd.bus, G_sysConfigData.avsbus_vdd.rail, G_sysConfigData.avsbus_vdd.loadline);
+ CNFG_DBG("data_store_avsbus_config: Vdd bus[%d] rail[%d]",
+ G_sysConfigData.avsbus_vdd.bus, G_sysConfigData.avsbus_vdd.rail);
}
else
{
@@ -1035,9 +1034,8 @@ errlHndl_t data_store_avsbus_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
G_avsbus_vdn_monitoring = TRUE;
G_sysConfigData.avsbus_vdn.bus = l_cmd_ptr->vdn_bus;
G_sysConfigData.avsbus_vdn.rail = l_cmd_ptr->vdn_rail;
- G_sysConfigData.avsbus_vdn.loadline = l_cmd_ptr->vdn_loadline;
- CNFG_DBG("data_store_avsbus_config: Vdn bus[%d] rail[%d] loadline[0x%02X]",
- G_sysConfigData.avsbus_vdn.bus, G_sysConfigData.avsbus_vdn.rail, G_sysConfigData.avsbus_vdn.loadline);
+ CNFG_DBG("data_store_avsbus_config: Vdn bus[%d] rail[%d]",
+ G_sysConfigData.avsbus_vdn.bus, G_sysConfigData.avsbus_vdn.rail);
if (G_avsbus_vdd_monitoring &&
(G_sysConfigData.avsbus_vdd.bus == G_sysConfigData.avsbus_vdn.bus))
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h
index 1a71b8c..b3c2cb3 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h
@@ -140,10 +140,10 @@ typedef struct __attribute__ ((packed))
uint8_t version;
uint8_t vdd_bus;
uint8_t vdd_rail;
- uint16_t vdd_loadline;
+ uint16_t reserved1;
uint8_t vdn_bus;
uint8_t vdn_rail;
- uint16_t vdn_loadline;
+ uint16_t reserved2;
}cmdh_avsbus_config_t;
// Used by TMGT to send OCC the PCAP config data.
diff --git a/src/occ_405/dimm/dimm.c b/src/occ_405/dimm/dimm.c
index 567fca5..fb62d6b 100755
--- a/src/occ_405/dimm/dimm.c
+++ b/src/occ_405/dimm/dimm.c
@@ -281,6 +281,15 @@ void mark_dimm_failed()
g_amec->proc[0].memctl[port].centaur.dimm_temps[dimm].flags |= FRU_SENSOR_STATUS_ERROR;
+ if (port == 0)
+ {
+ INCREMENT_ERR_HISTORY(ERR_DIMM_I2C_PORT0);
+ }
+ else
+ {
+ INCREMENT_ERR_HISTORY(ERR_DIMM_I2C_PORT1);
+ }
+
if (++G_dimm[port][dimm].errorCount > MAX_CONSECUTIVE_DIMM_RESETS)
{
// Disable collection on this DIMM, collect FFDC and log error
diff --git a/src/occ_405/errl/errl.c b/src/occ_405/errl/errl.c
index a309279..07b5e6e 100755
--- a/src/occ_405/errl/errl.c
+++ b/src/occ_405/errl/errl.c
@@ -61,6 +61,9 @@ errlHndl_t G_occErrSlots[ERRL_MAX_SLOTS] = {
(errlHndl_t) G_callslot
};
+// Array of error counters that are only cleared on OCC reset
+uint8_t G_error_history[ERR_HISTORY_SIZE] = {0};
+
extern uint8_t G_occ_interrupt_type;
extern bool G_fir_collection_required;
@@ -305,6 +308,9 @@ errlHndl_t createErrl(
// add trace
addTraceToErrl( i_trace, i_traceSz, l_rc );
+ // add error history
+ addErrHistory( l_rc );
+
// save off entry Id
l_rc->iv_entryId = l_id;
@@ -518,6 +524,64 @@ void addTraceToErrl(
}
+
+
+// Function Specification
+//
+// Name: addErrHistory
+//
+// Description: Add error trace history to log
+//
+// End Function Specification
+void addErrHistory(errlHndl_t io_err)
+{
+ // 1. Check if error log is not null
+ // 2. error log is not invalid
+ // 3. error log has not been commited
+ // 4. free space is enough (to hold new user detail header + data)
+ if( (io_err != NULL) &&
+ (io_err != INVALID_ERR_HNDL) &&
+ (io_err->iv_userDetails.iv_committed == 0) &&
+ ((io_err->iv_userDetails.iv_entrySize + sizeof(ErrlUserDetailsEntry_t) + sizeof(G_error_history)) < MAX_ERRL_ENTRY_SZ ) )
+ {
+ void * l_errPtr = io_err;
+ ErrlUserDetailsEntry_t l_usrDtlsEntry;
+ const uint16_t l_usrDtlsHeaderSz = sizeof(l_usrDtlsEntry);
+
+ // io_err |-----------------------------------------|
+ // | ErrlEntry_t |
+ // | {iv_userDetails.iv_userDetailEntrySize, | <== elog header and optional user details sections, need to add length
+ // | ... other elements ... }| of new usrdtl section(ErrlUserDetailsEntry_t + data len)
+ // |-----------------------------------------|
+ // | ErrlUserDetailsEntry_t | <== new user detail header (l_usrDtlsEntry)
+ // |-----------------------------------------|
+ // | data ... | <== new user detail data (G_error_history)
+ // | ... |
+
+ l_usrDtlsEntry.iv_size = sizeof(G_error_history);
+ l_usrDtlsEntry.iv_type = (uint8_t) ERRL_USR_DTL_HISTORY_DATA;
+ l_usrDtlsEntry.iv_version = 1;
+
+ // Calculate trace data address (err address + sizeof(ErrlEntry_t + existing usrDtls) + sizeof(ErrlUserDetailsEntry_t))
+ void * l_dataAddr = l_errPtr + io_err->iv_userDetails.iv_entrySize + l_usrDtlsHeaderSz;
+ memcpy(l_dataAddr, G_error_history, sizeof(G_error_history));
+
+ // Calculate entire data length including usrDtl header.
+ const uint16_t l_sizeOfUsrDtls = l_usrDtlsHeaderSz + l_usrDtlsEntry.iv_size;
+
+ // Copy new user details header into log
+ memcpy(l_errPtr+((io_err->iv_userDetails.iv_entrySize)), &l_usrDtlsEntry, l_usrDtlsHeaderSz);
+
+ //update master user details size with new data
+ io_err->iv_userDetails.iv_userDetailEntrySize += l_sizeOfUsrDtls;
+
+ //update error log with new size
+ io_err->iv_userDetails.iv_entrySize += l_sizeOfUsrDtls;
+ }
+
+} // end addErrHistory()
+
+
// Function Specification
//
// Name: reportErrorLog
@@ -571,7 +635,7 @@ void commitErrl( errlHndl_t *io_err )
if (l_oisr0_status.fields.check_stop_ppc405)
{
- TRAC_IMP("addTraceToErrl: System checkstop detected: ppc405, OISR0[0x%08x]",
+ TRAC_IMP("commitErrl: System checkstop detected: ppc405, OISR0[0x%08x]",
l_oisr0_status.value);
//Go to the reset state to minimize errors
reset_state_request(RESET_REQUESTED_DUE_TO_ERROR);
diff --git a/src/occ_405/errl/errl.h b/src/occ_405/errl/errl.h
index 217dde2..fcfb83b 100755
--- a/src/occ_405/errl/errl.h
+++ b/src/occ_405/errl/errl.h
@@ -110,6 +110,7 @@ typedef enum
ERRL_USR_DTL_TRACE_DATA = 0x01,
ERRL_USR_DTL_CALLHOME_DATA = 0x02,
ERRL_USR_DTL_BINARY_DATA = 0x03,
+ ERRL_USR_DTL_HISTORY_DATA = 0x04,
} ERRL_USR_DETAIL_TYPE;
// These are the possible OCC States.
@@ -265,6 +266,23 @@ extern uint8_t G_occErrIdCounter;
extern errlHndl_t G_occErrSlots[ERRL_MAX_SLOTS];
+// Array of error counters that are only cleared on OCC reset
+#define ERR_HISTORY_SIZE 32
+extern uint8_t G_error_history[ERR_HISTORY_SIZE];
+typedef enum {
+ ERR_AVSBUS_VDD_CURRENT = 1,
+ ERR_AVSBUS_VDD_VOLTAGE = 2,
+ ERR_AVSBUS_VDN_CURRENT = 3,
+ ERR_AVSBUS_VDN_VOLTAGE = 4,
+ ERR_DIMM_I2C_PORT0 = 5,
+ ERR_DIMM_I2C_PORT1 = 6
+} ERR_HISTORY_INDEX;
+#define INCREMENT_ERR_HISTORY(errorIndex) { \
+ if ((errorIndex < ERR_HISTORY_SIZE) && (G_error_history[errorIndex] < 255)) { \
+ ++G_error_history[errorIndex]; \
+ } \
+}
+
// Globals used by testcases
extern uint8_t G_errslot1[MAX_ERRL_ENTRY_SZ];
extern uint8_t G_errslot2[MAX_ERRL_ENTRY_SZ];
@@ -296,6 +314,9 @@ void addTraceToErrl(
errlHndl_t io_errl
);
+// Add Error history data to the Error Log
+void addErrHistory(errlHndl_t io_err);
+
/* Commit the Error Log */
void commitErrl( errlHndl_t * io_err );
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index 7023233..fdbe9f3 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -110,6 +110,9 @@ bool G_fir_collection_required = FALSE;
// Global flag indicating we are running on Simics
bool G_simics_environment = FALSE;
+// Nest frequency in MHz
+uint32_t G_nest_frequency_mhz;
+
extern uint8_t g_trac_inf_buffer[];
extern uint8_t g_trac_imp_buffer[];
extern uint8_t g_trac_err_buffer[];
@@ -1261,14 +1264,14 @@ int main(int argc, char **argv)
// all HOMER versions.
uint32_t l_tb_freq_hz = 0;
l_homerrc2 = homer_hd_map_read_unmap(HOMER_NEST_FREQ,
- &l_tb_freq_hz,
+ &G_nest_frequency_mhz,
&l_ssxrc2);
if ((HOMER_SUCCESS == l_homerrc2) || (HOMER_SSX_UNMAP_ERR == l_homerrc2))
{
// Data is in Mhz upon return and needs to be converted to Hz and then
// quartered.
- l_tb_freq_hz = (l_tb_freq_hz * 1000000)/4;
+ l_tb_freq_hz = G_nest_frequency_mhz * (1000000 / 4);
// @TODO: this parameter should be passsed to all the GPEs/CMEs/etc
// Can be stored in GPE accessible SRAM areas.
@@ -1277,6 +1280,7 @@ int main(int argc, char **argv)
else
{
l_tb_freq_hz = PPC405_TIMEBASE_HZ;
+ G_nest_frequency_mhz = (l_tb_freq_hz * 4) / 1000000;
}
CHECKPOINT(SSX_STARTING);
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index 2654851..b96ff0d 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -79,6 +79,7 @@ enum occReasonCode
CENT_LFIR_ERROR = 0x42,
AVSBUS_TIMEOUT = 0x50,
AVSBUS_ERROR = 0x51,
+ AVSBUS_CRC_ERROR = 0x52,
/// Throttle in nominal or turbo mode due to the bulk power limit being reached with both power supplies good
PCAP_THROTTLE_POWER_LIMIT = 0x61,
/// Firmware Failure: equivalent to assertion failures
diff --git a/src/occ_405/pss/avsbus.c b/src/occ_405/pss/avsbus.c
index b958271..6b76379 100644
--- a/src/occ_405/pss/avsbus.c
+++ b/src/occ_405/pss/avsbus.c
@@ -43,20 +43,16 @@
#define AVS_DBG(frmt,args...)
#endif
-
// AVS Bus usage will be determined after receiving config data from TMGT
bool G_avsbus_vdd_monitoring = FALSE;
bool G_avsbus_vdn_monitoring = FALSE;
-// The following constants are used after a command is put on the bus.
-// The code will wait for the o2s_ongoing bit to change (which indicates cmd completion).
-// Max wait time will be: O2S_ONGOING_CHECK_ATTEMPTS * O2S_ONGOING_CHECK_DELAY_NS (in nanoseconds)
-const uint32_t O2S_ONGOING_CHECK_ATTEMPTS = 10;
-const uint32_t O2S_ONGOING_CHECK_DELAY_NS = 100;
+extern uint32_t G_nest_frequency_mhz;
+#define AVSBUS_FREQUENCY_MHZ 10
// Number of read failures allowed before elog is created and reset requested.
// This should be no longer than 4ms (or it will impact WOF calculations)
-// (readings are taken every 500ms => 500us * 8 = 4ms)
+// (readings are taken every 500us => 500us * 8 = 4ms)
const uint8_t MAX_READ_ATTEMPTS = 8;
// NOTE: OCC must use Bridge B, because Bridge A is reserved for PGPE
@@ -142,13 +138,14 @@ void avsbus_init()
// 2 o2s_cpol = 0 (positive active clock)
// 3 o2s_cpha = 0 (first edge data launch/sample)
// 4:13 o2s_clock_divider = set based on the nest frequency for the desired frequency of 10MHz (assumed speed) per O2SCTRL1_[a][n] description.
- // = (nest_freq / (SPI_freq*8))-1 = (500M/(10M*8))-1 = 5.25
// 14:16 reserved
// 17 o2s_nr_of_frames = 1 (2 frames to account for the first and second frames of an AVSBus command)
// 18:63 reserved
// 1r00DDDD DDDDDDrr r1rrrrrr rrrrrrrrr
- value = 0x8014400000000000;
- // TODO: RTC163992 - Determine correct o2s_clock_divider based on nest freq
+ value = 0x8000400000000000;
+ // calculate o2s_clock_divider based on nest freq and target bus freq
+ const uint64_t divider = (G_nest_frequency_mhz / (AVSBUS_FREQUENCY_MHZ * 8)) - 1;
+ value |= (divider << 50);
if (bus0_monitoring)
{
out64(OCB_O2SCTRL10B, value);
@@ -160,27 +157,29 @@ void avsbus_init()
}
-// Calculate and update command with correct CRC
+// Calculate CRC for specified AVS Bus command
// Function which generates a 3 bit CRC value for 29 bit data
// from: ekb/chips/p9/procedures/hwp/lib/p9_avsbus_lib.C
+// (CRC is bits 29:31 in the AVS bus command)
+#define AVS_CRC_MASK 0x0000000700000000
#define AVS_CRC_DATA_MASK 0xFFFFFFF800000000
-void avs_crc_update(uint64_t *io_avs_cmd)
+uint64_t avs_crc_calculate(const uint64_t i_avs_cmd)
{
//Polynomial= x^3 + x^1 + x^0 = 1*x^3 + 0*x^2 + 1*x^1 + 1*x^0 = divisor(1011)
- uint64_t l_crc_value = 0;
+ uint64_t o_crc_value = 0;
uint64_t l_polynomial = 0xB000000000000000;
uint64_t l_msb = 0x8000000000000000;
- l_crc_value = *io_avs_cmd & AVS_CRC_DATA_MASK;
+ o_crc_value = i_avs_cmd & AVS_CRC_DATA_MASK;
- while (l_crc_value & AVS_CRC_DATA_MASK)
+ while (o_crc_value & AVS_CRC_DATA_MASK)
{
- if (l_crc_value & l_msb)
+ if (o_crc_value & l_msb)
{
//if l_msb is 1'b1, divide by l_polynomial and shift l_polynomial
// to the right
- l_crc_value = l_crc_value ^ l_polynomial;
+ o_crc_value = o_crc_value ^ l_polynomial;
l_polynomial = l_polynomial >> 1;
}
else
@@ -192,26 +191,22 @@ void avs_crc_update(uint64_t *io_avs_cmd)
l_msb = l_msb >> 1;
}
- // Add CRC to avs command (lower 3 bits of cmd)
- *io_avs_cmd |= l_crc_value;
+ return o_crc_value;
}
#define ERRORCOUNT_MAXTYPES 2
#define ERRORCOUNT_MAXCMDS 2
-// Read and return the voltage or current for specified rail
-// (voltage units are mV, current units are in 10mA)
-uint16_t avsbus_read(const avsbus_type_e i_type,
- const avsbus_cmdtype_e i_cmdtype)
+// Initiate read for specified type (Vdd/Vdn) and cmd (Voltage/Current)
+void avsbus_read_start(const avsbus_type_e i_type,
+ const avsbus_cmdtype_e i_cmdtype)
{
if (isSafeStateRequested())
{
// No need to attempt read if OCC will be reset
- return 0;
+ return;
}
- uint16_t o_reading = 0;
- bool l_failure = FALSE;
avsbusData_t l_data;
// Create error array for each type (Vdd/Vdn) and command (Voltage/Current)
@@ -222,8 +217,6 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
l_cmd_index = 1;
l_trace_cmd = 'C';
}
- static uint32_t L_error_count[ERRORCOUNT_MAXTYPES][ERRORCOUNT_MAXCMDS] = {{0}};
- uint32_t * l_error_count = &L_error_count[i_type][l_cmd_index];
char l_trace_type = 'd';
if (AVSBUS_VDD == i_type)
@@ -237,11 +230,12 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
}
#ifdef AVSDEBUG
- static bool L_traced[ERRORCOUNT_MAXTYPES][ERRORCOUNT_MAXCMDS] = {{0}};
- bool * l_traced = &L_traced[i_type][l_cmd_index];
- if (!*l_traced)
+ static uint32_t L_trace_count[ERRORCOUNT_MAXTYPES][ERRORCOUNT_MAXCMDS] = {{0}};
+ uint32_t * l_trace_count = &L_trace_count[i_type][l_cmd_index];
+ uint32_t DEBUG_TRACE_MAX = 2;
+ if (*l_trace_count < DEBUG_TRACE_MAX)
{
- TRAC_INFO("avsbus_read: Vd%c %c - bus[%d] rail[%d]",
+ TRAC_INFO("avsbus_read_start: Vd%c %c - bus[%d] rail[%d]",
l_trace_type, l_trace_cmd, l_data.bus, l_data.rail);
}
#endif
@@ -249,14 +243,10 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
// Determine register based on the bus number
uint32_t o2scmd_reg = OCB_O2SCMD0B;
uint32_t o2swd_reg = OCB_O2SWD0B;
- uint32_t o2sst_reg = OCB_O2SST0B;
- uint32_t o2srd_reg = OCB_O2SRD0B;
if (1 == l_data.bus)
{
o2scmd_reg = OCB_O2SCMD1B;
o2swd_reg = OCB_O2SWD1B;
- o2sst_reg = OCB_O2SST1B;
- o2srd_reg = OCB_O2SRD1B;
}
// Write O2SCMD[a][n]
@@ -277,16 +267,87 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
// 29:31 CRC
// 01110DDD DRRRR111 11111111 11111CCC
value = 0x7007FFF800000000 | ((uint64_t) i_cmdtype << 55) | ((uint64_t)l_data.rail << 51);
- avs_crc_update(&value);
+ // Calculate/add CRC
+ value |= avs_crc_calculate(value);
out64(o2swd_reg, value);
+ // Read has been started so now just wait for HW to complete
+
// HW: Wait for bus op to complete
// HW: arbitration between two bridges
// HW: o2s_ongoning: 0 -> 1
// HW: execution completes
// HW: o2s_ongoing 1 -> 0
- // Poll waiting for o2s_ongoing to change to 0 or an error bit is set
+#ifdef AVSDEBUG
+ ++*l_trace_count; // DEBUG
+#endif
+
+} // end avsbus_read_start()
+
+
+// Read and return the voltage or current for specified rail
+// (voltage units are mV, current units are in 10mA)
+uint16_t avsbus_read(const avsbus_type_e i_type,
+ const avsbus_cmdtype_e i_cmdtype)
+{
+ if (isSafeStateRequested())
+ {
+ // No need to attempt read if OCC will be reset
+ return 0;
+ }
+
+ uint16_t o_reading = 0;
+ bool l_failure = FALSE;
+
+ uint8_t l_cmd_index = 0;
+ char l_trace_cmd = 'V';
+ if (i_cmdtype == AVSBUS_CURRENT)
+ {
+ l_cmd_index = 1;
+ l_trace_cmd = 'C';
+ }
+
+ // Static error counters for each type (Vdd/Vdn) and command (Voltage/Current)
+ static uint32_t L_error_count[ERRORCOUNT_MAXTYPES][ERRORCOUNT_MAXCMDS] = {{0}};
+ uint32_t * l_error_count = &L_error_count[i_type][l_cmd_index];
+
+ char l_trace_type = 'd';
+ avsbusData_t l_data = G_sysConfigData.avsbus_vdd;
+ if (AVSBUS_VDN == i_type)
+ {
+ l_trace_type = 'n';
+ l_data = G_sysConfigData.avsbus_vdn;
+ }
+
+#ifdef AVSDEBUG
+ static uint32_t L_trace_count[ERRORCOUNT_MAXTYPES][ERRORCOUNT_MAXCMDS] = {{0}};
+ uint32_t * l_trace_count = &L_trace_count[i_type][l_cmd_index];
+ uint32_t DEBUG_TRACE_MAX = 2;
+ if (*l_trace_count < DEBUG_TRACE_MAX)
+ {
+ TRAC_INFO("avsbus_read: Vd%c %c - bus[%d] rail[%d]",
+ l_trace_type, l_trace_cmd, l_data.bus, l_data.rail);
+ }
+#endif
+
+ // Determine register based on the bus number
+ uint32_t o2sst_reg = OCB_O2SST0B;
+ uint32_t o2srd_reg = OCB_O2SRD0B;
+ if (1 == l_data.bus)
+ {
+ o2sst_reg = OCB_O2SST1B;
+ o2srd_reg = OCB_O2SRD1B;
+ }
+
+ // HW: Wait for bus op to complete
+ // HW: arbitration between two bridges
+ // HW: o2s_ongoning: 0 -> 1
+ // HW: execution completes
+ // HW: o2s_ongoing 1 -> 0
+
+ // Since read was started in previous tick, it should have already completed
+ // (no need to poll/wait on o2s_ongoing)
enum occReasonCode rc = OCC_SUCCESS_REASON_CODE;
uint64_t l_status = in64(o2sst_reg);
// OCC O2S Status Register
@@ -297,46 +358,16 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
// 7 FSM error
// 8:63 reserved
// GrrrrBrF rrrrrrrr rrrrrrrr rrrrrrrr
- uint32_t l_max_attempts = O2S_ONGOING_CHECK_ATTEMPTS;
-
- while ((1 == (l_status >> 63)) &&
- (0 == (l_status & 0x0500000000000000)))
- {
- if (l_max_attempts-- == 0)
- {
- l_failure = TRUE;
- (*l_error_count)++;
- if ((*l_error_count == 1) || (*l_error_count == MAX_READ_ATTEMPTS))
- {
- TRAC_ERR("avsbus_read: Vd%c %c timeout waiting for o2s_ongoing change O2SST[0x%08X] = [0x%08X] / Command[0x%08X]",
- l_trace_type, l_trace_cmd, o2sst_reg, WORD_HIGH(l_status), WORD_HIGH(value));
- /*
- * @errortype
- * @moduleid PSS_MID_AVSBUS_READ
- * @reasoncode AVSBUS_TIMEOUT
- * @userdata1 AVS Bus type/bus/rail
- * @userdata2 status
- * @devdesc task_apss_complete_pwr_meas schedule failed
- * @devdesc Timeout when reading AVS Bus
- */
- rc = AVSBUS_TIMEOUT;
- }
- break;
- }
- // TODO: RTC 163992
- //ssx_sleep(SSX_NANOSECONDS(O2S_ONGOING_CHECK_DELAY_NS));
- l_status = in64(o2sst_reg);
- }
if (0 != (l_status & 0x0500000000000000))
{
+ // error bit was set
l_failure = TRUE;
(*l_error_count)++;
if ((*l_error_count == 1) || (*l_error_count == MAX_READ_ATTEMPTS))
{
- // error bit was set
- TRAC_ERR("avsbus_read: Error found in Vd%c %c O2SST[0x%08X] = [0x%08X] / Command[0x%08X]",
- l_trace_type, l_trace_cmd, o2sst_reg, WORD_HIGH(l_status), WORD_HIGH(value));
+ TRAC_ERR("avsbus_read: Error found in Vd%c %c O2SST[0x%08X] = [0x%08X]",
+ l_trace_type, l_trace_cmd, o2sst_reg, WORD_HIGH(l_status));
/*
* @errortype
* @moduleid PSS_MID_AVSBUS_READ
@@ -348,13 +379,31 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
rc = AVSBUS_ERROR;
}
}
+ else if (1 == (l_status >> 63)) // o2s_ongoing
+ {
+ // o2s_ongoing bit was still set (operation did not complete)
+ l_failure = TRUE;
+ (*l_error_count)++;
+ if ((*l_error_count == 1) || (*l_error_count == MAX_READ_ATTEMPTS))
+ {
+ TRAC_ERR("avsbus_read: Vd%c %c timeout waiting for o2s_ongoing change O2SST[0x%08X] = [0x%08X]",
+ l_trace_type, l_trace_cmd, o2sst_reg, WORD_HIGH(l_status));
+ /*
+ * @errortype
+ * @moduleid PSS_MID_AVSBUS_READ
+ * @reasoncode AVSBUS_TIMEOUT
+ * @userdata1 AVS Bus type/bus/rail
+ * @userdata2 status
+ * @devdesc Timeout when reading AVS Bus
+ */
+ rc = AVSBUS_TIMEOUT;
+ }
+ }
if (FALSE == l_failure)
{
// Read the response data
- value = in64(o2srd_reg);
-
- // Check for valid command operation and extract read data
+ uint64_t value = in64(o2srd_reg);
// AVS Bus response (read voltage or current):
// 0:1 SlaveAck (0b00 from slave indicates good CRC and action was taken)
// 2 0
@@ -363,11 +412,34 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
// 24:28 Reserved (must be all 1s)
// 29:31 CRC
// AA0SSSSS VVVVVVVV VVVVVVVV 11111CCC
- if (0 == (value & 0xC000000000000000))
+
+ // Validate CRC
+ const uint64_t crc = avs_crc_calculate(value);
+ if (crc != (value & AVS_CRC_MASK))
+ {
+ l_failure = TRUE;
+ (*l_error_count)++;
+ if ((*l_error_count == 1) || (*l_error_count == MAX_READ_ATTEMPTS))
+ {
+ TRAC_ERR("avsbus_read: CRC mismatch in Vd%c %c rsp O2SRD[0x%08X] = [0x%08X] (calculated CRC 0x%08X)",
+ l_trace_type, l_trace_cmd, o2srd_reg, WORD_HIGH(value), WORD_HIGH(crc));
+ /*
+ * @errortype
+ * @moduleid PSS_MID_AVSBUS_READ
+ * @reasoncode AVSBUS_CRC_ERROR
+ * @userdata1 AVS Bus type/bus/rail
+ * @userdata2 status
+ * @devdesc CRC error reading AVS Bus
+ */
+ rc = AVSBUS_CRC_ERROR;
+ }
+ }
+ // Check for valid command operation and extract read data
+ else if (0 == (value & 0xC000000000000000))
{
o_reading = (value >> 40) & 0x0000FFFF;
#ifdef AVSDEBUG
- if (!*l_traced)
+ if (*l_trace_count < DEBUG_TRACE_MAX)
{
if (i_cmdtype == AVSBUS_VOLTAGE)
{
@@ -403,31 +475,39 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
if (l_failure)
{
- if (*l_error_count == MAX_READ_ATTEMPTS)
+ enum occExtReasonCode exrc = ERC_AVSBUS_VDD_VOLTAGE_FAILURE;
+ if (AVSBUS_VDD == i_type)
{
- TRAC_ERR("avsbus_read: Reached %d consecutive Vd%c %c errors, requesting reset",
- *l_error_count, l_trace_type, l_trace_cmd);
- G_avsbus_vdd_monitoring = FALSE;
- G_avsbus_vdn_monitoring = FALSE;
- enum occExtReasonCode exrc = ERC_AVSBUS_VDD_VOLTAGE_FAILURE;
- if (AVSBUS_VDD == i_type)
+ if (i_cmdtype == AVSBUS_CURRENT)
{
- if (i_cmdtype == AVSBUS_CURRENT)
- {
- exrc = ERC_AVSBUS_VDD_CURRENT_FAILURE;
- }
+ exrc = ERC_AVSBUS_VDD_CURRENT_FAILURE;
+ INCREMENT_ERR_HISTORY(ERR_AVSBUS_VDD_CURRENT);
}
else
{
- if (i_cmdtype == AVSBUS_CURRENT)
- {
- exrc = ERC_AVSBUS_VDN_CURRENT_FAILURE;
- }
- else
- {
- exrc = ERC_AVSBUS_VDN_VOLTAGE_FAILURE;
- }
+ INCREMENT_ERR_HISTORY(ERR_AVSBUS_VDD_VOLTAGE);
+ }
+ }
+ else
+ {
+ if (i_cmdtype == AVSBUS_CURRENT)
+ {
+ exrc = ERC_AVSBUS_VDN_CURRENT_FAILURE;
+ INCREMENT_ERR_HISTORY(ERR_AVSBUS_VDN_CURRENT);
}
+ else
+ {
+ exrc = ERC_AVSBUS_VDN_VOLTAGE_FAILURE;
+ INCREMENT_ERR_HISTORY(ERR_AVSBUS_VDN_VOLTAGE);
+ }
+ }
+
+ if (*l_error_count == MAX_READ_ATTEMPTS)
+ {
+ TRAC_ERR("avsbus_read: Reached %d consecutive Vd%c %c errors, requesting reset",
+ *l_error_count, l_trace_type, l_trace_cmd);
+ G_avsbus_vdd_monitoring = FALSE;
+ G_avsbus_vdn_monitoring = FALSE;
errlHndl_t l_err = createErrl(PSS_MID_AVSBUS_READ,
rc,
exrc,
@@ -444,8 +524,9 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
REQUEST_RESET(l_err);
}
}
+
#ifdef AVSDEBUG
- *l_traced = TRUE; // DEBUG
+ ++*l_trace_count; // DEBUG
#endif
return o_reading;
@@ -453,5 +534,22 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
} // end avsbus_read()
+// Start the AVS Bus read for both buses (if enabled)
+void initiate_avsbus_reads(avsbus_cmdtype_e i_cmdType)
+{
+ if (G_avsbus_vdd_monitoring)
+ {
+ // AVS Bus Vdd config data was received:
+ // Initiate AVS Bus read for Vdd (voltage or current)
+ avsbus_read_start(AVSBUS_VDD, i_cmdType);
+ }
+
+ if (G_avsbus_vdn_monitoring)
+ {
+ // AVS Bus Vdn config data was received:
+ // Initiate AVS Bus read for Vdn (voltage or current)
+ avsbus_read_start(AVSBUS_VDN, i_cmdType);
+ }
+} // end initiate_avsbus_reads()
diff --git a/src/occ_405/pss/avsbus.h b/src/occ_405/pss/avsbus.h
index f2dfb2e..80b91cf 100755
--- a/src/occ_405/pss/avsbus.h
+++ b/src/occ_405/pss/avsbus.h
@@ -48,9 +48,16 @@ typedef enum
// Setup the AVS Bus for reading
void avsbus_init();
-// Read and return the voltage or current for specified rail
-// (voltage units are mV, current units are in 10mA)
+// Initiate AVS Bus read for specified cmdtype (Voltage / Current)
+// (results can then be read on the next tick)
+void initiate_avsbus_reads(avsbus_cmdtype_e i_cmdType);
+
+// Process AVS Bus read results (or errors) for specified bus/cmdtype.
+// Returns the data requested (voltage units are mV, current units are in 10mA)
+// Predictive error will be logged after MAX_READ_ATTEMPTS failures on the specific
+// bus/cmdtype and an OCC reset will be requested
uint16_t avsbus_read(const avsbus_type_e i_type,
const avsbus_cmdtype_e i_cmdtype);
+
#endif //_AVSBUS_H
diff --git a/src/occ_405/sensor/sensor_enum.h b/src/occ_405/sensor/sensor_enum.h
index 0c793d0..37c411c 100755
--- a/src/occ_405/sensor/sensor_enum.h
+++ b/src/occ_405/sensor/sensor_enum.h
@@ -69,6 +69,9 @@ enum e_gsid
PROBE250US6, // Internal Sensor for debug via AMESTER
PROBE250US7, // Internal Sensor for debug via AMESTER
+ VOLTVDDSENSE, // chip voltage (remote sense adjusted for loadline)
+ VOLTVDNSENSE, // chip voltage (remote sense adjusted for loadline)
+
GPEtickdur0, // Duration on the GPE0 Engine
GPEtickdur1, // Duration on the GPE1 Engine
RTLtickdur, // Duration on the RTL tick interrupt
diff --git a/src/occ_405/sensor/sensor_info.c b/src/occ_405/sensor/sensor_info.c
index cc9e253..dc7e77f 100755
--- a/src/occ_405/sensor/sensor_info.c
+++ b/src/occ_405/sensor/sensor_info.c
@@ -223,6 +223,8 @@ const sensor_info_t G_sensor_info[] =
SENSOR_INFO_T_ENTRY( PROBE250US5, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
SENSOR_INFO_T_ENTRY( PROBE250US6, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
SENSOR_INFO_T_ENTRY( PROBE250US7, "n/a\0", AMEC_SENSOR_TYPE_GENERIC, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( VOLTVDDSENSE, "mV\0", AMEC_SENSOR_TYPE_VOLTAGE, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, -1) ),
+ SENSOR_INFO_T_ENTRY( VOLTVDNSENSE, "mV\0", AMEC_SENSOR_TYPE_VOLTAGE, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, -1) ),
SENSOR_INFO_T_ENTRY( GPEtickdur0, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
SENSOR_INFO_T_ENTRY( GPEtickdur1, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
SENSOR_INFO_T_ENTRY( RTLtickdur, "us\0", AMEC_SENSOR_TYPE_TIME, AMEC_SENSOR_LOC_OCC, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ),
diff --git a/src/occ_405/sensor/sensor_table.c b/src/occ_405/sensor/sensor_table.c
index 33c34d7..faa7d68 100755
--- a/src/occ_405/sensor/sensor_table.c
+++ b/src/occ_405/sensor/sensor_table.c
@@ -287,7 +287,8 @@ const sensor_ptr_t G_amec_sensor_list[] =
SENSOR_PTR( PROBE250US5, &g_amec_sys.fw.probe250us[5]),
SENSOR_PTR( PROBE250US6, &g_amec_sys.fw.probe250us[6]),
SENSOR_PTR( PROBE250US7, &g_amec_sys.fw.probe250us[7]),
-
+ SENSOR_PTR( VOLTVDDSENSE, &g_amec_sys.fw.voltvddsense),
+ SENSOR_PTR( VOLTVDNSENSE, &g_amec_sys.fw.voltvdnsense),
SENSOR_PTR( GPEtickdur0, &g_amec_sys.fw.gpetickdur[0]),
SENSOR_PTR( GPEtickdur1, &g_amec_sys.fw.gpetickdur[1]),
SENSOR_PTR( RTLtickdur, &g_amec_sys.fw.prcdupdatedur),
@@ -467,6 +468,8 @@ const minisensor_ptr_t G_amec_mini_sensor_list[] INIT_SECTION =
MINI_SENSOR_PTR( PROBE250US5, NULL),
MINI_SENSOR_PTR( PROBE250US6, NULL),
MINI_SENSOR_PTR( PROBE250US7, NULL),
+ MINI_SENSOR_PTR( VOLTVDDSENSE, NULL),
+ MINI_SENSOR_PTR( VOLTVDNSENSE, NULL),
MINI_SENSOR_PTR( GPEtickdur0, NULL),
MINI_SENSOR_PTR( GPEtickdur1, NULL),
MINI_SENSOR_PTR( RTLtickdur, NULL),
OpenPOWER on IntegriCloud