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 /src/occ_gpe0 | |
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>
Diffstat (limited to 'src/occ_gpe0')
-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 |
11 files changed, 453 insertions, 650 deletions
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); - } -} |