summaryrefslogtreecommitdiffstats
path: root/src/occ_405/pss
diff options
context:
space:
mode:
authorWilliam Bryan <wilbryan@us.ibm.com>2015-08-03 12:38:58 -0500
committerWilliam A. Bryan <wilbryan@us.ibm.com>2015-08-03 15:32:27 -0500
commit420e6d248cc6d2b3c39bc3970e3bb6747b3bddc3 (patch)
treec9f6691eddba39193e39aa769367e1267fb9fc86 /src/occ_405/pss
parentadade8c8ef30ed519322674c762d95663009c5d4 (diff)
downloadtalos-occ-420e6d248cc6d2b3c39bc3970e3bb6747b3bddc3.tar.gz
talos-occ-420e6d248cc6d2b3c39bc3970e3bb6747b3bddc3.zip
new ssx and lib files
Change-Id: I2328b1e86d59e3788910687d762fb70ec680058f Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/19503 Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Tested-by: William A. Bryan <wilbryan@us.ibm.com>
Diffstat (limited to 'src/occ_405/pss')
-rwxr-xr-xsrc/occ_405/pss/apss.c838
-rw-r--r--src/occ_405/pss/apss.h138
-rwxr-xr-xsrc/occ_405/pss/dpss.c189
-rwxr-xr-xsrc/occ_405/pss/dpss.h40
-rwxr-xr-xsrc/occ_405/pss/pss_service_codes.h43
-rwxr-xr-xsrc/occ_405/pss/test/Makefile79
-rwxr-xr-xsrc/occ_405/pss/test/app.mk102
-rwxr-xr-xsrc/occ_405/pss/test/apsstest.c415
8 files changed, 1844 insertions, 0 deletions
diff --git a/src/occ_405/pss/apss.c b/src/occ_405/pss/apss.c
new file mode 100755
index 0000000..4c2cc59
--- /dev/null
+++ b/src/occ_405/pss/apss.c
@@ -0,0 +1,838 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pss/apss.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 */
+
+#include "ssx.h"
+
+#include <trac_interface.h>
+#include <apss.h>
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <pss_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <state.h>
+#include <occ_sys_config.h>
+#include <dcom.h>
+#include "pss_constants.h"
+
+// Threshold for calling out the redundant APSS
+#define MAX_BACKUP_FAILURES 8
+
+// Configure both GPIOs (directoin/drive/interrupts): All Input, All 1's, No Interrupts
+const apssGpioConfigStruct_t G_gpio_config[2] = { {0x00, 0xFF, 0x00}, {0x00, 0xFF, 0x00} };
+
+// Configure streaming of: 16 ADCs, 2 GPIOs
+const apssCompositeConfigStruct_t G_apss_composite_config = { 16, 2 };
+
+// Power Measurements (read from APSS every RealTime loop)
+apssPwrMeasStruct_t G_apss_pwr_meas = { {0} };
+
+GPE_BUFFER(initGpioArgs_t G_gpe_apss_initialize_gpio_args);
+GPE_BUFFER(setCompositeModeArgs_t G_gpe_apss_set_composite_mode_args);
+
+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;
+
+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);
+
+PoreEntryPoint GPE_apss_start_pwr_meas_read;
+PoreEntryPoint GPE_apss_continue_pwr_meas_read;
+PoreEntryPoint GPE_apss_complete_pwr_meas_read;
+
+// Up / down counter for redundant apss failures
+uint32_t G_backup_fail_count = 0;
+
+// Used to tell slave inbox that pwr meas is complete
+volatile bool G_ApssPwrMeasCompleted = FALSE;
+
+// Function Specification
+//
+// Name: dumpHexString
+//
+// Description: TODO Add description
+//
+// End Function Specification
+#if ( (!defined(NO_TRAC_STRINGS)) && defined(TRAC_TO_SIMICS) )
+
+// Utility function to dump hex data to screen
+void dumpHexString(const void *i_data, const unsigned int len, const char *string)
+{
+ unsigned int i, j;
+ char text[17];
+ uint8_t *data = (uint8_t*)i_data;
+ unsigned int l_len = len;
+
+ text[16] = '\0';
+ if (string != NULL)
+ {
+ printf("%s\n", string);
+ }
+
+ if (len > 0x0800) l_len = 0x800;
+ for(i = 0; i < l_len; i++)
+ {
+ if (i % 16 == 0)
+ {
+ if (i > 0) printf(" \"%s\"\n", text);
+ printf(" %04x:",i);
+ }
+ if (i % 4 == 0) printf(" ");
+
+ printf("%02x",(int)data[i]);
+ if (isprint(data[i])) text[i%16] = data[i];
+ else text[i%16] = '.';
+ }
+ if ((i%16) != 0) {
+ text[i%16] = '\0';
+ for(j = (i % 16); j < 16; ++j) {
+ printf(" ");
+ if (j % 4 == 0) printf(" ");
+ }
+ }
+ printf(" \"%s\"\n", text);
+ return;
+}
+#endif
+
+// Function Specification
+//
+// Name: do_apss_recovery
+//
+// Description: Collect FFDC and attempt recovery for APSS failures
+//
+// End Function Specification
+void do_apss_recovery(void)
+{
+#define PSS_START_COMMAND 0x8000000000000000ull
+#define PSS_RESET_COMMAND 0x4000000000000000ull
+ int l_scom_rc = 0;
+ uint32_t l_scom_addr;
+ uint64_t l_spi_adc_ctrl0;
+ uint64_t l_spi_adc_ctrl1;
+ uint64_t l_spi_adc_ctrl2;
+ uint64_t l_spi_adc_status;
+ uint64_t l_spi_adc_reset;
+ uint64_t l_spi_adc_wdata;
+
+
+ TRAC_ERR("detected invalid power data[%08x%08x]",
+ (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));
+
+ do
+ {
+ // Collect SPI ADC FFDC data
+ l_scom_addr = SPIPSS_ADC_RESET_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_reset, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG0;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl0, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG1;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl1, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG2;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl2, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_STATUS_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_status, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_WDATA_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_wdata, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ TRAC_ERR("70000[%08x] 70001[%08x] 70002[%08x] 70003|70005[%08x] 70010[%08x]",
+ (uint32_t)(l_spi_adc_ctrl0 >> 32),
+ (uint32_t)(l_spi_adc_ctrl1 >> 32),
+ (uint32_t)(l_spi_adc_ctrl2 >> 32),
+ (uint32_t)((l_spi_adc_status >> 32) | (l_spi_adc_reset >> 48)), // Stuff reset register in lower 16 bits
+ (uint32_t)(l_spi_adc_wdata >> 32));
+
+ // Special error handling on OCC backup. Keep an up/down counter of
+ // fail/success and log predictive error when we reach the limit.
+ if(G_occ_role == OCC_SLAVE)
+ {
+ if(G_backup_fail_count < MAX_BACKUP_FAILURES)
+ {
+ // Increment the up/down counter
+ G_backup_fail_count++;
+ }
+ else
+ {
+ //We're logging the error so stop running apss tasks
+ rtl_stop_task(TASK_ID_APSS_START);
+ rtl_stop_task(TASK_ID_APSS_CONT);
+ rtl_stop_task(TASK_ID_APSS_DONE);
+
+ TRAC_INFO("Redundant APSS has exceeded failure threshold. Logging Error");
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_DO_APSS_RECOVERY
+ * @reasoncode REDUNDANT_APSS_GPE_FAILURE
+ * @userdata1 0
+ * @userdata2 0
+ * @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);
+
+ // APSS callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ // Processor callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ // Backplane callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.backplane_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ // Firmware callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ commitErrl(&l_err);
+
+ break;
+ }
+ }
+
+ TRAC_INFO("Starting APSS recovery. fail_count=%d", G_backup_fail_count);
+
+ // Reset the ADC engine
+ l_scom_addr = SPIPSS_ADC_RESET_REG;
+ l_scom_rc = _putscom(l_scom_addr, PSS_RESET_COMMAND, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ // Zero out the reset register
+ l_scom_rc = _putscom(l_scom_addr, 0, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ // Attempt recovery by sending the apss
+ // command that was set up earlier by initialization GPE
+ l_scom_addr = SPIPSS_P2S_COMMAND_REG;
+ l_scom_rc = _putscom(l_scom_addr, PSS_START_COMMAND, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ }while(0);
+
+ // Just trace it if we get a scom failure trying to collect FFDC
+ if(l_scom_rc)
+ {
+ TRAC_ERR("apss recovery scom failure. addr=0x%08x, rc=0x%08x", l_scom_addr, l_scom_rc);
+ }
+}
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_start_request;
+// Function Specification
+//
+// Name: task_apss_start_pwr_meas
+//
+// Description: Start the GPE program to request power measurement data from APSS
+// If previous call had failed, commit the error and request reset
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// End Function Specification
+void task_apss_start_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_start_pwr_meas_read (non-blocking)
+ APSS_DBG("GPE_start_pwr_meas_read started\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_start_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_start_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ // Check if we need to try recovering the apss
+ if(G_apss_recovery_requested)
+ {
+ // Do recovery then wait until next tick to do anything more.
+ do_apss_recovery();
+ break;
+ }
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_start_request.request.completion_state) ||
+ (0 != G_gpe_start_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_start_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_start_pwr_meas_read_args.error.rc,
+ G_gpe_start_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_start_pwr_meas_read_args.error.ffdc,
+ G_meas_start_request.request.completion_state);
+
+ // Collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_START_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_START_MEAS, // i_modId
+ APSS_GPE_FAILURE, // i_reasonCode
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_start_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_start_request.ffdc,
+ sizeof(G_meas_start_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ // Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ // Clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_start_pwr_meas_read_args.error.error = 0;
+ G_gpe_start_pwr_meas_read_args.error.ffdc = 0;
+
+ // Submit the next request
+ l_rc = pore_flex_schedule(&G_meas_start_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_start_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_START_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_start_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_START_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ // Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+
+ APSS_DBG("GPE_start_pwr_meas_read finished w/rc=0x%08X\n", G_gpe_start_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_start_pwr_meas_read_args, sizeof(G_gpe_start_pwr_meas_read_args), "G_gpe_start_pwr_meas_read_args");
+ G_ApssPwrMeasCompleted = FALSE; // Will complete when 3rd task is complete.
+ G_gpe_apss_time_start = ssx_timebase_get();
+
+
+} // end task_apss_start_pwr_meas()
+
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_cont_request;
+// Function Specification
+//
+// Name: task_apss_continue_pwr_meas
+//
+// Description: Start GPE to collect 1st block of power measurement data and request
+// the 2nd block
+// If previous call had failed, commit the error and request reset
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// End Function Specification
+void task_apss_continue_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_apss_continue_pwr_meas_read (non-blocking)
+ APSS_DBG("Calling task_apss_continue_pwr_meas.\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_cont_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_continue_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ //Don't run anything if apss recovery is in progress
+ if(G_apss_recovery_requested)
+ {
+ break;
+ }
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_cont_request.request.completion_state) ||
+ (0 != G_gpe_continue_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_continue_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_continue_pwr_meas_read_args.error.rc,
+ G_gpe_continue_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_continue_pwr_meas_read_args.error.ffdc,
+ G_meas_cont_request.request.completion_state);
+
+
+ // Collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_CONT_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_CONT_MEAS, // i_modId
+ APSS_GPE_FAILURE, // i_reasonCode
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_continue_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_cont_request.ffdc,
+ sizeof(G_meas_cont_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ // Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ // Clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_continue_pwr_meas_read_args.error.error = 0;
+ G_gpe_continue_pwr_meas_read_args.error.ffdc = 0;
+
+ // Submit the next request
+ l_rc = pore_flex_schedule(&G_meas_cont_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_cont_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_CONT_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_continue_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_CONT_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ // Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+ }while (0);
+
+ APSS_DBG("task_apss_continue_pwr_meas: finished w/rc=0x%08X\n", G_gpe_continue_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_continue_pwr_meas_read_args, sizeof(G_gpe_continue_pwr_meas_read_args), "G_gpe_continue_pwr_meas_read_args");
+
+} // end task_apss_continue_pwr_meas
+
+// Function Specification
+//
+// Name: reformat_meas_data
+//
+// Description: Extract measurement from GPE programs into G_apss_pwr_meas structure
+// This function is called when the GPE completes the final measurement
+// collection for this loop.
+//
+// End Function Specification
+#define APSS_ADC_SEQ_MASK 0xf000f000f000f000ull
+#define APSS_ADC_SEQ_CHECK 0x0000100020003000ull
+void reformat_meas_data()
+{
+ APSS_DBG("GPE_complete_pwr_meas_read finished w/rc=0x%08X\n", G_gpe_complete_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_complete_pwr_meas_read_args, sizeof(G_gpe_complete_pwr_meas_read_args), "G_gpe_complete_pwr_meas_read_args");
+
+ do
+ {
+ // Make sure complete was successful
+ if (G_gpe_complete_pwr_meas_read_args.error.error)
+ {
+ break;
+ }
+
+ // 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) ||
+ !(G_gpe_continue_pwr_meas_read_args.meas_data[0] & ~APSS_ADC_SEQ_MASK))
+ {
+ // Recovery will begin on the next tick
+ G_apss_recovery_requested = TRUE;
+ break;
+ }
+
+ // Decrement up/down fail counter for backup on success.
+ if(G_backup_fail_count)
+ {
+ G_backup_fail_count--;
+ }
+
+ // Don't do the copy unless this is the master OCC
+ if(G_occ_role == OCC_MASTER)
+ {
+
+ // Fail every 16 seconds
+ APSS_DBG("Populate meas data:\n");
+
+ // Merge continue/complete data into a single buffer
+ const uint16_t l_continue_meas_length = sizeof(G_gpe_continue_pwr_meas_read_args.meas_data);
+ const uint16_t l_complete_meas_length = sizeof(G_gpe_complete_pwr_meas_read_args.meas_data);
+ uint8_t l_buffer[l_continue_meas_length+l_complete_meas_length];
+ memcpy(&l_buffer[ 0], G_gpe_continue_pwr_meas_read_args.meas_data, l_continue_meas_length);
+ memcpy(&l_buffer[l_continue_meas_length], G_gpe_complete_pwr_meas_read_args.meas_data, l_complete_meas_length);
+ APSS_DBG_HEXDUMP(l_buffer, sizeof(l_buffer), "l_buffer");
+
+ // Copy measurements into correct struction locations (based on composite config)
+ uint16_t l_index = 0;
+ memcpy(G_apss_pwr_meas.adc, &l_buffer[l_index], (G_apss_composite_config.numAdcChannelsToRead * 2));
+ l_index += (G_apss_composite_config.numAdcChannelsToRead * 2);
+ memcpy(G_apss_pwr_meas.gpio, &l_buffer[l_index], (G_apss_composite_config.numGpioPortsToRead * 2));
+ // TOD is always located at same offset
+ memcpy(&G_apss_pwr_meas.tod, &l_buffer[l_continue_meas_length+l_complete_meas_length-8], 8);
+
+ APSS_DBG("...into structure: (%d ADC, %d GPIO)\n", G_apss_composite_config.numAdcChannelsToRead,
+ G_apss_composite_config.numGpioPortsToRead);
+ APSS_DBG_HEXDUMP(&G_apss_pwr_meas, sizeof(G_apss_pwr_meas), "G_apss_pwr_meas");
+ }
+
+ // Mark apss pwr meas completed and valid
+ G_ApssPwrMeasCompleted = TRUE;
+ G_gpe_apss_time_end = ssx_timebase_get();
+ APSS_DBG("APSS Completed - %d\n",(int) ssx_timebase_get());
+ }while(0);
+}
+
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_complete_request;
+
+// Function Specification
+//
+// Name: task_apss_complete_pwr_meas
+//
+// Description: Start GPE to collect 2nd block of power measurement data and TOD.
+// If previous call had failed, commit the error and request reset
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// End Function Specification
+void task_apss_complete_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_apss_complete_pwr_meas_read (non-blocking)
+ APSS_DBG("Calling task_apss_complete_pwr_meas.\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_complete_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_complete_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ if(G_apss_recovery_requested)
+ {
+ // Allow apss measurement to proceed on next tick
+ G_apss_recovery_requested = FALSE;
+ break;
+ }
+
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_complete_request.request.completion_state) ||
+ (0 != G_gpe_complete_pwr_meas_read_args.error.error))
+ {
+ // Error should only be non-zero in the case where the GPE timed out waiting for
+ // the APSS master to complete the last operation. Just keep retrying until
+ // DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_complete_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_complete_pwr_meas_read_args.error.rc,
+ G_gpe_complete_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_complete_pwr_meas_read_args.error.ffdc,
+ G_meas_complete_request.request.completion_state);
+
+ // Collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_COMPLETE_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_COMPLETE_MEAS, // i_modId
+ APSS_GPE_FAILURE, // i_reasonCode
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_complete_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_complete_request.ffdc,
+ sizeof(G_meas_complete_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ // Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ // Clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_complete_pwr_meas_read_args.error.error = 0;
+ G_gpe_complete_pwr_meas_read_args.error.ffdc = 0;
+
+ // Submit the next request
+ l_rc = pore_flex_schedule(&G_meas_complete_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_complete_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_COMPLETE_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_complete_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_COMPLETE_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ // Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+ APSS_DBG("task_apss_complete_pwr_meas: finished w/rc=0x%08X\n", G_gpe_complete_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_complete_pwr_meas_read_args, sizeof(G_gpe_complete_pwr_meas_read_args), "G_gpe_complete_pwr_meas_read_args");
+
+
+} // end task_apss_complete_pwr_meas
+
+bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value)
+{
+ bool l_valid = FALSE;
+
+ if( (i_pin_number != SYSCFG_INVALID_PIN) && (o_pin_value != NULL) )
+ {
+ // Check if G_dcom_slv_inbox_rx is valid.
+ // The default value is all 0, so check if it's no-zero
+ bool l_dcom_data_valid = FALSE;
+ int i=0;
+ for(;i<sizeof(G_dcom_slv_inbox_rx);i++)
+ {
+ if( ((char*)&G_dcom_slv_inbox_rx)[i] != 0 )
+ {
+ l_dcom_data_valid = TRUE;
+ break;
+ }
+ }
+
+ if( l_dcom_data_valid == TRUE)
+ {
+ uint8_t l_gpio_port = i_pin_number/NUM_OF_APSS_PINS_PER_GPIO_PORT;
+ uint8_t l_gpio_mask = 0x1 << i_pin_number % NUM_OF_APSS_PINS_PER_GPIO_PORT;
+ l_valid = TRUE;
+ if( G_dcom_slv_inbox_rx.gpio[l_gpio_port] & l_gpio_mask )
+ {
+ *o_pin_value = 1;
+ }
+ else
+ {
+ *o_pin_value = 0;
+ }
+ }
+ }
+ return l_valid;
+}
+
diff --git a/src/occ_405/pss/apss.h b/src/occ_405/pss/apss.h
new file mode 100644
index 0000000..8abd42e
--- /dev/null
+++ b/src/occ_405/pss/apss.h
@@ -0,0 +1,138 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pss/apss.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 _APSS_H
+#define _APSS_H
+
+#include <occ_common.h>
+#include <trac_interface.h>
+#include <errl.h>
+#include <gpe_export.h>
+#include <rtls.h>
+
+#define NUM_OF_APSS_GPIO_PORTS 2
+#define NUM_OF_APSS_PINS_PER_GPIO_PORT 8
+#define MAX_APSS_ADC_CHANNELS 16
+#define MAX_APSS_GPIO_PORTS NUM_OF_APSS_GPIO_PORTS
+#define MEAS_PADDING_REQUIRED (28-MAX_APSS_ADC_CHANNELS+MAX_APSS_GPIO_PORTS)
+#define APSS_12BIT_ADC_MASK 0x0fff
+
+#if ( (!defined(NO_TRAC_STRINGS)) && defined(TRAC_TO_SIMICS) )
+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_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.
+
+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.
+#define APSS_SUCCESS() {(G_apss_fail_updown_count = 0);}
+
+// Increment APSS_FAIL_COUNT by APSS_DATA_FAILURE_STEP to a maximum of APSS_DATA_FAIL_MAX.
+#define APSS_FAIL() {((APSS_DATA_FAIL_MAX - G_apss_fail_updown_count) >= APSS_DATA_FAILURE_STEP)? \
+ (G_apss_fail_updown_count += APSS_DATA_FAILURE_STEP): \
+ (G_apss_fail_updown_count = APSS_DATA_FAIL_MAX);}
+
+struct apssGpioConfigStruct
+{
+ uint8_t direction;
+ uint8_t drive;
+ uint8_t interrupt;
+} __attribute__ ((__packed__));
+typedef struct apssGpioConfigStruct apssGpioConfigStruct_t;
+
+struct apssCompositeConfigStruct
+{
+ uint8_t numAdcChannelsToRead;
+ uint8_t numGpioPortsToRead;
+} __attribute__ ((__packed__));
+typedef struct apssCompositeConfigStruct apssCompositeConfigStruct_t;
+
+struct apssPwrMeasStruct
+{
+ uint16_t adc[MAX_APSS_ADC_CHANNELS];
+ uint16_t gpio[MAX_APSS_GPIO_PORTS];
+ uint16_t pad[MEAS_PADDING_REQUIRED]; // padding to allow TOD to be 8 byte aligned
+ uint64_t tod; // Time of Day that the ADC Collection Completed
+} __attribute__ ((__packed__));
+typedef struct apssPwrMeasStruct apssPwrMeasStruct_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ apssGpioConfigStruct_t config0; // G_gpio_config[0] (input to APSS)
+ apssGpioConfigStruct_t config1; // G_gpio_config[1] (input to APSS)
+} initGpioArgs_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ apssCompositeConfigStruct_t config; // G_apss_composite_config (input to APSS)
+} setCompositeModeArgs_t;
+
+typedef struct
+{
+ PoreGpeErrorStruct error;
+} apss_start_args_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ uint64_t meas_data[4]; // G_apss_pwr_meas (1st block of data) (output from APSS)
+} apss_continue_args_t;
+
+typedef struct {
+ PoreGpeErrorStruct error;
+ uint64_t meas_data[4]; // G_apss_pwr_meas (2nd block of data) (output from APSS)
+} apss_complete_args_t;
+
+// @TODO - Does G_gpio_config and G_apss_composite_config need to be used outside of APSS? If not I will remove from .h
+// G_gpio_config: configuration for APSS GPIO pins (default all input, all 1's, not int)
+extern const apssGpioConfigStruct_t G_gpio_config[NUM_OF_APSS_GPIO_PORTS];
+// G_apss_composite_config: system parms needed to select correct composite command options
+extern const apssCompositeConfigStruct_t G_apss_composite_config;
+
+// G_apss_pwr_meas: power, temp and GPIO readings that OCC gathers from APSS every tick
+extern apssPwrMeasStruct_t G_apss_pwr_meas;
+
+// Used to tell slave inbox that pwr meas is complete
+extern volatile bool G_ApssPwrMeasCompleted;
+
+extern initGpioArgs_t G_gpe_apss_initialize_gpio_args;
+extern setCompositeModeArgs_t G_gpe_apss_set_composite_mode_args;
+
+extern uint64_t G_gpe_apss_time_start;
+extern uint64_t G_gpe_apss_time_end;
+
+// apss_initialize is product applet
+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 apss_test_pwr_meas(); // @temp cc - used to test measurements
+void reformat_meas_data();
+bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value);
+
+#endif //_APSS_H
diff --git a/src/occ_405/pss/dpss.c b/src/occ_405/pss/dpss.c
new file mode 100755
index 0000000..6db3cdc
--- /dev/null
+++ b/src/occ_405/pss/dpss.c
@@ -0,0 +1,189 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pss/dpss.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 */
+
+#include "ssx.h"
+
+#include <dpss.h>
+#include <trac.h>
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <occ_sys_config.h>
+#include <trac_interface.h>
+#include <occ_service_codes.h>
+#include <pss_service_codes.h>
+#include <state.h>
+#include <amec_oversub.h>
+#include <ppc405_irq.h>
+
+// Macro creates a 'bridge' handler that converts the initial fast-mode to full-
+// mode interrupt handler
+SSX_IRQ_FAST2FULL(isr_dpss_oversubscription_handler, isr_dpss_oversubscription_handler_full);
+
+// Increment a counter each time we see a phantom interrupt (used by health monitor thread)
+uint32_t G_occ_phantom_critical_count = 0;
+uint32_t G_occ_phantom_noncritical_count = 0;
+
+// Function Specification
+//
+// Name: isr_dpss_oversubscription_handler_full
+//
+// Description: From the flow diagram:
+// Will eventually be doing something to set the Pstates & Memory
+// Throttles when this interrupt occurs, but for now just put in this
+// comment and no code besides clearing the irq and tracing the fact that
+// we got an interrupt.
+//
+// End Function Specification
+void isr_dpss_oversubscription_handler_full(void *private, SsxIrqId irq, int priority)
+{
+ SsxMachineContext ctx;
+
+ // disable further interrupts at this level
+ ssx_irq_disable(irq);
+
+ // enter the protected context
+ ssx_critical_section_enter( SSX_CRITICAL, &ctx );
+
+ // clear this irq
+ ssx_irq_status_clear(irq);
+
+ // exit the protected context
+ ssx_critical_section_exit( &ctx );
+
+ // call oversub isr
+ amec_oversub_isr();
+
+ // re-enable interrupts at this level
+ ssx_irq_enable(irq);
+
+} // end isr_dpss_oversubscription_handler_full
+
+// Function Specification
+//
+// Name: occ_phantom_irq_handler
+//
+// Description:
+// handler for an interrupt that fired and then went away before
+// we could read what it was.
+//
+// End Function Specification
+void occ_phantom_irq_handler(void* i_arg, SsxIrqId i_irq, int i_critical)
+{
+ if(i_critical == SSX_CRITICAL)
+ {
+ G_occ_phantom_critical_count++;
+ }
+ else
+ {
+ G_occ_phantom_noncritical_count++;
+ }
+}
+
+// Function Specification
+//
+// Name: dpss_oversubscription_irq_initialize
+//
+// Description:
+// Installs the power oversubscription IRQ handler for the DPSS
+//
+// End Function Specification
+errlHndl_t dpss_oversubscription_irq_initialize()
+{
+ int rc = 0;
+ errlHndl_t l_err = NULL;
+
+ // NOTE: It is believed that the oversubscription interrupt bounces
+ // on and off as power supplies are re-inserted. If it happens quickly enough
+ // it will clear the interrupt before the code has a chance to see the cause
+ // of the interrupt. The default phantom handler would then be invoked and
+ // cause occ to panic. Instead, we just increment a counter and log an info
+ // error.
+ __ppc405_phantom_irq.handler = occ_phantom_irq_handler;
+
+ // Disable the IRQ while we work on it
+ ssx_irq_disable(PGP_IRQ_EXTERNAL_TRAP);
+
+ // Setup the IRQ
+ rc = ssx_irq_setup(PGP_IRQ_EXTERNAL_TRAP,
+ SSX_IRQ_POLARITY_ACTIVE_LOW,
+ SSX_IRQ_TRIGGER_LEVEL_SENSITIVE);
+
+ if( rc ) {
+ TRAC_ERR("%s: Failed IRQ setup.", __FUNCTION__);
+
+ /*@
+ * @moduleid PSS_MID_DPSS_OVS_IRQ_INIT
+ * @reasonCode SSX_GENERIC_FAILURE
+ * @severity ERRL_SEV_PREDICTIVE
+ * @userdata1 ssx_irq_setup return code
+ * @userdata4 ERC_SSX_IRQ_SETUP_FAILURE
+ * @devdesc Firmware failure initializing DPSS IRQ
+ */
+ l_err = createErrl( PSS_MID_DPSS_OVS_IRQ_INIT, // i_modId
+ SSX_GENERIC_FAILURE, // i_reasonCode
+ ERC_SSX_IRQ_SETUP_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL, // tracDesc_t i_trace
+ 0, // i_traceSz
+ rc, // i_userData1
+ 0); // i_userData2
+ }
+ else {
+ // Set the IRQ handler
+ rc = ssx_irq_handler_set(PGP_IRQ_EXTERNAL_TRAP,
+ isr_dpss_oversubscription_handler,
+ NULL,
+ SSX_NONCRITICAL);
+
+ if( rc ) {
+ TRAC_ERR("%s: Failed to set the IRQ handler.", __FUNCTION__);
+
+ /*@
+ * @moduleid PSS_MID_DPSS_OVS_IRQ_INIT
+ * @reasonCode SSX_GENERIC_FAILURE
+ * @severity ERRL_SEV_PREDICTIVE
+ * @userdata1 ssx_irq_handler_set return code
+ * @userdata4 ERC_SSX_IRQ_HANDLER_SET_FAILURE
+ * @devdesc Firmware failure setting up DPSS routine
+ */
+ l_err = createErrl( PSS_MID_DPSS_OVS_IRQ_INIT, // i_modId
+ SSX_GENERIC_FAILURE, // i_reasonCode
+ ERC_SSX_IRQ_HANDLER_SET_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL, // tracDesc_t i_trace
+ 0, // i_traceSz
+ rc, // i_userData1
+ 0); // i_userData2
+ }
+ else {
+ // Enable the IRQ
+ ssx_irq_status_clear(PGP_IRQ_EXTERNAL_TRAP);
+ ssx_irq_enable(PGP_IRQ_EXTERNAL_TRAP);
+ }
+ }
+
+ return l_err;
+} // end dpss_oversubscription_irq_initialize
+
diff --git a/src/occ_405/pss/dpss.h b/src/occ_405/pss/dpss.h
new file mode 100755
index 0000000..6b42f72
--- /dev/null
+++ b/src/occ_405/pss/dpss.h
@@ -0,0 +1,40 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pss/dpss.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 _DPSS_H
+#define _DPSS_H
+
+#include <errl.h>
+#include <rtls.h>
+
+// dpss_initialize is part of the dpss init applet
+
+// DPSS oversubscription IRQ handler
+void isr_dpss_oversubscription_handler_full(void *private, SsxIrqId irq, int priority);
+
+// Installs the DPSS oversubscription IRQ handler
+errlHndl_t dpss_oversubscription_irq_initialize();
+
+#endif //_DPSS_H
diff --git a/src/occ_405/pss/pss_service_codes.h b/src/occ_405/pss/pss_service_codes.h
new file mode 100755
index 0000000..a4eda54
--- /dev/null
+++ b/src/occ_405/pss/pss_service_codes.h
@@ -0,0 +1,43 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pss/pss_service_codes.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 _PSS_SERVICE_CODES_H_
+#define _PSS_SERVICE_CODES_H_
+
+#include <comp_ids.h>
+
+enum pssModuleId
+{
+ PSS_MID_APSS_INIT = PSS_COMP_ID | 0x00,
+ PSS_MID_APSS_START_MEAS = PSS_COMP_ID | 0x01,
+ PSS_MID_APSS_CONT_MEAS = PSS_COMP_ID | 0x02,
+ PSS_MID_APSS_COMPLETE_MEAS = PSS_COMP_ID | 0x03,
+ PSS_MID_DPSS_INIT = PSS_COMP_ID | 0x04,
+ PSS_MID_DPSS_OVS_IRQ_INIT = PSS_COMP_ID | 0x05,
+ PSS_MID_DPSS_RD_STATUS = PSS_COMP_ID | 0x06,
+ PSS_MID_DO_APSS_RECOVERY = PSS_COMP_ID | 0x07,
+};
+
+#endif /* #ifndef _PSS_SERVICE_CODES_H_ */
diff --git a/src/occ_405/pss/test/Makefile b/src/occ_405/pss/test/Makefile
new file mode 100755
index 0000000..045693b
--- /dev/null
+++ b/src/occ_405/pss/test/Makefile
@@ -0,0 +1,79 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/occ_405/pss/test/Makefile $
+#
+# 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
+
+apsstest_CFILES = \
+ ../../common.c \
+ ../../errl/errl.c \
+ ../../thread/threadSch.c \
+ ../apss.c \
+ apsstest.c
+all_cfiles = ${apsstest_CFILES}
+
+
+occ_GPEFILES = ../../gpe/apss_init.S \
+ ../../gpe/apss_composite.S \
+ ../../gpe/apss_meas_read_start.S \
+ ../../gpe/apss_meas_read_cont.S \
+ ../../gpe/apss_meas_read_complete.S \
+ ../../gpe/pore_test.S
+all_gpefiles = ${occ_GPEFILES}
+
+
+APP = apsstest
+APP_INCLUDES += -I../../../ssx
+APP_INCLUDES += -I../../../lib
+APP_INCLUDES += -I../../incl
+APP_INCLUDES += -I../../trac
+APP_INCLUDES += -I../../async
+APP_INCLUDES += -I../../errl
+APP_INCLUDES += -I../../gpe
+APP_INCLUDES += -I../../thread
+#APP_INCLUDES += -I../../aplt
+#APP_INCLUDES += -I../../rtls
+#APP_INCLUDES += -I../../sensor
+APP_INCLUDES += -I../../pss
+APP_INCLUDES += -I.
+
+D = -DSIMICS_MAGIC_PANIC=1
+
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+
+SOURCES = ${all_cfiles} ${all_gpefiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10' ${all_gpefiles}
diff --git a/src/occ_405/pss/test/app.mk b/src/occ_405/pss/test/app.mk
new file mode 100755
index 0000000..c1cf490
--- /dev/null
+++ b/src/occ_405/pss/test/app.mk
@@ -0,0 +1,102 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/occ_405/pss/test/app.mk $
+#
+# 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
+
+OCC = ../../
+SSX = ../../../ssx
+LIB = ../../../lib
+PGP = $(SSX)/pgp
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+
+#*******************************************************************************
+# Export
+#*******************************************************************************
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+#*******************************************************************************
+# Flags
+#*******************************************************************************
+
+INCLUDES = -I $(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+
+C-OBJECTS = $(SOURCES:.c=.o)
+OBJECTS = $(C-OBJECTS:.S=.o)
+
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32
+
+
+DEFS += $(D)
+
+#*******************************************************************************
+# compilation
+#*******************************************************************************
+all: $(OBJECTS) libssx.a
+ $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e
+ $(CPP) -P $(DEFS) < $(PGP)/linkssx.cmd > linkscript
+ $(LD) $(OBJECTS) \
+ -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out
+ $(OBJCOPY) -O binary $(APP).out $(APP).bin
+ $(OBJDUMP) -d $(APP).out > $(APP).dis
+
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+#*******************************************************************************
+# clean
+#*******************************************************************************
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.*
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+#*******************************************************************************
+# Doxygen
+#*******************************************************************************
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+#*******************************************************************************
+# .d file creation
+#*******************************************************************************
+
+-include $(OBJECTS:.o=.d)
diff --git a/src/occ_405/pss/test/apsstest.c b/src/occ_405/pss/test/apsstest.c
new file mode 100755
index 0000000..768bdbe
--- /dev/null
+++ b/src/occ_405/pss/test/apsstest.c
@@ -0,0 +1,415 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pss/test/apsstest.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 */
+
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include <thread.h>
+#include <threadSch.h>
+#include <errl.h>
+#include <apss.h>
+
+// Period in which to run #timer_routine
+#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(5000)
+SsxSemaphore prcd_sem;
+
+int g_j = 0;
+int g_k = 0;
+
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t critical_stack[CRITICAL_STACK_SIZE];
+
+SsxTimer G_test_timer;
+
+extern void timer_routine(void *private);
+extern void rtloop_ocb_init(void);
+
+// Function Specification
+//
+// Name: pgp_validation_ssx_main_hook
+//
+// Description:
+//
+// End Function Specification
+void pgp_validation_ssx_main_hook(void)
+{
+
+}
+
+// Function Specification
+//
+// Name: Cmd_Hndl_thread_routine
+//
+// Description:
+//
+// End Function Specification
+//TODO placeholder
+void Cmd_Hndl_thread_routine(void *arg)
+{
+ do
+ {
+ int x=0;
+ for(x=0; x < 1000; x++)
+ {
+
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: App_thread_routine
+//
+// Description:
+//
+// End Function Specification
+void App_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Thermal_Monitor_thread_routine
+//
+// Description:
+//
+// End Function Specification
+void Thermal_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Hlth_Monitor_thread_routine
+//
+// Description:
+//
+// End Function Specification
+void Hlth_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: FFDC_thread_routine
+//
+// Description:
+//
+// End Function Specification
+void FFDC_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ //printf("Thread A running");
+ }while(1);
+
+}
+
+/** PRCD Thread
+ *
+ * This thread loops as the highest priority thread, where it currently
+ * just
+ *
+ */
+// Function Specification
+//
+// Name: prcd_thread_routine
+//
+// Description:
+//
+// End Function Specification
+void prcd_thread_routine(void *private)
+{
+ while(1)
+ {
+ // Just sit here until this semaphore is posted, which will never happen.
+ ssx_semaphore_pend(&prcd_sem, SSX_WAIT_FOREVER);
+
+ // Only trace the first XX times that this function loops
+ if(g_j < 20)
+ {
+ g_k = 0;
+ g_j++;
+
+ }
+ }
+}
+
+
+// Function Specification
+//
+// Name: apss_test_pwr_meas
+//
+// Description: Request the full power measurement data in a single function call for TESTING ONLY
+//
+// End Function Specification
+extern PoreEntryPoint pore_test; // Sleep for specified amount of time...
+void apss_test_pwr_meas(void)
+{
+ task_apss_start_pwr_meas();
+
+ // Schedule GPE program to delay to ensure the data is available... (BLOCKING)
+ // bad: 48, good: 56
+ PoreFlex test_request;
+ DEBUG_PRINTF(("apss_test_pwr_meas: delay...\n"));
+ pore_flex_create(&test_request,
+ &pore_gpe0_queue,
+ (void*)pore_test, // entry_point
+ (uint32_t)56, // entry_point argument
+ NULL, // callback,
+ NULL, // callback arg
+ ASYNC_REQUEST_BLOCKING); // options
+ pore_flex_schedule(&test_request);
+ DEBUG_PRINTF(("apss_test_pwr_meas: delay complete\n"));
+
+ task_apss_continue_pwr_meas();
+
+ task_apss_complete_pwr_meas();
+
+} // end apss_test_pwr_meas()
+
+
+
+
+/** Main Thread
+ *
+ * This thread currently just loops as the lowest priority thread, handling
+ * the lowest priority tasks.
+ *
+ */
+// Function Specification
+//
+// Name: main_thread_routine
+//
+// Description:
+//
+// End Function Specification
+void main_thread_routine(void *private)
+{
+ // Start the critical 250uS timer
+ ssx_timer_schedule(&timer, 1, TIMER_INTERVAL);
+
+ // Initialize APSS
+ errlHndl_t l_errl = apss_initialize();
+ if (l_errl)
+ {
+ // init failed, attempt one more time before giving up
+ printf("ERROR: apss_initialize failed! (retrying)\n");
+ setErrlSevToInfo(l_errl);
+ commitErrl(&l_errl);
+
+ l_errl = apss_initialize();
+ if (l_errl)
+ {
+ printf("ERROR: apss_initialize failed again! (OCC will be reset)");
+ commitErrl(&l_errl);
+
+ // $TODO - Request Reset
+ }
+ }
+
+ // Attempt to retrieve 3 sets of measurements
+ printf("Attempting to gather power measurements\n");
+ apss_test_pwr_meas();
+ apss_test_pwr_meas();
+ apss_test_pwr_meas();
+
+ while(1)
+ {
+ // Only trace the first XX times that this function loops
+ if(g_k < 3)
+ {
+ g_k++;
+
+ // TRACE: Main Thread
+ }
+
+
+ // Sleep for 1000 before we run the loop again
+ ssx_sleep_absolute(1000);
+ }
+}
+
+// Function Specification
+//
+// Name: dump_thread_info
+//
+// Description:
+//
+// End Function Specification
+void dump_thread_info(void *arg)
+{
+
+ printf("dumping thread info--------------------------\n");
+ int l_rc = 0;
+ SsxThreadState l_state = 0;
+ SsxThreadPriority l_pri = 0;
+ int l_runnable=0;
+ int x=0;
+ for(x=0; x < THREADS_TO_SCHEDULE; x++)
+ {
+ l_rc = ssx_thread_info_get(G_scheduledThreads[x],
+ &l_state,
+ &l_pri,
+ &l_runnable);
+
+ printf("Thread %p: State %x priority %x runnable %x rc %x Global index %x\n",G_scheduledThreads[x],
+ l_state,
+ l_pri,
+ l_runnable,
+ l_rc,
+ G_threadSchedulerIndex);
+
+ }
+
+}
+
+/** Entry point for OCC execution
+ *
+ * main() currently initalizes our trace buffer along with creating threads
+ * and timers for execution. Note that once main runs ssx_start_threads, we
+ * never return as the SSX kernel takes over.
+ *
+ */
+// Function Specification
+//
+// Name: main
+//
+// Description:
+//
+// End Function Specification
+int main(int argc, char **argv)
+{
+ //locals
+ errlHndl_t l_errl = NULL;
+
+ // Initialize Trace Buffers immediately, so they can be used
+ // from this point on.
+ //TRAC_init_buffers();
+
+ // Initialize stdout so we can do printf from within simics env
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+
+ printf("Inside apsstest main\n");
+
+ // Initialize SSX Stacks (note that this also reinitializes the time base to 0)
+ ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE,
+ (SsxAddress)critical_stack, CRITICAL_STACK_SIZE,
+ 0);
+
+ // Create Global Semaphores
+ ssx_semaphore_create(&prcd_sem, 0, 13);
+
+ // Create Threads
+ ssx_thread_create(&main_thread,
+ main_thread_routine,
+ (void *)0,
+ (SsxAddress)main_thread_stack,
+ THREAD_STACK_SIZE,
+ 1);
+
+ // Create Threads
+ ssx_thread_create(&prcd_thread,
+ prcd_thread_routine,
+ (void *)0,
+ (SsxAddress)prcd_thread_stack,
+ THREAD_STACK_SIZE,
+ 0);
+
+ // Make Threads runnable
+ ssx_thread_resume(&main_thread);
+ ssx_thread_resume(&prcd_thread);
+
+ //Initialize the thread scheduler
+ l_errl = initThreadScheduler();
+
+ if( l_errl )
+ {
+ // Trace and commit error
+
+ // TODO add trace
+
+ // commit log
+ // NOTE: log should be deleted by reader mechanism
+ commitErrl( &l_errl );
+ }
+
+ //kick off timer
+ ssx_timer_create(&G_test_timer, dump_thread_info, 0);
+ ssx_timer_schedule(&G_test_timer, 1, 500000000);
+
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
OpenPOWER on IntegriCloud