summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/registers/ocb_firmware_registers.h92
-rwxr-xr-xsrc/occ_405/Makefile1
-rwxr-xr-xsrc/occ_405/common.c408
-rw-r--r--src/occ_405/common.h21
-rwxr-xr-xsrc/occ_405/dimm/dimm.c523
-rw-r--r--src/occ_405/dimm/dimm.h6
-rwxr-xr-xsrc/occ_405/errl/errl.c11
-rw-r--r--src/occ_405/img_defs.mk1
-rwxr-xr-xsrc/occ_405/lock/lock.c404
-rw-r--r--src/occ_405/lock/lock.h54
-rwxr-xr-xsrc/occ_405/main.c7
-rw-r--r--src/occ_405/occLinkInputFile2
-rw-r--r--src/occ_405/occ_service_codes.h3
-rwxr-xr-xsrc/occ_405/reset.c85
-rwxr-xr-xsrc/occ_405/rtls/rtls.h2
-rwxr-xr-xsrc/occ_405/rtls/rtls_tables.c37
-rw-r--r--src/occ_405/topfiles.mk2
-rw-r--r--src/occ_gpe1/gpe1_dimm_read.c6
-rw-r--r--src/occ_gpe1/gpe1_dimm_reset.c30
19 files changed, 1081 insertions, 614 deletions
diff --git a/src/include/registers/ocb_firmware_registers.h b/src/include/registers/ocb_firmware_registers.h
index 14c1c63..3e93668 100644
--- a/src/include/registers/ocb_firmware_registers.h
+++ b/src/include/registers/ocb_firmware_registers.h
@@ -1243,13 +1243,19 @@ typedef union ocb_occmisc {
struct {
#ifdef _BIG_ENDIAN
uint32_t core_ext_intr : 1;
- uint32_t spare : 15;
+ uint32_t ext_intr_service_required : 1;
+ uint32_t ext_intr_i2c_change : 1;
+ uint32_t ext_intr_shmem_change : 1;
+ uint32_t spare : 12;
uint32_t i2cm_intr_status : 3;
uint32_t reserved1 : 13;
#else
uint32_t reserved1 : 13;
uint32_t i2cm_intr_status : 3;
- uint32_t spare : 15;
+ uint32_t spare : 11;
+ uint32_t ext_intr_shmem_change : 1;
+ uint32_t ext_intr_i2c_change : 1;
+ uint32_t ext_intr_service_required : 1;
uint32_t core_ext_intr : 1;
#endif // _BIG_ENDIAN
} fields;
@@ -1257,42 +1263,6 @@ typedef union ocb_occmisc {
-typedef union ocb_occmisc_clr {
-
- uint32_t value;
- struct {
-#ifdef _BIG_ENDIAN
- uint32_t core_ext_intr : 1;
- uint32_t spare : 15;
- uint32_t reserved1 : 16;
-#else
- uint32_t reserved1 : 16;
- uint32_t spare : 15;
- uint32_t core_ext_intr : 1;
-#endif // _BIG_ENDIAN
- } fields;
-} ocb_occmisc_clr_t;
-
-
-
-typedef union ocb_occmisc_or {
-
- uint32_t value;
- struct {
-#ifdef _BIG_ENDIAN
- uint32_t core_ext_intr : 1;
- uint32_t spare : 15;
- uint32_t reserved1 : 16;
-#else
- uint32_t reserved1 : 16;
- uint32_t spare : 15;
- uint32_t core_ext_intr : 1;
-#endif // _BIG_ENDIAN
- } fields;
-} ocb_occmisc_or_t;
-
-
-
typedef union ocb_ohtmcr {
uint32_t value;
@@ -1442,43 +1412,29 @@ typedef union ocb_occflg {
uint32_t value;
struct {
#ifdef _BIG_ENDIAN
- uint32_t occ_flags : 32;
+ uint32_t reserved_gpe : 16;
+ uint32_t i2c_engine1_lock_host : 1;
+ uint32_t i2c_engine1_lock_occ : 1;
+ uint32_t i2c_engine2_lock_host : 1;
+ uint32_t i2c_engine2_lock_occ : 1;
+ uint32_t i2c_engine3_lock_host : 1;
+ uint32_t i2c_engine3_lock_occ : 1;
+ uint32_t reserved_occ : 10;
#else
- uint32_t occ_flags : 32;
+ uint32_t reserved_occ : 10;
+ uint32_t i2c_engine3_lock_occ : 1;
+ uint32_t i2c_engine3_lock_host : 1;
+ uint32_t i2c_engine2_lock_occ : 1;
+ uint32_t i2c_engine2_lock_host : 1;
+ uint32_t i2c_engine1_lock_occ : 1;
+ uint32_t i2c_engine1_lock_host : 1;
+ uint32_t reserved_gpe : 16;
#endif // _BIG_ENDIAN
} fields;
} ocb_occflg_t;
-typedef union ocb_occflg_clr {
-
- uint32_t value;
- struct {
-#ifdef _BIG_ENDIAN
- uint32_t occ_flags : 32;
-#else
- uint32_t occ_flags : 32;
-#endif // _BIG_ENDIAN
- } fields;
-} ocb_occflg_clr_t;
-
-
-
-typedef union ocb_occflg_or {
-
- uint32_t value;
- struct {
-#ifdef _BIG_ENDIAN
- uint32_t occ_flags : 32;
-#else
- uint32_t occ_flags : 32;
-#endif // _BIG_ENDIAN
- } fields;
-} ocb_occflg_or_t;
-
-
-
typedef union ocb_occhbr {
uint32_t value;
diff --git a/src/occ_405/Makefile b/src/occ_405/Makefile
index e6add69..1a1cd63 100755
--- a/src/occ_405/Makefile
+++ b/src/occ_405/Makefile
@@ -56,6 +56,7 @@ LIB_DIRS = -L$(OBJDIR) \
-L$(OBJDIR)/dcom \
-L$(OBJDIR)/dimm \
-L$(OBJDIR)/errl \
+ -L$(OBJDIR)/lock \
-L$(OBJDIR)/pss \
-L$(OBJDIR)/rtls \
-L$(OBJDIR)/sensor \
diff --git a/src/occ_405/common.c b/src/occ_405/common.c
index e90515d..f383cfc 100755
--- a/src/occ_405/common.c
+++ b/src/occ_405/common.c
@@ -23,229 +23,207 @@
/* */
/* IBM_PROLOG_END_TAG */
-// Description: Standard Library Calls
+// Description: Common 405 functions
-#include "ssx.h"
-#include "ssx_io.h"
#include <common.h>
-#include <trac_service_codes.h>
-#include <string.h>
+#include <trac.h>
+
+
+uint8_t G_host_notifications_pending = 0;
-// Function Specification
-//
-// Name: memcmp
-//
-// Description: Standard Library Calls
-// Need implemented, since we can't statically link in Open Source libs
-// These implementations aren't optimized, but allow the code to function
-// so we can test out the code port.
-//
-// End Function Specification
-//int memcmp ( const void * ptr1, const void * ptr2, size_t num )
-//{
-// return 0;
-//}
// Function Specification
//
-// Name: gpstCheckByte
+// Name: task_misc_405_checks
//
-// Description: Generate check byte for each entry of the Pstate table.
+// Description: Perform periodic checks on the 405 including:
+// - host notifications
+// - checkstops
//
// End Function Specification
-uint8_t gpstCheckByte(const uint64_t gpstEntry)
+void task_misc_405_checks(task_t *i_self)
+{
+ if (G_host_notifications_pending != 0)
+ {
+ notify_host(G_host_notifications_pending);
+ }
+
+ // Check for checkstops
+/* TEMP -- NO MORE PORE / check_stop field no longer exists */
+#if 0
+ pore_status_t l_gpe0_status;
+
+ ocb_oisr0_t l_oisr0_status;
+ static bool L_checkstop_traced = FALSE;
+ uint8_t l_reason_code = 0;
+
+ do
+ {
+ // This check is disabled once a checkstop or frozen GPE is detected
+ if(L_checkstop_traced)
+ {
+ break;
+ }
+
+ // Looked for a frozen GPE, a sign that the chip has stopped working or
+ // check-stopped. This check also looks for an interrupt status flag that
+ // indicates if the system has check-stopped.
+ l_gpe0_status.value = in64(PORE_GPE0_STATUS);
+ l_oisr0_status.value = in32(OCB_OISR0);
+
+ if (l_gpe0_status.fields.freeze_action
+ ||
+ l_oisr0_status.fields.check_stop)
+ {
+ errlHndl_t l_err = NULL;
+
+ if (l_gpe0_status.fields.freeze_action)
+ {
+ TRAC_IMP("Frozen GPE0 detected by RTL");
+ l_reason_code = OCC_GPE_HALTED;
+ }
+
+ if (l_oisr0_status.fields.check_stop)
+ {
+ TRAC_IMP("System checkstop detected by RTL");
+ l_reason_code = OCC_SYSTEM_HALTED;
+ }
+
+ L_checkstop_traced = TRUE;
+
+ /*
+ * @errortype
+ * @moduleid MAIN_SYSTEM_HALTED_MID
+ * @reasoncode OCC_GPE_HALTED
+ * @userdata1 High order word of PORE_GPE0_STATUS
+ * @userdata2 OCB_OISR0
+ * @devdesc OCC detected frozen GPE0
+ */
+ /*
+ * @errortype
+ * @moduleid MAIN_SYSTEM_HALTED_MID
+ * @reasoncode OCC_SYSTEM_HALTED
+ * @userdata1 High order word of PORE_GPE0_STATUS
+ * @userdata2 OCB_OISR0
+ * @devdesc OCC detected system checkstop
+ */
+ l_err = createErrl(MAIN_SYSTEM_HALTED_MID,
+ l_reason_code,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_gpe0_status.words.high_order,
+ l_oisr0_status.value);
+
+ // The commit code will check for the frozen GPE0 and system
+ // checkstop conditions and take appropriate actions.
+ commitErrl(&l_err);
+ }
+ }
+ while(0);
+#endif // #if 0
+
+} // end task_misc_405_checks()
+
+
+// Trigger interrupt to the host with the specified reason (OCCMISC/core_ext_intr)
+// Returns true if notification was sent, false if interrupt already outstanding
+// If notifcation was not sent, G_host_notifications_pending will be set
+// so that it is retried during next tick.
+bool notify_host(const ext_intr_reason_t i_reason)
{
- int cb[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- cb[0] ^= BIT(gpstEntry, 0);
- cb[0] ^= BIT(gpstEntry, 1);
- cb[0] ^= BIT(gpstEntry, 2);
- cb[0] ^= BIT(gpstEntry, 3);
- cb[0] ^= BIT(gpstEntry, 4);
- cb[0] ^= BIT(gpstEntry, 5);
- cb[0] ^= BIT(gpstEntry, 6);
- cb[0] ^= BIT(gpstEntry, 7);
- cb[0] ^= BIT(gpstEntry, 24);
- cb[0] ^= BIT(gpstEntry, 25);
- cb[0] ^= BIT(gpstEntry, 26);
- cb[0] ^= BIT(gpstEntry, 28);
- cb[0] ^= BIT(gpstEntry, 33);
- cb[0] ^= BIT(gpstEntry, 38);
- cb[0] ^= BIT(gpstEntry, 42);
- cb[0] ^= BIT(gpstEntry, 43);
- cb[0] ^= BIT(gpstEntry, 44);
- cb[0] ^= BIT(gpstEntry, 45);
- cb[0] ^= BIT(gpstEntry, 52);
- cb[0] ^= BIT(gpstEntry, 53);
- cb[0] ^= BIT(gpstEntry, 54);
- cb[0] ^= BIT(gpstEntry, 55);
- cb[1] ^= BIT(gpstEntry, 0);
- cb[1] ^= BIT(gpstEntry, 3);
- cb[1] ^= BIT(gpstEntry, 4);
- cb[1] ^= BIT(gpstEntry, 7);
- cb[1] ^= BIT(gpstEntry, 8);
- cb[1] ^= BIT(gpstEntry, 9);
- cb[1] ^= BIT(gpstEntry, 10);
- cb[1] ^= BIT(gpstEntry, 11);
- cb[1] ^= BIT(gpstEntry, 12);
- cb[1] ^= BIT(gpstEntry, 13);
- cb[1] ^= BIT(gpstEntry, 14);
- cb[1] ^= BIT(gpstEntry, 15);
- cb[1] ^= BIT(gpstEntry, 32);
- cb[1] ^= BIT(gpstEntry, 33);
- cb[1] ^= BIT(gpstEntry, 34);
- cb[1] ^= BIT(gpstEntry, 36);
- cb[1] ^= BIT(gpstEntry, 41);
- cb[1] ^= BIT(gpstEntry, 46);
- cb[1] ^= BIT(gpstEntry, 50);
- cb[1] ^= BIT(gpstEntry, 51);
- cb[1] ^= BIT(gpstEntry, 52);
- cb[1] ^= BIT(gpstEntry, 53);
- cb[2] ^= BIT(gpstEntry, 4);
- cb[2] ^= BIT(gpstEntry, 5);
- cb[2] ^= BIT(gpstEntry, 6);
- cb[2] ^= BIT(gpstEntry, 7);
- cb[2] ^= BIT(gpstEntry, 8);
- cb[2] ^= BIT(gpstEntry, 11);
- cb[2] ^= BIT(gpstEntry, 12);
- cb[2] ^= BIT(gpstEntry, 15);
- cb[2] ^= BIT(gpstEntry, 16);
- cb[2] ^= BIT(gpstEntry, 17);
- cb[2] ^= BIT(gpstEntry, 18);
- cb[2] ^= BIT(gpstEntry, 19);
- cb[2] ^= BIT(gpstEntry, 20);
- cb[2] ^= BIT(gpstEntry, 21);
- cb[2] ^= BIT(gpstEntry, 22);
- cb[2] ^= BIT(gpstEntry, 23);
- cb[2] ^= BIT(gpstEntry, 40);
- cb[2] ^= BIT(gpstEntry, 41);
- cb[2] ^= BIT(gpstEntry, 42);
- cb[2] ^= BIT(gpstEntry, 44);
- cb[2] ^= BIT(gpstEntry, 49);
- cb[2] ^= BIT(gpstEntry, 54);
- cb[3] ^= BIT(gpstEntry, 2);
- cb[3] ^= BIT(gpstEntry, 3);
- cb[3] ^= BIT(gpstEntry, 4);
- cb[3] ^= BIT(gpstEntry, 5);
- cb[3] ^= BIT(gpstEntry, 12);
- cb[3] ^= BIT(gpstEntry, 13);
- cb[3] ^= BIT(gpstEntry, 14);
- cb[3] ^= BIT(gpstEntry, 15);
- cb[3] ^= BIT(gpstEntry, 16);
- cb[3] ^= BIT(gpstEntry, 19);
- cb[3] ^= BIT(gpstEntry, 20);
- cb[3] ^= BIT(gpstEntry, 23);
- cb[3] ^= BIT(gpstEntry, 24);
- cb[3] ^= BIT(gpstEntry, 25);
- cb[3] ^= BIT(gpstEntry, 26);
- cb[3] ^= BIT(gpstEntry, 27);
- cb[3] ^= BIT(gpstEntry, 28);
- cb[3] ^= BIT(gpstEntry, 29);
- cb[3] ^= BIT(gpstEntry, 30);
- cb[3] ^= BIT(gpstEntry, 31);
- cb[3] ^= BIT(gpstEntry, 48);
- cb[3] ^= BIT(gpstEntry, 49);
- cb[3] ^= BIT(gpstEntry, 50);
- cb[3] ^= BIT(gpstEntry, 52);
- cb[4] ^= BIT(gpstEntry, 1);
- cb[4] ^= BIT(gpstEntry, 6);
- cb[4] ^= BIT(gpstEntry, 10);
- cb[4] ^= BIT(gpstEntry, 11);
- cb[4] ^= BIT(gpstEntry, 12);
- cb[4] ^= BIT(gpstEntry, 13);
- cb[4] ^= BIT(gpstEntry, 20);
- cb[4] ^= BIT(gpstEntry, 21);
- cb[4] ^= BIT(gpstEntry, 22);
- cb[4] ^= BIT(gpstEntry, 23);
- cb[4] ^= BIT(gpstEntry, 24);
- cb[4] ^= BIT(gpstEntry, 27);
- cb[4] ^= BIT(gpstEntry, 28);
- cb[4] ^= BIT(gpstEntry, 31);
- cb[4] ^= BIT(gpstEntry, 32);
- cb[4] ^= BIT(gpstEntry, 33);
- cb[4] ^= BIT(gpstEntry, 34);
- cb[4] ^= BIT(gpstEntry, 35);
- cb[4] ^= BIT(gpstEntry, 36);
- cb[4] ^= BIT(gpstEntry, 37);
- cb[4] ^= BIT(gpstEntry, 38);
- cb[4] ^= BIT(gpstEntry, 39);
- cb[5] ^= BIT(gpstEntry, 0);
- cb[5] ^= BIT(gpstEntry, 1);
- cb[5] ^= BIT(gpstEntry, 2);
- cb[5] ^= BIT(gpstEntry, 4);
- cb[5] ^= BIT(gpstEntry, 9);
- cb[5] ^= BIT(gpstEntry, 14);
- cb[5] ^= BIT(gpstEntry, 18);
- cb[5] ^= BIT(gpstEntry, 19);
- cb[5] ^= BIT(gpstEntry, 20);
- cb[5] ^= BIT(gpstEntry, 21);
- cb[5] ^= BIT(gpstEntry, 28);
- cb[5] ^= BIT(gpstEntry, 29);
- cb[5] ^= BIT(gpstEntry, 30);
- cb[5] ^= BIT(gpstEntry, 31);
- cb[5] ^= BIT(gpstEntry, 32);
- cb[5] ^= BIT(gpstEntry, 35);
- cb[5] ^= BIT(gpstEntry, 36);
- cb[5] ^= BIT(gpstEntry, 39);
- cb[5] ^= BIT(gpstEntry, 40);
- cb[5] ^= BIT(gpstEntry, 41);
- cb[5] ^= BIT(gpstEntry, 42);
- cb[5] ^= BIT(gpstEntry, 43);
- cb[5] ^= BIT(gpstEntry, 44);
- cb[5] ^= BIT(gpstEntry, 45);
- cb[5] ^= BIT(gpstEntry, 46);
- cb[5] ^= BIT(gpstEntry, 47);
- cb[6] ^= BIT(gpstEntry, 8);
- cb[6] ^= BIT(gpstEntry, 9);
- cb[6] ^= BIT(gpstEntry, 10);
- cb[6] ^= BIT(gpstEntry, 12);
- cb[6] ^= BIT(gpstEntry, 17);
- cb[6] ^= BIT(gpstEntry, 22);
- cb[6] ^= BIT(gpstEntry, 26);
- cb[6] ^= BIT(gpstEntry, 27);
- cb[6] ^= BIT(gpstEntry, 28);
- cb[6] ^= BIT(gpstEntry, 29);
- cb[6] ^= BIT(gpstEntry, 36);
- cb[6] ^= BIT(gpstEntry, 37);
- cb[6] ^= BIT(gpstEntry, 38);
- cb[6] ^= BIT(gpstEntry, 39);
- cb[6] ^= BIT(gpstEntry, 40);
- cb[6] ^= BIT(gpstEntry, 43);
- cb[6] ^= BIT(gpstEntry, 44);
- cb[6] ^= BIT(gpstEntry, 47);
- cb[6] ^= BIT(gpstEntry, 48);
- cb[6] ^= BIT(gpstEntry, 49);
- cb[6] ^= BIT(gpstEntry, 50);
- cb[6] ^= BIT(gpstEntry, 51);
- cb[6] ^= BIT(gpstEntry, 52);
- cb[6] ^= BIT(gpstEntry, 53);
- cb[6] ^= BIT(gpstEntry, 54);
- cb[6] ^= BIT(gpstEntry, 55);
- cb[7] ^= BIT(gpstEntry, 16);
- cb[7] ^= BIT(gpstEntry, 17);
- cb[7] ^= BIT(gpstEntry, 18);
- cb[7] ^= BIT(gpstEntry, 20);
- cb[7] ^= BIT(gpstEntry, 25);
- cb[7] ^= BIT(gpstEntry, 30);
- cb[7] ^= BIT(gpstEntry, 34);
- cb[7] ^= BIT(gpstEntry, 35);
- cb[7] ^= BIT(gpstEntry, 36);
- cb[7] ^= BIT(gpstEntry, 37);
- cb[7] ^= BIT(gpstEntry, 44);
- cb[7] ^= BIT(gpstEntry, 45);
- cb[7] ^= BIT(gpstEntry, 46);
- cb[7] ^= BIT(gpstEntry, 47);
- cb[7] ^= BIT(gpstEntry, 48);
- cb[7] ^= BIT(gpstEntry, 51);
- cb[7] ^= BIT(gpstEntry, 52);
- cb[7] ^= BIT(gpstEntry, 55);
- return
- (cb[0] << 7) |
- (cb[1] << 6) |
- (cb[2] << 5) |
- (cb[3] << 4) |
- (cb[4] << 3) |
- (cb[5] << 2) |
- (cb[6] << 1) |
- (cb[7] << 0);
+ bool notify_success = false;
+ //TRAC_INFO("notify_host(0x%02X) called (G_host_notifications_pending=0x%02X)", i_reason, G_host_notifications_pending);
+
+ // Use input reason unless there are outstanding notifications pending
+ uint8_t notifyReason = i_reason;
+ if (G_host_notifications_pending)
+ {
+ // Add reason to pending notifications
+ notifyReason = G_host_notifications_pending | i_reason;
+ // Determine next outstanding notifcation (highest priority first)
+ if (notifyReason & INTR_REASON_OPAL_SHARED_MEM_CHANGE)
+ {
+ notifyReason = INTR_REASON_OPAL_SHARED_MEM_CHANGE;
+ }
+ else if (notifyReason & INTR_REASON_HTMGT_SERVICE_REQUIRED)
+ {
+ notifyReason = INTR_REASON_HTMGT_SERVICE_REQUIRED;
+ }
+ else if (notifyReason & INTR_REASON_I2C_OWNERSHIP_CHANGE)
+ {
+ notifyReason = INTR_REASON_I2C_OWNERSHIP_CHANGE;
+ }
+ else
+ {
+ INTR_TRAC_ERR("notify_host: G_host_notification_pending has unrecognized value: 0x%02X",
+ notifyReason);
+ notifyReason = i_reason;
+ }
+ }
+
+ // Build new value for register
+ ocb_occmisc_t new_occmisc = {0};
+ new_occmisc.fields.core_ext_intr = 1;
+ switch(notifyReason)
+ {
+ case INTR_REASON_HTMGT_SERVICE_REQUIRED:
+ new_occmisc.fields.ext_intr_service_required = 1;
+ break;
+ case INTR_REASON_I2C_OWNERSHIP_CHANGE:
+ new_occmisc.fields.ext_intr_i2c_change = 1;
+ break;
+ case INTR_REASON_OPAL_SHARED_MEM_CHANGE:
+ new_occmisc.fields.ext_intr_shmem_change = 1;
+ break;
+ default:
+ INTR_TRAC_ERR("notify_host: Invalid reason specified: 0x%02X", notifyReason);
+ new_occmisc.value = 0;
+ break;
+ }
+
+ if (new_occmisc.value != 0)
+ {
+ // Check if we can send interrupt to host (no other interrupts outstanding)
+ ocb_occmisc_t current_occmisc;
+ current_occmisc.value = in32(OCB_OCCMISC);
+ if (current_occmisc.fields.core_ext_intr == 0)
+ {
+#ifdef SIMICS_FLAG_ISSUE
+ out32(OCB_OCCMISC, new_occmisc.value); // _CLR and _OR not working
+#else
+ if (current_occmisc.fields.ext_intr_service_required ||
+ current_occmisc.fields.ext_intr_i2c_change ||
+ current_occmisc.fields.ext_intr_shmem_change)
+ {
+ // clear external interrupt reason
+ current_occmisc.value = 0;
+ current_occmisc.fields.ext_intr_service_required = 1;
+ current_occmisc.fields.ext_intr_i2c_change = 1;
+ current_occmisc.fields.ext_intr_shmem_change = 1;
+ out32(OCB_OCCMISC_CLR, current_occmisc.value);
+ }
+
+ out32(OCB_OCCMISC_OR, new_occmisc.value);
+#endif
+ notify_success = true;
+ TRAC_INFO("notify_host: notification of reason 0x%02X has been sent", notifyReason);
+ G_host_notifications_pending &= ~notifyReason;
+ }
+ else
+ {
+ // Host already has an interrupt outstanding, resend notification later
+ if ((G_host_notifications_pending & i_reason) == 0)
+ {
+ TRAC_INFO("notify_host: OCCMISC/core_ext_intr not clear yet (register=0x%08X, reason=0x%02X)",
+ current_occmisc.value, i_reason);
+ G_host_notifications_pending |= i_reason;
+ }
+ }
+ }
+
+ return notify_success;
}
+
+
diff --git a/src/occ_405/common.h b/src/occ_405/common.h
index 0f6810d..6501783 100644
--- a/src/occ_405/common.h
+++ b/src/occ_405/common.h
@@ -25,9 +25,26 @@
#ifndef _common_h
#define _common_h
+#include <rtls.h>
-#define BIT(x, n) (((x) >> (63 - (n))) & 1)
-uint8_t gpstCheckByte(const uint64_t gpstEntry);
+// Reasons why the OCCMISC external interrupt was triggered
+typedef enum
+{
+ // defined as individual bits (since multiple interrupts could be queued)
+ INTR_REASON_HTMGT_SERVICE_REQUIRED = 0x04,
+ INTR_REASON_I2C_OWNERSHIP_CHANGE = 0x02,
+ INTR_REASON_OPAL_SHARED_MEM_CHANGE = 0x01
+} ext_intr_reason_t;
+
+
+// Miscellaneous checks to be done by 405
+// - check for pending host notifications
+// - check for checkstop
+void task_misc_405_checks(task_t *i_self);
+
+// Trigger interrupt to the host with the specified reason (OCCMISC/core_ext_intr)
+// Returns true if notification was sent, false if interrupt already outstanding
+bool notify_host(const ext_intr_reason_t i_reason);
#endif // _common_h
diff --git a/src/occ_405/dimm/dimm.c b/src/occ_405/dimm/dimm.c
index 3008979..fd308a9 100755
--- a/src/occ_405/dimm/dimm.c
+++ b/src/occ_405/dimm/dimm.c
@@ -40,7 +40,8 @@
#include <occ_sys_config.h>
#include "sensor.h"
#include "amec_sys.h"
-
+#include "lock.h"
+#include "common.h"
extern bool G_mem_monitoring_allowed;
extern task_t G_task_table[TASK_END];
@@ -59,8 +60,6 @@ typedef struct {
} 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
@@ -71,6 +70,7 @@ GpeRequest G_dimm_sm_request;
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)
@@ -250,13 +250,11 @@ 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,
+ INTR_TRAC_ERR("mark_dimm_failed: DIMM%04X failed in state/rc/count=0x%06X "
+ "(ffdc 0x%08X%08X, completion_state 0x%02X)",
+ DIMM_AND_PORT, (G_dimm_sm_args.state << 16) | (G_dimm_sm_args.error.rc << 8) | G_dimm[port][dimm].errorCount,
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)
@@ -411,17 +409,18 @@ 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 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))
{
- // 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))
+ failed = true;
+ // Only mark DIMM as failed if not during an I2C reset
+ if (false == G_dimm_i2c_reset_required)
{
mark_dimm_failed();
- failed = true;
}
}
}
@@ -473,8 +472,7 @@ uint8_t dimm_reset_sm()
{
// 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)");
+ DIMM_DBG("dimm_reset_sm: I2C reset completed (1 port)");
}
}
break;
@@ -496,8 +494,7 @@ uint8_t dimm_reset_sm()
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");
+ DIMM_DBG("dimm_reset_sm: I2C reset completed");
}
break;
@@ -512,6 +509,92 @@ uint8_t dimm_reset_sm()
} // end dimm_reset_sm()
+
+#ifdef DEBUG_LOCK_TESTING
+// TODO: remove testing code once SIMICS_FLAG_ISSUE removed
+// Simulate I2C locking behavior from the host
+void host_i2c_lock_request();
+void host_i2c_lock_release();
+#define DURATION_EXTINT 2 // number of ticks before clearing external interrupt
+#define DURATION_LOCK 6 // 80 // minimum ticks to keep lock
+#define DURATION_LOCK_DELTA 5 // additional ticks to hold lock (for timing variation)
+#define DURATION_UNLOCK 20 // 15 // number of ticks before host releases lock
+void SIMULATE_HOST()
+{
+ static int lockDuration = DURATION_LOCK; // Unlock when this gets to 0
+ static int unlockDuration = DURATION_UNLOCK; // Request lock after this gets to 0
+ static int extIntDuration = DURATION_EXTINT; // Release external interrupt when this gets to 0
+ static int durationDelta = DURATION_LOCK_DELTA; // additional variability on how long lock is kept
+
+#if 1
+ // Force notifications (to ensure they are queued correctly
+ static int newNotification = 45; // new notification every ticks
+ if (--newNotification == 0)
+ {
+ ocb_occmisc_t current_occmisc0;
+ current_occmisc0.value = in32(OCB_OCCMISC);
+ TRAC_INFO("SIMULATE_HOST: forcing additional notifications (tmgt+tmgt+tmgt+shmem) currentInt=%d",
+ current_occmisc0.fields.core_ext_intr);
+ notify_host(INTR_REASON_HTMGT_SERVICE_REQUIRED);
+ //notify_host(INTR_REASON_I2C_OWNERSHIP_CHANGE);
+ notify_host(INTR_REASON_HTMGT_SERVICE_REQUIRED);
+ notify_host(INTR_REASON_HTMGT_SERVICE_REQUIRED);
+ notify_host(INTR_REASON_OPAL_SHARED_MEM_CHANGE);
+ newNotification = 20;
+ }
+#endif
+
+ ocb_occflg_t occ_flags = {0};
+ occ_flags.value = in32(OCB_OCCFLG);
+ if (occ_flags.fields.i2c_engine3_lock_host == 1)
+ {
+ if (occ_flags.fields.i2c_engine3_lock_occ == 0)
+ {
+ // Host owns lock
+ if (--lockDuration == 0)
+ {
+ host_i2c_lock_release();
+ unlockDuration = DURATION_UNLOCK;
+ }
+ }
+ else
+ {
+ // Host requested lock, but does not own it yet
+ }
+ }
+ else
+ {
+ // Host has NOT requested lock yet
+ if (--unlockDuration == 0)
+ {
+ // Request the lock
+ host_i2c_lock_request();
+ lockDuration = DURATION_LOCK + durationDelta;
+ if (--durationDelta < 0)
+ {
+ durationDelta = DURATION_LOCK_DELTA;
+ }
+ }
+ }
+
+ // Handle clearing the external interrupt periodically
+ ocb_occmisc_t current_occmisc;
+ current_occmisc.value = in32(OCB_OCCMISC);
+ if (current_occmisc.fields.core_ext_intr)
+ {
+ if (--extIntDuration == 0)
+ {
+ TRAC_INFO("SIMULATE_HOST: clearing ext_intr");
+ current_occmisc.fields.core_ext_intr = 0;
+ out32(OCB_OCCMISC,current_occmisc.value);
+ extIntDuration = 2;
+ }
+ }
+}
+#endif // DEBUG_LOCK_TESTING
+
+
+
// Function Specification
//
// Name: task_dimm_sm
@@ -530,217 +613,279 @@ void task_dimm_sm(struct task *i_self)
#define MAX_READ_ATTEMPT 3
static uint8_t L_readAttempt = 0;
static bool L_readIssued = false;
+ const uint8_t engine = G_sysConfigData.dimm_i2c_engine;
+ static bool L_occ_owns_lock = true;
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;
+#ifdef DEBUG_LOCK_TESTING
+ // TODO: remove testing code once SIMICS_FLAG_ISSUE removed
+ SIMULATE_HOST();
+#endif
+ // First handle any outstanding I2C reset
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))
+ if ((G_dimm_state != DIMM_STATE_RESET_MASTER) && (check_for_i2c_failure()))
{
- nextState = DIMM_STATE_WRITE_MODE;
+ // I2C failure occurred during a reset...
+ INTR_TRAC_ERR("task_dimm_sm: Failure during I2C reset - memory monitoring disabled");
+ // release I2C lock to the host for this engine and stop monitoring
+ occ_i2c_lock_release(G_dimm_sm_args.i2cEngine);
+ L_occ_owns_lock = false;
+ G_mem_monitoring_allowed = false;
+ // TODO: What else do we need to do? go to Safe State?
+ }
+ else
+ {
+ if (G_dimm_state == DIMM_STATE_INIT)
+ {
+ // Reset has completed successfully
+ TRAC_INFO("task_dimm_sm: I2C reset completed");
+ G_dimm_i2c_reset_required = false;
+ // Check if host needs I2C lock
+ L_occ_owns_lock = check_and_update_i2c_lock(engine);
+ }
+ else
+ {
+ // Reset still in progress
+ G_dimm_state = dimm_reset_sm();
+ }
}
}
- else
+
+ if (G_dimm_i2c_reset_required == false)
{
- bool intTriggered = check_for_i2c_interrupt(G_sysConfigData.dimm_i2c_engine);
- if (intTriggered == false)
+ if ((L_occ_owns_lock == false) && ((DIMM_TICK == 0) || (DIMM_TICK == 8)))
{
- ++L_notReadyCount;
+ // Check if host gave up the I2C lock
+ L_occ_owns_lock = check_and_update_i2c_lock(engine);
+ if (L_occ_owns_lock)
+ {
+ // Start over at the INIT state after receiving the lock
+ G_dimm_state = DIMM_STATE_INIT;
+ }
}
- // Check if prior command completed (or timed out waiting for it)
- if (intTriggered || (L_notReadyCount > MAX_TICK_COUNT_WAIT))
+ if (L_occ_owns_lock)
{
- if (ASYNC_REQUEST_STATE_COMPLETE == G_dimm_sm_request.request.completion_state)
+ // Check for failure on prior operation
+ if (check_for_i2c_failure())
{
- // 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;
+ // If there was a failure, continue to the next DIMM (after I2c reset)
+ use_next_dimm(&L_dimmPort, &L_dimmIndex);
+ }
- 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;
+ uint8_t nextState = G_dimm_state;
- default:
- // Nothing to do
- break;
- }
- }
- 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)",
+ engine, G_sysConfigData.mem_type);
+ G_dimm_sm_args.i2cEngine = engine;
+ if (schedule_dimm_req(DIMM_STATE_INIT))
{
- // 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;
- }
+ nextState = DIMM_STATE_WRITE_MODE;
}
}
- }
-
- if (false == G_dimm_i2c_reset_required)
- {
- // Handle new DIMM state
- switch (G_dimm_state)
+ else
{
- case DIMM_STATE_WRITE_MODE:
- // Only start a DIMM read on tick 0 or 8
- if ((DIMM_TICK == 0) || (DIMM_TICK == 8))
+ bool intTriggered = check_for_i2c_interrupt(engine);
+ if (intTriggered == false)
+ {
+ // Interrupt not generated, I2C operation may not have completed.
+ // After MAX_TICK_COUNT_WAIT, attempt operation anyway.
+ ++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)
{
- // 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))
+ // IPC request completed, now check return code
+ if (GPE_RC_SUCCESS == G_dimm_sm_args.error.rc)
{
- 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))
+ // last request completed without error
+ switch (G_dimm_sm_args.state)
{
- nextState = DIMM_STATE_WRITE_ADDR;
+ 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;
+
+ // Check if host needs the I2C lock
+ L_occ_owns_lock = check_and_update_i2c_lock(engine);
+ }
+ break;
+
+ default:
+ // Nothing to do
+ break;
}
}
else
{
- // Skip current DIMM and move on to next one
- use_next_dimm(&L_dimmPort, &L_dimmIndex);
+ // 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;
+ }
}
}
- break;
+ }
- case DIMM_STATE_WRITE_ADDR:
- if (intTriggered || (L_notReadyCount > MAX_TICK_COUNT_WAIT))
+ if (L_occ_owns_lock)
+ {
+ if (false == G_dimm_i2c_reset_required)
{
- 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))
+ // Handle new DIMM state
+ switch (G_dimm_state)
{
- nextState = DIMM_STATE_INITIATE_READ;
- L_readAttempt = 0;
- L_readIssued = false;
- }
- }
- break;
+ 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_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;
+ 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;
}
}
- break;
-
- case DIMM_STATE_READ_TEMP:
- if (intTriggered || (L_notReadyCount > MAX_TICK_COUNT_WAIT))
+ else
{
- if (schedule_dimm_req(DIMM_STATE_READ_TEMP))
- {
- L_readIssued = true;
- nextState = DIMM_STATE_WRITE_MODE;
- }
+ // Previous op triggered reset
+ nextState = dimm_reset_sm();
}
- break;
+ }
+ else
+ {
+ // OCC no longer holds the i2c lock (no DIMM state change required)
+ nextState = G_dimm_state;
+ }
+ }
- default:
- INTR_TRAC_ERR("task_dimm_sm: INVALID STATE: 0x%02X", G_dimm_state);
- break;
+ 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;
}
}
- 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;
}
}
diff --git a/src/occ_405/dimm/dimm.h b/src/occ_405/dimm/dimm.h
index cfbb898..c453e9a 100644
--- a/src/occ_405/dimm/dimm.h
+++ b/src/occ_405/dimm/dimm.h
@@ -31,11 +31,10 @@
#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
+#define DIMM_TICK (CURRENT_TICK % MAX_NUM_TICKS)
+
typedef enum
{
DIMM_READ_SUCCESS = 0x00,
@@ -49,6 +48,7 @@ typedef enum
PIB_I2C_ENGINE_C = 0x01,
PIB_I2C_ENGINE_D = 0x02,
PIB_I2C_ENGINE_E = 0x03,
+ PIB_I2C_ENGINE_ALL = 0xFF,
} PIB_I2C_ENGINE;
typedef enum
diff --git a/src/occ_405/errl/errl.c b/src/occ_405/errl/errl.c
index 2192665..6ef8f15 100755
--- a/src/occ_405/errl/errl.c
+++ b/src/occ_405/errl/errl.c
@@ -30,6 +30,7 @@
#include <trac.h>
#include <state.h>
#include <dcom.h>
+#include <common.h>
uint32_t G_occErrSlotBits = 0x000000000;
uint8_t G_occErrIdCounter= 0x00;
@@ -540,8 +541,6 @@ void addTraceToErrl(
// End Function Specification
void reportErrorLog( errlHndl_t i_err, uint16_t i_entrySize )
{
- ocb_occmisc_t l_reg;
-
// report the log
// will need to give them the address and size to read
@@ -557,13 +556,7 @@ void reportErrorLog( errlHndl_t i_err, uint16_t i_entrySize )
// Host can inform HTMGT to collect the error log
if (G_occ_interrupt_type == PSIHB_INTERRUPT)
{
- // From OCC OpenPower Interface v1.1, OCC needs to set bits 0 and 1 of
- // the OCB_OCCMISC register
- l_reg.fields.core_ext_intr = 1;
-// TEMP -- reason_intr field no longer exists
-// l_reg.fields.reason_intr = 1;
-
- out32(OCB_OCCMISC_OR, l_reg.value);
+ notify_host(INTR_REASON_HTMGT_SERVICE_REQUIRED);
}
}
}
diff --git a/src/occ_405/img_defs.mk b/src/occ_405/img_defs.mk
index a2f6d50..a1257a5 100644
--- a/src/occ_405/img_defs.mk
+++ b/src/occ_405/img_defs.mk
@@ -213,6 +213,7 @@ APP_INCLUDES = -I$(IMAGE_SRCDIR)/rtls \
-I$(IMAGE_SRCDIR)/cent \
-I$(IMAGE_SRCDIR)/firdata \
-I$(IMAGE_SRCDIR)/dimm \
+ -I$(IMAGE_SRCDIR)/lock \
-I$(IMAGE_SRCDIR)/../occ_gpe0 \
INCLUDES += $(IMG_INCLUDES) $(GLOBAL_INCLUDES) $(APP_INCLUDES) \
diff --git a/src/occ_405/lock/lock.c b/src/occ_405/lock/lock.c
new file mode 100755
index 0000000..0e75a93
--- /dev/null
+++ b/src/occ_405/lock/lock.c
@@ -0,0 +1,404 @@
+/* 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 */
+
+// TODO: Simics currently does not support the atomic _OR/_CLR OCI registers
+#define SIMICS_FLAG_ISSUE
+
+// Debug trace
+//#define LOCK_DEBUG
+#ifdef LOCK_DEBUG
+ #define LOCK_DBG(frmt,args...) \
+ TRAC_INFO(frmt,##args)
+#else
+ #define LOCK_DBG(frmt,args...)
+#endif
+
+#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 "lock.h"
+#include "common.h"
+#include "state.h"
+
+extern bool G_mem_monitoring_allowed;
+
+typedef enum
+{
+ LOCK_RELEASE = 0x00,
+ LOCK_ACQUIRE = 0x01
+} lockOperation_e;
+
+
+#ifdef DEBUG_LOCK_TESTING
+// DEBUG: Simulate I2C lock request from the host
+void host_i2c_lock_request()
+{
+ ocb_occflg_t occ_flags = {0};
+ TRAC_INFO("host_i2c_lock_request called (tick %d / %d)", CURRENT_TICK, DIMM_TICK);
+#ifdef SIMICS_FLAG_ISSUE
+ // NON-ATOMIC OPERATION
+ occ_flags.value = in32(OCB_OCCFLG);
+ occ_flags.fields.i2c_engine3_lock_host = 1;
+ out32(OCB_OCCFLG, occ_flags.value);
+#else
+ // TODO - OCB_OCCFLG_OR is currently not working in SIMICS 1/27/2016
+ occ_flags.fields.i2c_engine3_lock_host = 1;
+ TRAC_INFO("host_i2c_lock_request - writing %04X to _OR(0x%08X)", occ_flags.value, OCB_OCCFLG_OR);
+ out32(OCB_OCCFLG_OR, occ_flags.value);
+#endif
+
+ occ_flags.value = in32(OCB_OCCFLG);
+ //TRAC_INFO("host_i2c_lock_request - 0x%08X returned value=0x%04X", OCB_OCCFLG, occ_flags.value);
+ if (occ_flags.fields.i2c_engine3_lock_host != 1)
+ {
+ TRAC_INFO("ERROR: host_i2c_lock_request - host not locked! (0x%08X value=0x%04X)", OCB_OCCFLG, occ_flags.value);
+ occ_flags.fields.i2c_engine3_lock_host = 1;
+ occ_flags.fields.i2c_engine3_lock_occ = 1;
+ out32(OCB_OCCFLG, occ_flags.value);
+ occ_flags.value = in32(OCB_OCCFLG);
+ TRAC_INFO("host_i2c_lock_request - write+read 0x%08X returned value=0x%04X", OCB_OCCFLG, occ_flags.value);
+ }
+}
+
+// DEBUG: Simulate I2C lock release from host
+void host_i2c_lock_release()
+{
+ TRAC_INFO("host_i2c_lock_release called (tick %d / %d)", CURRENT_TICK, DIMM_TICK);
+
+ ocb_occmisc_t occmiscreg = {0};
+ ocb_occflg_t occ_flags = {0};
+#ifdef SIMICS_FLAG_ISSUE // NON-ATOMIC OPERATION
+ // clear external interrupt (so OCC can notify host when lock released)
+ occmiscreg.value = in32(OCB_OCCMISC);
+ occmiscreg.fields.core_ext_intr = 0;
+ out32(OCB_OCCMISC, occmiscreg.value);
+
+ // Clear the host request
+ occ_flags.value = in32(OCB_OCCFLG);
+ occ_flags.fields.i2c_engine3_lock_host = 0;
+ out32(OCB_OCCFLG, occ_flags.value);
+#else
+ // TODO - OCB_OCCFLG_CLR is currently not working in SIMICS 1/27/2016
+ // clear external interrupt (so OCC can notify host when lock released)
+ occmiscreg.fields.core_ext_intr = 1;
+ out32(OCB_OCCMISC_CLR, occmiscreg.value);
+
+ // Clear the host request
+ occ_flags.fields.i2c_engine3_lock_host = 1;
+ TRAC_INFO("host_i2c_lock_release - writing %04X to _CLR(0x%08X)", occ_flags.value, OCB_OCCFLG_CLR);
+ out32(OCB_OCCFLG_CLR, occ_flags.value);
+#endif
+
+ occ_flags.value = in32(OCB_OCCFLG);
+ //TRAC_INFO("host_i2c_lock_release - 0x%08X returned value=0x%04X", OCB_OCCFLG, occ_flags.value);
+ if (occ_flags.fields.i2c_engine3_lock_host != 0)
+ {
+ TRAC_INFO("ERROR: host_i2c_lock_release - host not released! (0x%08X value=0x%04X)", OCB_OCCFLG, occ_flags.value);
+ occ_flags.fields.i2c_engine3_lock_host = 0;
+ occ_flags.fields.i2c_engine3_lock_occ = 1;
+ out32(OCB_OCCFLG, occ_flags.value);
+ occ_flags.value = in32(OCB_OCCFLG);
+ TRAC_INFO("host_i2c_lock_release - write+read 0x%08X returned value=0x%04X", OCB_OCCFLG, occ_flags.value);
+ }
+}
+#endif
+
+
+// Update I2C log information for specified engine
+// i_op values:
+// LOC_ACQUIRE = OCC should take ownership of lock
+// LOC_RELEASE = OCC should release ownership of lock and notify host
+void update_i2c_lock(const lockOperation_e i_op, const uint8_t i_engine)
+{
+ ocb_occflg_t occ_flags = {0};
+
+#ifdef DEBUG_LOCK_TESTING
+ ocb_occflg_t flag;
+ flag.value = in32(OCB_OCCFLG);
+ if (LOCK_RELEASE == i_op)
+ {
+ LOCK_DBG("update_i2c_lock: I2C engine %d RELEASE - host=%d, occ=%d, dimmTick=%d",
+ i_engine, flag.fields.i2c_engine3_lock_host, flag.fields.i2c_engine3_lock_occ, DIMM_TICK);
+ }
+ else
+ {
+ LOCK_DBG("update_i2c_lock: I2C engine %d LOCK - host=%d, occ=%d, dimmTick=%d",
+ i_engine, flag.fields.i2c_engine3_lock_host, flag.fields.i2c_engine3_lock_occ, DIMM_TICK);
+ }
+#endif
+
+#ifdef SIMICS_FLAG_ISSUE
+ // TODO - OCB_OCCFLG_OR is currently not working in SIMICS 1/27/2016
+ // NON-ATOMIC OPERATION
+ occ_flags.value = in32(OCB_OCCFLG);
+ if (PIB_I2C_ENGINE_E == i_engine)
+ {
+ occ_flags.fields.i2c_engine3_lock_occ = i_op;
+ }
+ else if (PIB_I2C_ENGINE_D == i_engine)
+ {
+ occ_flags.fields.i2c_engine2_lock_occ = i_op;
+ }
+ else if (PIB_I2C_ENGINE_C == i_engine)
+ {
+ occ_flags.fields.i2c_engine1_lock_occ = i_op;
+ }
+#else
+ if (PIB_I2C_ENGINE_E == i_engine)
+ {
+ occ_flags.fields.i2c_engine3_lock_occ = 1;
+ }
+ else if (PIB_I2C_ENGINE_D == i_engine)
+ {
+ occ_flags.fields.i2c_engine2_lock_occ = 1;
+ }
+ else if (PIB_I2C_ENGINE_C == i_engine)
+ {
+ occ_flags.fields.i2c_engine1_lock_occ = 1;
+ }
+#endif
+
+ if (LOCK_RELEASE == i_op)
+ {
+#ifdef SIMICS_FLAG_ISSUE
+ out32(OCB_OCCFLG, occ_flags.value);
+#else
+ out32(OCB_OCCFLG_CLR, occ_flags.value);
+#endif
+
+ // OCC had the lock and host wants it, so send interrupt to host
+ notify_host(INTR_REASON_I2C_OWNERSHIP_CHANGE);
+
+ TRAC_IMP("update_i2c_lock: OCC has released lock for I2C engine %d", i_engine);
+ }
+ else // LOCK_ACQUIRE
+ {
+#ifdef SIMICS_FLAG_ISSUE
+ out32(OCB_OCCFLG, occ_flags.value);
+#else
+ out32(OCB_OCCFLG_OR, occ_flags.value);
+#endif
+
+ TRAC_IMP("update_i2c_lock: OCC has aquired lock for I2C engine %d", i_engine);
+ }
+
+} // end update_i2c_lock()
+
+
+// Release the OCC lock indefinitely
+// This should be called when OCC goes into safe mode or will be reset
+// to allow the host to use the specified I2C engines.
+// If no engine is specified, locks for all I2C engines will be released
+void occ_i2c_lock_release(const uint8_t i_engine)
+{
+ TRAC_INFO("occ_i2c_lock_release(engine %d) called", i_engine); // TODO DEBUG
+
+ if ((PIB_I2C_ENGINE_ALL == i_engine) ||
+ (PIB_I2C_ENGINE_E == i_engine) || (PIB_I2C_ENGINE_D == i_engine) || (PIB_I2C_ENGINE_C == i_engine))
+ {
+ ocb_occflg_t occ_flags;
+ occ_flags.value = in32(OCB_OCCFLG);
+
+ if ((PIB_I2C_ENGINE_E == i_engine) || (PIB_I2C_ENGINE_ALL == i_engine))
+ {
+ update_i2c_lock(LOCK_RELEASE, PIB_I2C_ENGINE_E);
+ }
+ if ((PIB_I2C_ENGINE_D == i_engine) || (PIB_I2C_ENGINE_ALL == i_engine))
+ {
+ update_i2c_lock(LOCK_RELEASE, PIB_I2C_ENGINE_D);
+ }
+ if ((PIB_I2C_ENGINE_C == i_engine) || (PIB_I2C_ENGINE_ALL == i_engine))
+ {
+ update_i2c_lock(LOCK_RELEASE, PIB_I2C_ENGINE_C);
+ }
+ }
+ else
+ {
+ INTR_TRAC_ERR("occ_i2c_lock_release: Invalid engine specified: 0x%02X", i_engine);
+ }
+
+} // end occ_i2c_lock_release()
+
+
+// Determine if the OCC currently owns the lock
+// Returns true if OCC owns the lock, else false
+bool occ_owns_i2c_lock(const ocb_occflg_t i_flags, const uint8_t i_engine)
+{
+ bool ownsLock = false;
+ if (PIB_I2C_ENGINE_E == i_engine)
+ {
+ ownsLock = i_flags.fields.i2c_engine3_lock_occ;
+ }
+ else if (PIB_I2C_ENGINE_D == i_engine)
+ {
+ ownsLock = i_flags.fields.i2c_engine2_lock_occ;
+ }
+ else if (PIB_I2C_ENGINE_C == i_engine)
+ {
+ ownsLock = i_flags.fields.i2c_engine1_lock_occ;
+ }
+ return ownsLock;
+}
+
+
+// Determine if the Host wants the i2c lock
+// Returns true if Host wants the lock, else false
+bool host_wants_i2c_lock(const ocb_occflg_t i_flags, const uint8_t i_engine)
+{
+ bool wantsLock = false;
+ if (PIB_I2C_ENGINE_E == i_engine)
+ {
+ wantsLock = i_flags.fields.i2c_engine3_lock_host;
+ }
+ else if (PIB_I2C_ENGINE_D == i_engine)
+ {
+ wantsLock = i_flags.fields.i2c_engine2_lock_host;
+ }
+ else if (PIB_I2C_ENGINE_C == i_engine)
+ {
+ wantsLock = i_flags.fields.i2c_engine1_lock_host;
+ }
+ return wantsLock;
+}
+
+
+// Check and update lock ownership for the specified i2c engine.
+// Returns true if OCC owns the lock, or false if host owns lock
+//
+// If host has requesed the i2c lock, it will be released and an external interrupt
+// will be generated/queued and function will return false.
+// If the host has not released the lock, function will return false.
+// If the host cleared its lock bit, OCC will take back ownership and return true.
+//
+bool check_and_update_i2c_lock(const uint8_t i_engine)
+{
+ bool occ_owns_lock = true;
+
+ if ((PIB_I2C_ENGINE_E == i_engine) ||
+ (PIB_I2C_ENGINE_D == i_engine) ||
+ (PIB_I2C_ENGINE_C == i_engine))
+ {
+ bool needRetry = false;
+ do
+ {
+ ocb_occflg_t occ_flags;
+ ocb_occflg_t original_occflags;
+ original_occflags.value = in32(OCB_OCCFLG);
+ occ_flags.value = original_occflags.value;
+
+ LOCK_DBG("check_and_update_i2c_lock: I2C engine %d - host=%d, occ=%d (dimmTick=%d)",
+ i_engine, original_occflags.fields.i2c_engine3_lock_host, original_occflags.fields.i2c_engine3_lock_occ, DIMM_TICK);
+ if (occ_owns_i2c_lock(original_occflags, i_engine))
+ {
+ if (host_wants_i2c_lock(original_occflags, i_engine))
+ {
+ // Host requested lock, clear the OCC lock and notify host
+ update_i2c_lock(LOCK_RELEASE, i_engine);
+ occ_owns_lock = false;
+ }
+ // else OCC already owns the lock
+ }
+ else
+ {
+ // OCC does not own the lock
+ occ_owns_lock = false;
+ if (false == host_wants_i2c_lock(original_occflags, i_engine))
+ {
+ // Host is not requesting the lock, acquire lock for OCC
+ update_i2c_lock(LOCK_ACQUIRE, i_engine);
+ occ_owns_lock = true;
+ }
+ // else Host still holds the lock
+ }
+
+ if ((occ_owns_lock) &&
+ (original_occflags.fields.i2c_engine1_lock_host == 0) &&
+ (original_occflags.fields.i2c_engine1_lock_occ == 0))
+ {
+ // If neither lock bit is set, we must read back the register to make
+ // sure the host did not set at same time (lock conflict)
+ ocb_occflg_t verify_occflags;
+ verify_occflags.value = in32(OCB_OCCFLG);
+ if (host_wants_i2c_lock(verify_occflags, i_engine))
+ {
+ // Host wrote their lock bit at same time, clear OCC lock and notify host
+ update_i2c_lock(LOCK_RELEASE, i_engine);
+ occ_owns_lock = false;
+ }
+ else
+ {
+ if (false == occ_owns_i2c_lock(verify_occflags, i_engine))
+ {
+ // ERROR - OCC OWNERSHIP BIT DID NOT GET SET
+ INTR_TRAC_ERR("check_and_update_i2c_lock: I2C lock bit did not get set (OCCFLAGS reg: 0x%08X)",
+ verify_occflags.value);
+
+ if (needRetry)
+ {
+ // After one retry, log error and goto safe
+ /*
+ * @errortype
+ * @moduleid I2C_LOCK_UPDATE
+ * @reasoncode OCI_WRITE_FAILURE
+ * @userdata1 I2C engine number
+ * @userdata2 OCC Flags register
+ * @devdesc Invalid memory type detected
+ */
+ errlHndl_t err = createErrl(I2C_LOCK_UPDATE,
+ OCI_WRITE_FAILURE,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ i_engine,
+ verify_occflags.value);
+ REQUEST_RESET(err);
+ occ_owns_lock = false;
+ break;
+ }
+ needRetry = true;
+ }
+ // else verify succeeded (OCC owns lock)
+ }
+ }
+ } while (needRetry);
+ }
+ else
+ {
+ // Invalid engine
+ INTR_TRAC_ERR("check_and_update_i2c_lock: Invalid engine specified: 0x%02X", i_engine);
+ }
+
+ return occ_owns_lock;
+
+} // end check_and_update_i2c_lock()
diff --git a/src/occ_405/lock/lock.h b/src/occ_405/lock/lock.h
new file mode 100644
index 0000000..dc570f2
--- /dev/null
+++ b/src/occ_405/lock/lock.h
@@ -0,0 +1,54 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/lock/lock.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 _LOCK_H
+#define _LOCK_H
+
+#include <occ_common.h>
+#include <dimm.h>
+
+
+// TODO: remove testing code once SIMICS_FLAG_ISSUE removed
+//#define DEBUG_LOCK_TESTING
+
+
+
+// Release the OCC lock indefinitely
+// This should be called when OCC goes into safe mode or will be reset
+// to allow the host to use the specified I2C engines.
+// Use PIB_I2C_ENGINE_ALL, if locks for all I2C engines should be released
+void occ_i2c_lock_release(const uint8_t i_engine);
+
+
+// Check and update lock ownership for the specified i2c engine
+// If host has requesed lock, and there is no other outstanding interrupt
+// release the lock, generate and external interrupt and return false.
+// If the host has not released the lock, set ownership back to OCC and
+// return true.
+//
+// Returns true if OCC owns the lock, or false if host owns lock
+bool check_and_update_i2c_lock(const uint8_t i_engine);
+
+#endif //_LOCK_H
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index 8e77fcf..629e88c 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -874,12 +874,7 @@ void Main_thread_routine(void *private)
// Host can inform HTMGT to collect the error log
if (G_occ_interrupt_type == PSIHB_INTERRUPT)
{
- // From OCC OpenPower Interface v1.1, OCC needs to set bits 0 and 1 of
- // the OCB_OCCMISC register
- ocb_occmisc_t l_occmiscreg;
- l_occmiscreg.fields.core_ext_intr = 1;
- l_occmiscreg.fields.reason_intr = 1;
- out32(OCB_OCCMISC_OR, l_occmiscreg.value);
+ notify_host(INTR_REASON_HTMGT_SERVICE_REQUIRED);
}
}
*/
diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile
index 9f6059b..0cb4978 100644
--- a/src/occ_405/occLinkInputFile
+++ b/src/occ_405/occLinkInputFile
@@ -18,6 +18,7 @@ INPUT ( amec_data.o
cmdh_fsp.o
cmdh_snapshot.o
cmdh_thread.o
+ common.o
dcom.o
dcom_thread.o
dcomMasterRx.o
@@ -29,6 +30,7 @@ INPUT ( amec_data.o
fir_data_collect.o
homer.o
ll_ffdc.o
+ lock.o
main.o
mode.o
occ_sys_config.o
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index e355f28..0ced425 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -51,6 +51,8 @@ enum occReasonCode
PROC_ERROR_TEMP = 0x10,
/// Timed out reading processor temperature
PROC_TEMP_TIMEOUT = 0x11,
+ // OCI write did not retain value
+ OCI_WRITE_FAILURE = 0x12,
/// Processor SCOM failure
PROC_SCOM_ERROR = 0x16,
/// Any failure coming from the SSX RTOS code
@@ -220,6 +222,7 @@ enum occModuleId
AMEC_VERIFY_FREQ_MID = MAIN_COMP_ID | 0x0d,
FIR_DATA_MID = MAIN_COMP_ID | 0x0e,
CMDH_DBUG_MID = MAIN_COMP_ID | 0x0f,
+ I2C_LOCK_UPDATE = MAIN_COMP_ID | 0x10,
};
enum occUserDataType
diff --git a/src/occ_405/reset.c b/src/occ_405/reset.c
index 5d970b8..0d79add 100755
--- a/src/occ_405/reset.c
+++ b/src/occ_405/reset.c
@@ -141,88 +141,3 @@ void reset_state_request(uint8_t i_request)
}
}
-// Function Specification
-//
-// Name: task_check_for_checkstop
-//
-// Description: Check for checkstop
-//
-// End Function Specification
-void task_check_for_checkstop(task_t *i_self)
-{
-/* TEMP -- NO MORE PORE / check_stop field no longer exists */
-#if 0
- pore_status_t l_gpe0_status;
-
- ocb_oisr0_t l_oisr0_status;
- static bool L_checkstop_traced = FALSE;
- uint8_t l_reason_code = 0;
-
- do
- {
- // This check is disabled once a checkstop or frozen GPE is detected
- if(L_checkstop_traced)
- {
- break;
- }
-
- // Looked for a frozen GPE, a sign that the chip has stopped working or
- // check-stopped. This check also looks for an interrupt status flag that
- // indicates if the system has check-stopped.
- l_gpe0_status.value = in64(PORE_GPE0_STATUS);
- l_oisr0_status.value = in32(OCB_OISR0);
-
- if (l_gpe0_status.fields.freeze_action
- ||
- l_oisr0_status.fields.check_stop)
- {
- errlHndl_t l_err = NULL;
-
- if (l_gpe0_status.fields.freeze_action)
- {
- TRAC_IMP("Frozen GPE0 detected by RTL");
- l_reason_code = OCC_GPE_HALTED;
- }
-
- if (l_oisr0_status.fields.check_stop)
- {
- TRAC_IMP("System checkstop detected by RTL");
- l_reason_code = OCC_SYSTEM_HALTED;
- }
-
- L_checkstop_traced = TRUE;
-
- /*
- * @errortype
- * @moduleid MAIN_SYSTEM_HALTED_MID
- * @reasoncode OCC_GPE_HALTED
- * @userdata1 High order word of PORE_GPE0_STATUS
- * @userdata2 OCB_OISR0
- * @devdesc OCC detected frozen GPE0
- */
- /*
- * @errortype
- * @moduleid MAIN_SYSTEM_HALTED_MID
- * @reasoncode OCC_SYSTEM_HALTED
- * @userdata1 High order word of PORE_GPE0_STATUS
- * @userdata2 OCB_OISR0
- * @devdesc OCC detected system checkstop
- */
- l_err = createErrl(MAIN_SYSTEM_HALTED_MID,
- l_reason_code,
- OCC_NO_EXTENDED_RC,
- ERRL_SEV_INFORMATIONAL,
- NULL,
- DEFAULT_TRACE_SIZE,
- l_gpe0_status.words.high_order,
- l_oisr0_status.value);
-
- // The commit code will check for the frozen GPE0 and system
- // checkstop conditions and take appropriate actions.
- commitErrl(&l_err);
- }
- }
- while(0);
-#endif // #if 0
-}
-
diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h
index 5b95791..91dd5ac 100755
--- a/src/occ_405/rtls/rtls.h
+++ b/src/occ_405/rtls/rtls.h
@@ -52,7 +52,7 @@ typedef enum {
TASK_ID_DCOM_RX_OUTBX,
TASK_ID_DCOM_TX_OUTBX,
// TASK_ID_DCOM_PARSE_FW_MSG,
- TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS, // Miscellaneous checks to be done by 405
TASK_ID_AMEC_SLAVE, // AMEC SMH tasks
// TASK_ID_AMEC_MASTER, // AMEC SMH tasks
// TASK_ID_CORE_DATA_CONTROL,
diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c
index 9d63762..20b60dd 100755
--- a/src/occ_405/rtls/rtls_tables.c
+++ b/src/occ_405/rtls/rtls_tables.c
@@ -34,6 +34,7 @@
#include <centaur_control.h>
#include "amec_master_smh.h"
#include "dimm.h"
+#include <common.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
@@ -62,7 +63,7 @@
#define FLAGS_APSS_DONE_MEAS APSS_TASK_FLAGS
#define FLAGS_DCOM_PARSE_OCC_FW_MSG 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_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
-#define FLAGS_CHECK_FOR_CHECKSTOP 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_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_MISC_405_CHECKS 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_STANDBY | RTL_FLAG_RST_REQ | RTL_FLAG_APSS_NOT_INITD
#define FLAGS_CORE_DATA_CONTROL 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
@@ -112,7 +113,7 @@ task_t G_task_table[TASK_END] = {
{ FLAGS_DCOM_TX_SLV_OUTBOX, task_dcom_tx_slv_outbox, NULL }, // TASK_ID_DCOM_TX_OUTBX
// TEMP -- NOT SUPPORTED YET IN PHASE1
// { FLAGS_DCOM_PARSE_OCC_FW_MSG, task_dcom_parse_occfwmsg, NULL }, // TASK_ID_DCOM_PARSE_FW_MSG
- { FLAGS_CHECK_FOR_CHECKSTOP, task_check_for_checkstop, NULL }, // TASK_ID_CHECK_FOR_CHECKSTOP
+ { FLAGS_MISC_405_CHECKS, task_misc_405_checks, NULL }, // TASK_ID_MISC_405_CHECKS
// TEMP -- NOT SUPPORTED YET IN PHASE1
{ FLAGS_AMEC_SLAVE, task_amec_slave, NULL }, // TASK_ID_AMEC_SLAVE
// TEMP -- NOT SUPPORTED YET IN PHASE1
@@ -143,7 +144,7 @@ const uint8_t G_tick0_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick1_seq[] = {
@@ -162,7 +163,7 @@ const uint8_t G_tick1_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick2_seq[] = {
@@ -181,7 +182,7 @@ const uint8_t G_tick2_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick3_seq[] = {
@@ -200,7 +201,7 @@ const uint8_t G_tick3_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick4_seq[] = {
@@ -220,7 +221,7 @@ const uint8_t G_tick4_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick5_seq[] = {
@@ -239,7 +240,7 @@ const uint8_t G_tick5_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick6_seq[] = {
@@ -258,7 +259,7 @@ const uint8_t G_tick6_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick7_seq[] = {
@@ -277,7 +278,7 @@ const uint8_t G_tick7_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick8_seq[] = {
@@ -297,7 +298,7 @@ const uint8_t G_tick8_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick9_seq[] = {
@@ -316,7 +317,7 @@ const uint8_t G_tick9_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick10_seq[] = {
@@ -335,7 +336,7 @@ const uint8_t G_tick10_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick11_seq[] = {
@@ -354,7 +355,7 @@ const uint8_t G_tick11_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick12_seq[] = {
@@ -374,7 +375,7 @@ const uint8_t G_tick12_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick13_seq[] = {
@@ -393,7 +394,7 @@ const uint8_t G_tick13_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick14_seq[] = {
@@ -412,7 +413,7 @@ const uint8_t G_tick14_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
const uint8_t G_tick15_seq[] = {
@@ -431,7 +432,7 @@ const uint8_t G_tick15_seq[] = {
TASK_ID_AMEC_SLAVE,
//TASK_ID_AMEC_MASTER,
//TASK_ID_DCOM_PARSE_FW_MSG,
- //TASK_ID_CHECK_FOR_CHECKSTOP,
+ TASK_ID_MISC_405_CHECKS,
TASK_END };
// The Global Tick Table
diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk
index 0d2b7b3..93b574f 100644
--- a/src/occ_405/topfiles.mk
+++ b/src/occ_405/topfiles.mk
@@ -45,6 +45,7 @@ TOP-C-SOURCES = amec/amec_data.c \
cmdh/cmdh_thread.c \
cmdh/cmdh_tunable_parms.c \
cmdh/ffdc.c \
+ common.c \
dcom/dcom.c \
dcom/dcom_thread.c \
dcom/dcomMasterRx.c \
@@ -54,6 +55,7 @@ TOP-C-SOURCES = amec/amec_data.c \
errl/errl.c \
firdata/fir_data_collect.c \
homer.c \
+ lock/lock.c \
main.c \
mode.c \
occ_sys_config.c \
diff --git a/src/occ_gpe1/gpe1_dimm_read.c b/src/occ_gpe1/gpe1_dimm_read.c
index be19506..d89b0bf 100644
--- a/src/occ_gpe1/gpe1_dimm_read.c
+++ b/src/occ_gpe1/gpe1_dimm_read.c
@@ -210,7 +210,7 @@ void dimm_write_int_mask(ipc_msg_t* cmd, void* arg)
scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
// max_num_of_ports (bits 9:15)
args->maxPorts = (regValue >> 48) & 0x7F;
- PK_TRACE("dimm_write_int_mask: maxPorts = %d", args->maxPorts);
+ GPE1_DIMM_DBG("dimm_write_int_mask: maxPorts = %d", args->maxPorts);
}
} // end dimm_write_int_mask()
@@ -481,8 +481,8 @@ void dimm_read_temp(ipc_msg_t* cmd, void* arg)
args->error.error = 0;
args->error.rc = GPE_RC_SUCCESS;
args->error.ffdc = 0;
- PK_TRACE("dimm_read_temp: DIMM%04X temperature=%dC",
- (args->i2cPort<<8)|args->dimm, args->temp);
+ GPE1_DIMM_DBG("dimm_read_temp: DIMM%04X temperature=%dC",
+ (args->i2cPort<<8)|args->dimm, args->temp);
// Check for operation complete bit
// (operation complete bit will not get set until all
diff --git a/src/occ_gpe1/gpe1_dimm_reset.c b/src/occ_gpe1/gpe1_dimm_reset.c
index 9963eec..eedc917 100644
--- a/src/occ_gpe1/gpe1_dimm_reset.c
+++ b/src/occ_gpe1/gpe1_dimm_reset.c
@@ -76,22 +76,22 @@ void dimm_reset_master(ipc_msg_t* cmd, void* arg)
{
GPE1_DIMM_DBG("dimm_reset_master: putscom(0x%08X,0x%08X%08X) SUCCESS - IMM_RESET_I2C",
scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
- }
- // Force reset of Port_busy_register
- scomAddr = I2C_BUSY_REGISTER | SCOM_ENGINE_OFFSET(args->i2cEngine);
- regValue = 0x8000000000000000;
- rc = putscom_abs(scomAddr, regValue);
- if(rc)
- {
- PK_TRACE("dimm_reset_master: I2C_BUSY_REGISTER putscom 0x%08X->0x%08X%08X FAILED. rc = 0x%08x",
- scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue), rc);
- gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_PUT_FAILED, rc);
- }
- else
- {
- GPE1_DIMM_DBG("dimm_reset_master: putscom(0x%08X,0x%08X%08X) SUCCESS - I2C_BUSY_REGISTER",
- scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ // Force reset of Port_busy_register
+ scomAddr = I2C_BUSY_REGISTER | SCOM_ENGINE_OFFSET(args->i2cEngine);
+ regValue = 0x8000000000000000;
+ rc = putscom_abs(scomAddr, regValue);
+ if(rc)
+ {
+ PK_TRACE("dimm_reset_master: I2C_BUSY_REGISTER putscom 0x%08X->0x%08X%08X FAILED. rc = 0x%08x",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue), rc);
+ gpe_set_ffdc(&(args->error), scomAddr, GPE_RC_SCOM_PUT_FAILED, rc);
+ }
+ else
+ {
+ GPE1_DIMM_DBG("dimm_reset_master: putscom(0x%08X,0x%08X%08X) SUCCESS - I2C_BUSY_REGISTER",
+ scomAddr, WORD_HIGH(regValue), WORD_LOW(regValue));
+ }
}
} // end dimm_reset_master()
OpenPOWER on IntegriCloud