summaryrefslogtreecommitdiffstats
path: root/src/occ_405/pss
diff options
context:
space:
mode:
authorChris Cain <cjcain@us.ibm.com>2017-09-08 08:19:07 -0500
committerChristopher J. Cain <cjcain@us.ibm.com>2017-09-15 13:20:32 -0400
commitf92b6d26c9d2f3d1fe0e25de3768ce972d7051d1 (patch)
tree20dfd8574b602479ceeb69e4aef78cbd139ddbd0 /src/occ_405/pss
parent852ad09ac2d25bf0afe543b1bf81c2cfea0429e2 (diff)
downloadtalos-occ-f92b6d26c9d2f3d1fe0e25de3768ce972d7051d1.tar.gz
talos-occ-f92b6d26c9d2f3d1fe0e25de3768ce972d7051d1.zip
Add deglitching for AVS bus status bits
Change-Id: I798515cfd81662dcf12e44f6f200ff3c53dbddbb RTC: 178625 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/45894 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
Diffstat (limited to 'src/occ_405/pss')
-rw-r--r--src/occ_405/pss/avsbus.c235
-rwxr-xr-xsrc/occ_405/pss/avsbus.h3
2 files changed, 212 insertions, 26 deletions
diff --git a/src/occ_405/pss/avsbus.c b/src/occ_405/pss/avsbus.c
index 815979f..d6252c5 100644
--- a/src/occ_405/pss/avsbus.c
+++ b/src/occ_405/pss/avsbus.c
@@ -39,6 +39,7 @@
//#define AVSDEBUG
#ifdef AVSDEBUG
+#define DEBUG_TRACE_MAX 1
static bool G_trace_scoms = TRUE;
#define AVS_DBG(frmt,args...) TRAC_INFO(frmt,##args)
#define DEBUG_IN32(reg, result, name) if (G_trace_scoms) { TRAC_INFO(" in32(%08X) returned 0x%08X "name, reg, result); }
@@ -73,8 +74,79 @@ const uint8_t MAX_READ_ATTEMPTS = 8;
const uint16_t AVSBUS_STATUS_READ_ERROR = 0xFFFF;
extern data_cnfg_t * G_data_cnfg;
+uint32_t avs_crc_calculate(const uint32_t i_avs_cmd);
+
// NOTE: OCC must use Bridge B, because Bridge A is reserved for PGPE
+
+// Clear OT/OC bit in status reg for both busses
+uint32_t deglitch_status_errors(const uint8_t i_bus, const uint32_t i_status_mask)
+{
+ // 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;
+ if (i_bus != 0)
+ {
+ o2scmd_reg = OCB_O2SCMD1B;
+ o2swd_reg = OCB_O2SWD1B;
+ o2sst_reg = OCB_O2SST1B;
+ }
+
+ // Write O2SCMD[a][n]
+ // o2s_clear_sticky_bits = 1
+ uint32_t value = 0x40000000;
+ DEBUG_OUT32(o2scmd_reg, value, "OCB_O2SCMDxB");
+ out32(o2scmd_reg, value);
+
+ // To deglitch the status bits, set the status bits you wish to clear with a 1. (in CmdData)
+ // After the write completes, if the status is still active, then the
+ // signal must be solid failure.
+
+ TRAC_INFO("deglitch_status_errors(AVSBUS %d,0x%08X)", i_bus, i_status_mask);
+ // AVS Bus command (write staus):
+ // 0:1 StartCode = 0b01
+ // 2:3 Cmd = 0b00 (write+commit)
+ // 4 CmdGroup = 0b0 (AVSBus)
+ // 5:8 CmdDataType (STATUS = 01110b)
+ // 9:12 Select (All rails / broadcast = 01111b )
+ // 13:28 CmdData (status bits to clear)
+ // 29:31 CRC
+ // 01000DDD DRRRRXXX XXXXXXXX XXXXXCCC
+ // 01000111 01111--- -------- -----CCC
+ uint32_t cmd_data = AVSBUS_STATUS_OVER_CURRENT_MASK | AVSBUS_STATUS_OVER_TEMPERATURE_MASK;
+ value = 0x47780000 | (cmd_data << 3);
+ // Calculate/add CRC
+ value |= avs_crc_calculate(value);
+ DEBUG_OUT32(o2swd_reg, value, "OCB_O2SWDxB");
+ out32(o2swd_reg, value);
+
+ // Wait for operation to complete (clear ongoing)
+ uint32_t l_status = in32(o2sst_reg);
+ DEBUG_IN32(o2sst_reg, l_status, "OCB_O2SSTxB");
+ unsigned int loops = 0;
+ while ((l_status & AVSBUS_STATUS_ONGOING) && (loops < 500))
+ {
+ // o2s_ongoing bit was still set (operation did not complete)
+ l_status = in32(o2sst_reg);
+ ++loops;
+ }
+ DEBUG_IN32(o2sst_reg, l_status, "OCB_O2SSTxB");
+ if (0 != (l_status & AVSBUS_STATUS_ERRORS))
+ {
+ TRAC_ERR("deglitch_status_errors(): error in status register: 0x%08X", l_status);
+ }
+ else if (l_status & AVSBUS_STATUS_ONGOING) // o2s_ongoing
+ {
+ TRAC_ERR("deglitch_status_errors(): timeout waiting for ongoing bit to clear (%d loops) 0x%08X", loops, l_status);
+ }
+
+ // return the last read status
+ return l_status;
+
+} // end deglitch_status_errors()
+
+
// AVS Bus setup that must be done once (common between read/write operations)
void avsbus_init()
{
@@ -181,6 +253,11 @@ void avsbus_init()
out32(OCB_O2SCTRL21B, value);
}
+ // Clear OC/OT masks in the status reg
+ const uint32_t error_mask = AVSBUS_STATUS_OVER_CURRENT_MASK | AVSBUS_STATUS_OVER_TEMPERATURE_MASK;
+ deglitch_status_errors(0, error_mask);
+ deglitch_status_errors(1, error_mask);
+
} // end avsbus_init()
@@ -263,8 +340,6 @@ void avsbus_read_start(const avsbus_type_e i_type,
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_start: Vd%c %c - bus[%d] rail[%d]",
@@ -356,7 +431,6 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
#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]",
@@ -393,7 +467,7 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
// 8:63 reserved
// GrrrrBrF rrrrrrrr rrrrrrrr rrrrrrrr
- if (0 != (l_status & 0x05000000))
+ if (0 != (l_status & AVSBUS_STATUS_ERRORS))
{
// error bit was set
l_failure = TRUE;
@@ -413,7 +487,7 @@ uint16_t avsbus_read(const avsbus_type_e i_type,
rc = AVSBUS_ERROR;
}
}
- else if (l_status & 0x80000000) // o2s_ongoing
+ else if (l_status & AVSBUS_STATUS_ONGOING) // o2s_ongoing
{
// o2s_ongoing bit was still set (operation did not complete)
l_failure = TRUE;
@@ -601,7 +675,6 @@ void initiate_avsbus_read_status()
#ifdef AVSDEBUG
static uint32_t L_trace_count = 0;
- uint32_t DEBUG_TRACE_MAX = 2;
#endif
unsigned int index;
@@ -711,7 +784,6 @@ uint16_t avsbus_read_status(const avsbus_type_e i_type)
#ifdef AVSDEBUG
static uint32_t L_trace_count = 0;
- uint32_t DEBUG_TRACE_MAX = 2;
if (L_trace_count < DEBUG_TRACE_MAX)
{
TRAC_INFO("avsbus_read_status: Vd%c - bus[%d] rail[%d]",
@@ -748,7 +820,7 @@ uint16_t avsbus_read_status(const avsbus_type_e i_type)
// 8:63 reserved
// GrrrrBrF rrrrrrrr rrrrrrrr rrrrrrrr
- if (0 != (l_status & 0x05000000))
+ if (0 != (l_status & AVSBUS_STATUS_ERRORS))
{
// error bit was set
l_failure = TRUE;
@@ -768,7 +840,7 @@ uint16_t avsbus_read_status(const avsbus_type_e i_type)
rc = AVSBUS_ERROR;
}
}
- else if (l_status & 0x80000000) // o2s_ongoing
+ else if (l_status & AVSBUS_STATUS_ONGOING) // o2s_ongoing
{
// o2s_ongoing bit was still set (operation did not complete)
l_failure = TRUE;
@@ -837,6 +909,7 @@ uint16_t avsbus_read_status(const avsbus_type_e i_type)
// 8-15 reserved
o_reading = (value >> 8) & 0x0000FFFF;
+
#ifdef AVSDEBUG
static uint16_t L_lastReading = 0;
if ((L_trace_count < DEBUG_TRACE_MAX) || (o_reading != L_lastReading))
@@ -917,6 +990,14 @@ uint8_t process_avsbus_status()
uint8_t foundOC = 0;
uint16_t vdd_status = 0;
uint16_t vdn_status = 0;
+ static bool L_vdd_ot_found = FALSE;
+ static bool L_vdd_oc_found = FALSE;
+ static bool L_vdn_ot_found = FALSE;
+ static bool L_vdn_oc_found = FALSE;
+ static bool L_vdd_ot_counted = FALSE;
+ static bool L_vdd_oc_counted = FALSE;
+ static bool L_vdn_ot_counted = FALSE;
+ static bool L_vdn_oc_counted = FALSE;
if (G_vrm_thermal_monitoring)
{
@@ -925,16 +1006,67 @@ uint8_t process_avsbus_status()
vdd_status = avsbus_read_status(AVSBUS_VDD);
if (vdd_status != AVSBUS_STATUS_READ_ERROR)
{
- if (vdd_status & AVSBUS_STATUS_OVER_TEMPERATURE_MASK)
+ if ((vdd_status & (AVSBUS_STATUS_OVER_TEMPERATURE_MASK|AVSBUS_STATUS_OVER_CURRENT_MASK)) == 0)
{
- foundOT = 1;
- INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDD_OVER_TEMPERATURE);
+ // No OT/OC errors found
+ if (L_vdd_ot_found) TRAC_INFO("process_avsbus_status: Vdd OT cleared");
+ L_vdd_ot_found = FALSE;
+ L_vdd_ot_counted = FALSE;
+ if (L_vdd_oc_found) TRAC_INFO("process_avsbus_status: Vdd OC cleared");
+ L_vdd_oc_found = FALSE;
+ L_vdd_oc_counted = FALSE;
}
-
- if (vdd_status & AVSBUS_STATUS_OVER_CURRENT_MASK)
+ else
{
- foundOC = 1;
- INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDD_OVER_CURRENT);
+ // Deglitch error if needed
+ uint32_t deglitch_mask = 0;
+ if ((vdd_status & AVSBUS_STATUS_OVER_TEMPERATURE_MASK) && (!L_vdd_ot_found))
+ {
+ deglitch_mask |= AVSBUS_STATUS_OVER_TEMPERATURE_MASK;
+ L_vdd_ot_found = TRUE;
+ }
+ if ((vdd_status & AVSBUS_STATUS_OVER_CURRENT_MASK) && (!L_vdd_oc_found))
+ {
+ deglitch_mask |= AVSBUS_STATUS_OVER_CURRENT_MASK;
+ L_vdd_oc_found = TRUE;
+ }
+ if (deglitch_mask)
+ {
+ // Deglitch error bit(s)
+ deglitch_status_errors(G_sysConfigData.avsbus_vdd.bus, deglitch_mask);
+
+ // Clear error bit(s) since could be false reading
+ vdd_status &= (~deglitch_mask);
+ }
+
+ // Process error (if already deglitched)
+ if (vdd_status & AVSBUS_STATUS_OVER_TEMPERATURE_MASK)
+ {
+ foundOT = 1;
+ if (!L_vdd_ot_counted)
+ {
+ INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDD_OVER_TEMPERATURE);
+ L_vdd_ot_counted = TRUE;
+ }
+ }
+ else
+ {
+ L_vdd_ot_counted = FALSE;
+ }
+
+ if (vdd_status & AVSBUS_STATUS_OVER_CURRENT_MASK)
+ {
+ foundOC = 1;
+ if (!L_vdd_oc_counted)
+ {
+ INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDD_OVER_CURRENT);
+ L_vdd_oc_counted = TRUE;
+ }
+ }
+ else
+ {
+ L_vdd_oc_counted = FALSE;
+ }
}
}
else
@@ -948,20 +1080,71 @@ uint8_t process_avsbus_status()
vdn_status = avsbus_read_status(AVSBUS_VDN);
if (vdn_status != AVSBUS_STATUS_READ_ERROR)
{
- if (vdn_status & AVSBUS_STATUS_OVER_TEMPERATURE_MASK)
+ if ((vdn_status & (AVSBUS_STATUS_OVER_TEMPERATURE_MASK|AVSBUS_STATUS_OVER_CURRENT_MASK)) == 0)
+ {
+ // No OT/OC errors found
+ if (L_vdn_ot_found) TRAC_INFO("process_avsbus_status: Vdn OT cleared");
+ L_vdn_ot_found = FALSE;
+ L_vdn_ot_counted = FALSE;
+ if (L_vdn_oc_found) TRAC_INFO("process_avsbus_status: Vdn OC cleared");
+ L_vdn_oc_found = FALSE;
+ L_vdn_oc_counted = FALSE;
+ }
+ else
{
- // if no Vdd error, update OT result
- if (foundOT != 0xFF)
+ // Deglitch error if needed
+ uint32_t deglitch_mask = 0;
+ if ((vdn_status & AVSBUS_STATUS_OVER_TEMPERATURE_MASK) && (!L_vdn_ot_found))
{
- foundOT = 1;
+ deglitch_mask |= AVSBUS_STATUS_OVER_TEMPERATURE_MASK;
+ L_vdn_ot_found = TRUE;
}
- INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDN_OVER_TEMPERATURE);
- }
+ if ((vdn_status & AVSBUS_STATUS_OVER_CURRENT_MASK) && (!L_vdn_oc_found))
+ {
+ deglitch_mask |= AVSBUS_STATUS_OVER_CURRENT_MASK;
+ L_vdn_oc_found = TRUE;
+ }
+ if (deglitch_mask)
+ {
+ // Deglitch error bit(s)
+ deglitch_status_errors(G_sysConfigData.avsbus_vdn.bus, deglitch_mask);
- if (vdn_status & AVSBUS_STATUS_OVER_CURRENT_MASK)
- {
- foundOC = 1;
- INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDN_OVER_CURRENT);
+ // Clear error bit(s) since could be false reading
+ vdn_status &= (~deglitch_mask);
+ }
+
+ // Process error (if already deglitched)
+ if (vdn_status & AVSBUS_STATUS_OVER_TEMPERATURE_MASK)
+ {
+ // if no Vdd error, update OT result
+ if (foundOT != 0xFF)
+ {
+ foundOT = 1;
+ }
+ if (!L_vdn_ot_counted)
+ {
+ INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDN_OVER_TEMPERATURE);
+ L_vdn_ot_counted = TRUE;
+ }
+ }
+ else
+ {
+ L_vdn_ot_counted = FALSE;
+ }
+
+ if (vdn_status & AVSBUS_STATUS_OVER_CURRENT_MASK)
+ {
+ foundOC = 1;
+ if (!L_vdn_oc_counted)
+ {
+ INCREMENT_ERR_HISTORY(ERRH_AVSBUS_VDN_OVER_CURRENT);
+ L_vdn_oc_counted = TRUE;
+ }
+ }
+ else
+ {
+ L_vdn_oc_counted = FALSE;
+ }
}
}
else
diff --git a/src/occ_405/pss/avsbus.h b/src/occ_405/pss/avsbus.h
index 49a2af9..2b40aaa 100755
--- a/src/occ_405/pss/avsbus.h
+++ b/src/occ_405/pss/avsbus.h
@@ -36,6 +36,9 @@ extern bool G_avsbus_vdn_monitoring;
#define AVSBUS_STATUS_OVER_TEMPERATURE_MASK 0x1000
#define AVSBUS_STATUS_OVER_POWER_MASK 0x0800
+#define AVSBUS_STATUS_ONGOING 0x80000000 // o2s_ongoing
+#define AVSBUS_STATUS_ERRORS 0x05000000 // write_while_bridge_busy_error | FSM error
+
typedef enum
{
AVSBUS_VDD = 0x00,
OpenPOWER on IntegriCloud