diff options
| author | spashabk-in <shakeebbk@in.ibm.com> | 2017-12-10 11:48:20 -0600 |
|---|---|---|
| committer | Sachin Gupta <sgupta2m@in.ibm.com> | 2018-01-24 22:39:07 -0500 |
| commit | 6db778b0fd24312e943ba96a5a99f5044f623dc2 (patch) | |
| tree | c61fcc2cb6b1760988fd74f7f3a1c029496fe3c9 /src/sbefw/app/common | |
| parent | c47554f1d2ee06e40bcb6f5b2427b02790aa280a (diff) | |
| download | talos-sbe-6db778b0fd24312e943ba96a5a99f5044f623dc2.tar.gz talos-sbe-6db778b0fd24312e943ba96a5a99f5044f623dc2.zip | |
[SBE-code-re-org][7] App and core files separation
Separating app specific code from core library
Change-Id: I4b67aa4ff6230cbeea44417ebadb94db6010cbc0
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/50745
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com>
Diffstat (limited to 'src/sbefw/app/common')
| -rw-r--r-- | src/sbefw/app/common/appcommonfiles.mk | 10 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdCntrlTimer.C | 153 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdCntrlTimer.H (renamed from src/sbefw/app/common/sbeappcommon.C) | 31 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdgeneric.C | 398 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdgeneric.H | 158 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdringaccess.C | 361 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdringaccess.H | 71 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdscomaccess.C | 433 | ||||
| -rw-r--r-- | src/sbefw/app/common/sbecmdscomaccess.H | 97 |
9 files changed, 1702 insertions, 10 deletions
diff --git a/src/sbefw/app/common/appcommonfiles.mk b/src/sbefw/app/common/appcommonfiles.mk index 98a1da7a..cb8ac54d 100644 --- a/src/sbefw/app/common/appcommonfiles.mk +++ b/src/sbefw/app/common/appcommonfiles.mk @@ -5,7 +5,8 @@ # # OpenPOWER sbe Project # -# Contributors Listed Below - COPYRIGHT 2015,2017 +# Contributors Listed Below - COPYRIGHT 2015,2018 +# [+] International Business Machines Corp. # # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,14 +22,17 @@ # permissions and limitations under the License. # # IBM_PROLOG_END_TAG -APPCOMMONPIBMEM-CPP-SOURCES = sbeappcommon.C +APPCOMMONPIBMEM-CPP-SOURCES = sbecmdscomaccess.C +APPCOMMONPIBMEM-CPP-SOURCES += sbecmdringaccess.C +APPCOMMONPIBMEM-CPP-SOURCES += sbecmdCntrlTimer.C +APPCOMMONPIBMEM-CPP-SOURCES += sbecmdgeneric.C APPCOMMONPIBMEM-C-SOURCES = APPCOMMONPIBMEM-S-SOURCES = APPCOMMONPIBMEM_OBJECTS = $(APPCOMMONPIBMEM-C-SOURCES:.c=.o) $(APPCOMMONPIBMEM-CPP-SOURCES:.C=.o) $(APPCOMMONPIBMEM-S-SOURCES:.S=.o) -APPCOMMONSEEPROM-CPP-SOURCES = sbeappcommon.C +APPCOMMONSEEPROM-CPP-SOURCES = sbecmdgeneric.C APPCOMMONSEEPROM-C-SOURCES = APPCOMMONSEEPROM-S-SOURCES = diff --git a/src/sbefw/app/common/sbecmdCntrlTimer.C b/src/sbefw/app/common/sbecmdCntrlTimer.C new file mode 100644 index 00000000..ff650eac --- /dev/null +++ b/src/sbefw/app/common/sbecmdCntrlTimer.C @@ -0,0 +1,153 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/app/common/sbecmdCntrlTimer.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* */ +/* */ +/* 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 */ +/* + * @file: src/sbefw/sbecmdCntrlTimer.C + * + * @brief This file contains the SBE Timer Commands + * + */ + +#include "sbecmdCntrlTimer.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeFFDC.H" +#include "sbeHostMsg.H" +#include "sbeHostUtils.H" +#include "sbeTimerSvc.H" +#include "sbeglobals.H" + +#include "fapi2.H" +using namespace fapi2; + +// Global instance to track PK timer +static timerService g_hostTimerSvc; + +// Callback +void sbeTimerExpiryCallback(void *) +{ + #define SBE_FUNC "sbeTimerExpiryCallback " + SBE_ENTER(SBE_FUNC); + + do + { + // indicate the Host via Bit SBE_SBE2PSU_DOORBELL_SET_BIT14 + // that Timer has expired + SBE_INFO(SBE_FUNC "Updating door bell bit 14"); + uint32_t l_rc = sbeSetSbe2PsuDbBitX(SBE_SBE2PSU_DOORBELL_SET_BIT14); + if(l_rc) + { + SBE_ERROR(SBE_FUNC " Failed to Write " + "SBE_SBE2PSU_DOORBELL_SET_BIT14"); + pk_halt(); + } + }while(0); + SBE_EXIT(SBE_FUNC); + #undef SBE_FUNC + +} +///////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +uint32_t sbeCntrlTimer( uint8_t *i_pArg ) +{ + #define SBE_FUNC "sbeCntrlTimer " + SBE_ENTER(SBE_FUNC); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_fapiRc = FAPI2_RC_SUCCESS; + + do + { + if(SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_START_TIMER) + { + uint64_t time = 0; + l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(time)/sizeof(uint64_t)), + &time, true); + + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1"); + break; + } + + SBE_INFO(SBE_FUNC "Start Timer. Time: [%08X]us", + SBE::lower32BWord(time)); + + l_rc = g_hostTimerSvc.stopTimer( ); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INTERNAL_ERROR, l_rc); + SBE_ERROR(SBE_FUNC" g_hostTimerSvc.stopTimer failed"); + l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + break; + } + + l_rc = g_hostTimerSvc.startTimer( (uint32_t )time, + (PkTimerCallback)&sbeTimerExpiryCallback); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INTERNAL_ERROR, l_rc); + SBE_ERROR(SBE_FUNC" g_hostTimerSvc.startTimer failed"); + l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + break; + } + break; + } + // Acknowledge host + l_rc = sbeAcknowledgeHost(); + if(l_rc) + { + SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over " + "SBE_SBE2PSU_DOORBELL_SET_BIT1"); + break; + } + + if(SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags & SBE_PSU_FLAGS_STOP_TIMER) + { + SBE_INFO(SBE_FUNC "Stop Timer."); + l_rc = g_hostTimerSvc.stopTimer( ); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INTERNAL_ERROR, l_rc); + SBE_ERROR(SBE_FUNC" g_hostTimerSvc.stopTimer failed"); + l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + break; + } + break; + } + + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus( SBE_PRI_INVALID_COMMAND, + SBE_SEC_COMMAND_NOT_SUPPORTED); + SBE_ERROR(SBE_FUNC" Not a valid flag 0x%4X", + (uint16_t) SBE_GLOBAL->sbePsu2SbeCmdReqHdr.flags); + }while(0); + + // Send the response + sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + diff --git a/src/sbefw/app/common/sbeappcommon.C b/src/sbefw/app/common/sbecmdCntrlTimer.H index 46ebbab6..2236586f 100644 --- a/src/sbefw/app/common/sbeappcommon.C +++ b/src/sbefw/app/common/sbecmdCntrlTimer.H @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/sbefw/app/common/sbeappcommon.C $ */ +/* $Source: src/sbefw/app/common/sbecmdCntrlTimer.H $ */ /* */ /* OpenPOWER sbe Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -21,8 +21,25 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -#ifdef __SBEFW_SEEPROM__ -void func1(){} -#else -void func2(){} -#endif //__SBEFW_SEEPROM__ +/* + * @file: ppe/sbe/sbefw/sbecmdCntrlTimer.H + * + * @brief This file contains the SBE control timer command details + * + */ + +#ifndef __SBEFW_SBECMD_CNTRL_TIMER_H +#define __SBEFW_SBECMD_CNTRL_TIMER_H + +#include <stdint.h> + +/** + * @brief SBE Psu Control timer chipop (0xD401) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the Psu access utility + */ +uint32_t sbeCntrlTimer( uint8_t *i_pArg ); + +#endif // __SBEFW_SBECMD_CNTRL_TIMER_H diff --git a/src/sbefw/app/common/sbecmdgeneric.C b/src/sbefw/app/common/sbecmdgeneric.C new file mode 100644 index 00000000..0601c20b --- /dev/null +++ b/src/sbefw/app/common/sbecmdgeneric.C @@ -0,0 +1,398 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/app/common/sbecmdgeneric.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* */ +/* */ +/* 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 */ +/* + * @file: ppe/sbe/sbefw/sbecmdgeneric.C + * + * @brief This file contains the SBE generic Commands + * + */ + +#include "sbecmdgeneric.H" +#include "sbefifo.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbe_build_info.H" +#include "sbeFifoMsgUtils.H" +#include "sbeFFDC.H" +#include "sberegaccess.H" +#include "sbestates.H" +#include "sbeHostMsg.H" +#include "sbeHostUtils.H" +#include "sbeglobals.H" +#include "sbeXipUtils.H" + +#include "fapi2.H" +//#include "p9_xip_image.h" + +using namespace fapi2; + +#ifdef __SBEFW_SEEPROM__ +// Functions +//---------------------------------------------------------------------------- +uint32_t sbeGetCapabilities (uint8_t *i_pArg) +{ + #define SBE_FUNC "sbeGetCapabilities " + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t len = 0; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeCapabilityRespMsg_t capMsg; + + do + { + // Dequeue the EOT entry as no more data is expected. + rc = sbeUpFifoDeq_mult (len, NULL); + // @TODO via RTC : 130575 + // Optimize both the RC handling and + // FIFO operation infrastructure. + if ( rc != SBE_SEC_OPERATION_SUCCESSFUL ) + { + // Let command processor routine to handle the RC + break; + } + + len = sizeof(capMsg)/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &capMsg); + if (rc) + { + break; + } + + rc = sbeDsSendRespHdr(respHdr); + }while(0); + + if( rc ) + { + SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc); + } + return rc; + #undef SBE_FUNC +} + +// Functions +//---------------------------------------------------------------------------- +uint32_t sbeGetFfdc (uint8_t *i_pArg) +{ + #define SBE_FUNC "sbeGetFfdc " + SBE_ENTER(SBE_FUNC); + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t len = 0; + sbeRespGenHdr_t respHdr; + respHdr.init(); + + do + { + // Dequeue the EOT entry as no more data is expected. + rc = sbeUpFifoDeq_mult (len, NULL); + + if ( rc != SBE_SEC_OPERATION_SUCCESSFUL ) + { + // Let command processor routine to handle the RC + break; + } + + SbeFFDCPackage sbeFfdcPack; + sbeResponseFfdc_t l_ffdc; + + // If need be, force collect HWP FFDC async to the real HWP fail. + // Else, just send back what the SBE already has. + sbeFfdcPack.collectAsyncHwpFfdc (); + + l_ffdc.setRc(g_FfdcData.fapiRc); + SBE_INFO(SBE_FUNC"FAPI RC is %x", g_FfdcData.fapiRc); + // If no ffdc , exit; + if( (l_ffdc.getRc() != FAPI2_RC_SUCCESS)) + { + // making sure ffdc length is multiples of uint32_t + assert((g_FfdcData.ffdcLength % sizeof(uint32_t)) == 0); + uint32_t ffdcDataLenInWords = g_FfdcData.ffdcLength + / sizeof(uint32_t); + // Set failed command information + // Sequence Id is 0 by default for Fifo interface + // @TODO via RTC : 149074 + // primary and secondary status should be picked + // from the globals. + l_ffdc.setCmdInfo(0, respHdr.cmdClass, respHdr.command); + // Add HWP specific ffdc data length + l_ffdc.lenInWords += ffdcDataLenInWords; + len = sizeof(sbeResponseFfdc_t)/sizeof(uint32_t); + rc = sbeDownFifoEnq_mult ( len, ( uint32_t *) &l_ffdc); + if (rc) + { + break; + } + //Send HWP internal Data + rc = sbeDownFifoEnq_mult ( ffdcDataLenInWords, + ( uint32_t *) &g_FfdcData.ffdcData); + if (rc) + { + break; + } + + } + //Send the FFDC data over FIFO. + // @TODO via RTC : 149074 + // primary and secondary status should be picked + // from the globals. + // Check for Primary and Secondary Status from Globals and then send + // internal FFDC. + rc = sbeFfdcPack.sendOverFIFO(respHdr, + SBE_FFDC_ALL_DUMP, + len, + true); + if (rc) + { + break; + } + rc = sbeDsSendRespHdr(respHdr); + + if (rc) + { + break; + } + // If we are able to send ffdc, turn off async ffdc bit + (void)SbeRegAccess::theSbeRegAccess().updateAsyncFFDCBit(false); + SBE_GLOBAL->asyncFfdcRC = FAPI2_RC_SUCCESS; + + }while(0); + + if( rc ) + { + SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc); + } + return rc; + #undef SBE_FUNC +} + +//--------------------------------------------------------------------------- +uint32_t sbeSetFFDCAddr(uint8_t *i_pArg) +{ +#define SBE_FUNC "sbeSetFFDCAddr" + SBE_ENTER(SBE_FUNC); + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_fapiRc = FAPI2_RC_SUCCESS; + sbeSetFFDCAddrReq_t l_req = {}; + + do + { + // Extract the request + // and send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1 + rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(l_req)/sizeof(uint64_t)), + (uint64_t*)&l_req, + true); + if(SBE_SEC_OPERATION_SUCCESSFUL != rc) + { + SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and " + "SBE_HOST_PSU_MBOX_REG2"); + break; + } + + l_req.getFFDCAddr(SBE_GLOBAL->hostFFDCAddr); + l_req.getPassThroughCmdAddr(SBE_GLOBAL->hostPassThroughCmdAddr); + + SBE_INFO(SBE_FUNC" Global hostFFDCAddr size[0x%08X] Address[0x%08X%08X]", + static_cast<uint32_t>(SBE_GLOBAL->hostFFDCAddr.size), + static_cast<uint32_t>(SBE::higher32BWord(SBE_GLOBAL->hostFFDCAddr.addr)), + static_cast<uint32_t>(SBE::lower32BWord(SBE_GLOBAL->hostFFDCAddr.addr))); + SBE_INFO(SBE_FUNC" Global hostPassCmdAddr size[0x%08X] Address[0x%08X%08X]", + static_cast<uint32_t>(SBE_GLOBAL->hostPassThroughCmdAddr.size), + static_cast<uint32_t>(SBE::higher32BWord(SBE_GLOBAL->hostPassThroughCmdAddr.addr)), + static_cast<uint32_t>(SBE::lower32BWord(SBE_GLOBAL->hostPassThroughCmdAddr.addr))); + + } while(false); + // Send the response + sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, rc); + + return rc; + SBE_EXIT(SBE_FUNC); +#undef SBE_FUNC +} + +//---------------------------------------------------------------------------- +uint32_t sbeStashKeyAddrPair( uint8_t *i_pArg ) +{ + #define SBE_FUNC "sbeStashKeyAddrPair" + SBE_ENTER(SBE_FUNC); + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t fapiRc = FAPI2_RC_SUCCESS; + do + { + stashMsg_t l_stashMsg; + // Send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1, once both + // key/addr is extracted out of MBOX_REG1 and MBOX_REG2 + rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(stashMsg_t)/sizeof(uint64_t)), + (uint64_t*)&l_stashMsg, true); + if(SBE_SEC_OPERATION_SUCCESSFUL != rc) + { + SBE_ERROR(SBE_FUNC" Failed to extract " + "SBE_HOST_PSU_MBOX_REG1/SBE_HOST_PSU_MBOX_REG2"); + break; + } + + SBE_INFO(SBE_FUNC "Key[0x%08X] Addr[0x%08X %08X]", + l_stashMsg.key, SBE::higher32BWord(l_stashMsg.addr), + SBE::lower32BWord(l_stashMsg.addr)); + + // Update the Key-Addr Pair in local Memory + bool update = SBE_GLOBAL->sbeKeyAddrPair.updatePair(l_stashMsg.key, + l_stashMsg.addr); + if(false == update) + { + // Update RC to indicate Host that Stash memory is full + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus( + SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_INPUT_BUFFER_OVERFLOW); + break; + } + }while(0); + + // Send the response + sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, fapiRc, rc); + + SBE_EXIT(SBE_FUNC); + return rc; + #undef SBE_FUNC +} + +//---------------------------------------------------------------------------- +uint32_t sbeSetSystemFabricMap( uint8_t *i_pArg ) +{ + #define SBE_FUNC "sbeSetSystemFabricMap" + SBE_ENTER(SBE_FUNC); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_fapiRc = FAPI2_RC_SUCCESS; + + do + { + uint64_t l_sysFabricMap = 0; + //send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1 + l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(l_sysFabricMap)/sizeof(uint64_t)), + &l_sysFabricMap, true); + + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC" Failed to extract SBE_HOST_PSU_MBOX_REG1"); + break; + } + + SBE_INFO(SBE_FUNC "Sytem Fabric Map [0x%08X][%08X]", + SBE::higher32BWord(l_sysFabricMap), + SBE::lower32BWord(l_sysFabricMap)); + + PLAT_ATTR_INIT(fapi2::ATTR_SBE_SYS_CONFIG, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + l_sysFabricMap); + }while(0); + + // Send the response + sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} +#endif //__SBEFW_SEEPROM__ + +#ifndef __SBEFW_SEEPROM__ +//---------------------------------------------------------------------------- +uint32_t sbeFifoQuiesce( uint8_t *i_pArg ) +{ + #define SBE_FUNC "sbeFifoQuiesce" + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t len = 0; + sbeRespGenHdr_t respHdr; + respHdr.init(); + + do + { + // Dequeue the EOT entry as no more data is expected. + rc = sbeUpFifoDeq_mult (len, NULL); + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc); + + // Set Quiesce State + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_QUIESCE_EVENT); + + rc = sbeDsSendRespHdr(respHdr); + if(rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + SBE_ERROR(SBE_FUNC "sbeDsSendRespHdr failed"); + // Not Breaking here since we can't revert back on the set state + } + }while(0); + + if( rc ) + { + SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc); + } + return rc; + #undef SBE_FUNC +} + +//---------------------------------------------------------------------------- +uint32_t sbePsuQuiesce( uint8_t *i_pArg ) +{ + #define SBE_FUNC "sbePsuQuiesce" + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + + do + { + // Send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1 + // This util method will check internally on the mbox0 register if + // ACK is requested. + rc = sbeAcknowledgeHost(); + if (rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + SBE_ERROR(SBE_FUNC " Failed to Sent Ack to Host over " + "SBE_SBE2PSU_DOORBELL_SET_BIT1"); + break; + } + + // Set Quiesce State + (void)SbeRegAccess::theSbeRegAccess().stateTransition( + SBE_QUIESCE_EVENT); + + rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + (uint64_t*)(&SBE_GLOBAL->sbeSbe2PsuRespHdr), + (sizeof(SBE_GLOBAL->sbeSbe2PsuRespHdr)/sizeof(uint64_t)), + true); + if(rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + SBE_ERROR(SBE_FUNC" Failed to write SBE_HOST_PSU_MBOX_REG4"); + // Not Breaking here since we can't revert back on the set state + } + }while(0); + + if( rc ) + { + SBE_ERROR( SBE_FUNC"Failed. rc[0x%X]", rc); + } + return rc; + #undef SBE_FUNC +} +#endif //not __SBEFW_SEEPROM__ + diff --git a/src/sbefw/app/common/sbecmdgeneric.H b/src/sbefw/app/common/sbecmdgeneric.H new file mode 100644 index 00000000..9ff350a5 --- /dev/null +++ b/src/sbefw/app/common/sbecmdgeneric.H @@ -0,0 +1,158 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/app/common/sbecmdgeneric.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ +/* */ +/* */ +/* 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 */ +/* + * @file: ppe/sbe/sbefw/sbecmdgeneric.H + * + * @brief This file contains the SBE Generic command details + * + */ + +#ifndef __SBEFW_SBECMDGENERIC_H +#define __SBEFW_SBECMDGENERIC_H + +#include <stdint.h> +#include <p9_sbe_hb_structures.H> + +typedef struct sbeStashMemoryPair +{ + // This is coming from p9_sbe_hb_structures.H + keyAddrPair_t keyValuePairfromHost; + + // Default Constructor to initialize addr/key to 0xFF + sbeStashMemoryPair() + { + for(uint8_t cnt=0; cnt<MAX_ROW_COUNT; cnt++) + { + keyValuePairfromHost.addr[cnt] = 0xFFFFFFFFFFFFFFFFULL; + keyValuePairfromHost.key[cnt] = 0xFF; + } + } + + bool updatePair(uint8_t key, uint64_t addr) + { + bool l_return = false; + // Check if Key already exist, if yes update addr there + for(uint8_t cnt=0; cnt<MAX_ROW_COUNT; cnt++) + { + if(keyValuePairfromHost.key[cnt] == key) + { + keyValuePairfromHost.addr[cnt] = addr; + l_return = true; + break; + } + } + if(false == l_return) // Insert the new key into a free pair + { + for(uint8_t cnt=0; cnt<MAX_ROW_COUNT; cnt++) + { + if(keyValuePairfromHost.key[cnt] == 0xFF) + { + keyValuePairfromHost.key[cnt] = key; + keyValuePairfromHost.addr[cnt] = addr; + l_return = true; + break; + } + } + } + return l_return; + } + + uint64_t fetchStashAddrAttribute() + { + return (uint64_t)((uint8_t*)(&keyValuePairfromHost)); + } +}sbeStashMemoryPair_t; + +// Message struct to receive the key/addr pair from host +typedef struct stashMsg +{ + uint64_t reserve:56; + uint64_t key:8; + uint64_t addr; +}stashMsg_t; + +/** + * @brief retrieve SBE FFDC on request from FSP. (0xA801) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetFfdc(uint8_t *i_pArg); + +/** + * @brief SBE Generic capabilities (0xA802) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetCapabilities(uint8_t *i_pArg); + +/** + * @brief SBE Fifo Quiesce (0xA806) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeFifoQuiesce(uint8_t *i_pArg); + +/** + * @brief SBE Psu Set FFDC Address(0xD704) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the Psu access utility + */ +uint32_t sbeSetFFDCAddr(uint8_t *i_pArg); + +/** + * @brief SBE Psu Quiesce (0xD705) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the Psu access utility + */ +uint32_t sbePsuQuiesce(uint8_t *i_pArg); + +/** + * @brief SBE Psu Set System Fabric Map (0xD706) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the Psu access utility + */ +uint32_t sbeSetSystemFabricMap(uint8_t *i_pArg); + +/** + * @brief SBE stash the key addr pair into sbe memory (0xD707) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the Psu access utility + */ +uint32_t sbeStashKeyAddrPair(uint8_t *i_pArg); + +#endif // __SBEFW_SBECMDGENERIC_H diff --git a/src/sbefw/app/common/sbecmdringaccess.C b/src/sbefw/app/common/sbecmdringaccess.C new file mode 100644 index 00000000..07328eda --- /dev/null +++ b/src/sbefw/app/common/sbecmdringaccess.C @@ -0,0 +1,361 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/app/common/sbecmdringaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ +/* */ +/* */ +/* 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 */ +/* + * @file: ppe/sbe/sbefw/sbecmdringaccess.C + * + * @brief This file contains the SBE Ring Access chipOps + * + */ + +#include "sbecmdringaccess.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbeHostMsg.H" +#include "sbeHostUtils.H" +#include "sbeFifoMsgUtils.H" +#include "sbeutil.H" +#include "sbefapiutil.H" +#include "fapi2.H" +#include "plat_hw_access.H" +#include "sbeglobals.H" + +using namespace fapi2; + +static const uint32_t SIZE_OF_LENGTH_INWORDS = 1; +static const uint32_t NUM_WORDS_PER_GRANULE = 2; +static const uint32_t GETRING_GRANULE_SIZE_IN_BITS = 64; + + +uint32_t sbePutRingFromImagePSU (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutRingFromImagePSU " + SBE_ENTER(SBE_FUNC); + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_fapiRc = FAPI2_RC_SUCCESS; + sbePSUPutRingCMD_t l_cmd = {0}; + do + { + // Fetch Ring ID, Ring mode and pervasive chiplet id from the message + // and also send Ack to Host via SBE_SBE2PSU_DOORBELL_SET_BIT1 + l_rc = sbeReadPsu2SbeMbxReg(SBE_HOST_PSU_MBOX_REG1, + (sizeof(l_cmd)/sizeof(uint64_t)), + (uint64_t*)&l_cmd, + true); + if(SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + SBE_ERROR(SBE_FUNC "Failed to extract SBE_HOST_PSU_MBOX_REG1 and " + "SBE_HOST_PSU_MBOX_REG2"); + break; + } + + // Construct a Target from Chiplet ID and Target Type + fapi2::plat_target_handle_t l_tgtHndl; + if(!sbeGetFapiTargetHandle(l_cmd.TargetType, l_cmd.ChipletID, + l_tgtHndl)) + { + SBE_ERROR(SBE_FUNC "Invalid target type [0x%04x]", + (uint16_t)l_cmd.TargetType); + SBE_GLOBAL->sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_DATA, + SBE_SEC_INVALID_TARGET_TYPE_PASSED); + break; + } + fapi2::Target<TARGET_TYPE_ALL> l_Tgt(l_tgtHndl); + + // Initialize with HEADER CHECK mode + uint16_t l_ringMode = sbeToFapiRingMode(l_cmd.RingMode); + + l_fapiRc = (uint32_t)putRing(l_Tgt, (RingID)l_cmd.RingID, + (RingMode)l_ringMode); + if(l_fapiRc != FAPI2_RC_SUCCESS) + { + SBE_ERROR(SBE_FUNC "putRing HWP failure - " + "MSG - Target Type [0x%04x] Ring ID [0x%04x]" + " Ring Mode [0x%04x] Chiplet ID [0x%04x]", + l_cmd.TargetType, + l_cmd.RingID, + l_cmd.RingMode, + l_cmd.ChipletID); + break; + } + }while(0); // End of do-while + + // Send the response + sbePSUSendResponse(SBE_GLOBAL->sbeSbe2PsuRespHdr, l_fapiRc, l_rc); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeGetRing(uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeGetRing " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbeGetRingAccessMsgHdr_t l_reqMsg; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeResponseFfdc_t l_ffdc; + ReturnCode l_fapiRc; + uint32_t l_len = 0; + + //Note-Read operation flow is SHIFT and then READ. + // First time , the shift count will be 0.. because of the way it + // works. if we shift 64bits in the very first iteration then we + // loose first 64 bit. But still we should update l_bitSentCnt + // because we are sending back this data + uint32_t l_bitSentCnt = 64; + const uint32_t LONG_ROTATE_ADDRESS = 0x0003E000; + + do + { + // Get the ring access header + l_len = sizeof(sbeGetRingAccessMsgHdr_t)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len, (uint32_t *)&l_reqMsg); // EOT fetch + + // If FIFO access failure + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + + SBE_INFO(SBE_FUNC "Ring Address 0x%08X User Ring Mode 0x%04X " + "Length in Bits 0x%08X", + (uint32_t)l_reqMsg.ringAddr, + (uint32_t)l_reqMsg.ringMode, + (uint32_t)l_reqMsg.ringLenInBits); + + uint16_t l_ringMode = sbeToFapiRingMode(l_reqMsg.ringMode); + + // Call getRing_setup - loads the scan region data for the given ring + // address and updates the check word data + l_fapiRc = fapi2::getRing_setup(l_reqMsg.ringAddr, + (fapi2::RingMode)l_ringMode); + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_setup failed. RingAddress:0x%08X " + "RingMode:0x%04x", l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + // Calculate the iteration length + uint32_t l_loopCnt = + (l_reqMsg.ringLenInBits / GETRING_GRANULE_SIZE_IN_BITS); + // Check for modulus - remainder + uint8_t l_mod = (l_reqMsg.ringLenInBits % GETRING_GRANULE_SIZE_IN_BITS); + if(l_mod) + { + ++l_loopCnt; + } + + // fix for the alignment issue + uint32_t l_buf[NUM_WORDS_PER_GRANULE]__attribute__ ((aligned (8))) ={0}; + uint32_t l_bitShift = 0; + l_len = NUM_WORDS_PER_GRANULE; + plat_target_handle_t l_hndl; + uint32_t l_chipletId = (uint32_t)(l_reqMsg.ringAddr) & 0xFF000000; + uint32_t l_scomAddress = 0; + + // Fetch the ring data in bits, each iteration will give you 64bits + for(uint32_t l_cnt=0; l_cnt < l_loopCnt; l_cnt++) + { + + l_scomAddress = LONG_ROTATE_ADDRESS | l_chipletId; + l_scomAddress |= l_bitShift; + l_fapiRc = getscom_abs_wrap (&l_hndl, + l_scomAddress, + (uint64_t*)&l_buf); + + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_granule_data failed. " + "RingAddress:0x%08X RingMode:0x%04x", + l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + // if the length of ring is not divisible by 64 then mod value + // should be considered which will match with the length in bits + // that passed + if((l_cnt == (l_loopCnt -1)) && (l_mod)) + { + l_bitShift = l_mod; + } + // Send it to DS Fifo + // If this is the last iteration in the loop, let the full 64bit + // go, even for 1bit of remaining length. The length passed to + // the user will take care of actual number of bits. + l_rc = sbeDownFifoEnq_mult (l_len, (uint32_t *)&l_buf); + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(l_rc); + l_bitSentCnt = l_bitSentCnt + l_bitShift; + l_bitShift = GETRING_GRANULE_SIZE_IN_BITS; + } + if ( (l_fapiRc == FAPI2_RC_SUCCESS) && + (l_rc == SBE_SEC_OPERATION_SUCCESSFUL) ) + { + if (!l_mod) + { + l_mod = GETRING_GRANULE_SIZE_IN_BITS; + } + //Here we need to shift with the mod value to enter into the + //starting position of the ring.But the data is already read in the + //above for loop.. so here we ignore the data + l_scomAddress = LONG_ROTATE_ADDRESS | l_chipletId; + l_scomAddress |= l_mod; + l_fapiRc = getscom_abs_wrap (&l_hndl, + l_scomAddress, + (uint64_t*)&l_buf); + + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_granule_data failed. " + "RingAddress:0x%08X RingMode:0x%04x", + l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + break; + } + + // Call getRing_verifyAndcleanup - verify the check word data is + // matching or not and will clean up the scan region data + l_fapiRc = getRing_verifyAndcleanup((uint32_t)(l_reqMsg.ringAddr), + (fapi2::RingMode)l_ringMode); + if( l_fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" getRing_verifyAndcleanup failed. " + "RingAddress:0x%08X RingMode:0x%04x", + l_reqMsg.ringAddr, l_ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + l_ffdc.setRc(l_fapiRc); + } + } + }while(false); + + // Now build and enqueue response into downstream FIFO + // If there was a FIFO error, will skip sending the response, + // instead give the control back to the command processor thread + if ( SBE_SEC_OPERATION_SUCCESSFUL == l_rc ) + { + l_len = SIZE_OF_LENGTH_INWORDS; + l_rc = sbeDownFifoEnq_mult (l_len, &(l_bitSentCnt)); + if(SBE_SEC_OPERATION_SUCCESSFUL == l_rc) + { + l_rc = sbeDsSendRespHdr( respHdr, &l_ffdc); + } + } + SBE_EXIT(SBE_FUNC); + return l_rc; +#undef SBE_FUNC +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutRing(uint8_t *i_pArg) +{ +#define SBE_FUNC " sbePutRing " + SBE_ENTER(SBE_FUNC); + + uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbePutRingMsg_t reqMsg; + sbeRespGenHdr_t respHdr; + respHdr.init(); + sbeResponseFfdc_t ffdc; + ReturnCode fapiRc; + sbePutRingMsgHdr_t hdr; + uint32_t len = 0; + + do + { + // Get the length of payload + // Length is not part of chipop. So take length from total length + len = SBE_GLOBAL->sbeFifoCmdHdr.len - + sizeof(SBE_GLOBAL->sbeFifoCmdHdr)/sizeof(uint32_t); + uint32_t rs4FifoEntries = len - + sizeof(sbePutRingMsgHdr_t)/sizeof(uint32_t); + + if( rs4FifoEntries > (SBE_PUT_RING_RS4_MAX_DOUBLE_WORDS * 2) ) + { + SBE_ERROR(SBE_FUNC" RS4 palyload size is wrong." + "size(entries):0x%08x", rs4FifoEntries); + respHdr.setStatus( SBE_PRI_INVALID_DATA, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + // flush the fifo + rc = sbeUpFifoDeq_mult(len, NULL,true, true); + break; + } + + len = sizeof(sbePutRingMsgHdr_t)/sizeof(uint32_t); + rc = sbeUpFifoDeq_mult (len, (uint32_t *)&hdr, false); + // If FIFO access failure + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc); + + len = rs4FifoEntries; + rc = sbeUpFifoDeq_mult (len, (uint32_t *)&reqMsg); + // If FIFO access failure + CHECK_SBE_RC_AND_BREAK_IF_NOT_SUCCESS(rc); + + uint16_t ringMode = sbeToFapiRingMode(hdr.ringMode); + bool i_applyOverride = false; + + if (hdr.ringMode & SBE_RING_MODE_APPLY_OVERRIDE) + { + i_applyOverride = true; + } + + + + Target<TARGET_TYPE_PROC_CHIP> proc = plat_getChipTarget(); + // No need to pass length as platform api takes length from payload. + fapiRc = rs4DecompressionSvc(proc, (uint8_t *)reqMsg.rs4Payload, + i_applyOverride, (fapi2::RingMode)ringMode); + if( fapiRc != FAPI2_RC_SUCCESS ) + { + SBE_ERROR(SBE_FUNC" rs4DecompressionSvc failed." + "RingMode:0x%04x", ringMode); + respHdr.setStatus( SBE_PRI_GENERIC_EXECUTION_FAILURE, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + ffdc.setRc(fapiRc); + break; + } + }while(false); + + // Now build and enqueue response into downstream FIFO + // If there was a FIFO error, will skip sending the response, + // instead give the control back to the command processor thread + if ( SBE_SEC_OPERATION_SUCCESSFUL == rc ) + { + rc = sbeDsSendRespHdr( respHdr, &ffdc); + } + SBE_EXIT(SBE_FUNC); + return rc; +#undef SBE_FUNC +} + diff --git a/src/sbefw/app/common/sbecmdringaccess.H b/src/sbefw/app/common/sbecmdringaccess.H new file mode 100644 index 00000000..a008f4d3 --- /dev/null +++ b/src/sbefw/app/common/sbecmdringaccess.H @@ -0,0 +1,71 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/app/common/sbecmdringaccess.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ +/* */ +/* */ +/* 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 */ +/* + * @file: ppe/sbe/sbefw/sbecmdringaccess.H + * + * @brief This file contains the Interfaces for the RING Access chip-ops + * + */ + +#ifndef __SBEFW_SBECMDRINGACCESS_H +#define __SBEFW_SBECMDRINGACCESS_H + +#include <stdint.h> + +typedef struct +{ + uint64_t TargetType:16; + uint64_t ChipletID:16; + uint64_t RingID:16; + uint64_t RingMode:16; +} sbePSUPutRingCMD_t; + +/** + * @brief Put Ring From Image Command (0xD301) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return RC from the PSU access utility + */ +uint32_t sbePutRingFromImagePSU(uint8_t *i_pArg); + +/** + * @brief sbeGetRing : Get the ring data + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetRing(uint8_t *i_pArg); + +/** + * @brief Put Ring Command + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return RC from the FIFO access utility + */ +uint32_t sbePutRing(uint8_t *i_pArg); + +#endif /* __SBEFW_SBECMDRINGACCESS_H */ diff --git a/src/sbefw/app/common/sbecmdscomaccess.C b/src/sbefw/app/common/sbecmdscomaccess.C new file mode 100644 index 00000000..ebb838da --- /dev/null +++ b/src/sbefw/app/common/sbecmdscomaccess.C @@ -0,0 +1,433 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/app/common/sbecmdscomaccess.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* */ +/* */ +/* 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 */ +/* + * @file: ppe/sbe/sbefw/sbecmdscomaccess.C + * + * @brief This file contains the SBE SCOM Access chipOps + * + */ + +#include "sbecmdscomaccess.H" +#include "sbefifo.H" +#include "sbe_sp_intf.H" +#include "sbetrace.H" +#include "sbescom.H" +#include "sbeutil.H" +#include "sbeFifoMsgUtils.H" +#include "plat_hw_access.H" +#include "sbeglobals.H" + +namespace SBE_COMMON +{ +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeGetScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeGetScom " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbeGetScomReqMsg_t l_getScomReqMsg; + sbeRespGenHdr_t l_hdr; + l_hdr.init(); + sbeResponseFfdc_t l_ffdc; + + do + { + // Will attempt to dequeue two entries for + // the scom addresses plus the expected + // EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_getScomReqMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_getScomReqMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + uint32_t l_len2enqueue = 0; + uint32_t l_sbeDownFifoRespBuf[2] = {0}; + + uint64_t l_addr = ( (uint64_t)l_getScomReqMsg.hiAddr << 32) | + l_getScomReqMsg.lowAddr; + uint64_t l_scomData = 0; + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]", + l_getScomReqMsg.hiAddr, l_getScomReqMsg.lowAddr); + checkIndirectAndDoScom(true, l_addr, + l_scomData, &l_hdr, + &l_ffdc); + + if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"getscom failed, " + "scomAddr[0x%08X%08X]", + l_getScomReqMsg.hiAddr, l_getScomReqMsg.lowAddr); + break; + } + else // successful scom + { + SBE_DEBUG(SBE_FUNC"getscom succeeds, l_scomData[0x%016X]", + l_scomData); + + l_sbeDownFifoRespBuf[0] = (uint32_t)(l_scomData>>32); + l_sbeDownFifoRespBuf[1] = (uint32_t)(l_scomData); + + // Push the data into downstream FIFO + l_len2enqueue = 2; + l_rc = sbeDownFifoEnq_mult (l_len2enqueue, + &l_sbeDownFifoRespBuf[0]); + if (l_rc) + { + // will let command processor routine + // handle the failure + break; + } + } // end successful scom + + } while(false); + + if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL) + { + // Build the response header packet + l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc); + // will let command processor routine + // handle the failure + } + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutScom " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbePutScomReqMsg_t l_putScomReqMsg; + sbeRespGenHdr_t l_hdr; + l_hdr.init(); + sbeResponseFfdc_t l_ffdc; + + do + { + // Will attempt to dequeue four entries for + // the scom address (two entries) and the + // corresponding data (two entries) plus + // the expected EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_putScomReqMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_putScomReqMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + uint64_t l_scomData = 0; + // successfully dequeued two entries for + // scom address followed by the EOT entry + + // Data entry 0 : Scom Register Address (0..31) + // Data entry 1 : Scom Register Address (32..63) + // Data entry 2 : Scom Register Data (0..31) + // Data entry 3 : Scom Register Data (32..63) + // For Direct SCOM, will ignore entry 0 + + l_scomData = l_putScomReqMsg.getScomData(); + + uint64_t l_addr = ( (uint64_t) l_putScomReqMsg.hiAddr << 32) | + l_putScomReqMsg.lowAddr; + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]", + l_putScomReqMsg.hiAddr, l_putScomReqMsg.lowAddr); + checkIndirectAndDoScom(false, l_addr, + l_scomData, &l_hdr, &l_ffdc); + + if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"putscom failure data, " + "scomAddr[0x%08X%08X], " + "scomData[0x%08X%08X]", + l_putScomReqMsg.hiAddr, + l_putScomReqMsg.lowAddr, + SBE::higher32BWord(l_scomData), + SBE::lower32BWord(l_scomData)); + break; + } + + } while(false); + + if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL) + { + // Build the response header packet + l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc); + // will let command processor routine + // handle the failure + } + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeModifyScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeModifyScom " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + sbeModifyScomReqMsg_t l_modifyScomMsg; + sbeRespGenHdr_t l_hdr; + l_hdr.init(); + sbeResponseFfdc_t l_ffdc; + + do + { + // Will attempt to dequeue the following entries: + // Entry 1 : Operation Mode + // Entry 2 : Scom Register Address (0..31) + // Entry 3 : Scom Register Address (32..63) + // Entry 4 : Modifying Data (0..31) + // Entry 5 : Modifying Data (32..63) + // Entry 6 : EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_modifyScomMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_modifyScomMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + // Modifying Data + uint64_t l_modifyingData = l_modifyScomMsg.getModifyingData(); + + SBE_DEBUG(SBE_FUNC"OpMode[0x%02X], modifyingData[0x%016X]", + l_modifyScomMsg.opMode, + SBE::higher32BWord(l_modifyingData), + SBE::lower32BWord(l_modifyingData)); + + // The following steps need to be done as part of this command : + // 1. Read Register Data (getscom) + // 2. 'AND' the Mask with the data read from register + // 3. 'OR' the modifying data with the result of step 2 + // 4. Write the result of step 3 into the register (putscom) + do + { + // Check for a valid OpMode + if ( (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_OR) && + (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_AND) && + (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_XOR) ) + { + // Invalid Data passed + SBE_ERROR(SBE_FUNC"Invalid OpMode"); + l_hdr.setStatus(SBE_PRI_INVALID_DATA, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION); + break; + } + + uint64_t l_addr = ( (uint64_t) l_modifyScomMsg.hiAddr << 32) | + l_modifyScomMsg.lowAddr; + uint64_t l_scomData = 0; + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]", + l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr); + checkIndirectAndDoScom(true, l_addr, + l_scomData, &l_hdr, &l_ffdc); + + if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"getscom failed," + " ScomAddress[0x%08X %08X]", + l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr); + break; + } + + if (l_modifyScomMsg.opMode == SBE_MODIFY_MODE_OR) + { + l_modifyingData |= l_scomData; + } + else if (l_modifyScomMsg.opMode == SBE_MODIFY_MODE_AND) + { + l_modifyingData &= l_scomData; + } + else + { + l_modifyingData ^= l_scomData; + } + + // Write the modified data + checkIndirectAndDoScom(false, l_addr, + l_modifyingData, &l_hdr, &l_ffdc); + + if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"putscom failed," + " ScomAddress[0x%08X%08X]", + l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr); + SBE_ERROR(SBE_FUNC"modifyingData[0x%08X%08X]", + SBE::higher32BWord(l_modifyingData), + SBE::lower32BWord(l_modifyingData)); + break; + } + } while (false); + + if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL) + { + // Build the response header packet + l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc); + if (l_rc) + { + // will let command processor routine + // handle the failure + break; + } + } + + } while(false); + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbePutScomUnderMask (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbePutScomUnderMask " + SBE_ENTER(SBE_FUNC); + + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + sbePutScomUnderMaskReqMsg_t l_putScomUmaskMsg; + sbeRespGenHdr_t l_hdr; + l_hdr.init(); + sbeResponseFfdc_t l_ffdc; + + do + { + // Will attempt to dequeue the following entries: + // Entry 1 : Scom Register Address (0..31) + // Entry 2 : Scom Register Address (32..63) + // Entry 3 : Modifying Data (0..31) + // Entry 4 : Modifying Data (32..63) + // Entry 5 : Mask Data (0..31) + // Entry 6 : Mask Data (32..63) + // Entry 7 : EOT entry at the end + + uint32_t l_len2dequeue = sizeof(l_putScomUmaskMsg)/sizeof(uint32_t); + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, + (uint32_t *)&l_putScomUmaskMsg); + + // If FIFO access failure + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + // Let command processor routine to handle the RC. + break; + } + + SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]," + "modifyingData[0x%08X%08X]", + l_putScomUmaskMsg.hiAddr, + l_putScomUmaskMsg.lowAddr, + l_putScomUmaskMsg.hiInputData, + l_putScomUmaskMsg.lowInputData); + SBE_INFO(SBE_FUNC"maskData[0x%08X%08X]", + l_putScomUmaskMsg.hiMaskData, + l_putScomUmaskMsg.lowMaskData); + + // PutScomUnderMask formula: + // dest_reg = (dest_reg & ~input_mask) | (input_data & input_mask) + + do + { + uint64_t l_scomData = 0; + + uint64_t l_addr = ( (uint64_t) l_putScomUmaskMsg.hiAddr << 32) | + l_putScomUmaskMsg.lowAddr; + checkIndirectAndDoScom(true, l_addr, + l_scomData, &l_hdr, &l_ffdc); + + if (l_hdr.secondaryStatus == SBE_SEC_OPERATION_SUCCESSFUL) // scom success + { + l_putScomUmaskMsg.getScomData(l_scomData); + + // Write the modified data + checkIndirectAndDoScom(false, l_addr, + l_scomData, &l_hdr, &l_ffdc); + } + + if (l_hdr.secondaryStatus != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed + { + SBE_ERROR(SBE_FUNC"scom failed, " + "ScomAddress[0x%08X%08X]", + l_putScomUmaskMsg.hiAddr, + l_putScomUmaskMsg.lowAddr); + SBE_ERROR(SBE_FUNC"modifyingData[0x%08X%08X]" + "maskData[0x%08X%08X]", + l_putScomUmaskMsg.hiInputData, + l_putScomUmaskMsg.lowInputData, + l_putScomUmaskMsg.hiMaskData, + l_putScomUmaskMsg.lowMaskData); + + break; + } + } while (false); + } while(false); + + if(l_rc == SBE_SEC_OPERATION_SUCCESSFUL) + { + // Build the response header packet + l_rc = sbeDsSendRespHdr(l_hdr, &l_ffdc); + // will let command processor routine + // handle the failure + } + + SBE_EXIT(SBE_FUNC); + return l_rc; + #undef SBE_FUNC +} + +///////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeMultiScom (uint8_t *i_pArg) +{ + #define SBE_FUNC " sbeMultiScom " + return 0; + #undef SBE_FUNC +} +} // namespace SBE_COMMON diff --git a/src/sbefw/app/common/sbecmdscomaccess.H b/src/sbefw/app/common/sbecmdscomaccess.H new file mode 100644 index 00000000..3cd2c5e9 --- /dev/null +++ b/src/sbefw/app/common/sbecmdscomaccess.H @@ -0,0 +1,97 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/app/common/sbecmdscomaccess.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* */ +/* */ +/* 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 */ +/* + * @file: ppe/sbe/sbefw/sbecmdscomaccess.H + * + * @brief This file contains the Interfaces for the SCOM Access chip-ops + * + */ + +#ifndef __SBEFW_SBECMDSCOMACCESS_H +#define __SBEFW_SBECMDSCOMACCESS_H + +#include <stdint.h> + +namespace SBE_COMMON +{ + +/** + * @brief sbeDownFifoGetStatus : Write data into Downstream FIFO + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeGetScom (uint8_t *i_pArg); + + +/** + * @brief sbeDownFifoGetStatus : Write data into Downstream FIFO + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbePutScom (uint8_t *i_pArg); + + +/** + * @brief sbeModifyScom : Modify the Scom data + * This chipOp needs to do the following + * 1. Read Register Data (getscom) + * 2. modify the scomData using the given op mode + * 3. Write the modified Data into the Register (putscom) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeModifyScom (uint8_t *i_pArg); + + +/** + * @brief sbePutScomUnderMask : Write data into Downstream FIFO + * The following steps need to be done as part of this command : + * 1. Read Register Data (getscom) + * 2. 'AND' the Mask with the data read from register + * 3. 'OR' the modifying data with the result of step 2 + * 4. Write the result of step 3 into the register (putscom) + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbePutScomUnderMask (uint8_t *i_pArg); + +/** + * @brief sbeMultiScom: + * + * @param[in] i_pArg Buffer to be passed to the function (not used as of now) + * + * @return Rc from the FIFO access utility + */ +uint32_t sbeMultiScom (uint8_t *i_pArg); +} // namespace SBE_COMMON + +#endif /* __SBEFW_SBECMDSCOMACCESS_H */ |

