From 0bf193d8d4f98934d4f539b1950e8b46c03a2716 Mon Sep 17 00:00:00 2001 From: Doug Gilbert Date: Fri, 10 Nov 2017 06:01:29 -0600 Subject: APSS Reset Support Change-Id: I23dd10a7bc78841ecd4382e8ac8667afbb7c2ddd RTC: 163601 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/49871 Tested-by: FSP CI Jenkins Reviewed-by: Christopher J. Cain Reviewed-by: William A. Bryan Reviewed-by: Martha Broyles --- src/common/apss_structs.h | 4 + src/common/ipc_func_ids.h | 1 + src/occ_405/amec/amec_master_smh.c | 7 +- src/occ_405/amec/amec_sensors_power.c | 4 +- src/occ_405/dcom/dcom.h | 4 +- src/occ_405/dcom/dcomMasterTx.c | 5 +- src/occ_405/occ_service_codes.h | 1 + src/occ_405/pss/apss.c | 426 +++++++++++++++++++++++++++++++--- src/occ_405/pss/apss.h | 14 +- src/occ_405/pss/pss_service_codes.h | 1 + src/occ_405/rtls/rtls.h | 1 + src/occ_405/rtls/rtls_tables.c | 10 + src/occ_gpe0/apss_init.c | 89 +++++++ src/occ_gpe0/ipc_func_tables.c | 3 +- src/occ_gpe1/gpe_gpu_init.c | 2 +- 15 files changed, 533 insertions(+), 39 deletions(-) diff --git a/src/common/apss_structs.h b/src/common/apss_structs.h index af64fe0..99242fa 100644 --- a/src/common/apss_structs.h +++ b/src/common/apss_structs.h @@ -91,4 +91,8 @@ typedef struct { uint64_t meas_data[4]; // G_apss_pwr_meas (2nd block of data) (output from APSS) } apss_complete_args_t; +typedef struct { + GpeErrorStruct error; +} apss_reset_args_t; + #endif //_APSS_STRUCTS_H diff --git a/src/common/ipc_func_ids.h b/src/common/ipc_func_ids.h index cdd80fb..4684937 100644 --- a/src/common/ipc_func_ids.h +++ b/src/common/ipc_func_ids.h @@ -61,6 +61,7 @@ IPC_FUNCIDS_TABLE_START IPC_FUNC_ID(IPC_ST_GET_NEST_DTS_FUNCID) IPC_FUNC_ID(IPC_ST_FIR_COLLECTION) IPC_FUNC_ID(IPC_ST_GET_TOD_FUNCID) + IPC_FUNC_ID(IPC_ST_APSS_RESET_FUNCID) IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE0) //Functions that are only supported by GPE1 should be defined here diff --git a/src/occ_405/amec/amec_master_smh.c b/src/occ_405/amec/amec_master_smh.c index ab2a3af..74559c6 100755 --- a/src/occ_405/amec/amec_master_smh.c +++ b/src/occ_405/amec/amec_master_smh.c @@ -899,8 +899,11 @@ void amec_mst_common_tasks_post(void) //Call OCC pcaps mismatch function amec_mst_check_pcaps_match(); - //Call check under power cap function - amec_mst_check_under_pcap(); + if(0 == G_dcom_slv_inbox_doorbell_rx.apss_recovery_in_progress) + { + //Call check under power cap function + amec_mst_check_under_pcap(); + } } } diff --git a/src/occ_405/amec/amec_sensors_power.c b/src/occ_405/amec/amec_sensors_power.c index b168c02..77e727b 100755 --- a/src/occ_405/amec/amec_sensors_power.c +++ b/src/occ_405/amec/amec_sensors_power.c @@ -198,7 +198,9 @@ void amec_update_apss_sensors(void) { // Need to check to make sure APSS data has been received // via slave inbox first - if (G_slv_inbox_received && (G_pwr_reading_type == PWR_READING_TYPE_APSS)) + if (G_slv_inbox_received && + (G_pwr_reading_type == PWR_READING_TYPE_APSS) && + (0 == G_dcom_slv_inbox_doorbell_rx.apss_recovery_in_progress)) { uint8_t l_proc = G_pbax_id.chip_id; uint32_t temp32 = 0; diff --git a/src/occ_405/dcom/dcom.h b/src/occ_405/dcom/dcom.h index 109b4ef..3bbfcda 100755 --- a/src/occ_405/dcom/dcom.h +++ b/src/occ_405/dcom/dcom.h @@ -273,8 +273,10 @@ typedef struct uint16_t adc[MAX_APSS_ADC_CHANNELS]; // 32 bytes // Time of Day Clock from the last APSS reading uint64_t tod; // 8 bytes + // Apss reset in progress + uint8_t apss_recovery_in_progress; // 1 byte // Reserved - uint8_t _reserved_1[51]; // 51 bytes + uint8_t _reserved_1[50]; // 50 bytes // Counter in case we want to determine sequence errors uint8_t magic_counter; // 1 byte // Magic Number for denoting the end of the packet diff --git a/src/occ_405/dcom/dcomMasterTx.c b/src/occ_405/dcom/dcomMasterTx.c index a65dc31..7ba80e3 100644 --- a/src/occ_405/dcom/dcomMasterTx.c +++ b/src/occ_405/dcom/dcomMasterTx.c @@ -183,6 +183,7 @@ uint32_t dcom_build_slv_inbox(void) G_dcom_slv_inbox_doorbell_tx.gpio[0] = G_apss_pwr_meas.gpio[0]; G_dcom_slv_inbox_doorbell_tx.gpio[1] = G_apss_pwr_meas.gpio[1]; G_dcom_slv_inbox_doorbell_tx.tod = G_apss_pwr_meas.tod; + G_dcom_slv_inbox_doorbell_tx.apss_recovery_in_progress = G_apss_recovery_requested; G_dcom_slv_inbox_doorbell_tx.magic_counter++; G_dcom_slv_inbox_doorbell_tx.magic2 = PBAX_MAGIC_NUMBER_32B; @@ -245,7 +246,9 @@ void task_dcom_tx_slv_inbox( task_t *i_self) { // If we are in standby or no APSS present, we need to fake out // the APSS data since we aren't talking to APSS. - if( (OCC_STATE_STANDBY == CURRENT_STATE()) || (G_pwr_reading_type != PWR_READING_TYPE_APSS) ) + if( (OCC_STATE_STANDBY == CURRENT_STATE()) || + (G_pwr_reading_type != PWR_READING_TYPE_APSS) || + G_apss_recovery_requested ) { G_ApssPwrMeasCompleted = TRUE; } diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h index 6eb66a4..f357c88 100644 --- a/src/occ_405/occ_service_codes.h +++ b/src/occ_405/occ_service_codes.h @@ -199,6 +199,7 @@ enum occExtReasonCode ERC_APSS_ADC_OUT_OF_RANGE_FAILURE = 0x0026, ERC_APSS_ADC_DUPLICATED_FAILURE = 0x0027, ERC_APSS_NO_VALID_DATA = 0x0028, + ERC_APSS_RESET_FAILURE = 0x0029, ERC_AMEC_PCAPS_MISMATCH_FAILURE = 0x002A, ERC_AMEC_UNDER_PCAP_FAILURE = 0x002B, diff --git a/src/occ_405/pss/apss.c b/src/occ_405/pss/apss.c index 6e50313..6c68a74 100755 --- a/src/occ_405/pss/apss.c +++ b/src/occ_405/pss/apss.c @@ -59,18 +59,23 @@ uint64_t G_gpe_apss_time_start; uint64_t G_gpe_apss_time_end; // Flag for requesting APSS recovery when OCC detects all zeroes or data out of sync -bool G_apss_recovery_requested = FALSE; +volatile bool G_apss_recovery_requested = FALSE; bool G_apss_data_traced = FALSE; GPE_BUFFER(apss_start_args_t G_gpe_start_pwr_meas_read_args); GPE_BUFFER(apss_continue_args_t G_gpe_continue_pwr_meas_read_args); GPE_BUFFER(apss_complete_args_t G_gpe_complete_pwr_meas_read_args); +GPE_BUFFER(apss_reset_args_t G_gpe_apss_reset_args); GpeRequest G_meas_start_request; GpeRequest G_meas_cont_request; GpeRequest G_meas_complete_request; +GpeRequest G_init_gpio_request; +GpeRequest G_init_mode_request; +GpeRequest G_apss_reset_request; // Up / down counter for redundant apss failures uint32_t G_backup_fail_count = 0; +uint32_t G_apss_reset_count = 0; #ifdef DEBUG_APSS_SEQ uint32_t G_sequence_start = 0; @@ -144,9 +149,11 @@ void dumpHexString(const void *i_data, const unsigned int len, const char *strin // End Function Specification void do_apss_recovery(void) { + errlHndl_t l_err = NULL; + if (!G_apss_data_traced) { - INTR_TRAC_ERR("detected invalid power data[%08x%08x]", + INTR_TRAC_ERR("detected invalid power data[%08x%08x]. Requesting APSS reset.", (uint32_t)(G_gpe_continue_pwr_meas_read_args.meas_data[0] >> 32), (uint32_t)(G_gpe_continue_pwr_meas_read_args.meas_data[0] & 0x00000000ffffffffull)); G_apss_data_traced = TRUE; @@ -160,6 +167,12 @@ void do_apss_recovery(void) { // Increment the up/down counter G_backup_fail_count++; + + rtl_stop_task(TASK_ID_APSS_START); + rtl_stop_task(TASK_ID_APSS_CONT); + rtl_stop_task(TASK_ID_APSS_DONE); + + rtl_start_task(TASK_ID_APSS_RESET); } else { @@ -179,14 +192,14 @@ void do_apss_recovery(void) * @userdata4 OCC_NO_EXTENDED_RC * @devdesc Redundant APSS failure. Power Management Redundancy Lost. */ - errlHndl_t l_err = createErrl(PSS_MID_DO_APSS_RECOVERY, - REDUNDANT_APSS_GPE_FAILURE, - OCC_NO_EXTENDED_RC, - ERRL_SEV_PREDICTIVE, - NULL, - DEFAULT_TRACE_SIZE, - 0, - 0); + l_err = createErrl(PSS_MID_DO_APSS_RECOVERY, + REDUNDANT_APSS_GPE_FAILURE, + OCC_NO_EXTENDED_RC, + ERRL_SEV_PREDICTIVE, + NULL, + DEFAULT_TRACE_SIZE, + 0, + 0); // APSS callout addCalloutToErrl(l_err, @@ -212,6 +225,45 @@ void do_apss_recovery(void) commitErrl(&l_err); } } + else + { + rtl_stop_task(TASK_ID_APSS_START); + rtl_stop_task(TASK_ID_APSS_CONT); + rtl_stop_task(TASK_ID_APSS_DONE); + + if(G_apss_reset_count < APSS_MAX_NUM_RESET_RETRIES) + { + ++G_apss_reset_count; + rtl_start_task(TASK_ID_APSS_RESET); + } + else + { + /* + * @errortype + * @moduleid PSS_MID_DO_APSS_RECOVERY + * @reasoncode APSS_HARD_FAILURE + * @userdata1 0 + * @userdata2 0 + * @userdata4 ERC_APSS_RESET_FAILURE + * @devdesc apss reset failed 3 times + */ + l_err = createErrl(PSS_MID_DO_APSS_RECOVERY, + APSS_HARD_FAILURE, + ERC_APSS_RESET_FAILURE, + ERRL_SEV_UNRECOVERABLE, + NULL, + DEFAULT_TRACE_SIZE, + 0, + 0); + + addCalloutToErrl(l_err, + ERRL_CALLOUT_TYPE_HUID, + G_sysConfigData.apss_huid, + ERRL_CALLOUT_PRIORITY_HIGH); + + REQUEST_RESET(l_err); + } + } } // Note: The complete request must be global, since it must stick around until after the @@ -412,7 +464,7 @@ void task_apss_continue_pwr_meas(struct task *i_self) break; } - //Don't run anything if apss recovery is in progress + // Don't run anything if apps recovery has been requested if(G_apss_recovery_requested) { break; @@ -551,6 +603,12 @@ void task_apss_continue_pwr_meas(struct task *i_self) // End Function Specification #define APSS_ADC_SEQ_MASK 0xf000f000f000f000ull #define APSS_ADC_SEQ_CHECK 0x0000100020003000ull + +#ifdef DEBUG_APSS_RESET +// Make var in cacheless section +GPE_BUFFER(volatile int g_force_apss_reset) = 0; +#endif + void reformat_meas_data() { // NO TRACING ALLOWED IN CRITICAL INTERRUPT (any IPC callback functions) @@ -566,7 +624,11 @@ void reformat_meas_data() } // Check that the first 4 sequence nibbles are 0, 1, 2, 3 in the ADC data - if (((G_gpe_continue_pwr_meas_read_args.meas_data[0] & APSS_ADC_SEQ_MASK) != APSS_ADC_SEQ_CHECK) || + if( +#ifdef DEBUG_APSS_RESET + g_force_apss_reset || +#endif + ((G_gpe_continue_pwr_meas_read_args.meas_data[0] & APSS_ADC_SEQ_MASK) != APSS_ADC_SEQ_CHECK) || !(G_gpe_continue_pwr_meas_read_args.meas_data[0] & ~APSS_ADC_SEQ_MASK)) { // Recovery will begin on the next tick @@ -574,6 +636,9 @@ void reformat_meas_data() // Indicate that collection completed but is invalid so tx_slv_inbox will stop waiting for valid data G_ApssPwrMeasDoneInvalid = TRUE; G_apss_recovery_requested = TRUE; +#ifdef DEBUG_APSS_RESET + g_force_apss_reset = 0; +#endif break; } else @@ -649,12 +714,11 @@ void task_apss_complete_pwr_meas(struct task *i_self) } if(G_apss_recovery_requested) { - // Allow apss measurement to proceed on next tick - G_apss_recovery_requested = FALSE; + // Just in case it's possible to get here after G_apss_recovery_requested is true, + // but before apss reset starts break; } - if (L_scheduled) { if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_complete_request.request.completion_state) || @@ -831,7 +895,6 @@ bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value) errlHndl_t initialize_apss(void) { errlHndl_t l_err = NULL; - GpeRequest l_request; //Used once here to initialize apss. uint8_t l_retryCount = 0; // Initialize APSS @@ -855,7 +918,7 @@ errlHndl_t initialize_apss(void) // Create/schedule IPC_ST_APSS_INIT_GPIO_FUNCID and wait for it to complete (BLOCKING) TRAC_INFO("initialize_apss: Creating request for GPE_apss_initialize_gpio"); - gpe_request_create(&l_request, // request + gpe_request_create(&G_init_gpio_request, // request &G_async_gpe_queue0, // queue IPC_ST_APSS_INIT_GPIO_FUNCID, // Function ID &G_gpe_apss_initialize_gpio_args, // GPE argument_ptr @@ -866,10 +929,10 @@ errlHndl_t initialize_apss(void) // Schedule the request to be executed TRAC_INFO("initialize_apss: Scheduling request for IPC_ST_APSS_INIT_GPIO_FUNCID"); - gpe_request_schedule(&l_request); + gpe_request_schedule(&G_init_gpio_request); // Check for a timeout only; will create the error below. - if(ASYNC_REQUEST_STATE_TIMED_OUT == l_request.request.completion_state) + if(ASYNC_REQUEST_STATE_TIMED_OUT == G_init_gpio_request.request.completion_state) { // For whatever reason, we hit a timeout. It could be either // that the HW did not work, or the request didn't ever make @@ -881,10 +944,10 @@ errlHndl_t initialize_apss(void) TRAC_INFO("initialize_apss: GPE_apss_initialize_gpio completed w/rc=0x%08x", - l_request.request.completion_state); + G_init_gpio_request.request.completion_state); // Only continue if initializaton completed without any errors. - if ((ASYNC_REQUEST_STATE_COMPLETE == l_request.request.completion_state) && + if ((ASYNC_REQUEST_STATE_COMPLETE == G_init_gpio_request.request.completion_state) && (G_gpe_apss_initialize_gpio_args.error.rc == ERRL_RC_SUCCESS)) { // Setup the mode structure to pass to the GPE program @@ -899,7 +962,7 @@ errlHndl_t initialize_apss(void) // Create/schedule GPE_apss_set_mode and wait for it to complete (BLOCKING) TRAC_INFO("initialize_apss: Creating request for GPE_apss_set_mode"); - gpe_request_create(&l_request, // request + gpe_request_create(&G_init_mode_request, // request &G_async_gpe_queue0, // queue IPC_ST_APSS_INIT_MODE_FUNCID, // Function ID &G_gpe_apss_set_mode_args, // GPE argument_ptr @@ -908,10 +971,10 @@ errlHndl_t initialize_apss(void) NULL, // callback arg ASYNC_REQUEST_BLOCKING); // options //Schedule set_mode - gpe_request_schedule(&l_request); + gpe_request_schedule(&G_init_mode_request); // Check for a timeout, will create the error log later - if(ASYNC_REQUEST_STATE_TIMED_OUT == l_request.request.completion_state) + if(ASYNC_REQUEST_STATE_TIMED_OUT == G_init_mode_request.request.completion_state) { // For whatever reason, we hit a timeout. It could be either // that the HW did not work, or the request didn't ever make @@ -922,10 +985,10 @@ errlHndl_t initialize_apss(void) } TRAC_INFO("initialize_apss: GPE_apss_set_mode completed w/rc=0x%08x", - l_request.request.completion_state); + G_init_mode_request.request.completion_state); //Continue only if mode set was successful. - if ((ASYNC_REQUEST_STATE_COMPLETE != l_request.request.completion_state) || + if ((ASYNC_REQUEST_STATE_COMPLETE != G_init_mode_request.request.completion_state) || (G_gpe_apss_set_mode_args.error.rc != ERRL_RC_SUCCESS)) { /* @@ -944,8 +1007,8 @@ errlHndl_t initialize_apss(void) ERRL_SEV_UNRECOVERABLE, // i_severity NULL, // i_trace, 0x0000, // i_traceSz, - l_request.request.completion_state, // i_userData1, - l_request.request.abort_state); // i_userData2 + G_init_mode_request.request.completion_state, // i_userData1, + G_init_mode_request.request.abort_state); // i_userData2 addUsrDtlsToErrl(l_err, (uint8_t*)&G_gpe_apss_set_mode_args, sizeof(G_gpe_apss_set_mode_args), @@ -973,8 +1036,8 @@ errlHndl_t initialize_apss(void) ERRL_SEV_UNRECOVERABLE, // i_severity NULL, // tracDesc_t i_trace, 0x0000, // i_traceSz, - l_request.request.completion_state, // i_userData1, - l_request.request.abort_state); // i_userData2 + G_init_gpio_request.request.completion_state, // i_userData1, + G_init_gpio_request.request.abort_state); // i_userData2 addUsrDtlsToErrl(l_err, (uint8_t*)&G_gpe_apss_initialize_gpio_args, @@ -1021,6 +1084,36 @@ errlHndl_t initialize_apss(void) NULL, // callback arg ASYNC_CALLBACK_IMMEDIATE); // options + // Active state versions of initialization requests + TRAC_INFO("initialize_apss: Creating request G_init_gpio_request for active state."); + gpe_request_create(&G_init_gpio_request, // request + &G_async_gpe_queue0, // queue + IPC_ST_APSS_INIT_GPIO_FUNCID, // Function ID + &G_gpe_apss_initialize_gpio_args, // GPE argument_ptr + SSX_WAIT_FOREVER, // timeout + NULL, // callback + NULL, // callback arg + ASYNC_CALLBACK_IMMEDIATE); // options + + TRAC_INFO("initialize_apss: Creating request G_init_mode_request for active state."); + gpe_request_create(&G_init_mode_request, // request + &G_async_gpe_queue0, // queue + IPC_ST_APSS_INIT_MODE_FUNCID, // Function ID + &G_gpe_apss_set_mode_args, // GPE argument_ptr + SSX_WAIT_FOREVER, // timeout + NULL, // callback + NULL, // callback arg + ASYNC_CALLBACK_IMMEDIATE); // options + + TRAC_INFO("initialize_apss: Creating request G_reset_request."); + gpe_request_create(&G_apss_reset_request, // request + &G_async_gpe_queue0, // queue + IPC_ST_APSS_RESET_FUNCID, // Function ID + &G_gpe_apss_reset_args, // GPE argument_ptr + SSX_WAIT_FOREVER, // timeout + NULL, // callback + NULL, // callback arg + ASYNC_CALLBACK_IMMEDIATE); // options // Successfully initialized APSS, no need to go through again. Let's leave. break; } @@ -1042,3 +1135,276 @@ errlHndl_t initialize_apss(void) return l_err; } + +void task_apss_reset(task_t *i_self) +{ + int schedule_rc = 0; + static int L_apss_reset_state = APSS_RESET_STATE_START; + + static bool L_scheduled_reset = FALSE; + static bool L_scheduled_init_gpio = FALSE; + static bool L_scheduled_init_mode = FALSE; + + static bool L_reset_ffdc_collected = FALSE; + static bool L_init_gpio_ffdc_collected = FALSE; + static bool L_init_mode_ffdc_collected = FALSE; + + APSS_DBG("Calling task_apss_reset. State %d",L_apss_reset_state); + + do + { + if(L_scheduled_reset) + { + if (!async_request_is_idle(&G_apss_reset_request.request)) + { + INTR_TRAC_INFO("E>task_apss_reset: gpe apss reset request " + "is not idle."); + break; + } + + if((ASYNC_REQUEST_STATE_COMPLETE != + G_apss_reset_request.request.completion_state) || + (0 != G_gpe_apss_reset_args.error.error)) + { + INTR_TRAC_ERR("task_apss_reset: reset request failed with " + "rc:0x%08x, ffdc:0x%08X%08X. " + "CompletionState:0x%X.", + G_gpe_apss_reset_args.error.rc, + (uint32_t) (G_gpe_apss_reset_args.error.ffdc >> 32), + (uint32_t) G_gpe_apss_reset_args.error.ffdc, + G_apss_reset_request.request.completion_state); + if(!L_reset_ffdc_collected) + { + errlHndl_t err = NULL; + + /* + * @errortype + * @moduleid PSS_MID_APSS_RESET + * @reasoncode APSS_GPE_FAILURE + * @userdata1 GPE return code + * @userdata2 0 + * @userdata4 ERC_APSS_RESET_FAILURE + * @devdesc Failed to reset apss + */ + err = createErrl(PSS_MID_APSS_RESET, // moduleId + APSS_GPE_FAILURE, //reasonCode + ERC_APSS_RESET_FAILURE, + ERRL_SEV_INFORMATIONAL, + NULL, + DEFAULT_TRACE_SIZE, + G_gpe_apss_reset_args.error.rc, + 0); + addUsrDtlsToErrl(err, + (uint8_t*)&G_apss_reset_request.ffdc, + sizeof(G_apss_reset_request.ffdc), + ERRL_STRUCT_VERSION_1, + ERRL_USR_DTL_BINARY_DATA); + commitErrl(&err); + + L_reset_ffdc_collected = TRUE; + } + } + } + + if(L_scheduled_init_gpio) + { + if (!async_request_is_idle(&G_init_gpio_request.request)) + { + INTR_TRAC_INFO("E>task_apss_reset: gpe apss init gpio request " + "is not idle."); + break; + } + + if((ASYNC_REQUEST_STATE_COMPLETE != + G_init_gpio_request.request.completion_state) || + (0 != G_gpe_apss_initialize_gpio_args.error.error)) + { + INTR_TRAC_ERR("task_apss_reset: reset request failed with " + "rc:0x%08x, ffdc:0x%08X%08X. " + "CompletionState:0x%X.", + G_gpe_apss_initialize_gpio_args.error.rc, + (uint32_t) (G_gpe_apss_initialize_gpio_args.error.ffdc >> 32), + (uint32_t) G_gpe_apss_initialize_gpio_args.error.ffdc, + G_init_gpio_request.request.completion_state); + + if(!L_init_gpio_ffdc_collected) + { + errlHndl_t err = NULL; + + /* + * @errortype + * @moduleid PSS_MID_APSS_RESET + * @reasoncode APSS_GPE_FAILURE + * @userdata1 GPE return code + * @userdata2 0 + * @userdata4 ERC_PSS_GPIO_INIT_FAIL + * @devdesc Failed to reset apss + */ + err = createErrl(PSS_MID_APSS_RESET, // moduleId + APSS_GPE_FAILURE, //reasonCode + ERC_PSS_GPIO_INIT_FAIL, + ERRL_SEV_INFORMATIONAL, + NULL, + DEFAULT_TRACE_SIZE, + G_gpe_apss_initialize_gpio_args.error.rc, + 0); + addUsrDtlsToErrl(err, + (uint8_t*)&G_init_gpio_request.ffdc, + sizeof(G_init_gpio_request.ffdc), + ERRL_STRUCT_VERSION_1, + ERRL_USR_DTL_BINARY_DATA); + commitErrl(&err); + + L_init_gpio_ffdc_collected = TRUE; + } + } + } + + if(L_scheduled_init_mode) + { + if (!async_request_is_idle(&G_init_mode_request.request)) + { + INTR_TRAC_INFO("E>task_apss_reset: gpe apss init mode request " + "is not idle."); + break; + } + + if((ASYNC_REQUEST_STATE_COMPLETE != + G_init_mode_request.request.completion_state) || + (0 != G_gpe_apss_set_mode_args.error.error)) + { + INTR_TRAC_ERR("task_apss_reset: reset request failed with " + "rc:0x%08x, ffdc:0x%08X%08X. " + "CompletionState:0x%X.", + G_gpe_apss_set_mode_args.error.rc, + (uint32_t) (G_gpe_apss_set_mode_args.error.ffdc >> 32), + (uint32_t) G_gpe_apss_set_mode_args.error.ffdc, + G_init_mode_request.request.completion_state); + + if(!L_init_mode_ffdc_collected) + { + errlHndl_t err = NULL; + + /* + * @errortype + * @moduleid PSS_MID_APSS_RESET + * @reasoncode APSS_GPE_FAILURE + * @userdata1 GPE return code + * @userdata2 0 + * @userdata4 ERC_PSS_COMPOSITE_MODE_FAIL + * @devdesc Failed to reset apss + */ + err = createErrl(PSS_MID_APSS_RESET, // moduleId + APSS_GPE_FAILURE, //reasonCode + ERC_PSS_COMPOSITE_MODE_FAIL, + ERRL_SEV_INFORMATIONAL, + NULL, + DEFAULT_TRACE_SIZE, + G_gpe_apss_set_mode_args.error.rc, + 0); + addUsrDtlsToErrl(err, + (uint8_t*)&G_init_mode_request.ffdc, + sizeof(G_init_mode_request.ffdc), + ERRL_STRUCT_VERSION_1, + ERRL_USR_DTL_BINARY_DATA); + commitErrl(&err); + + L_init_mode_ffdc_collected = TRUE; + } + } + } + + switch (L_apss_reset_state) + { + case APSS_RESET_STATE_START: + case APSS_RESET_STATE_WAIT_1MS: + // TOGGLE apss reset GPIO pin + schedule_rc = gpe_request_schedule(&G_apss_reset_request); + L_scheduled_reset = TRUE; + break; + + case APSS_RESET_STATE_WAIT_DONE: + + G_gpe_apss_initialize_gpio_args.error.error = 0; + G_gpe_apss_initialize_gpio_args.error.ffdc = 0; + + schedule_rc = gpe_request_schedule(&G_init_gpio_request); + + L_scheduled_reset = FALSE; + L_scheduled_init_gpio = TRUE; + break; + + case APSS_RESET_STATE_REINIT: + + G_gpe_apss_set_mode_args.error.error = 0; + G_gpe_apss_set_mode_args.error.ffdc = 0; + + schedule_rc = gpe_request_schedule(&G_init_mode_request); + + L_scheduled_init_gpio = FALSE; + L_scheduled_init_mode = TRUE; + break; + + case APSS_RESET_STATE_COMPLETE: + L_apss_reset_state = -1; + L_scheduled_init_mode = FALSE; + + // Disable this task + rtl_stop_task(TASK_ID_APSS_RESET); + + // Resuming your regulary scheduled programs. + rtl_start_task(TASK_ID_APSS_START); + rtl_start_task(TASK_ID_APSS_CONT); + rtl_start_task(TASK_ID_APSS_DONE); + + G_apss_recovery_requested = FALSE; + G_apss_data_traced = FALSE; + + break; + + default: + break; + } + + if(schedule_rc) + { + errlHndl_t err = NULL; + + INTR_TRAC_ERR("task_apss_reset: schedule failed w/rc=0x%08X (%d us)", schedule_rc, + (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000))); + + /* + * @errortype + * @moduleid PSS_MID_APSS_RESET + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 GPE shedule returned rc code + * @userdata2 APSS reset state + * @userdata4 ERC_APSS_SCHEDULE_FAILURE + * @devdesc task_apss_start_pwr_meas schedule failed + */ + err = createErrl(PSS_MID_APSS_RESET, + SSX_GENERIC_FAILURE, + ERC_APSS_SCHEDULE_FAILURE, + ERRL_SEV_PREDICTIVE, + NULL, + DEFAULT_TRACE_SIZE, + schedule_rc, + L_apss_reset_state); + + // Request reset since this should never happen. + REQUEST_RESET(err); + + L_scheduled_reset = FALSE; + L_scheduled_init_gpio = FALSE; + L_scheduled_init_mode = FALSE; + break; + } + + ++L_apss_reset_state; + + } + while(0); + + APSS_DBG("task_apss_reset finished w/rc=0x%08X\n", rc); +} + diff --git a/src/occ_405/pss/apss.h b/src/occ_405/pss/apss.h index ba0b775..0bd45ac 100644 --- a/src/occ_405/pss/apss.h +++ b/src/occ_405/pss/apss.h @@ -43,11 +43,12 @@ void dumpHexString(const void *i_data, const unsigned int len, const char *string); #endif -#define APSS_DATA_FAIL_PMAX_RAIL 16 //Number of steps before we lower Pmax_rail to nominal. This should allow for 4ms/16ticks with no APSS data. -#define APSS_DATA_FAIL_MAX 400 //Number of steps we reach before reseting OCC. This should allow for 100ms/400ticks with no APSS data. +#define APSS_DATA_FAIL_PMAX_RAIL 100 //Number of steps before we lower Pmax_rail to nominal. This should allow for 50ms/100 ticks with no APSS data. +#define APSS_DATA_FAIL_MAX 200 //Number of steps we reach before reseting OCC. This should allow for 100ms/200ticks with no APSS data. #define APSS_DATA_FAILURE_STEP 1 //Number of steps to increment FAIL_COUNT due to a failed APSS data collection. #define APSS_ERRORLOG_RESET_THRESHOLD 16 //When to allow apss tasks to log another error if count goes back to 0 again. #define APSS_MAX_NUM_INIT_RETRIES 2 +#define APSS_MAX_NUM_RESET_RETRIES 3 extern uint16_t G_apss_fail_updown_count; //Used to keep count of number of APSS data collection fails. //Decrement APSS_FAIL_COUNT to 0. @@ -58,6 +59,13 @@ extern uint16_t G_apss_fail_updown_count; //Used to keep count of number of (G_apss_fail_updown_count += APSS_DATA_FAILURE_STEP): \ (G_apss_fail_updown_count = APSS_DATA_FAIL_MAX);} +// Apss reset task is run every other tic (1 ms) +#define APSS_RESET_STATE_START 0 +#define APSS_RESET_STATE_WAIT_1MS 1 +#define APSS_RESET_STATE_WAIT_DONE 51 // Wait 50 ms +#define APSS_RESET_STATE_REINIT 52 +#define APSS_RESET_STATE_COMPLETE 53 + struct apssPwrMeasStruct { uint16_t adc[MAX_APSS_ADC_CHANNELS]; @@ -86,10 +94,12 @@ extern uint64_t G_gpe_apss_time_end; void task_apss_start_pwr_meas(task_t *i_self); void task_apss_continue_pwr_meas(task_t *i_self); void task_apss_complete_pwr_meas(task_t *i_self); +void task_apss_reset(task_t *i_self); void apss_test_pwr_meas(); // used to test measurements void reformat_meas_data(); bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value); errlHndl_t initialize_apss(void); +extern volatile bool G_apss_recovery_requested; #endif //_APSS_H diff --git a/src/occ_405/pss/pss_service_codes.h b/src/occ_405/pss/pss_service_codes.h index 5a7fe85..eadf141 100755 --- a/src/occ_405/pss/pss_service_codes.h +++ b/src/occ_405/pss/pss_service_codes.h @@ -39,6 +39,7 @@ enum pssModuleId PSS_MID_DPSS_RD_STATUS = PSS_COMP_ID | 0x06, PSS_MID_DO_APSS_RECOVERY = PSS_COMP_ID | 0x07, PSS_MID_AVSBUS_READ = PSS_COMP_ID | 0x08, + PSS_MID_APSS_RESET = PSS_COMP_ID | 0x09, }; #endif /* #ifndef _PSS_SERVICE_CODES_H_ */ diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h index 973bab4..1d01b11 100755 --- a/src/occ_405/rtls/rtls.h +++ b/src/occ_405/rtls/rtls.h @@ -63,6 +63,7 @@ typedef enum { TASK_ID_24X7, // 24x7 data collection task TASK_ID_GPE_TIMINGS, TASK_ID_GET_TOD, // Get time of day task + TASK_ID_APSS_RESET, // (HW) reset APSS TASK_END // This must always be the last enum in this list, // so that TASK_END always equals the last task ID + 1. } task_id_t; diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c index c23e1ea..9d1f18e 100755 --- a/src/occ_405/rtls/rtls_tables.c +++ b/src/occ_405/rtls/rtls_tables.c @@ -72,6 +72,7 @@ #define FLAGS_APSS_START_MEAS APSS_TASK_FLAGS #define FLAGS_APSS_CONT_MEAS APSS_TASK_FLAGS #define FLAGS_APSS_DONE_MEAS APSS_TASK_FLAGS +#define FLAGS_APSS_RESET RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY #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_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 @@ -127,9 +128,11 @@ task_t G_task_table[TASK_END] = { { FLAGS_24X7, task_24x7, NULL }, // TASK_ID_24X7 { FLAGS_GPE_TIMINGS, task_gpe_timings, NULL }, // TASK_ID_GPE_TIMINGS { FLAGS_GET_TOD, task_get_tod, NULL }, // TASK_ID_GET_TOD + { FLAGS_APSS_RESET, task_apss_reset, NULL }, // TASK_APSS_RESET }; const uint8_t G_tick0_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, @@ -176,6 +179,7 @@ const uint8_t G_tick1_seq[] = { TASK_END }; const uint8_t G_tick2_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, @@ -222,6 +226,7 @@ const uint8_t G_tick3_seq[] = { TASK_END }; const uint8_t G_tick4_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, @@ -268,6 +273,7 @@ const uint8_t G_tick5_seq[] = { TASK_END }; const uint8_t G_tick6_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, @@ -313,6 +319,7 @@ const uint8_t G_tick7_seq[] = { TASK_END }; const uint8_t G_tick8_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, @@ -359,6 +366,7 @@ const uint8_t G_tick9_seq[] = { TASK_END }; const uint8_t G_tick10_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, @@ -404,6 +412,7 @@ const uint8_t G_tick11_seq[] = { TASK_END }; const uint8_t G_tick12_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, @@ -450,6 +459,7 @@ const uint8_t G_tick13_seq[] = { TASK_END }; const uint8_t G_tick14_seq[] = { + TASK_ID_APSS_RESET, TASK_ID_APSS_START, TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, diff --git a/src/occ_gpe0/apss_init.c b/src/occ_gpe0/apss_init.c index 702393a..efb3f8d 100644 --- a/src/occ_gpe0/apss_init.c +++ b/src/occ_gpe0/apss_init.c @@ -29,6 +29,11 @@ #include "pss_constants.h" #include //H file common with occ_405 #include "gpe_util.h" +#include "p9_misc_scom_addresses.h" + +// PV_CP0_P_PRV_GPIO2 +#define APSS_RESET_GPIO (0x2000000000000000ull) + // Default to Auto-2 for now, should get set when the mode // is initialized, and before any APSS data is gathered. @@ -201,6 +206,45 @@ void apss_init_gpio(ipc_msg_t* cmd, void* arg) break; } }//End of port while loop. + if (rc) + { + break; + } + + // Enable GPIO that's used for APSS resets + // + // Set APSS_RESET_GPIO output high before enabling it's output + + regValue = APSS_RESET_GPIO; + rc = putscom_abs(PU_GPIO_OUTPUT_OR, regValue); + if(rc) + { + PK_TRACE("apss_init: APSS_RESET_GPIO_OUTPUT low failed. rc:0x%08x",rc); + gpe_set_ffdc(&(args->error), 0, GPE_RC_SCOM_PUT_FAILED, rc); + break; + } + + // Read output enable pins. + rc = getscom_abs(PU_GPIO_OUTPUT_EN, ®Value); + if(rc) + { + PK_TRACE("apss_init: Read APSS_RESET_GPIO_OUTPUT_EN failed. rc:0x%08x",rc); + gpe_set_ffdc(&(args->error), 0, GPE_RC_SCOM_GET_FAILED, rc); + break; + } + + // Enable APSS_RESET_GPIO as output + regValue |= APSS_RESET_GPIO; + + rc = putscom_abs(PU_GPIO_OUTPUT_EN, regValue); + if(rc) + { + PK_TRACE("apss_init: APSS_RESET_GPIO_OUTPUT_EN failed. rc:0x%08x",rc); + gpe_set_ffdc(&(args->error), 0, GPE_RC_SCOM_PUT_FAILED, rc); + break; + } + + }while(0); // send back a successful response. OCC will check rc and ffdc @@ -353,3 +397,48 @@ void apss_init_mode(ipc_msg_t* cmd, void* arg) PK_TRACE("apss_init_mode: completed successfully."); } } + + +// ---------------------------------------------------- +// Toggle the output of the APSS RESET pin +// ---------------------------------------------------- +void apss_toggle_hw_reset(ipc_msg_t* cmd, void* arg) +{ + static int g_apss_reset_state = ~(0); + + int rc = 0; + uint32_t apss_reset_address; + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + initGpioArgs_t *args = (initGpioArgs_t*)async_cmd->cmd_data; + + if(g_apss_reset_state) // not in reset + { + apss_reset_address = PU_GPIO_OUTPUT_CLR; + } + else + { + apss_reset_address = PU_GPIO_OUTPUT_OR; + } + g_apss_reset_state = ~g_apss_reset_state; + PK_TRACE("apss_toggle_apss_hw_reset: %d",(uint16_t)g_apss_reset_state); + + + // Set/clear GPIO2 output + rc = putscom_abs(apss_reset_address, APSS_RESET_GPIO); + if(rc) + { + PK_TRACE("apss_toggle_hw_reset: APSS_RESET_GPIO_OUTPUT toggle failed. rc:0x%08x",rc); + gpe_set_ffdc(&(args->error), 0, GPE_RC_SCOM_PUT_FAILED, rc); + } + + // send back a successful response. OCC will check rc and ffdc + rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS); + + if(rc) + { + PK_TRACE("apss_toggle_hw_reset: Failed to send response back. rc = 0x%08x. Halting GPE0", + rc); + gpe_set_ffdc(&(args->error), 0x00, rc, 0); + pk_halt(); + } +} diff --git a/src/occ_gpe0/ipc_func_tables.c b/src/occ_gpe0/ipc_func_tables.c index 14166df..110f9fa 100644 --- a/src/occ_gpe0/ipc_func_tables.c +++ b/src/occ_gpe0/ipc_func_tables.c @@ -32,6 +32,7 @@ void apss_init_mode(ipc_msg_t* cmd, void* arg); void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg); void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg); void apss_complete_pwr_meas_read(ipc_msg_t* cmd, void* arg); +void apss_toggle_hw_reset(ipc_msg_t* cmd, void* arg); void gpe_get_core_data(ipc_msg_t* cmd, void* arg); void gpe_get_nest_dts(ipc_msg_t* cmd, void* arg); void gpe_get_tod(ipc_msg_t* cmd, void* arg); @@ -75,7 +76,7 @@ IPC_HANDLER(gpe0_nop, 0) // 8 - IPC_ST_GPE0_NOP IPC_HANDLER(gpe_get_nest_dts, 0) // 9 - IPC_ST_GET_NEST_DTS_FUNCID IPC_HANDLER(ipc_fir_collection, 0) // 10 - IPC_ST_FIR_COLLECTION IPC_HANDLER(gpe_get_tod, 0) // 11 - IPC_ST_GET_TOD_FUNCID -IPC_HANDLER_DEFAULT // 12 +IPC_HANDLER(apss_toggle_hw_reset, 0) // 12 - IPC_ST_APSS_RESET_FUNCID IPC_HANDLER_DEFAULT // 13 IPC_HANDLER_DEFAULT // 14 IPC_HANDLER_DEFAULT // 15 diff --git a/src/occ_gpe1/gpe_gpu_init.c b/src/occ_gpe1/gpe_gpu_init.c index a293905..d7dc29b 100644 --- a/src/occ_gpe1/gpe_gpu_init.c +++ b/src/occ_gpe1/gpe_gpu_init.c @@ -39,7 +39,7 @@ void gpe_gpu_init(ipc_msg_t* cmd, void* arg) gpe_set_ffdc(&(args->error), 0, GPE_RC_GPU_INIT_FAILED, rc); } - // pin0 as output, pin1 as input, pin3 unchanged + // pin0 as output, pin1 as input, pin2 unchanged data64 &= 0xBfffffffffffffffull; data64 |= 0x8000000000000000ull; -- cgit v1.2.1