From 10df96d0bf6378f2d6ede7bfb27f21af41c309d5 Mon Sep 17 00:00:00 2001 From: Wael El-Essawy Date: Fri, 20 Nov 2015 13:47:12 -0600 Subject: OCC GPE0: Core Data Collection infrastructure in GPE0 Create IPC function for core data collection return dummy data at this point to allow 405 to schedule and "use" data back. Change-Id: I520e9333fa25e37127d6af693ad6f21da3431939 RTC: 131183 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22247 Reviewed-by: Fadi Kassem Reviewed-by: Wael Elessawy Tested-by: Fadi Kassem --- src/occ_gpe0/apss_init.c | 704 ++++++++++++++++++++--------------------- src/occ_gpe0/apss_read.c | 28 +- src/occ_gpe0/apss_util.c | 196 ------------ src/occ_gpe0/apss_util.h | 48 --- src/occ_gpe0/core_data.c | 18 +- src/occ_gpe0/gpe_core_data.c | 76 +++++ src/occ_gpe0/gpe_util.c | 196 ++++++++++++ src/occ_gpe0/gpe_util.h | 48 +++ src/occ_gpe0/ipc_func_tables.c | 9 +- src/occ_gpe0/topfiles.mk | 3 +- 10 files changed, 707 insertions(+), 619 deletions(-) delete mode 100644 src/occ_gpe0/apss_util.c delete mode 100644 src/occ_gpe0/apss_util.h create mode 100644 src/occ_gpe0/gpe_core_data.c create mode 100644 src/occ_gpe0/gpe_util.c create mode 100644 src/occ_gpe0/gpe_util.h (limited to 'src/occ_gpe0') diff --git a/src/occ_gpe0/apss_init.c b/src/occ_gpe0/apss_init.c index 91af255..ec232fd 100644 --- a/src/occ_gpe0/apss_init.c +++ b/src/occ_gpe0/apss_init.c @@ -22,355 +22,355 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -#include "pk.h" -#include "ppe42_scom.h" -#include "ipc_api.h" -#include "ipc_async_cmd.h" -#include "pss_constants.h" -#include //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, regValue); - 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 - { - - busy_wait(5); - - if (!i_noWait) - { - rc = wait_spi_completion(&(args->error), 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; - uint32_t ipc_send_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; - - PK_TRACE("apss_init_gpio: started."); - - do - { - // Wait for SPI operations to be complete (up to 10usec timeout) - rc = wait_spi_completion(&(args->error), 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, regValue); - 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, regValue); - 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, regValue); - 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, regValue); - 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, regValue); - 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, regValue); - 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 - ipc_send_rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS); - - if(ipc_send_rc) - { - PK_TRACE("apss_init_gpio: Failed to send response back. rc = 0x%08x. Halting GPE0", - ipc_send_rc); - apss_set_ffdc(&(args->error), 0x00, ipc_send_rc, regValue); - pk_halt(); - } - - if(rc == 0) // if ipc_send_rc is 0, wont reach this instruction (pk_halt) - { - PK_TRACE("apss_init_gpio: completed successfully."); - } - -} - -/* - * 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 = GPE_RC_SUCCESS; - uint32_t ipc_rc = IPC_RC_SUCCESS; - uint32_t ipc_send_rc; - ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; - setApssModeArgs_t *args = (setApssModeArgs_t*)async_cmd->cmd_data; - uint64_t regValue = 0; - - PK_TRACE("apss_init_mode: started."); - - do - { - // Wait for SPI operations to be complete (up to 10usec timeout) - rc = wait_spi_completion(&(args->error), 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, regValue); - 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, regValue); - 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, regValue); - 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 = GPE_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, regValue); - 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, regValue); - 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 - busy_wait(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); - ipc_send_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(ipc_send_rc) - { - PK_TRACE("apss_init_mode: Failed to send response back to mode initialization. Halting GPE0", - ipc_send_rc); - apss_set_ffdc(&(args->error), 0x00, ipc_send_rc, regValue); - pk_halt(); - } - - if(rc == 0 && ipc_rc == IPC_RC_SUCCESS) // if ipc_send_rc, wont reach this instruction (pk_halt) - { - PK_TRACE("apss_init_mode: completed successfully."); - } -} +#include "pk.h" +#include "ppe42_scom.h" +#include "ipc_api.h" +#include "ipc_async_cmd.h" +#include "pss_constants.h" +#include //H file common with occ_405 +#include "gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_start_spi_command: SPIPSS_P2S_COMMAND_REG putscom failed. rc = 0x%08x", + rc); + gpe_set_ffdc(&(args->error), SPIPSS_P2S_COMMAND_REG, rc, 0x8000000000000000); + } + else + { + + busy_wait(5); + + if (!i_noWait) + { + rc = wait_spi_completion(&(args->error), 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; + uint32_t ipc_send_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; + + PK_TRACE("apss_init_gpio: started."); + + do + { + // Wait for SPI operations to be complete (up to 10usec timeout) + rc = wait_spi_completion(&(args->error), 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, regValue); + if (rc) + { + PK_TRACE("apss_init_gpio: SPIPSS_P2S_CTRL_REG0 putscom failed. rc = 0x%08x", rc); + gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_init_gpio: SPIPSS_P2S_CTRL_REG1 putscom failed. rc = 0x%08x", rc); + gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_init_gpio: SPIPSS_P2S_CTRL_REG2 putscom failed. rc = 0x%08x", rc); + gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_init_gpio: SPIPSS_P2S_WDATA_REG putscom failed. value:0x%X. rc = 0x%08x", + regValue, rc); + gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_init_gpio: SPIPSS_P2S_WDATA_REG putscom failed. value:0x%X. rc = 0x%08x", + regValue, rc); + gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_init_gpio: SPIPSS_P2S_WDATA_REG putscom failed. value:0x%X. rc = 0x%08x", + regValue, rc); + gpe_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 + ipc_send_rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS); + + if(ipc_send_rc) + { + PK_TRACE("apss_init_gpio: Failed to send response back. rc = 0x%08x. Halting GPE0", + ipc_send_rc); + gpe_set_ffdc(&(args->error), 0x00, ipc_send_rc, regValue); + pk_halt(); + } + + if(rc == 0) // if ipc_send_rc is 0, wont reach this instruction (pk_halt) + { + PK_TRACE("apss_init_gpio: completed successfully."); + } + +} + +/* + * 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 = GPE_RC_SUCCESS; + uint32_t ipc_rc = IPC_RC_SUCCESS; + uint32_t ipc_send_rc; + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + setApssModeArgs_t *args = (setApssModeArgs_t*)async_cmd->cmd_data; + uint64_t regValue = 0; + + PK_TRACE("apss_init_mode: started."); + + do + { + // Wait for SPI operations to be complete (up to 10usec timeout) + rc = wait_spi_completion(&(args->error), 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, regValue); + if (rc) + { + PK_TRACE("apss_init_mode: SPIPSS_P2S_CTRL_REG0 putscom failed. rc = 0x%08x", rc); + gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_init_mode: SPIPSS_P2S_CTRL_REG1 putscom failed. rc = 0x%08x", rc); + gpe_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, regValue); + if (rc) + { + PK_TRACE("apss_init_mode: SPIPSS_P2S_CTRL_REG2 putscom failed. rc = 0x%08x", rc); + gpe_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 = GPE_RC_INVALID_APSS_MODE; + gpe_set_ffdc(&(args->error), 0x00, rc, args->config.mode); + ipc_rc = IPC_RC_CMD_FAILED; + break; + } + + rc = putscom_abs(SPIPSS_P2S_WDATA_REG, regValue); + if (rc) + { + PK_TRACE("apss_init_mode: SPIPSS_P2S_WDATA_REG putscom to set MODE failed. value:0x%X. rc = 0x%08x", + regValue, rc); + gpe_set_ffdc(&(args->error), SPIPSS_P2S_WDATA_REG, rc, regValue); + break; + } + + regValue = 0x8000000000000000; + // Start SPI transaction + rc = putscom_abs(SPIPSS_P2S_COMMAND_REG, regValue); + if (rc) + { + PK_TRACE("apss_init_mode: SPIPSS_P2S_COMMAND_REG putscom failed. rc = 0x%08x", + rc); + gpe_set_ffdc(&(args->error), SPIPSS_P2S_COMMAND_REG, rc, 0x8000000000000000); + } + + //Wait 20usec for apss becoming ready to send out the frame of composite mode + busy_wait(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); + ipc_send_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(ipc_send_rc) + { + PK_TRACE("apss_init_mode: Failed to send response back to mode initialization. Halting GPE0", + ipc_send_rc); + gpe_set_ffdc(&(args->error), 0x00, ipc_send_rc, regValue); + pk_halt(); + } + + if(rc == 0 && ipc_rc == IPC_RC_SUCCESS) // if ipc_send_rc, wont reach this instruction (pk_halt) + { + PK_TRACE("apss_init_mode: completed successfully."); + } +} diff --git a/src/occ_gpe0/apss_read.c b/src/occ_gpe0/apss_read.c index 065a02b..bcc602c 100644 --- a/src/occ_gpe0/apss_read.c +++ b/src/occ_gpe0/apss_read.c @@ -30,7 +30,7 @@ #include "ipc_async_cmd.h" #include "pss_constants.h" #include -#include "apss_util.h" +#include "gpe_util.h" /* * Function Specifications: @@ -90,7 +90,7 @@ void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_start_pwr_meas_read: SPIPSS_ADC_CTRL_REG0 putscom failed. rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_CTRL_REG0, GPE_RC_SCOM_PUT_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_CTRL_REG0, GPE_RC_SCOM_PUT_FAILED, rc); break; } @@ -103,7 +103,7 @@ void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_start_pwr_meas_read: SPIPSS_ADC_CTRL_REG1 putscom failed. rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_CTRL_REG1, GPE_RC_SCOM_PUT_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_CTRL_REG1, GPE_RC_SCOM_PUT_FAILED, rc); break; } @@ -116,7 +116,7 @@ void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_start_pwr_meas_read: SPIPSS_ADC_CTRL_REG2 putscom failed. rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_CTRL_REG2, GPE_RC_SCOM_PUT_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_CTRL_REG2, GPE_RC_SCOM_PUT_FAILED, rc); break; } @@ -129,7 +129,7 @@ void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_start_pwr_meas_read: SPIPSS_ADC_WDATA_REG putscom failed. rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_WDATA_REG, GPE_RC_SCOM_PUT_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_WDATA_REG, GPE_RC_SCOM_PUT_FAILED, rc); break; } @@ -143,7 +143,7 @@ void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_start_pwr_meas_read: SPIPSS_ADC_COMMAND_REG putscom failed. rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_COMMAND_REG, GPE_RC_SCOM_PUT_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_COMMAND_REG, GPE_RC_SCOM_PUT_FAILED, rc); break; } @@ -154,7 +154,7 @@ void apss_start_pwr_meas_read(ipc_msg_t* cmd, void* arg) if(rc) { PK_TRACE("apss_start_pwr_meas_read: Failed to send response back. Halting GPE0", rc); - apss_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); pk_halt(); } } @@ -218,7 +218,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_continue_pwr_meas_read: SPIPSS_ADC_RDATA_REG0 getscom failed with rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG0, GPE_RC_SCOM_GET_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG0, GPE_RC_SCOM_GET_FAILED, rc); break; } @@ -228,7 +228,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_continue_pwr_meas_read: SPIPSS_ADC_RDATA_REG1 getscom failed with rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG1, GPE_RC_SCOM_GET_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG1, GPE_RC_SCOM_GET_FAILED, rc); break; } @@ -238,7 +238,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_continue_pwr_meas_read: SPIPSS_ADC_RDATA_REG2 getscom failed with rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG2, GPE_RC_SCOM_GET_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG2, GPE_RC_SCOM_GET_FAILED, rc); break; } @@ -248,7 +248,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_continue_pwr_meas_read: SPIPSS_ADC_RDATA_REG3 getscom failed with rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG3, GPE_RC_SCOM_GET_FAILED, rc); + gpe_set_ffdc(&(args->error), SPIPSS_ADC_RDATA_REG3, GPE_RC_SCOM_GET_FAILED, rc); break; } } while(0); @@ -258,7 +258,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg) if(rc) { PK_TRACE("apss_continue_pwr_meas_read: Failed to send response back. Halting GPE0", rc); - apss_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); pk_halt(); } } @@ -315,7 +315,7 @@ void apss_complete_pwr_meas_read(ipc_msg_t* cmd, void* arg) { PK_TRACE("apss_complete_pwr_meas_read: TOD_VALUE_REG getscom failed. rc = 0x%08x", rc); - apss_set_ffdc(&(args->error), TOD_VALUE_REG, GPE_RC_SCOM_GET_FAILED, rc); + gpe_set_ffdc(&(args->error), TOD_VALUE_REG, GPE_RC_SCOM_GET_FAILED, rc); break; } @@ -326,7 +326,7 @@ void apss_complete_pwr_meas_read(ipc_msg_t* cmd, void* arg) if(rc) { PK_TRACE("apss_complete_pwr_meas_read: Failed to send response back. Halting GPE0", rc); - apss_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); pk_halt(); } } diff --git a/src/occ_gpe0/apss_util.c b/src/occ_gpe0/apss_util.c deleted file mode 100644 index a742be3..0000000 --- a/src/occ_gpe0/apss_util.c +++ /dev/null @@ -1,196 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_gpe0/apss_util.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -#include "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; - -} - -/* - * Function Specification: - * - * Name: wait_spi_completion - * - * 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: error: a pointer to a GpeErrorStruct, to populate rc, ffdc, - * and address, in case a scom get error happens - * 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:31 are masked, and returned back for potential - * analysis of the reason that the transaction timed out - * - * End Function Specification - */ - -int wait_spi_completion(GpeErrorStruct *error, uint32_t reg, uint8_t timeout) -{ - int i = 0; - 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 = GPE_RC_INVALID_REG; - apss_set_ffdc(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(error, reg, GPE_RC_SCOM_GET_FAILED, rc); - rc = GPE_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 - busy_wait(1); - } - } - - //Timed out waiting on P2S_ONGOING / HWCTRL_ONGOING bit. - if (i >= timeout) - { - PK_TRACE("gpe0:wait_spi_completion Timed out waiting for p2s_ongoing to clear."); - apss_set_ffdc(error, reg, GPE_RC_SPI_TIMEOUT, rc); - rc = GPE_RC_SPI_TIMEOUT; - } - - return rc; -} - -/* - * Function Specification: - * - * Name: busy_wait - * - * Description: a counting loop to simulate sleep calls, and is ISR safe. - * - * Inputs: t_microseconds: time to sleep in microseconds - * - * return: none - * - * End Function Specification - */ - - -void busy_wait(uint32_t t_microseconds) -{ - uint32_t start_decrementer_value; // The decrementer register value at the beginning - uint32_t end_decrementer_value; // The decrementer register value at the end - uint32_t current_decrementer_value; // The current decrementer register value - uint32_t duration; - MFDEC(start_decrementer_value); // get the decrementer register value at the beginning - current_decrementer_value = start_decrementer_value; - - // multiply the delay time by the 37.5 MHz external clock frequency. - // I believe that the ppe42_mullw macro works fine, but the - // compiler parameter settings seems broken. - // @todo: This is a temporary fix, use external frequency directive. - duration = (t_microseconds << 5) - + (t_microseconds << 2) - + (t_microseconds) - + (t_microseconds >> 1); - - // Calculate the decrementer register value at the end of the busy wait period - end_decrementer_value = start_decrementer_value - duration; - - if(start_decrementer_value < end_decrementer_value); // decrementer overflows during the busy wait? - { - MFDEC(current_decrementer_value); - while(current_decrementer_value < end_decrementer_value) // Wait until Decrementer overflows - MFDEC(current_decrementer_value); - } - - while (current_decrementer_value > end_decrementer_value) // Wait until end_decrementer_value is reached - MFDEC(current_decrementer_value); -} - -void ipc_scom_operation(ipc_msg_t* cmd, void* arg) -{ - int l_rc; - ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; - ipc_scom_op_t *scom_op = (ipc_scom_op_t*) async_cmd->cmd_data; - - if (scom_op->read) - { - l_rc = getscom_abs(scom_op->addr, &scom_op->data); - } - else - { - l_rc = putscom_abs(scom_op->addr, scom_op->data); - } - - if(l_rc) - { - scom_op->rc = l_rc; - PK_TRACE("Error doing generic scom! RC: 0x%08X Addr: 0x%08X Read: %d Data: 0x%08X", l_rc, - scom_op->addr, scom_op->read, scom_op->data); - } -} diff --git a/src/occ_gpe0/apss_util.h b/src/occ_gpe0/apss_util.h deleted file mode 100644 index 2107d40..0000000 --- a/src/occ_gpe0/apss_util.h +++ /dev/null @@ -1,48 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/occ_gpe0/apss_util.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -#ifndef _APSS_UTIL_H -#define _APSS_UTIL_H - -#include -#include -#include -#include - -void apss_set_ffdc(GpeErrorStruct *o_error, uint32_t i_addr, uint32_t i_rc, uint64_t i_ffdc); - -int wait_spi_completion(GpeErrorStruct *error, uint32_t reg, uint8_t timeout); - -// Read decrementer register -#define MFDEC(reg_var) \ -asm volatile \ - ( \ - " mfdec %[dec_var] \n" \ - : [dec_var]"=r"(reg_var) \ - ); - -void busy_wait(uint32_t t_microseconds); - -#endif //_APSS_UTIL_H diff --git a/src/occ_gpe0/core_data.c b/src/occ_gpe0/core_data.c index da79327..5bf37fb 100644 --- a/src/occ_gpe0/core_data.c +++ b/src/occ_gpe0/core_data.c @@ -30,13 +30,21 @@ uint32_t get_core_data(uint32_t i_core, CoreData* o_data) { uint32_t rc = 0; - uint32_t size = sizeof(CoreData) / 8; +/* uint32_t size = sizeof(CoreData) / 8; uint64_t* ptr = (uint64_t*)o_data; uint32_t i = 0; - for(i = 0; i < size; ++i) - { - ptr[i] = 0; - } +*/ + // Fake Sensor Initialization for testing + + o_data->dts.core[0].fields.reading = 0x200+i_core*2; + o_data->dts.core[1].fields.reading = 0x200+i_core*2+1; + + o_data->dts.cache.fields.reading = 0x100+i_core; + + o_data->dts.core[0].fields.valid = 1; + o_data->dts.core[1].fields.valid = 1; + o_data->dts.cache.fields.valid = 1; + /* TODO RTC 141391 - No simics support to test this yet. uint32_t coreSelect = CHIPLET_CORE_ID(i_core); diff --git a/src/occ_gpe0/gpe_core_data.c b/src/occ_gpe0/gpe_core_data.c new file mode 100644 index 0000000..d4b56c5 --- /dev/null +++ b/src/occ_gpe0/gpe_core_data.c @@ -0,0 +1,76 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_gpe0/core_data.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include "core_data.h" +#include "ipc_async_cmd.h" +#include "gpe_err.h" +#include "gpe_util.h" +#include "proc_shared.h" + +/* + * Function Specifications: + * + * Name: gpe_get_core_data + * + * Description: extract core number, call get_core data with the + * proper core id and pointer to CoreData + * + * Inputs: cmd is a pointer to IPC msg's cmd and cmd_data struct + * + * Outputs: error: sets rc, address, and ffdc in the cmd_data's + * GpeErrorStruct + * + * End Function Specification + */ + + +void gpe_get_core_data(ipc_msg_t* cmd, void* arg) +{ + uint32_t rc; // return code + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + ipc_core_data_parms_t *args = (ipc_core_data_parms_t*) async_cmd->cmd_data; + + + rc = get_core_data(args->core_num, // core ID + args->data); // CoreData* + + if(rc) + { + PK_TRACE("gpe_get_core_data: get_core_data failed, rc = 0x%08x, core = 0x%08x", + rc, args->core_num); + gpe_set_ffdc(&(args->error), args->core_num, + GPE_RC_GET_CORE_DATA_FAILED, rc); + } + + // send back a response, IPC success even if ffdc/rc are non zeros + rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS); + if(rc) + { + PK_TRACE("gpe_get_core_data: Failed to send response back. Halting GPE0", rc); + gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + pk_halt(); + } + +} diff --git a/src/occ_gpe0/gpe_util.c b/src/occ_gpe0/gpe_util.c new file mode 100644 index 0000000..10996d4 --- /dev/null +++ b/src/occ_gpe0/gpe_util.c @@ -0,0 +1,196 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_gpe0/gpe_util.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include "pk.h" +#include "ppe42_scom.h" +#include "pss_constants.h" +#include "gpe_util.h" +#define SPIPSS_P2S_ONGOING_MASK 0x8000000000000000 + +/* + * Function Specification + * + * Name: gpe_set_ffdc + * + * Description: Fills up the error struct with the given data. + * + * End Function Specification + */ +void gpe_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; + +} + +/* + * Function Specification: + * + * Name: wait_spi_completion + * + * 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: error: a pointer to a GpeErrorStruct, to populate rc, ffdc, + * and address, in case a scom get error happens + * 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:31 are masked, and returned back for potential + * analysis of the reason that the transaction timed out + * + * End Function Specification + */ + +int wait_spi_completion(GpeErrorStruct *error, uint32_t reg, uint8_t timeout) +{ + int i = 0; + 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 = GPE_RC_INVALID_REG; + gpe_set_ffdc(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); + gpe_set_ffdc(error, reg, GPE_RC_SCOM_GET_FAILED, rc); + rc = GPE_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 + busy_wait(1); + } + } + + //Timed out waiting on P2S_ONGOING / HWCTRL_ONGOING bit. + if (i >= timeout) + { + PK_TRACE("gpe0:wait_spi_completion Timed out waiting for p2s_ongoing to clear."); + gpe_set_ffdc(error, reg, GPE_RC_SPI_TIMEOUT, rc); + rc = GPE_RC_SPI_TIMEOUT; + } + + return rc; +} + +/* + * Function Specification: + * + * Name: busy_wait + * + * Description: a counting loop to simulate sleep calls, and is ISR safe. + * + * Inputs: t_microseconds: time to sleep in microseconds + * + * return: none + * + * End Function Specification + */ + + +void busy_wait(uint32_t t_microseconds) +{ + uint32_t start_decrementer_value; // The decrementer register value at the beginning + uint32_t end_decrementer_value; // The decrementer register value at the end + uint32_t current_decrementer_value; // The current decrementer register value + uint32_t duration; + MFDEC(start_decrementer_value); // get the decrementer register value at the beginning + current_decrementer_value = start_decrementer_value; + + // multiply the delay time by the 37.5 MHz external clock frequency. + // I believe that the ppe42_mullw macro works fine, but the + // compiler parameter settings seems broken. + // @todo: This is a temporary fix, use external frequency directive. + duration = (t_microseconds << 5) + + (t_microseconds << 2) + + (t_microseconds) + + (t_microseconds >> 1); + + // Calculate the decrementer register value at the end of the busy wait period + end_decrementer_value = start_decrementer_value - duration; + + if(start_decrementer_value < end_decrementer_value); // decrementer overflows during the busy wait? + { + MFDEC(current_decrementer_value); + while(current_decrementer_value < end_decrementer_value) // Wait until Decrementer overflows + MFDEC(current_decrementer_value); + } + + while (current_decrementer_value > end_decrementer_value) // Wait until end_decrementer_value is reached + MFDEC(current_decrementer_value); +} + +void ipc_scom_operation(ipc_msg_t* cmd, void* arg) +{ + int l_rc; + ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd; + ipc_scom_op_t *scom_op = (ipc_scom_op_t*) async_cmd->cmd_data; + + if (scom_op->read) + { + l_rc = getscom_abs(scom_op->addr, &scom_op->data); + } + else + { + l_rc = putscom_abs(scom_op->addr, scom_op->data); + } + + if(l_rc) + { + scom_op->rc = l_rc; + PK_TRACE("Error doing generic scom! RC: 0x%08X Addr: 0x%08X Read: %d Data: 0x%08X", l_rc, + scom_op->addr, scom_op->read, scom_op->data); + } +} diff --git a/src/occ_gpe0/gpe_util.h b/src/occ_gpe0/gpe_util.h new file mode 100644 index 0000000..a6a086e --- /dev/null +++ b/src/occ_gpe0/gpe_util.h @@ -0,0 +1,48 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_gpe0/gpe_util.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef _APSS_UTIL_H +#define _APSS_UTIL_H + +#include +#include +#include +#include + +void gpe_set_ffdc(GpeErrorStruct *o_error, uint32_t i_addr, uint32_t i_rc, uint64_t i_ffdc); + +int wait_spi_completion(GpeErrorStruct *error, uint32_t reg, uint8_t timeout); + +// Read decrementer register +#define MFDEC(reg_var) \ +asm volatile \ + ( \ + " mfdec %[dec_var] \n" \ + : [dec_var]"=r"(reg_var) \ + ); + +void busy_wait(uint32_t t_microseconds); + +#endif //_APSS_UTIL_H diff --git a/src/occ_gpe0/ipc_func_tables.c b/src/occ_gpe0/ipc_func_tables.c index 4d1e97f..a1ed36d 100644 --- a/src/occ_gpe0/ipc_func_tables.c +++ b/src/occ_gpe0/ipc_func_tables.c @@ -24,7 +24,8 @@ /* IBM_PROLOG_END_TAG */ #include "ipc_api.h" #include "ipc_ping.h" -#include "apss_util.h" +#include "core_data.h" +#include "proc_shared.h" void apss_init_gpio(ipc_msg_t* cmd, void* arg); void apss_init_mode(ipc_msg_t* cmd, void* arg); @@ -33,6 +34,8 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg); void apss_complete_pwr_meas_read(ipc_msg_t* cmd, void* arg); void ipc_scom_operation(ipc_msg_t* cmd, void* arg); +void gpe_get_core_data(ipc_msg_t* cmd, void* arg); + extern ipc_msgq_t G_gpe0_test_msgq0; // Function table for multi target (common) functions @@ -61,8 +64,8 @@ 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(ipc_scom_operation, 0) // 6 - IPC_ST_SCOM_OPERATION -IPC_HANDLER_DEFAULT // 7 +IPC_HANDLER(gpe_get_core_data, 0) // 6 - IPC_ST_GET_CORE_DATA_FUNCID +IPC_HANDLER(ipc_scom_operation, 0) // 7 - IPC_ST_SCOM_OPERATION IPC_HANDLER_DEFAULT // 8 IPC_HANDLER_DEFAULT // 9 IPC_HANDLER_DEFAULT // 10 diff --git a/src/occ_gpe0/topfiles.mk b/src/occ_gpe0/topfiles.mk index 6e1b3b1..58f261c 100644 --- a/src/occ_gpe0/topfiles.mk +++ b/src/occ_gpe0/topfiles.mk @@ -22,7 +22,8 @@ # 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 apss_util.c apss_init.c core_data.c +TOP-C-SOURCES = gpe0_main.c pk_app_irq_table.c ipc_func_tables.c apss_read.c \ + apss_init.c gpe_util.c core_data.c gpe_core_data.c TOP-S-SOURCES = TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o) -- cgit v1.2.1