diff options
author | Fadi Kassem <fmkassem@us.ibm.com> | 2015-08-31 12:12:16 -0500 |
---|---|---|
committer | William A. Bryan <wilbryan@us.ibm.com> | 2015-09-01 16:28:41 -0500 |
commit | 970de5b7c235898fbac1ca4db6a8336db3469399 (patch) | |
tree | 6992f38625710db548796197c14ebf57c9fde553 | |
parent | e03cb51af12a6d787485d15dcb235f5febd022d0 (diff) | |
download | talos-occ-970de5b7c235898fbac1ca4db6a8336db3469399.tar.gz talos-occ-970de5b7c235898fbac1ca4db6a8336db3469399.zip |
APSS init support
Change-Id: I57df832e0611a097eac5285f52366061be091343
RTC:133242
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/20250
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Reviewed-by: Wael Elessawy <welessa@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Tested-by: William A. Bryan <wilbryan@us.ibm.com>
-rw-r--r-- | src/apss_structs.h | 45 | ||||
-rw-r--r-- | src/ipc_func_ids.h | 4 | ||||
-rwxr-xr-x | src/occ_405/main.c | 251 | ||||
-rwxr-xr-x | src/occ_405/pss/apss.c | 16 | ||||
-rw-r--r-- | src/occ_405/pss/apss.h | 8 | ||||
-rwxr-xr-x | src/occ_gpe0/apss_composite.pS | 155 | ||||
-rw-r--r-- | src/occ_gpe0/apss_init.c | 333 | ||||
-rwxr-xr-x | src/occ_gpe0/apss_init.pS | 226 | ||||
-rw-r--r-- | src/occ_gpe0/apss_read.c | 9 | ||||
-rw-r--r-- | src/occ_gpe0/apss_util.c | 96 | ||||
-rw-r--r-- | src/occ_gpe0/apss_util.h | 11 | ||||
-rwxr-xr-x | src/occ_gpe0/gpe_export.h | 2 | ||||
-rwxr-xr-x | src/occ_gpe0/gpe_macros.h | 153 | ||||
-rw-r--r-- | src/occ_gpe0/ipc_func_tables.c | 12 | ||||
-rw-r--r-- | src/occ_gpe0/topfiles.mk | 2 | ||||
-rw-r--r-- | src/occ_gpe0/wait_spi.c | 104 |
16 files changed, 701 insertions, 726 deletions
diff --git a/src/apss_structs.h b/src/apss_structs.h index a43ec3b..953e475 100644 --- a/src/apss_structs.h +++ b/src/apss_structs.h @@ -23,15 +23,35 @@ /* */ /* IBM_PROLOG_END_TAG */ +/* This header file is used by both occ_405 and occ_gpe0. */ +/* Contains common structures and globals. */ + #ifndef _APSS_STRUCTS_H #define _APSS_STRUCTS_H #include <gpe_export.h> + +// List of supported APSS Modes set in occ_gpe0/apss_init.c +#define APSS_MODE_COMPOSITE 0 +#define APSS_MODE_AUTO2 1 + + +// List of possible apss Return Codes +#define APSS_RC_SUCCESS 0x0 +#define APSS_RC_SPI_TIMEOUT 0x1 +#define APSS_RC_SCOM_GET_FAILED 0x2 +#define APSS_RC_SCOM_PUT_FAILED 0x3 +#define APSS_RC_INVALID_REG 0x4 +#define APSS_RC_IPC_SEND_FAILED 0x5 +#define APSS_RC_INVALID_APSS_MODE 0x6 + + + /* This data structure holds the common args data structures between the */ /* 405 and the GPE0, used in IPC communications. */ /* We started by adding these common apss data structures to test the */ -/* code the way it worked before using the PORE GPE assembly. We will */ +/* code the way it worked before using the GPE assembly. We will */ /* probably have to add the apssPwrMeasStruct_t to include GPIO, */ /* measurements, and to maintain a single data structure for all GPE0's */ /* ASPSS routine (or may be consolidate the three routines in a single */ @@ -48,36 +68,37 @@ struct apssGpioConfigStruct } __attribute__ ((__packed__)); typedef struct apssGpioConfigStruct apssGpioConfigStruct_t; -struct apssCompositeConfigStruct +struct apssModeConfigStruct { - uint8_t numAdcChannelsToRead; - uint8_t numGpioPortsToRead; + uint8_t mode; + uint8_t numAdcChannelsToRead; + uint8_t numGpioPortsToRead; } __attribute__ ((__packed__)); -typedef struct apssCompositeConfigStruct apssCompositeConfigStruct_t; +typedef struct apssModeConfigStruct apssModeConfigStruct_t; typedef struct { - PoreGpeErrorStruct error; + GpeErrorStruct 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; + GpeErrorStruct error; + apssModeConfigStruct_t config; // G_apss_composite_config (input to APSS) +} setApssModeArgs_t; typedef struct { - PoreGpeErrorStruct error; + GpeErrorStruct error; } apss_start_args_t; typedef struct { - PoreGpeErrorStruct error; + GpeErrorStruct 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; + GpeErrorStruct error; uint64_t meas_data[4]; // G_apss_pwr_meas (2nd block of data) (output from APSS) } apss_complete_args_t; diff --git a/src/ipc_func_ids.h b/src/ipc_func_ids.h index a2eb58c..e253e39 100644 --- a/src/ipc_func_ids.h +++ b/src/ipc_func_ids.h @@ -55,6 +55,8 @@ IPC_FUNCIDS_TABLE_START //These function ID's can only be sent to GPE0 IPC_FUNCIDS_ST_START(OCCHW_INST_ID_GPE0) IPC_FUNC_ID(IPC_ST_TEST_FUNC0) + IPC_FUNC_ID(IPC_ST_APSS_INIT_GPIO_FUNCID) + IPC_FUNC_ID(IPC_ST_APSS_INIT_MODE_FUNCID) IPC_FUNC_ID(IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID) IPC_FUNC_ID(IPC_ST_APSS_CONTINUE_PWR_MEAS_READ_FUNCID) IPC_FUNC_ID(IPC_ST_APSS_COMPLETE_PWR_MEAS_READ_FUNCID) @@ -73,7 +75,7 @@ IPC_FUNCIDS_TABLE_START //Functions that are only supported by GPE3 should be defined here //These function ID's can only be sent to GPE3 IPC_FUNCIDS_ST_START(OCCHW_INST_ID_GPE3) - IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE3) + IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE3) //Functions that are only supported by PPC should be defined here //These function ID's can only be sent to the PPC diff --git a/src/occ_405/main.c b/src/occ_405/main.c index d795eef..b4246ba 100755 --- a/src/occ_405/main.c +++ b/src/occ_405/main.c @@ -56,6 +56,7 @@ #include <thrm_thread.h> #include "scom.h" //#include <fir_data_collect.h> +#include <pss_service_codes.h> extern void __ssx_boot; extern uint32_t G_occ_phantom_critical_count; @@ -63,7 +64,7 @@ extern uint32_t G_occ_phantom_noncritical_count; extern uint8_t G_occ_interrupt_type; // Remove the next LOC when dcom_initialize_roles() is un-commented -uint8_t G_occ_role = OCC_MASTER; // TEMP +uint8_t G_occ_role = OCC_MASTER; // TEMP // TEMP Remove next 6 LOC when apssInitApplet.c is added extern GpeRequest G_meas_start_request; @@ -362,8 +363,8 @@ void gpe_reset(uint32_t instance_id) * Name: occ_ipc_setup * * Description: Initialzes IPC (Inter Process Communication) that is used - * to communicate with GPEs. - * This will also start GPE0 and GPE1. + * to communicate with GPEs. + * This will also start GPE0 and GPE1. * NOTE: SGPE and PGPE are started prior to the OCC 405 during the IPL. * * End Function Specification @@ -547,58 +548,206 @@ void hmon_routine() void master_occ_init() { - OCC_APLT_STATUS_CODES l_status = OCC_APLT_SUCCESS; - errlHndl_t l_errl = NULL; + errlHndl_t l_err = NULL; + GpeRequest l_request; //Used once here to initialize apss. + // TODO: Move the APSS initialization code back to an applet once applets are running on P9. // Initialize APSS - // Start TEMP code until apssInitApplet.c is compiled and running applets is supported - TRAC_INFO("apss_initialize: Creating request G_meas_start_request."); - //Create the request for measure start. Scheduling will happen in apss.c - gpe_request_create(&G_meas_start_request, - &G_async_gpe_queue0, // queue - IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID, // entry_point - (uint32_t)&G_gpe_start_pwr_meas_read_args, // entry_point arg - SSX_WAIT_FOREVER, // no timeout - NULL, // callback - NULL, // callback arg - ASYNC_CALLBACK_IMMEDIATE); // options - - TRAC_INFO("apss_initialize: Creating request G_meas_cont_request."); - //Create the request for measure continue. Scheduling will happen in apss.c - gpe_request_create(&G_meas_cont_request, - &G_async_gpe_queue0, // request - IPC_ST_APSS_CONTINUE_PWR_MEAS_READ_FUNCID, // entry_point - (uint32_t)&G_gpe_continue_pwr_meas_read_args, // entry_point arg - SSX_WAIT_FOREVER, // no timeout - NULL, // callback - NULL, // callback arg - ASYNC_CALLBACK_IMMEDIATE); // options - - TRAC_INFO("apss_initialize: Creating request G_meas_complete_request."); - //Create the request for measure complete. Scheduling will happen in apss.c - gpe_request_create(&G_meas_complete_request, - &G_async_gpe_queue0, // queue - IPC_ST_APSS_COMPLETE_PWR_MEAS_READ_FUNCID, // entry_point - (uint32_t)&G_gpe_complete_pwr_meas_read_args, // entry_point arg - SSX_WAIT_FOREVER, // no timeout - (AsyncRequestCallback)reformat_meas_data, // callback, - (void*)NULL, // callback arg - ASYNC_CALLBACK_IMMEDIATE); // options - - // END TEMP code. Un-comment runApplet() when TEMP code is removed -/* runApplet(OCC_APLT_APSS_INIT, // Applet enum Name - NULL, // Applet arguments - TRUE, // Blocking call? - NULL, // Applet finished semaphore - &l_errl, // Error log handle - &l_status); // Error status -*/ - if( (NULL != l_errl) || (l_status != OCC_APLT_SUCCESS)) + // Setup the GPIO init structure to pass to the PPE program + G_gpe_apss_initialize_gpio_args.error.error = 0; + G_gpe_apss_initialize_gpio_args.error.ffdc = 0; + G_gpe_apss_initialize_gpio_args.config0.direction + = G_gpio_config[0].direction; + G_gpe_apss_initialize_gpio_args.config0.drive + = G_gpio_config[0].drive; + G_gpe_apss_initialize_gpio_args.config0.interrupt + = G_gpio_config[0].interrupt; + G_gpe_apss_initialize_gpio_args.config1.direction + = G_gpio_config[1].direction; + G_gpe_apss_initialize_gpio_args.config1.drive + = G_gpio_config[1].drive; + G_gpe_apss_initialize_gpio_args.config1.interrupt + = G_gpio_config[1].interrupt; + + // Create/schedule IPC_ST_APSS_INIT_GPIO_FUNCID and wait for it to complete (BLOCKING) + TRAC_INFO("master_occ_init: Creating request for GPE_apss_initialize_gpio"); + gpe_request_create(&l_request, // request + &G_async_gpe_queue0, // queue + IPC_ST_APSS_INIT_GPIO_FUNCID, // Function ID + (uint8_t)&G_gpe_apss_initialize_gpio_args, // GPE argument_ptr + SSX_SECONDS(5), // timeout + NULL, // callback + NULL, // callback arg + ASYNC_REQUEST_BLOCKING); // options + + // Schedule the request to be executed + TRAC_INFO("master_occ_init: Scheduling request for IPC_ST_APSS_INIT_GPIO_FUNCID"); + gpe_request_schedule(&l_request); + + // Check for a timeout only; will create the error below. + if(ASYNC_REQUEST_STATE_TIMED_OUT == l_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 + // it to the front of the queue. + // Let's log an error, and include the FFDC data if it was + // generated. + TRAC_ERR("master_occ_init: Timeout communicating with PPE for APSS Init."); + } + + + TRAC_INFO("master_occ_init: GPE_apss_initialize_gpio completed w/rc=0x%08x\n", + l_request.request.completion_state); + + + //TODO: The ipc command will return "SUCCESS" even if an internal PPE failure + // occurs. Make sure that checking for rc as seen below, is good enough. + + // Only continue if initializaton completed without any errors. + if ((ASYNC_REQUEST_STATE_COMPLETE == l_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 + G_gpe_apss_set_mode_args.error.error = 0; + G_gpe_apss_set_mode_args.error.ffdc = 0; + G_gpe_apss_set_mode_args.config.mode + = G_apss_mode_config.mode; //Mode used is set in apss.c + G_gpe_apss_set_mode_args.config.numAdcChannelsToRead + = G_apss_mode_config.numAdcChannelsToRead; + G_gpe_apss_set_mode_args.config.numGpioPortsToRead + = G_apss_mode_config.numGpioPortsToRead; + + // Create/schedule GPE_apss_set_mode and wait for it to complete (BLOCKING) + TRAC_INFO("master_occ_init: Creating request for GPE_apss_set_mode"); + gpe_request_create(&l_request, // request + &G_async_gpe_queue0, // queue + IPC_ST_APSS_INIT_MODE_FUNCID, // Function ID + (uint8_t)&G_gpe_apss_set_mode_args, // GPE argument_ptr + SSX_SECONDS(5), // timeout + NULL, // callback + NULL, // callback arg + ASYNC_REQUEST_BLOCKING); // options + //Schedule set_mode + gpe_request_schedule(&l_request); + + // Check for a timeout, will create the error log later + if(ASYNC_REQUEST_STATE_TIMED_OUT == l_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 + // it to the front of the queue. + // Let's log an error, and include the FFDC data if it was + // generated. + TRAC_ERR("master_occ_init: Timeout communicating with PPE for APSS Init"); + } + + TRAC_INFO("master_occ_init: GPE_apss_set_mode completed w/rc=0x%08x", + l_request.request.completion_state); + + //Continue only if mode set was successful. + if ((ASYNC_REQUEST_STATE_COMPLETE == l_request.request.completion_state) && + (G_gpe_apss_set_mode_args.error.rc == ERRL_RC_SUCCESS)) + { + TRAC_INFO("master_occ_init: Creating request G_meas_start_request."); + //Create the request for measure start. Scheduling will happen in apss.c + gpe_request_create(&G_meas_start_request, + &G_async_gpe_queue0, // queue + IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID, // entry_point + (uint8_t)&G_gpe_start_pwr_meas_read_args,// entry_point arg + SSX_WAIT_FOREVER, // no timeout + NULL, // callback + NULL, // callback arg + ASYNC_CALLBACK_IMMEDIATE); // options + + TRAC_INFO("master_occ_init: Creating request G_meas_cont_request."); + //Create the request for measure continue. Scheduling will happen in apss.c + gpe_request_create(&G_meas_cont_request, + &G_async_gpe_queue0, // request + IPC_ST_APSS_CONTINUE_PWR_MEAS_READ_FUNCID, // entry_point + (uint8_t)&G_gpe_continue_pwr_meas_read_args, // entry_point arg + SSX_WAIT_FOREVER, // no timeout + NULL, // callback + NULL, // callback arg + ASYNC_CALLBACK_IMMEDIATE); // options + + TRAC_INFO("master_occ_init: Creating request G_meas_complete_request."); + //Create the request for measure complete. Scheduling will happen in apss.c + gpe_request_create(&G_meas_complete_request, + &G_async_gpe_queue0, // queue + IPC_ST_APSS_COMPLETE_PWR_MEAS_READ_FUNCID, // entry_point + (uint8_t)&G_gpe_complete_pwr_meas_read_args, // entry_point arg + SSX_WAIT_FOREVER, // no timeout + (AsyncRequestCallback)reformat_meas_data, // callback, + (void*)NULL, // callback arg + ASYNC_CALLBACK_IMMEDIATE); // options + + } + else + { + /* + * @errortype + * @moduleid PSS_MID_APSS_INIT + * @reasoncode INTERNAL_FAILURE + * @userdata1 GPE returned rc code + * @userdata2 GPE returned abort code + * @userdata4 ERC_PSS_COMPOSITE_MODE_FAIL + * @devdesc Failure from GPE for setting composite mode on + * APSS + */ + l_err = createErrl(PSS_MID_APSS_INIT, // i_modId, + INTERNAL_FAILURE, // i_reasonCode, + ERC_PSS_COMPOSITE_MODE_FAIL, // extended reason code + 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 + addUsrDtlsToErrl(l_err, + (uint8_t*)&G_gpe_apss_set_mode_args, + sizeof(G_gpe_apss_set_mode_args), + ERRL_STRUCT_VERSION_1, + ERRL_USR_DTL_TRACE_DATA); + + // Returning an error log will cause us to go to safe + // state so we can report error to FSP + } + } + else { - TRAC_ERR("APSS init applet returned error: l_status: 0x%x", l_status); + /* + * @errortype + * @moduleid PSS_MID_APSS_INIT + * @reasoncode INTERNAL_FAILURE + * @userdata1 GPE returned rc code + * @userdata2 GPE returned abort code + * @userdata4 ERC_PSS_GPIO_INIT_FAIL + * @devdesc Failure from GPE for gpio initialization on APSS + */ + l_err = createErrl(PSS_MID_APSS_INIT, // i_modId, + INTERNAL_FAILURE, // i_reasonCode, + ERC_PSS_GPIO_INIT_FAIL, // extended reason code + 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 + addUsrDtlsToErrl(l_err, + (uint8_t*)&G_gpe_apss_initialize_gpio_args, + sizeof(G_gpe_apss_initialize_gpio_args), + ERRL_STRUCT_VERSION_1, + ERRL_USR_DTL_TRACE_DATA); + + // Returning an error log will cause us to go to safe + // state so we can report error to FSP + } + + if( (NULL != l_err)) + { + TRAC_ERR("APSS init applet returned error"); // commit & delete. CommitErrl handles NULL error log handle - REQUEST_RESET(l_errl); + // TEMP -- NO ERRL / RESET YET + //REQUEST_RESET(l_err); } // Reinitialize the PBAX Queues @@ -1137,7 +1286,7 @@ int main(int argc, char **argv) // The offset from the start of the HOMER is 0x00100000, we will need to // create a temporary mapping to this section of the HOMER with ppc405_mmu_map // (at address 0x00000000) read the value, convert it, and then unmap. - + // Don't do a version check before reading the nest freq, it's present in // all HOMER versions. uint32_t l_tb_freq_hz = 0; diff --git a/src/occ_405/pss/apss.c b/src/occ_405/pss/apss.c index 77a111f..fa08af8 100755 --- a/src/occ_405/pss/apss.c +++ b/src/occ_405/pss/apss.c @@ -44,14 +44,14 @@ // 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 }; +// Configure streaming of: APSS Mode, 16 ADCs, 2 GPIOs +const apssModeConfigStruct_t G_apss_mode_config = { APSS_MODE_AUTO2, 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); +GPE_BUFFER(setApssModeArgs_t G_gpe_apss_set_mode_args); uint64_t G_gpe_apss_time_start; uint64_t G_gpe_apss_time_end; @@ -637,14 +637,14 @@ void reformat_meas_data() // 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)); + memcpy(G_apss_pwr_meas.adc, &l_buffer[l_index], (G_apss_mode_config.numAdcChannelsToRead * 2)); + l_index += (G_apss_mode_config.numAdcChannelsToRead * 2); + memcpy(G_apss_pwr_meas.gpio, &l_buffer[l_index], (G_apss_mode_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("...into structure: (%d ADC, %d GPIO)\n", G_apss_mode_config.numAdcChannelsToRead, + G_apss_mode_config.numGpioPortsToRead); APSS_DBG_HEXDUMP(&G_apss_pwr_meas, sizeof(G_apss_pwr_meas), "G_apss_pwr_meas"); } diff --git a/src/occ_405/pss/apss.h b/src/occ_405/pss/apss.h index 482919e..a332bea 100644 --- a/src/occ_405/pss/apss.h +++ b/src/occ_405/pss/apss.h @@ -67,11 +67,11 @@ struct apssPwrMeasStruct } __attribute__ ((__packed__)); typedef struct apssPwrMeasStruct apssPwrMeasStruct_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 +// @TODO - Does G_gpio_config and G_apss_mode_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_mode_config: system parms needed to select correct mode command options +extern const apssModeConfigStruct_t G_apss_mode_config; // G_apss_pwr_meas: power, temp and GPIO readings that OCC gathers from APSS every tick extern apssPwrMeasStruct_t G_apss_pwr_meas; @@ -80,7 +80,7 @@ extern apssPwrMeasStruct_t G_apss_pwr_meas; 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 setApssModeArgs_t G_gpe_apss_set_mode_args; extern uint64_t G_gpe_apss_time_start; extern uint64_t G_gpe_apss_time_end; diff --git a/src/occ_gpe0/apss_composite.pS b/src/occ_gpe0/apss_composite.pS deleted file mode 100755 index 9e03c08..0000000 --- a/src/occ_gpe0/apss_composite.pS +++ /dev/null @@ -1,155 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/occ/gpe/apss_composite.pS $ -# -# OpenPOWER OnChipController Project -# -# Contributors Listed Below - COPYRIGHT 2011,2014 -# [+] Google Inc. -# [+] 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 - -////////////////////////////////////////////////////////////////////// -// Includes -////////////////////////////////////////////////////////////////////// -.nolist -#include "pgp.h" -#include "pgas.h" -.list - -////////////////////////////////////////////////////////////////////// -// Define Address Space -////////////////////////////////////////////////////////////////////// -.oci - -////////////////////////////////////////////////////////////////////// -// Define Symbols -////////////////////////////////////////////////////////////////////// - -#include <pss_constants.h> - -#define GPE_PROG_ID 0x0003 - -////////////////////////////////////////////////////////////////////// -// Define Structures -////////////////////////////////////////////////////////////////////// - -// Declare the offsets of the struct that will be passed to the -// GPE program via the ETR register -// -// struct G_gpe_apss_read_altitude_args = -// { -.struct 0 -ERROR_RC: - .struct ERROR_RC + 8 -ERROR_FFDC: - .struct ERROR_FFDC + 8 -CONFIG: -// }; - - -////////////////////////////////////////////////////////////////////// -// Begin Program -////////////////////////////////////////////////////////////////////// - -.text - -#include <gpe_macros.h> -#include <pss_macros.h> - -//-------------------------------------------------------------------- -// PORE-GPE Routine Specification: -// -// Name: GPE_apss_set_composite_mode -// -// Description: Set APSS into composite mode so OCC can read ADC, Temp & GPIO data -// -// Inputs: G_gpe_apss_set_composite_mode_args -// struct { -// PoreGpeErrorStruct error; -// apssCompositeConfigStruct_t config; // G_apss_composite_config (input to APSS) -// } G_gpe_apss_set_composite_mode_args; -// struct { -// uint64_t rc; // This should be read as 63:32=addr, 31:0=rc -// uint64_t ffdc; // Whatever GPE program puts in for FFDC data -// } PoreGpeErrorStruct; -// struct { -// uint8_t numAdcChannelsToRead; -// uint8_t numGpioPortsToRead; -// } apssCompositeConfigStruct -// -// Outputs: None (except FFDC on failure) -// -// End PORE-GPE Routine Specification -//-------------------------------------------------------------------- -.global GPE_apss_set_composite_mode -GPE_apss_set_composite_mode: - - // Copy passed Structure Pointer into A1 - mr A1, ETR - - // Wait for SPI operations to be complete (10usec timeout) - _wait_for_spi_ops_complete 10, error_timeout - - // Setup control regs - // frame size=16, out_count1=16, in_delay1=never, in_count2=16 - _putscom SPIPSS_P2S_CTRL_REG0, 0x4100000000000000 - // bridge_enable, clock_divider=7, 1 frame - _putscom SPIPSS_P2S_CTRL_REG1, 0x8090000000000000 - // inter_frame_delay=25 (2.5usec) - _putscom SPIPSS_P2S_CTRL_REG2, 0x0019000000000000 - - // APSS command to set composite data streaming mode (APSS cmd 0x8xxx, reserved bits are 1) - li D0, 0x8C00000000000000 - // last ADC channel address (0 = 1 ADC, etc) - ldandi D1, CONFIG, A1, 0x1F00000000000000 - srdi D1, D1, 56 - subs D1, D1, 1 - sldi D1, D1, 54 - or D0, D0, D1 - // number of GPIO ports to return (0 = 0 GPIOs, etc...) - ldandi D1, CONFIG, A1, 0x0003000000000000 - or D0, D0, D1 - // use auto2 mode (more reliable than composite mode) - _putscom SPIPSS_P2S_WDATA_REG, 0x3FC0000000000000 - - // Start SPI transaction - _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000 - - // Wait 20usec for apss becoming ready to send out the frame of composite mode - waits (20 * MICROSECONDS) - - halt - - -error_statusreg: - // An error/reserved bit was set when reading p2s status register... - // D0: P2S_STATUS_REG - _saveffdc GPE_PROG_ID, 0x0002 - halt - - -error_timeout: - // p2s_ongoing bit was never cleared after several retries... - // D0: P2S_STATUS_REG - _saveffdc GPE_PROG_ID, 0x0001 - halt - -////////////////////////////////////////////////////////////////////// -// End of Program -////////////////////////////////////////////////////////////////////// diff --git a/src/occ_gpe0/apss_init.c b/src/occ_gpe0/apss_init.c new file mode 100644 index 0000000..ca58404 --- /dev/null +++ b/src/occ_gpe0/apss_init.c @@ -0,0 +1,333 @@ +#include "pk.h"
+#include "ppe42_scom.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+#include "pss_constants.h"
+#include <apss_structs.h> //H file common with occ_405
+#include "apss_util.h"
+
+/*
+ * Function Specification
+ *
+ * Name: apss_start_spi_command
+ *
+ * Description: Writes the P2S_COMMAND register to trigger the execution
+ * of a command loaded into the P2S_WDATA_REG
+ *
+ * End Function Specification
+ */
+uint32_t apss_start_spi_command(initGpioArgs_t * args, uint8_t i_noWait)
+{
+ uint32_t rc = 0;
+ uint64_t regValue = 0x8000000000000000;
+
+ // Start SPI transaction
+ rc = putscom_abs(SPIPSS_P2S_COMMAND_REG, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_start_spi_command: SPIPSS_P2S_COMMAND_REG putscom failed. rc = 0x%08x",
+ rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_COMMAND_REG, rc, 0x8000000000000000);
+ }
+ else
+ {
+
+ pk_sleep(PK_MICROSECONDS(5));
+
+ if (!i_noWait)
+ {
+ rc = wait_spi_completion(args, SPIPSS_P2S_STATUS_REG, 10);
+ if (rc)
+ {
+ PK_TRACE("apss_start_spi_command: Timed out waiting for ops to complete. rc = 0x%08x",
+ rc);
+ //FFDC set in wait_spi_completion
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * Function Specification
+ *
+ * Name: apss_init_gpio
+ *
+ * Description: Initialize the APSS GPIO ports
+ *
+ * End Function Specification
+ */
+void apss_init_gpio(ipc_msg_t* cmd, void* arg)
+{
+ //Note: arg was set to 0 in ipc func table (ipc_func_tables.c), so don't use it
+
+ uint32_t rc;
+ ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd;
+ initGpioArgs_t *args = (initGpioArgs_t*)async_cmd->cmd_data;
+ uint64_t regValue = 0;
+
+ do
+ {
+ // Wait for SPI operations to be complete (up to 10usec timeout)
+ rc = wait_spi_completion(args, SPIPSS_P2S_STATUS_REG, 10);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: Timed out waiting for ops to complete. rc = 0x%08x", rc);
+ //FFDC set in wait_spi_completion
+ break;
+ }
+
+ ////////////////////////////
+ // Setup the control regs
+ // frame_size=16, out_count=16, in_delay1=never, in_count2=16
+ regValue = 0x410FC00004000000;
+ rc = putscom_abs(SPIPSS_P2S_CTRL_REG0, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPIPSS_P2S_CTRL_REG0 putscom failed. rc = 0x%08x", rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_CTRL_REG0, rc, regValue);
+ break;
+ }
+ // bridge_enable, clock_divider=7, 2 frames
+ regValue = 0x8090400000000000;
+ rc = putscom_abs(SPIPSS_P2S_CTRL_REG1, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPIPSS_P2S_CTRL_REG1 putscom failed. rc = 0x%08x", rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_CTRL_REG1, rc, regValue);
+ break;
+ }
+ // inter_frame_delay=50 (5usec)
+ regValue = 0x0019000000000000;
+ rc = putscom_abs(SPIPSS_P2S_CTRL_REG2, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPIPSS_P2S_CTRL_REG2 putscom failed. rc = 0x%08x", rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_CTRL_REG2, rc, regValue);
+ break;
+ }
+
+ uint64_t port = 0;
+ //Loop through the 2 ports setup
+ for (port=0; port <= 1; port++)
+ {
+ //////////////////////
+ // Direction (APSS cmd 0x4xxx); Configure GPIO mode (input or output)
+ regValue = args->config0.direction;
+ regValue = regValue << 48;
+ regValue |= 0x4000000000000000;
+ regValue |= (port << 56);
+
+ rc = putscom_abs(SPIPSS_P2S_WDATA_REG, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPIPSS_P2S_WDATA_REG putscom failed. value:0x%X. rc = 0x%08x",
+ regValue, rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_WDATA_REG, rc, regValue);
+ break;
+ }
+
+ // Start SPI transaction
+ rc = apss_start_spi_command(args,0);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPI command start failed. rc = 0x%08x", rc);
+ //FFDC already added
+ break;
+ }
+
+ //---------------
+ // Drive (APSS cmd 0x5xxx)
+ regValue = args->config0.drive;
+ regValue = regValue << 48;
+ regValue |= 0x5000000000000000;
+ regValue |= (port << 56);
+
+ rc = putscom_abs(SPIPSS_P2S_WDATA_REG, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPIPSS_P2S_WDATA_REG putscom failed. value:0x%X. rc = 0x%08x",
+ regValue, rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_WDATA_REG, rc, regValue);
+ break;
+ }
+ // Start SPI transaction
+ rc = apss_start_spi_command(args, 0);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPI command start failed. rc = 0x%08x", rc);
+ //FFDC already added.
+ break;
+ }
+
+ //--------------------
+ // Interrupt (APSS cmd 0x6xxx)
+ regValue = args->config0.interrupt;
+ regValue = regValue << 48;
+ regValue |= 0x6000000000000000;
+ regValue |= (port << 56);
+
+ rc = putscom_abs(SPIPSS_P2S_WDATA_REG, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPIPSS_P2S_WDATA_REG putscom failed. value:0x%X. rc = 0x%08x",
+ regValue, rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_WDATA_REG, rc, regValue);
+ break;
+ }
+
+ // Start SPI transaction
+ if (port == 0)
+ {
+ rc = apss_start_spi_command(args, 0);
+ }else
+ {
+ //No need to wait since it's the last command.
+ rc = apss_start_spi_command(args, 1);
+ }
+
+ if (rc)
+ {
+ PK_TRACE("apss_init_gpio: SPI command start failed. rc = 0x%08x", rc);
+ //FFDC already set
+ break;
+ }
+ }//End of port while loop.
+ }while(0);
+
+ // send back a successful response. OCC will check rc and ffdc
+ rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+
+ if(rc)
+ {
+ PK_TRACE("apss_init_gpio: Failed to send response back. Halting GPE0", rc);
+ apss_set_ffdc(&(args->error), 0x00, rc, regValue);
+ pk_halt();
+ }
+}
+
+/*
+ * Function Specification
+ *
+ * Name: apss_init_mode
+ *
+ * Description: Initialize the APSS mode
+ *
+ * End Function Specification
+ */
+void apss_init_mode(ipc_msg_t* cmd, void* arg)
+{
+ //Note: arg was set to 0 in ipc func table (ipc_func_tables.c), so don't use it
+
+ uint32_t rc = APSS_RC_SUCCESS;
+ uint32_t ipc_rc = IPC_RC_SUCCESS;
+ ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd;
+ setApssModeArgs_t *args = (setApssModeArgs_t*)async_cmd->cmd_data;
+ uint64_t regValue = 0;
+
+ do
+ {
+ // Wait for SPI operations to be complete (up to 10usec timeout)
+ rc = wait_spi_completion(args, SPIPSS_P2S_STATUS_REG, 10);
+ if (rc)
+ {
+ PK_TRACE("apss_init_mode: Timed out waiting for ops to complete. rc = 0x%08x", rc);
+ //FFDC set in wait_spi_completion
+ break;
+ }
+
+ ////////////////////////////
+ // Setup the control regs
+ // frame_size=16, out_count1=16, in_delay1=never, in_count2=16
+ regValue = 0x4100000000000000;
+ rc = putscom_abs(SPIPSS_P2S_CTRL_REG0, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_mode: SPIPSS_P2S_CTRL_REG0 putscom failed. rc = 0x%08x", rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_CTRL_REG0, rc, regValue);
+ break;
+ }
+
+ // bridge_enable, clock_divider=7, 1 frames
+ regValue = 0x8090000000000000;
+ rc = putscom_abs(SPIPSS_P2S_CTRL_REG1, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_mode: SPIPSS_P2S_CTRL_REG1 putscom failed. rc = 0x%08x", rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_CTRL_REG1, rc, regValue);
+ break;
+ }
+ // inter_frame_delay=25 (2.5usec)
+ regValue = 0x0019000000000000;
+ rc = putscom_abs(SPIPSS_P2S_CTRL_REG2, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_mode: SPIPSS_P2S_CTRL_REG2 putscom failed. rc = 0x%08x", rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_CTRL_REG2, rc, regValue);
+ break;
+ }
+
+ //Check for requested APSS mode.
+ if (args->config.mode == APSS_MODE_COMPOSITE)
+ {
+ // APSS command to set composite data streaming mode (APSS cmd 0x8xxx, reserved bits are 1)
+ // binary: 100011aaaa0000gg000000000000000000000000000000000000000000000000
+ regValue = args->config.numAdcChannelsToRead - 1; //aaaa => Address of last ADC channel (countOfADCChannels - 1)
+ regValue = regValue << 6; //Make space for GPIO port count
+ regValue |= (args->config.numGpioPortsToRead) & 0x03; //gg => Num of GPIO ports
+ regValue = (regValue << 51) | 0x8C00000000000000; //Add Command at D15-D12
+ }
+ else if (args->config.mode == APSS_MODE_AUTO2)
+ {
+ // Set Auto2 mode
+ regValue = 0x3FC0000000000000;
+ }
+ else
+ {
+ //Invalid mode.
+ PK_TRACE("apss_init_mode: Given invalid APSS Mode. Mode:0x%X", args->config.mode);
+ rc = APSS_RC_INVALID_APSS_MODE;
+ apss_set_ffdc(&(args->error), 0x00, rc, args->config.mode);
+ ipc_rc = IPC_RC_CMD_FAILED;
+ break;
+ }
+
+ rc = putscom_abs(SPIPSS_P2S_WDATA_REG, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_mode: SPIPSS_P2S_WDATA_REG putscom to set MODE failed. value:0x%X. rc = 0x%08x",
+ regValue, rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_WDATA_REG, rc, regValue);
+ break;
+ }
+
+ regValue = 0x8000000000000000;
+ // Start SPI transaction
+ rc = putscom_abs(SPIPSS_P2S_COMMAND_REG, ®Value);
+ if (rc)
+ {
+ PK_TRACE("apss_init_mode: SPIPSS_P2S_COMMAND_REG putscom failed. rc = 0x%08x",
+ rc);
+ apss_set_ffdc(&(args->error), SPIPSS_P2S_COMMAND_REG, rc, 0x8000000000000000);
+ }
+
+ //Wait 20usec for apss becoming ready to send out the frame of composite mode
+ pk_sleep(PK_MICROSECONDS(20));;
+
+ }while(0);
+
+ // send back a response
+ PK_TRACE("apss_init_mode: Sending APSS response ReturnCode:0x%X. APSSrc:0x%X (0 = Success)",
+ ipc_rc, rc);
+ rc = ipc_send_rsp(cmd, ipc_rc);
+
+ //If we fail to send ipc response, then this error takes prescedence over any other error.
+ //TODO: See if there's another space to write the error out to.
+ if(rc)
+ {
+ PK_TRACE("apss_init_mode: Failed to send response back to mode initialization. Halting GPE0", ipc_rc);
+ apss_set_ffdc(&(args->error), 0x00, ipc_rc, regValue);
+ pk_halt();
+ }
+}
diff --git a/src/occ_gpe0/apss_init.pS b/src/occ_gpe0/apss_init.pS deleted file mode 100755 index 23dfdd7..0000000 --- a/src/occ_gpe0/apss_init.pS +++ /dev/null @@ -1,226 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/occ/gpe/apss_init.pS $ -# -# OpenPOWER OnChipController Project -# -# Contributors Listed Below - COPYRIGHT 2011,2014 -# [+] Google Inc. -# [+] 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 - -////////////////////////////////////////////////////////////////////// -// Includes -////////////////////////////////////////////////////////////////////// -.nolist -#include "pgp.h" -#include "pgas.h" -.list - -////////////////////////////////////////////////////////////////////// -// Define Address Space -////////////////////////////////////////////////////////////////////// -.oci - -////////////////////////////////////////////////////////////////////// -// Define Symbols -////////////////////////////////////////////////////////////////////// - -#include <pss_constants.h> - -#define GPE_PROG_ID 0x0001 - -////////////////////////////////////////////////////////////////////// -// Define Structures -////////////////////////////////////////////////////////////////////// - -// Declare the offsets of the struct that will be passed to the -// GPE program via the ETR register -// -// struct G_gpe_apss_initialize_gpio_args = -// { -.struct 0 -ERROR_RC: - .struct ERROR_RC + 8 -ERROR_FFDC: - .struct ERROR_FFDC + 8 -CONFIG: -// }; - -////////////////////////////////////////////////////////////////////// -// Begin Program -////////////////////////////////////////////////////////////////////// - -.text - -#include <gpe_macros.h> -#include <pss_macros.h> - -//-------------------------------------------------------------------- -// Name: _perform_spi_transaction (MACRO) -// -// Description: Start SPI transaction, wait for 5usec, and then -// wait for operation to complete. -// -// Inputs: None -// -// Outputs: None (on error, D0 will contain status register) -// -// Modifies: CTR, D0, D1 -//-------------------------------------------------------------------- -.macro _perform_spi_transaction - -// Start SPI transaction -_putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000 - -// wait 5usec -waits (5 * MICROSECONDS) - -_wait_for_spi_ops_complete 10, error_timeout - -.endm - - -//-------------------------------------------------------------------- -// PORE-GPE Routine Specification: -// -// Name: GPE_apss_initialize_gpio -// -// Description: Initialize APSS GPIO pins for Input/Output, Interrupt -// Drive H/L -// -// Inputs: G_gpe_apss_initialize_gpio_args - Error and G_gpio_config -// struct { -// PoreGpeErrorStruct error; -// apssGpioConfigStruct gpio_config0 // G_gpio_config[0] (input to APSS) -// apssGpioConfigStruct gpio_config1 // G_gpio_config[1] (input to APSS) -// } G_gpe_apss_initialize_gpio_args -// struct { -// uint64_t rc; // This should be read as 63:32=addr, 31:0=rc -// uint64_t ffdc; // Whatever GPE program puts in for FFDC data -// } PoreGpeErrorStruct; -// struct apssGpioConfigStruct -// { -// uint8_t direction; -// uint8_t drive; -// uint8_t interrupt; -// } -// -// Outputs: None (except FFDC on failure) -// -// End PORE-GPE Routine Specification -//-------------------------------------------------------------------- -.global GPE_apss_initialize_gpio -GPE_apss_initialize_gpio: - - // Copy passed Structure Pointer into A1 - mr A1, ETR - halt - - // TODO Clean this up, unreachable code left over below, hook for future - // function - - // Wait for SPI operations to be complete (up to 10usec timeout) - _wait_for_spi_ops_complete 10, error_timeout - - // Setup control regs - // frame_size=16, out_count=16, in_delay1=never, in_count2=16 - _putscom SPIPSS_P2S_CTRL_REG0, 0x410FC00004000000 - // bridge_enable, clock_divider=7, 2 frames - _putscom SPIPSS_P2S_CTRL_REG1, 0x8090400000000000 - // inter_frame_delay=50 (5usec) - _putscom SPIPSS_P2S_CTRL_REG2, 0x0019000000000000 - - // Build apss commands based on gpio_config arguments - // Arguments are each 1 byte long and contain default - // value to be used to init each item (Direction/Drive/Interrupt) - - //// Port 0 - - // Port 0 - Direction (APSS cmd 0x40xx) - ldandi D0, CONFIG, A1, 0xFF00000000000000 - srdi D0, D0, 8 - ori D0, D0, 0x4000000000000000 - _putscom_d0 SPIPSS_P2S_WDATA_REG - - _perform_spi_transaction - - // Port 0 - Drive (APSS cmd 0x50xx) - ldandi D0, CONFIG, A1, 0x00FF000000000000 - ori D0, D0, 0x5000000000000000 - _putscom_d0 SPIPSS_P2S_WDATA_REG - - _perform_spi_transaction - - // Port 0 - Interrupt (APSS cmd 0x60xx) - ldandi D0, CONFIG, A1, 0x0000FF0000000000 - ori D0, D0, 0x0060000000000000 - sldi D0, D0, 8 - _putscom_d0 SPIPSS_P2S_WDATA_REG - - _perform_spi_transaction - - //// Port 1 - - // Port 1 - Direction (APSS cmd 0x41xx) - ldandi D0, CONFIG, A1, 0x000000FF00000000 - ori D0, D0, 0x0000410000000000 - sldi D0, D0, 16 - _putscom_d0 SPIPSS_P2S_WDATA_REG - - _perform_spi_transaction - - // Port 1 - Drive (APSS cmd 0x51xx) - ldandi D0, CONFIG, A1, 0x00000000FF000000 - ori D0, D0, 0x0000005100000000 - sldi D0, D0, 24 - _putscom_d0 SPIPSS_P2S_WDATA_REG - - _perform_spi_transaction - - // Port 1 - Interrups (APSS cmd 0x61xx) - ldandi D0, CONFIG, A1, 0x0000000000FF0000 - ori D0, D0, 0x0000000061000000 - sldi D0, D0, 32 - _putscom_d0 SPIPSS_P2S_WDATA_REG - - // Start SPI transaction (dont need to wait for p2s_ongoing bit since last cmd) - _putscom SPIPSS_P2S_COMMAND_REG, 0x8000000000000000 - - // wait 5usec - waits (5 * MICROSECONDS) - - halt - - -error_statusreg: - // An error/reserved bit was set when reading p2s status register... - // D0: P2S_STATUS_REG - _saveffdc GPE_PROG_ID, 0x0002 - halt - - -error_timeout: - // p2s_ongoing bit was never cleared after several retries... - // D0: P2S_STATUS_REG - _saveffdc GPE_PROG_ID, 0x0001 - halt - -////////////////////////////////////////////////////////////////////// -// End of Program -////////////////////////////////////////////////////////////////////// diff --git a/src/occ_gpe0/apss_read.c b/src/occ_gpe0/apss_read.c index 04d6e72..87863c6 100644 --- a/src/occ_gpe0/apss_read.c +++ b/src/occ_gpe0/apss_read.c @@ -30,8 +30,7 @@ #include "ipc_async_cmd.h" #include "pss_constants.h" #include <apss_structs.h> - -extern int wait_spi_completion(int reg, int timeout); //wait_spi.c +#include "apss_util.h" void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) { @@ -56,7 +55,7 @@ void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) // wait for ADC completion, or timeout after 5 micro seconds. // scom register SPIPSS_ADC_STATUS_REG's bit 0 (HWCTRL_ONGOING) // indicates when completion occurs. - rc = wait_spi_completion(SPIPSS_ADC_STATUS_REG, 5); + rc = wait_spi_completion(args, SPIPSS_ADC_STATUS_REG, 5); if(rc) // Timeout Reached, and SPI transaction didn't complete, copy over rc { PK_TRACE("gpe0:apss_start_pwr_meas_read:wait_spi_completion failed with rc = 0x%08x", rc); @@ -161,7 +160,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg) // wait for ADC completion, or timeout after 100 micro seconds. // scom register SPIPSS_ADC_STATUS_REG's bit 0 (HWCTRL_ONGOING) // indicates when completion occurs. - rc = wait_spi_completion(SPIPSS_ADC_STATUS_REG, 100); + rc = wait_spi_completion(args, SPIPSS_ADC_STATUS_REG, 100); if(rc) // Timeout Reached, and SPI transaction didn't complete, copy returned status into rc // REVIEW: Should we also copy something into the ffdc as well? { @@ -234,7 +233,7 @@ void apss_complete_pwr_meas_read(ipc_msg_t* cmd, void* arg) // wait for ADC completion, or timeout after 100 micro seconds. // scom register SPIPSS_ADC_STATUS_REG's bit 0 (HWCTRL_ONGOING) // indicates when completion occurs. - rc = wait_spi_completion(SPIPSS_ADC_STATUS_REG, 100); + rc = wait_spi_completion(args, SPIPSS_ADC_STATUS_REG, 100); if(rc) // Timeout Reached, and SPI transaction didn't complete, copy returned status into rc // REVIEW: Should we also copy something into the ffdc as well? whether in wait_spi_completion or here? { diff --git a/src/occ_gpe0/apss_util.c b/src/occ_gpe0/apss_util.c new file mode 100644 index 0000000..4fa586a --- /dev/null +++ b/src/occ_gpe0/apss_util.c @@ -0,0 +1,96 @@ + +#include "pk.h" +#include "ppe42_scom.h" +#include "pss_constants.h" +#include "apss_util.h" +#define SPIPSS_P2S_ONGOING_MASK 0x8000000000000000 + +/* + * Function Specification + * + * Name: apss_set_ffdc + * + * Description: Fills up the error struct with the given data. + * + * End Function Specification + */ +void apss_set_ffdc(GpeErrorStruct *o_error, uint32_t i_addr, uint32_t i_rc, uint64_t i_ffdc) +{ + + o_error->addr = i_addr; + //Return codes defined in apss_struct.h + o_error->rc = i_rc; + o_error->ffdc = i_ffdc; + +} + +//-------------------------------------------------------------------- +// Name: wait_spi +// +// Description: Read the specified register (SPIPSS_P2S_STATUS_REG +// or SPIPSS_ADC_STATUS_REG), and check if it's p2s_ongoing +// bit is 0 (operations done). If not, wait +// up to the timeout usec (~1usec per retry). +// If still not clear, continue looping, +// If error/reserved bits are set, a return code will be sent back +// +// Inputs: timeout - # usec to wait for ongoing bit to clear +// Register: SPIPSS_P2S_STATUS_REG or SPIPSS_ADC_STATUS_REG +// +// return: 0 -> Success: spi transaction completed within timeout limit +// not 0 -> timeout: spi transaction did not complete within timeout +// bits 0:7 are masked, and returned back for potential analysis +// of the reason that the transaction timed out +//-------------------------------------------------------------------- + +int wait_spi_completion(initGpioArgs_t *args, uint32_t reg, uint8_t timeout) +{ + int i; + int rc; + uint64_t status; + + if((reg != SPIPSS_P2S_STATUS_REG) && (reg != SPIPSS_ADC_STATUS_REG)) + { + PK_TRACE("gpe0:wait_spi_completion failed: Invalid Register 0x%08x", reg); + rc = APSS_RC_INVALID_REG; + apss_set_ffdc((&(args->error)),reg,rc, 0x00); + } + else + { + // Keep polling the P2S_ONGOING bits for timeout + for (i = 0; i< timeout; i++) + { + rc = getscom_abs(reg, &status); + if(rc) + { + PK_TRACE("gpe0:wait_spi_completion failed with rc = 0x%08x", rc); + apss_set_ffdc(&(args->error),reg,APSS_RC_SCOM_GET_FAILED, rc); + rc = APSS_RC_SCOM_GET_FAILED; + break; + } + + + // bit zero is the P2s_ONGOING / HWCTRL_ONGOING + // set to 1: means operation is in progress (ONGOING) + // set to 0: means operation is complete, therefore exit for loop. + if((status & SPIPSS_P2S_ONGOING_MASK) == 0) + { + rc = 0; + break; + } + + // sleep for 1 microsecond before retry + pk_sleep(PK_MICROSECONDS(1)); + } + } + + //Timed out waiting on P2S_ONGOING bit. + if (i >= timeout) + { + PK_TRACE("gpe0:wait_spi_completion Timed out waiting for p2s_ongoing to clear."); + apss_set_ffdc(&(args->error),reg,APSS_RC_SPI_TIMEOUT, rc); + rc = APSS_RC_SPI_TIMEOUT; + } + + return rc; +} diff --git a/src/occ_gpe0/apss_util.h b/src/occ_gpe0/apss_util.h new file mode 100644 index 0000000..a3a2f26 --- /dev/null +++ b/src/occ_gpe0/apss_util.h @@ -0,0 +1,11 @@ + +#ifndef _APSS_UTIL_H +#define _APSS_UTIL_H + +#include <apss_structs.h> + +void apss_set_ffdc(GpeErrorStruct *o_error, uint32_t i_addr, uint32_t i_rc, uint64_t i_ffdc); + +int wait_spi_completion(initGpioArgs_t *args, uint32_t reg, uint8_t timeout); + +#endif //_APSS_UTIL_H diff --git a/src/occ_gpe0/gpe_export.h b/src/occ_gpe0/gpe_export.h index 6922638..84184e7 100755 --- a/src/occ_gpe0/gpe_export.h +++ b/src/occ_gpe0/gpe_export.h @@ -36,6 +36,6 @@ typedef struct { uint64_t error; }; uint64_t ffdc; -} PoreGpeErrorStruct; // Same for every GPE program +} GpeErrorStruct; // Same for every GPE program #endif //_GPE_EXPORT_H diff --git a/src/occ_gpe0/gpe_macros.h b/src/occ_gpe0/gpe_macros.h deleted file mode 100755 index b5f605c..0000000 --- a/src/occ_gpe0/gpe_macros.h +++ /dev/null @@ -1,153 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/gpe/gpe_macros.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 _GPE_MACROS_H -#define _GPE_MACROS_H - -//-------------------------------------------------------------------- -// Macro Specification: -// -// Name: _saveffdc -// -// Description: Save FFDC into error structure -// -// struct { -// uint64_t rc; // This should be read as 63:32=addr, 31:0=rc -// uint64_t ffdc; // Whatever GPE program puts in for FFDC data -// } PoreGpeErrorStruct; -// -// - Copy D0 into PoreGpeErrorStruct->ffdc -// - Copy \gpe_id into PoreGpeErrorStruct->rc[63:32] -// - Copy \rc into PoreGpeErrorStruct->rc[31:0] -// -// Inputs: \gpe_id - Unique GPE program number to identify what prog failed -// \rc - Unique GPE error code that will indicate failure -// ETR - Assumed to be set to base address of -// passed argument structure -// -// End Macro Specification -//-------------------------------------------------------------------- -.macro _saveffdc, gpe_id, rc - - // Make sure passed Structure Pointer is loaded into A1 - mr A1, ETR - - // Save address to send back (upper word of D1) - srdi D1, D1, 32 - // TODO: Simcs does not support SPRG0 yet, so use 24 bit CTR for now - //mr SPRG0, D1 - mr CTR, D1 - - // Check if rc was already saved... - ld D1, 0, A1 - andi D1, D1, 0xFFFFFFFF00000000 - branz D1, 1f - - // Save D0 into FFDC of error structure - std D0, 8, A1 - ld D0, 8, A1 - - // Save address to send back... (truncated to 24 bits) - mr D0, CTR - // Save GPE progam ID - li D1, \gpe_id - sldi D1, D1, 16 - // and return code - ori D1, D1, \rc - sldi D1, D1, 32 - // combine GPE program/RC with address - or D0, D0, D1 - - // Save data into error structure - std D0, 0, A1 - ld D0, 8, A1 - ld D0, 0, A1 - -1: -.endm - - -//-------------------------------------------------------------------- -// Macro Specification: -// -// Name: _getscom -// -// Description: Get a SCOM based on passed in Address, put it in D0 -// -// Inputs: SCOM Address -// -// Outputs: D0 - Result of SCOM -// -// End Macro Specification -//-------------------------------------------------------------------- -.macro _getscom, address - - lpcs P0, \address - ld D0, \address, P0 -.endm - -//-------------------------------------------------------------------- -// Macro Specification: -// -// Name: _putscom -// -// Description: Store data into SCOM based on passed in Address -// -// Inputs: SCOM Address, Data -// -// Outputs: None -// -// End Macro Specification -//-------------------------------------------------------------------- -.macro _putscom, address, data - lpcs P0, \address - li D0, \data - std D0, \address, P0 -.endm - -//-------------------------------------------------------------------- -// Macro Specification: -// -// Name: _putscom_d0 -// -// Description: Store D0 into SCOM based on passed in Address -// -// Inputs: SCOM Address -// -// Outputs: None -// -// End Macro Specification -//-------------------------------------------------------------------- -.macro _putscom_d0, address - lpcs P0, \address - std D0, \address, P0 -.endm - -#define TOD_VALUE_REG 0x00040020 - -// Constant for use in wait statments: waits (5 * MICROSECONDS) -#define MICROSECONDS 600 - -#endif //_GPE_MACROS_H diff --git a/src/occ_gpe0/ipc_func_tables.c b/src/occ_gpe0/ipc_func_tables.c index 82ff16e..c1ea1e7 100644 --- a/src/occ_gpe0/ipc_func_tables.c +++ b/src/occ_gpe0/ipc_func_tables.c @@ -25,6 +25,8 @@ #include "ipc_api.h" #include "ipc_ping.h" +void apss_init_gpio(ipc_msg_t* cmd, void* arg); +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); @@ -52,11 +54,11 @@ IPC_MT_FUNC_TABLE_END // Function table for single target (processor-specific) functions IPC_ST_FUNC_TABLE_START IPC_MSGQ_HANDLER(&G_gpe0_test_msgq0) // 0 - IPC_ST_TEST_FUNC0 -IPC_HANDLER(apss_start_pwr_meas_read, 0) // 1 - IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID -IPC_HANDLER(apss_continue_pwr_meas_read, 0) // 2 - IPC_ST_APSS_CONTINUE_PWR_MEAS_READ_FUNCID -IPC_HANDLER(apss_complete_pwr_meas_read, 0) // 3 - IPC_ST_APSS_COMPLETE_PWR_MEAS_READ_FUNCID -IPC_HANDLER_DEFAULT // 4 -IPC_HANDLER_DEFAULT // 5 +IPC_HANDLER(apss_init_gpio, 0) // 1 - IPC_ST_APSS_INIT_GPIO_FUNCID +IPC_HANDLER(apss_init_mode, 0) // 2 - IPC_ST_APSS_INIT_MODE_FUNCID +IPC_HANDLER(apss_start_pwr_meas_read, 0) // 3 - IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID +IPC_HANDLER(apss_continue_pwr_meas_read, 0) // 4 - IPC_ST_APSS_CONTINUE_PWR_MEAS_READ_FUNCID +IPC_HANDLER(apss_complete_pwr_meas_read, 0) // 5 - IPC_ST_APSS_COMPLETE_PWR_MEAS_READ_FUNCID IPC_HANDLER_DEFAULT // 6 IPC_HANDLER_DEFAULT // 7 IPC_HANDLER_DEFAULT // 8 diff --git a/src/occ_gpe0/topfiles.mk b/src/occ_gpe0/topfiles.mk index e1c81b3..ae62fae 100644 --- a/src/occ_gpe0/topfiles.mk +++ b/src/occ_gpe0/topfiles.mk @@ -22,7 +22,7 @@ # permissions and limitations under the License. # # IBM_PROLOG_END_TAG -TOP-C-SOURCES = gpe0_main.c pk_app_irq_table.c ipc_func_tables.c apss_read.c wait_spi.c +TOP-C-SOURCES = gpe0_main.c pk_app_irq_table.c ipc_func_tables.c apss_read.c apss_util.c apss_init.c TOP-S-SOURCES = TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o) diff --git a/src/occ_gpe0/wait_spi.c b/src/occ_gpe0/wait_spi.c deleted file mode 100644 index 1bff747..0000000 --- a/src/occ_gpe0/wait_spi.c +++ /dev/null @@ -1,104 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_405/wait_spi.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 */ - - -// This file contains a single function that deals with polling the -// xxxxx_ONGOING status bit in two spi scom registers to confirm completion -// of SPI transactions. -// -// In the near future, this function may be combined with additional spi -// utilities and in that case the filename will definitely change. - - - -#include "pk.h" -#include "ppe42_scom.h" -#include "pss_constants.h" - -//-------------------------------------------------------------------- -// Name: wait_spi -// -// Description: Read the specified register (SPIPSS_P2S_STATUS_REG -// or SPIPSS_ADC_STATUS_REG), and and check if it p2s_ongoing -// bit is 0 (operations done). If not, wait -// up to the timeout usec (~1usec per retry). -// If still not clear, continue looping, -// If error/reserved bits are set, a return code will be sent back -// -// Inputs: timeout - # usec to wait for ongoing bit to clear -// Register: SPIPSS_P2S_STATUS_REG or SPIPSS_ADC_STATUS_REG -// -// return: 0 -> Success: spi transaction completed within timeout limit -// not 0 -> timeout: spi transaction did not complete within timeout -// bits 0:7 are masked, and returned back for potential analysis -// of the reason that the transaction timed out -//-------------------------------------------------------------------- - -int wait_spi_completion(int reg, int timeout) -{ - int i; - int rc; - uint64_t status; - - if(reg != SPIPSS_P2S_STATUS_REG && // Only these SPI status registers tested - reg != SPIPSS_ADC_STATUS_REG) // for xxxx_ONGOING bits for now. - { - PK_TRACE("gpe0:wait_spi_completion failed: Invalid Register 0x%08x", reg); - pk_halt(); - } - - for (i = 0; i< timeout; i++) // Keep polling the xxxx_ONGOING bits for timeout - { - rc = getscom_abs(reg, &status); - if(rc) - { - PK_TRACE("gpe0:wait_spi_completion failed with rc = 0x%08x", rc); - pk_halt(); - } - - - // bit zero is the P2s_ONGOING / HWCTRL_ONGOING - // set to 1: means operation is in progress (ONGOING) - // reset to 0: means operation is complete - if(status & 0x8000000000000000) - break; - pk_sleep(PK_MICROSECONDS(1)); // sleep for 1 microsecond before retry - } - - if (i < timeout) // success: transaction completed before timeout limit - { - // REVIEW: It is true that the operation completed, but should we - // check whether a reserved or error bit was set? ... - // If this is possible, then we should set the ffdc to indicate that - return 0; - } - else //timeout: - // P2s_ONGOING / HWCTRL_ONGOING bit is on, other status info too - // return 32 MSB only, (only 8 are used now, - // while the 56 LSB are reserved in P9 - { - return (status >> 32); - } -} |