diff options
-rw-r--r-- | src/include/registers/ocb_firmware_registers.h | 92 | ||||
-rwxr-xr-x | src/occ_405/Makefile | 1 | ||||
-rwxr-xr-x | src/occ_405/common.c | 408 | ||||
-rw-r--r-- | src/occ_405/common.h | 21 | ||||
-rwxr-xr-x | src/occ_405/dimm/dimm.c | 523 | ||||
-rw-r--r-- | src/occ_405/dimm/dimm.h | 6 | ||||
-rwxr-xr-x | src/occ_405/errl/errl.c | 11 | ||||
-rw-r--r-- | src/occ_405/img_defs.mk | 1 | ||||
-rwxr-xr-x | src/occ_405/lock/lock.c | 404 | ||||
-rw-r--r-- | src/occ_405/lock/lock.h | 54 | ||||
-rwxr-xr-x | src/occ_405/main.c | 7 | ||||
-rw-r--r-- | src/occ_405/occLinkInputFile | 2 | ||||
-rw-r--r-- | src/occ_405/occ_service_codes.h | 3 | ||||
-rwxr-xr-x | src/occ_405/reset.c | 85 | ||||
-rwxr-xr-x | src/occ_405/rtls/rtls.h | 2 | ||||
-rwxr-xr-x | src/occ_405/rtls/rtls_tables.c | 37 | ||||
-rw-r--r-- | src/occ_405/topfiles.mk | 2 | ||||
-rw-r--r-- | src/occ_gpe1/gpe1_dimm_read.c | 6 | ||||
-rw-r--r-- | src/occ_gpe1/gpe1_dimm_reset.c | 30 |
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() |