summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorBill Schwartz <whs@us.ibm.com>2015-10-26 13:04:25 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-02-26 12:07:18 -0600
commitbeb9c5104c5b7303abb0e3aea3a5789eaee774e8 (patch)
treeb1c0bf76ea27e5074355a86ccafde23dd055d007 /src/usr
parentab4c7f99e8ffff49232e26b6159990255caf51c3 (diff)
downloadtalos-hostboot-beb9c5104c5b7303abb0e3aea3a5789eaee774e8.tar.gz
talos-hostboot-beb9c5104c5b7303abb0e3aea3a5789eaee774e8.zip
Create SBE PSU device driver
Create SBE PSU device driver and implement Start and Stop dead man loop. Change-Id: Ic894842e586485074fda88b8920213969913d685 RTC: 132656 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22765 Tested-by: Jenkins Server Reviewed-by: Christian Geddes <crgeddes@us.ibm.com> Reviewed-by: WILLIAM G. HOFFA <wghoffa@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H14
-rw-r--r--src/usr/makefile1
-rw-r--r--src/usr/sbeio/makefile32
-rw-r--r--src/usr/sbeio/sbe_coreStateControl.C110
-rw-r--r--src/usr/sbeio/sbe_psudd.C409
-rw-r--r--src/usr/sbeio/sbe_psudd.H414
6 files changed, 980 insertions, 0 deletions
diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H
index 8d1c44ab4..4cd06b868 100644
--- a/src/usr/initservice/extinitsvc/extinitsvctasks.H
+++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H
@@ -168,6 +168,20 @@ const TaskInfo g_exttaskinfolist[] = {
}
},
#endif
+
+ /**
+ * @brief SBE IO Device Driver
+ */
+ {
+ "libsbeio.so", // taskname
+ NULL, // no ptr to fnct
+ {
+
+ INIT_TASK, // init only
+ EXT_IMAGE, // Extended Module
+ }
+ },
+
/**
* @brief FSI SCOM Device Driver
*/
diff --git a/src/usr/makefile b/src/usr/makefile
index f0ef233fe..a1e79fdd5 100644
--- a/src/usr/makefile
+++ b/src/usr/makefile
@@ -59,6 +59,7 @@ SUBDIRS += secureboot.d
SUBDIRS += devtree.d
#@TODO RTC:142091
#SUBDIRS += sbe.d
+SUBDIRS += sbeio.d
SUBDIRS += gpio.d
SUBDIRS += lpc.d
SUBDIRS += console.d
diff --git a/src/usr/sbeio/makefile b/src/usr/sbeio/makefile
new file mode 100644
index 000000000..421027557
--- /dev/null
+++ b/src/usr/sbeio/makefile
@@ -0,0 +1,32 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/sbeio/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2016
+# [+] 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
+ROOTPATH = ../../..
+
+MODULE = sbeio
+
+OBJS += sbe_psudd.o
+OBJS += sbe_coreStateControl.o
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/sbeio/sbe_coreStateControl.C b/src/usr/sbeio/sbe_coreStateControl.C
new file mode 100644
index 000000000..7d18d2c1a
--- /dev/null
+++ b/src/usr/sbeio/sbe_coreStateControl.C
@@ -0,0 +1,110 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/sbe_coreStateControl.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2012,2016 */
+/* [+] 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 */
+/**
+ * @file sbe_coreStateControl.C
+ * @brief Core State Control Messages to control the deadmap loop
+ */
+
+#include <config.h>
+#include <trace/interface.H>
+#include <errl/errlmanager.H>
+#include <sbeio/sbeioif.H>
+#include "sbe_psudd.H"
+
+extern trace_desc_t* g_trac_sbeio;
+
+#define SBE_TRACD(printf_string,args...) \
+ TRACDCOMP(g_trac_sbeio,"coreStateControl: " printf_string,##args)
+
+namespace SBEIO
+{
+
+/**
+ * @brief Start Deadman loop
+ *
+ * @param[in] i_waitTime Time to wait in milliseconds
+ *
+ * @return errlHndl_t Error log handle on failure.
+ *
+ */
+
+errlHndl_t startDeadmanLoop(const uint64_t i_waitTime )
+{
+ errlHndl_t errl = NULL;
+
+ SBE_TRACD(ENTER_MRK "startDeadmanLoop waitTime=0x%x",i_waitTime);
+
+ psuCommand l_psuCommand(
+ SBE_DMCONTROL_START | SBE_DMCONTROL_RESPONSE_REQUIRED, //control flags
+ SBE_PSU_CLASS_CORE_STATE, //command class
+ SBE_CMD_CONTROL_DEADMAN_LOOP); //comand
+ psuResponse l_psuResponse;
+
+ // set up PSU command message
+ l_psuCommand.cdl_waitTime = i_waitTime;
+
+ errl = performPsuChipOp(&l_psuCommand,
+ &l_psuResponse,
+ MAX_PSU_SHORT_TIMEOUT_NS,
+ SBE_DMCONTROL_START_REQ_USED_REGS,
+ SBE_DMCONTROL_START_RSP_USED_REGS);
+
+ SBE_TRACD(EXIT_MRK "startDeadmanLoop");
+
+ return errl;
+};
+
+
+
+/**
+ * @brief Stop Deadman loop
+ *
+ * @return errlHndl_t Error log handle on failure.
+ *
+ */
+errlHndl_t stopDeadmanLoop()
+{
+ errlHndl_t errl = NULL;
+
+ SBE_TRACD(ENTER_MRK "stopDeadmanLoop");
+
+ psuCommand l_psuCommand(
+ SBE_DMCONTROL_STOP + SBE_DMCONTROL_RESPONSE_REQUIRED, //control flags
+ SBE_PSU_CLASS_CORE_STATE, //command class
+ SBE_CMD_CONTROL_DEADMAN_LOOP); //comand
+ psuResponse l_psuResponse;
+
+ errl = performPsuChipOp(&l_psuCommand,
+ &l_psuResponse,
+ MAX_PSU_SHORT_TIMEOUT_NS,
+ SBE_DMCONTROL_STOP_REQ_USED_REGS,
+ SBE_DMCONTROL_STOP_RSP_USED_REGS);
+
+ SBE_TRACD(EXIT_MRK "stopDeadmanLoop");
+
+ return errl;
+};
+} //end namespace SBEIO
+
diff --git a/src/usr/sbeio/sbe_psudd.C b/src/usr/sbeio/sbe_psudd.C
new file mode 100644
index 000000000..bce5331f6
--- /dev/null
+++ b/src/usr/sbeio/sbe_psudd.C
@@ -0,0 +1,409 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/sbe_psudd.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2012,2016 */
+/* [+] 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 */
+/**
+ * @file sbe_psudd.C
+ * @brief SBE PSU device driver
+ */
+
+#include <sys/time.h>
+#include <trace/interface.H>
+#include <devicefw/driverif.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <errl/errludtarget.H>
+#include <targeting/common/target.H>
+#include <targeting/common/targetservice.H>
+#include <sbeio/sbeioreasoncodes.H>
+#include "sbe_psudd.H"
+
+trace_desc_t* g_trac_sbeio;
+TRAC_INIT(&g_trac_sbeio, SBEIO_COMP_NAME, 6*KILOBYTE, TRACE::BUFFER_SLOW);
+
+#define SBE_TRACF(printf_string,args...) \
+ TRACFCOMP(g_trac_sbeio,"psudd: " printf_string,##args)
+#define SBE_TRACD(printf_string,args...) \
+ TRACDCOMP(g_trac_sbeio,"psudd: " printf_string,##args)
+
+using namespace ERRORLOG;
+
+//TODO RTC 144313 implement error recovery and ffdc.
+
+namespace SBEIO
+{
+
+/**
+ * @brief perform SBE PSU chip-op
+ *
+ * @param[in] i_pPsuRequest Pointer to PSU request commands
+ * @param[out] o_pPsuResponse Pointer to PSU response
+ * @param[in] i_timeout Time out for response
+ * @param[in] i_reqMsgs 4 bit mask telling which regs to write
+ * @param[in] i_rspMsgs 4 bit mask telling which regs to read
+ */
+errlHndl_t performPsuChipOp(psuCommand * i_pPsuRequest,
+ psuResponse * o_pPsuResponse,
+ const uint64_t i_timeout,
+ uint8_t i_reqMsgs,
+ uint8_t i_rspMsgs)
+
+{
+ errlHndl_t errl = NULL;
+ TARGETING::Target * l_target = NULL;
+ static mutex_t l_psuOpMux = MUTEX_INITIALIZER;
+
+ SBE_TRACD(ENTER_MRK "performPsuChipOp");
+
+ //Serialize access to PSU
+ mutex_lock(&l_psuOpMux);
+
+ //Use master proc for SBE PSU access
+ (void)TARGETING::targetService().masterProcChipTargetHandle(l_target);
+ assert(l_target,"performPsuChipOp: master proc target is NULL");
+
+ do
+ {
+ // write PSU Request
+ errl = writeRequest(l_target,
+ i_pPsuRequest,
+ i_reqMsgs);
+ if (errl) break; // return with error
+
+ // read PSU response and check results
+ errl = readResponse(l_target,
+ i_pPsuRequest,
+ o_pPsuResponse,
+ i_timeout,
+ i_rspMsgs);
+ if (errl) break; // return with error
+
+ }
+ while (0);
+
+ mutex_unlock(&l_psuOpMux);
+
+ SBE_TRACD(EXIT_MRK "performPsuChipOp");
+
+ return errl;
+}
+
+/**
+ * @brief write PSU Request message
+ */
+errlHndl_t writeRequest(TARGETING::Target * i_target,
+ psuCommand * i_pPsuRequest,
+ uint8_t i_reqMsgs)
+{
+ errlHndl_t errl = NULL;
+ static uint16_t l_seqID = 0;
+
+ SBE_TRACD(ENTER_MRK "writeRequest");
+
+ do
+ {
+ // assign sequence ID and save to check that response matches
+ i_pPsuRequest->seqID = ++l_seqID;
+
+ // Read SBE doorbell to confirm ready to accept command.
+ // Since the device driver single threads the requests, we should
+ // never see not being ready to send a request.
+ uint64_t l_addr = PSU_SBE_DOORBELL_REG_RW;
+ uint64_t l_data = 0;
+ errl = readScom(i_target,l_addr,&l_data);
+ if (errl) break;
+ if (l_data & SBE_DOORBELL)
+ {
+ SBE_TRACF(ERR_MRK "writeRequest: SBE not ready to accept cmd");
+ SBE_TRACF(ERR_MRK " Control Flags,SeqID,Cmd,SubCmd=0x%016lx",
+ i_pPsuRequest->mbxReg0);
+ SBE_TRACF(ERR_MRK " Host to PSU door bell=0x%016lx",
+ l_data);
+ /*@
+ * @errortype
+ * @moduleid SBEIO_PSU
+ * @reasoncode SBEIO_PSU_NOT_READY
+ * @userdata1[0:15] Reserved
+ * @userdata1[16:31] Request Control Flags
+ * @userdata1[32:47] Request Sequence ID
+ * @userdata1[48:55] Request Command Class
+ * @userdata1[56:63] Request Command
+ * @userdata2 Host to SBE door bell register
+ *
+ * @devdesc SBE PSU device driver not ready
+ * to receive next command.
+ * @custdesc Firmware error communicating with boot device
+ */
+ errl = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
+ SBEIO_PSU,
+ SBEIO_PSU_NOT_READY,
+ i_pPsuRequest->mbxReg0,
+ l_data);
+ //TODO RTC 144313 review callouts and ffdc
+ errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ errl->collectTrace(SBEIO_COMP_NAME);
+ break; // return with error
+ }
+
+ //write the command registers
+ uint64_t * l_pMessage = (uint64_t *)i_pPsuRequest;
+ l_addr = PSU_HOST_SBE_MBOX0_REG;
+ for (uint8_t i=0;i<4;i++)
+ {
+ if (0x01 & i_reqMsgs) // write register if non-reserved
+ {
+ errl = writeScom(i_target,l_addr,l_pMessage);
+ if (errl) break;
+ }
+ i_reqMsgs>>=1;
+ l_addr++;
+ l_pMessage++;
+ }
+ if (errl) break;
+
+ //notify PSU command is ready
+ l_addr = PSU_SBE_DOORBELL_REG_OR;
+ l_data = SBE_DOORBELL;
+ errl = writeScom(i_target,l_addr,&l_data);
+ if (errl) break;
+
+ }
+ while (0);
+
+ SBE_TRACD(EXIT_MRK "writeRequest");
+
+ return errl;
+}
+
+/**
+ * @brief Read PSU response messages
+ */
+errlHndl_t readResponse(TARGETING::Target * i_target,
+ psuCommand * i_pPsuRequest,
+ psuResponse * o_pPsuResponse,
+ const uint64_t i_timeout,
+ uint8_t i_rspMsgs)
+{
+ errlHndl_t errl = NULL;
+
+ SBE_TRACD(ENTER_MRK "readResponse");
+
+ do
+ {
+ //wait for request to be completed
+ errl = pollForPsuComplete(i_target,i_timeout);
+ if (errl) break; // return with error
+
+ //read the response registers
+ uint64_t * l_pMessage = (uint64_t *)o_pPsuResponse;
+ uint64_t l_addr = PSU_HOST_SBE_MBOX4_REG;
+ for (uint8_t i=0;i<4;i++)
+ {
+ if (0x01 & i_rspMsgs) // read register if non-reserved
+ {
+ errl = readScom(i_target,l_addr,l_pMessage);
+ break;
+ }
+ i_rspMsgs>>=1;
+ l_addr++;
+ l_pMessage++;
+ }
+ if (errl) break;
+
+ //notify PSU response has been read
+ l_addr = PSU_HOST_DOORBELL_REG_AND;
+ uint64_t l_data = HOST_CLEAR_RESPONSE_WAITING;
+ errl = writeScom(i_target,l_addr,&l_data);
+ if (errl) break;
+
+ //check status and seq ID in response messages
+ if ((SBE_PRI_OPERATION_SUCCESSFUL != o_pPsuResponse->primaryStatus) ||
+ (SBE_SEC_OPERATION_SUCCESSFUL != o_pPsuResponse->secondaryStatus) ||
+ (i_pPsuRequest->seqID != o_pPsuResponse->seqID) )
+ {
+ SBE_TRACF(ERR_MRK "readResponse: failing response status "
+ " cmd=0x%08x prim=0x%08x secondary=0x%08x",
+ " expected seqID=%d actual seqID=%d",
+ i_pPsuRequest[1],
+ o_pPsuResponse->primaryStatus,
+ o_pPsuResponse->secondaryStatus,
+ i_pPsuRequest->seqID,
+ o_pPsuResponse->seqID);
+ /*@
+ * @errortype
+ * @moduleid SBEIO_PSU
+ * @reasoncode SBEIO_PSU_RESPONSE_ERROR
+ * @userdata1[0:31] Indirect size or 9 for direct command
+ * @userdata1[32:47] Request Sequence ID
+ * @userdata1[48:55] Request Command Class
+ * @userdata1[56:63] Request Command
+ * @userdata2[0:15] Response Primary Status
+ * @userdata2[16:31] Response Secondary Status
+ * @userdata2[32:47] Response Sequence ID
+ * @userdata2[48:55] Response Command Class
+ * @userdata2[56:63] Response Command
+ *
+ * @devdesc Unexpected sequence number or non zero
+ * primary or secondary status
+ * @custdesc Firmware error communicating with boot device
+ */
+ errl = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
+ SBEIO_PSU,
+ SBEIO_PSU_RESPONSE_ERROR,
+ i_pPsuRequest->mbxReg0,
+ o_pPsuResponse->mbxReg4);
+ //TODO RTC 144313 review callouts and ffdc
+ errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ errl->collectTrace(SBEIO_COMP_NAME);
+ break;
+ }
+
+ }
+ while (0);
+
+ SBE_TRACD(EXIT_MRK "readResponse");
+
+ return errl;
+}
+
+/**
+ * @brief poll for PSU to complete command
+ */
+errlHndl_t pollForPsuComplete(TARGETING::Target * i_target,
+ const uint64_t i_timeout)
+{
+ errlHndl_t errl = NULL;
+
+ SBE_TRACD(ENTER_MRK "pollForPsuComplete");
+
+ uint64_t l_elapsed_time_ns = 0;
+ uint64_t l_addr = PSU_HOST_DOORBELL_REG_RW;
+ uint64_t l_data = 0;
+ bool l_trace = true; //initialize so first call is traced
+
+ do
+ {
+ // read response doorbell to see if ready
+ errl = readScom(i_target,l_addr,&l_data,l_trace);
+ if (errl) break; // return with error
+
+ // check if response is now ready to be read
+ if (l_data & HOST_RESPONSE_WAITING)
+ {
+ break; // return with success
+ }
+
+ // time out if wait too long
+ if (l_elapsed_time_ns > i_timeout )
+ {
+ SBE_TRACF(ERR_MRK "pollForPsuComplete: "
+ "timeout waiting for PSU request to complete");
+
+ /*@
+ * @errortype
+ * @moduleid SBEIO_PSU
+ * @reasoncode SBEIO_PSU_RESPONSE_TIMEOUT
+ * @userdata1 Timeout in NS
+ * @devdesc Timeout waiting for PSU command to complete
+ * @custdesc Firmware error communicating with boot device
+ */
+ errl = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
+ SBEIO_PSU,
+ SBEIO_PSU_RESPONSE_TIMEOUT,
+ i_timeout,
+ 0);
+ //TODO RTC 144313 review callouts and ffdc
+ errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ errl->collectTrace(SBEIO_COMP_NAME);
+ break;
+ }
+
+ // try later
+ nanosleep( 0, 10000 ); //sleep for 10,000 ns
+ l_elapsed_time_ns += 10000;
+
+ // There will be many polls to check for the complete. If there
+ // is a problem, then there will be hundreds before timing out
+ // and giving up. Having one trace entry showing the poll request
+ // parameters is useful. Hundreds of identical entries is not. Hundreds
+ // with a non-continuous trace overruns the initial interaction.
+ l_trace = false; //only trace once to avoid flooding the trace
+ }
+ while (1);
+
+ SBE_TRACD(EXIT_MRK "pollForPsuComplete");
+
+ return errl;
+}
+
+/**
+ * @brief read Scom
+ */
+errlHndl_t readScom(TARGETING::Target * i_target,
+ uint64_t i_addr,
+ uint64_t * o_pData,
+ bool i_trace)
+{
+ errlHndl_t errl = NULL;
+
+ size_t l_64bitSize = sizeof(uint64_t);
+ errl = deviceOp(DeviceFW::READ,
+ i_target,
+ o_pData,
+ l_64bitSize,
+ DEVICE_SCOM_ADDRESS(i_addr));
+
+ if (i_trace)
+ {
+ SBE_TRACD(" readScom addr=0x%08lx data=0x%016lx",
+ i_addr,*o_pData);
+ }
+
+ return errl;
+}
+
+/**
+ * @brief write Scom
+ */
+errlHndl_t writeScom(TARGETING::Target * i_target,
+ uint64_t i_addr,
+ uint64_t * i_pData)
+{
+ errlHndl_t errl = NULL;
+
+ SBE_TRACD(" writeScom addr=0x%08lx data=0x%016lx",
+ i_addr,*i_pData);
+ size_t l_64bitSize = sizeof(uint64_t);
+ errl = deviceOp(DeviceFW::WRITE,
+ i_target,
+ i_pData,
+ l_64bitSize,
+ DEVICE_SCOM_ADDRESS(i_addr));
+
+ return errl;
+}
+
+} //end of namespace SBEIO
diff --git a/src/usr/sbeio/sbe_psudd.H b/src/usr/sbeio/sbe_psudd.H
new file mode 100644
index 000000000..9b6228d89
--- /dev/null
+++ b/src/usr/sbeio/sbe_psudd.H
@@ -0,0 +1,414 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/sbeio/sbe_psudd.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2012,2016 */
+/* [+] 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 __SBE_PSUDD_H
+#define __SBE_PSUDD_H
+
+/**
+ * @file sbe_psudd.H
+ * @brief SBE psu device driver specifics
+ */
+
+#include <stdint.h>
+#include <builtins.h>
+#include <sys/time.h>
+
+#include <errl/errlentry.H>
+
+namespace SBEIO
+{
+
+//-----------------------------------------------------------------------------
+// Interfaces to the SBE PSU device driver to be used by clients
+// within this component.
+//-----------------------------------------------------------------------------
+
+ /**
+ * @brief enums for SBE command class
+ */
+ enum psuCommandClass
+ {
+ SBE_PSU_CLASS_UNKNOWN = 0,
+ SBE_PSU_CLASS_CORE_STATE = 0xD1,
+ };
+
+ /**
+ * @brief enums for SBE core state control commands
+ */
+ enum psuCoreStateControlCommands
+ {
+ SBE_CMD_CONTROL_DEADMAN_LOOP = 0x01,
+ };
+
+ /**
+ * @brief enums for SBE core state control commands
+ */
+ enum psuDeadManControlFlags
+ {
+ SBE_DMCONTROL_START = 0x01,
+ SBE_DMCONTROL_STOP = 0x02,
+ SBE_DMCONTROL_RESPONSE_REQUIRED = 0x0100,
+ SBE_DMCONTROL_ACK_REQUIRED = 0x0200,
+ };
+
+ /**
+ * @brief non reserved word enums
+ *
+ * Shows which of the request and response msg registers are
+ * not reserved. Reserved registers do not need to be written
+ * or read.
+ *
+ * This is a 4 bit field:
+ * 0x1 - Reg 0 is non-reserved (read or write this reg)
+ * 0x2 - Reg 1 is non-reserved (read or write this reg)
+ * 0x4 - Reg 2 is non-reserved (read or write this reg)
+ * 0x8 - Reg 3 is non-reserved (read or write this reg)
+ */
+ enum psuCoreStateControlNonReservedMsgs
+ {
+ SBE_DMCONTROL_START_REQ_USED_REGS = 0x03,
+ SBE_DMCONTROL_START_RSP_USED_REGS = 0x01,
+ SBE_DMCONTROL_STOP_REQ_USED_REGS = 0x01,
+ SBE_DMCONTROL_STOP_RSP_USED_REGS = 0x01,
+ };
+
+ /**
+ * @brief Struct for PSU command message format
+ *
+ */
+ union psuCommand
+ {
+ struct //raw
+ {
+ uint64_t mbxReg0;
+ uint64_t mbxReg1;
+ uint64_t mbxReg2;
+ uint64_t mbxReg3;
+ } PACKED;
+ struct //common and direct fields
+ {
+ // mbxReg 0
+ uint16_t reserved;
+ uint16_t controlFlags;
+ uint16_t seqID;
+ uint8_t commandClass;
+ uint8_t command;
+ // mbxReg 1
+ uint32_t dataWord2;
+ uint32_t dataWord3;
+ // mbxReg 2
+ uint32_t dataWord4;
+ uint32_t dataWord5;
+ // mbxReg 3
+ uint32_t dataWord6;
+ uint32_t dataWord7;
+ } PACKED;
+ struct //indirect
+ {
+ // mbxReg 0
+ uint16_t indirect_reserved;
+ uint16_t indirect_controlFlags;
+ uint16_t indirect_seqID;
+ uint8_t indirect_commandClass;
+ uint8_t indirect_command;
+ // mbxReg 1
+ uint32_t indirect_dataWord2;
+ uint32_t indirect_dataWord3;
+ // mbxReg 2
+ uint32_t indirect_dataWord4;
+ uint32_t indirect_dataWord5;
+ // mbxReg 3
+ uint64_t indirect_address; // Data address (Mainstore/PBA)
+ } PACKED;
+ struct //controlDeadmanLoop
+ {
+ uint16_t cdl_reserved;
+ uint16_t cdl_controlFlags;
+ uint16_t cdl_seqID;
+ uint8_t cdl_commandClass;
+ uint8_t cdl_command;
+ uint64_t cdl_waitTime ;
+ uint64_t cdl_mbxReg2reserved;
+ uint64_t cdl_mbxReg3reserved;
+ } PACKED;
+ psuCommand(uint16_t i_controlFlags,
+ uint8_t i_commandClass,
+ uint8_t i_command) :
+ reserved (0),
+ controlFlags(i_controlFlags),
+ seqID(0),
+ commandClass(i_commandClass),
+ command(i_command),
+ dataWord2(0),
+ dataWord3(0),
+ dataWord4(0),
+ dataWord5(0),
+ dataWord6(0),
+ dataWord7(0)
+ {
+ }
+ };
+
+ /**
+ * @brief Struct for PSU response message format
+ *
+ */
+ union psuResponse
+ {
+ struct //raw
+ {
+ uint64_t mbxReg4;
+ uint64_t mbxReg5;
+ uint64_t mbxReg6;
+ uint64_t mbxReg7;
+ } PACKED;
+ struct //common and direct fields
+ {
+ // mbxReg 4
+ uint16_t primaryStatus;
+ uint16_t secondaryStatus;
+ uint16_t seqID;
+ uint8_t commandClass;
+ uint8_t command;
+ // mbxReg 5
+ uint32_t respWord0;
+ uint32_t respWord1;
+ // mbxReg 6
+ uint32_t respWord2;
+ uint32_t respWord3;
+ // mbxReg 7
+ uint32_t respWord4;
+ uint32_t respWord5;
+ } PACKED;
+ struct // indirect fields
+ {
+ // mbxReg 4
+ uint16_t indirect_primaryStatus;
+ uint16_t indirect_secondaryStatus;
+ uint16_t indirect_seqID;
+ uint8_t indirect_commandClass;
+ uint8_t indirect_command;
+ // mbxReg 5
+ uint32_t indirect_respWord0;
+ uint32_t indirect_respWord1;
+ // mbxReg 6
+ uint32_t indirect_respWord2;
+ uint32_t indirect_respWord3;
+ // mbxReg 7
+ uint32_t indirect_reserved;
+ uint32_t indirect_size; //Size in dbl words for Indirect data
+ } PACKED;
+ psuResponse() :
+ primaryStatus (0xffff), //invalid status
+ secondaryStatus (0xffff), //invalid status
+ seqID (0xffff), //unlikely seq ID
+ commandClass (0xff), //invalid command class
+ command (0xff), //invalid command
+ respWord0 (0),
+ respWord1 (0),
+ respWord2 (0),
+ respWord3 (0),
+ respWord4 (0),
+ respWord5 (0)
+ {
+ }
+ };
+
+ /**
+ * @brief timeout values
+ *
+ */
+ const uint64_t MAX_PSU_SHORT_TIMEOUT_NS = 100*NS_PER_MSEC; //=100ms
+ const uint64_t MAX_PSU_LONG_TIMEOUT_NS = 30000*NS_PER_MSEC; //=30 seconds
+
+ /**
+ * @brief enums for primary SBE response
+ *
+ */
+ enum sbePrimResponse
+ {
+ SBE_PRI_OPERATION_SUCCESSFUL = 0x00,
+ SBE_PRI_INVALID_COMMAND = 0x01,
+ SBE_PRI_INVALID_DATA = 0x02,
+ SBE_PRI_SEQUENCE_ERROR = 0x03,
+ SBE_PRI_INTERNAL_ERROR = 0x04,
+ SBE_PRI_GENERIC_EXECUTION_FAILURE = 0xFE,
+ };
+
+ /**
+ * @brief enums for secondary SBE response
+ * Discuss on SBE_SEC_INVALID_TARGET_ID_PASSED
+ *
+ */
+ enum sbeSecondaryResponse
+ {
+ SBE_SEC_OPERATION_SUCCESSFUL = 0x00,
+ SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED = 0x01,
+ SBE_SEC_COMMAND_NOT_SUPPORTED = 0x02,
+ SBE_SEC_INVALID_ADDRESS_PASSED = 0x03,
+ SBE_SEC_INVALID_TARGET_TYPE_PASSED = 0x04,
+ SBE_SEC_INVALID_TARGET_ID_PASSED = 0x05,
+ SBE_SEC_SPECIFIED_TARGET_NOT_PRESENT = 0x06,
+ SBE_SEC_SPECIFIED_TARGET_NOT_FUNCTIONAL = 0x07,
+ SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE = 0x08,
+ SBE_SEC_FUNCTIONALITY_NOT_SUPPORTED = 0x09,
+ SBE_SEC_GENERIC_FAILURE_IN_EXECUTION = 0x0A,
+ SBE_SEC_BACKLISTED_ACCESS = 0x0B,
+ SBE_SEC_OS_FAILURE = 0x0C,
+ SBE_SEC_HOST_MBX_REG_ACCESS_FAILURE = 0x0D,
+ SBE_SEC_INSUFFICIENT_DATA_PASSED = 0x0E,
+ SBE_SEC_EXCESS_DATA_PASSED = 0x0F,
+ SBE_SEC_SBE_BUSY_TO_HANDLE_COMMAND = 0x10,
+ };
+
+ /**
+ * @Brief perform SBE PSU chip-op
+ *
+ * @param[in] i_pPsuRequest Pointer to PSU request commands
+ * @param[out] o_pPsuResponse Pointer to PSU response
+ * @param[in] i_timeout Time out for response
+ * @param[in] i_reqMsgs 4 bit mask telling which regs to write
+ * @param[in] i_rspMsgs 4 bit mask telling which regs to read
+ */
+ errlHndl_t performPsuChipOp(psuCommand * i_pPsuCommand,
+ psuResponse * o_pPsuResponse,
+ const uint64_t i_timeout,
+ uint8_t i_reqMsgs,
+ uint8_t i_rspMsgs);
+
+//-----------------------------------------------------------------------------
+// Local definitions for the device driver
+//-----------------------------------------------------------------------------
+
+ /**
+ * @brief Write request to PSU
+ *
+ * @param[in] i_target Master proc to use for scoms
+ * @param[in] i_pPsuRequest Pointer to PSU request commands
+ * @param[in] i_reqMsgs 4 bit mask telling which regs to write
+ *
+ * @return errlHndl_t Error log handle on failure.
+ */
+ errlHndl_t writeRequest(TARGETING::Target * i_target,
+ psuCommand * i_pPsuRequest,
+ uint8_t i_reqMsgs);
+ /**
+ * @brief Read response from PSU
+ *
+ * @param[in] i_target Master proc to use for scoms
+ * @param[in] i_pPsuRequest Pointer to PSU request commands
+ * @param[out] o_pPsuResponse Pointer to PSU response
+ * @param[in] i_timeout Time out for response
+ * @param[in] i_rspMsgs 4 bit mask telling which regs to read
+ *
+ * @return errlHndl_t Error log handle on failure.
+ */
+ errlHndl_t readResponse(TARGETING::Target * i_target,
+ psuCommand * i_pPsuRequest,
+ psuResponse * o_pPsuResponse,
+ const uint64_t i_timeout,
+ uint8_t i_rspMsgs);
+ /**
+ * @brief Poll for response ready to be read
+ *
+ * @param[in] i_target Master proc to use for scoms
+ * @param[in] i_timeout Time out for response
+ *
+ * @return errlHndl_t Error log handle on failure.
+ */
+ errlHndl_t pollForPsuComplete(TARGETING::Target * i_target,
+ const uint64_t i_timeout);
+ /**
+ * @brief Read Scom wrapper
+ *
+ * @param[in] i_target Master proc to use for scoms
+ * @param[in] i_addr Scom address
+ * @param[out] o_pData Pointer to returned data
+ * @param[in] i_trace Trace control to avoid overruning trace buffer
+ * when polling for response ready to be read
+ *
+ * @return errlHndl_t Error log handle on failure.
+ */
+ errlHndl_t readScom(TARGETING::Target * i_target,
+ uint64_t i_addr,
+ uint64_t * o_pData,
+ bool i_trace=true);
+
+ /**
+ * @brief Write Scom wrapper
+ *
+ * @param[in] i_target Master proc to use for scoms
+ * @param[in] i_addr Scom address
+ * @param[in] i_pData Pointer to data to write
+ *
+ * @return errlHndl_t Error log handle on failure.
+ */
+ errlHndl_t writeScom(TARGETING::Target * i_target,
+ uint64_t i_addr,
+ uint64_t * i_pData);
+
+ /**
+ * @brief SBE PSU register addresses
+ */
+ enum psuRegs
+ {
+ PSU_HOST_SBE_MBOX0_REG = 0x000D0050,
+ PSU_HOST_SBE_MBOX1_REG = 0x000D0051,
+ PSU_HOST_SBE_MBOX2_REG = 0x000D0052,
+ PSU_HOST_SBE_MBOX3_REG = 0x000D0053,
+ PSU_HOST_SBE_MBOX4_REG = 0x000D0054,
+ PSU_HOST_SBE_MBOX5_REG = 0x000D0055,
+ PSU_HOST_SBE_MBOX6_REG = 0x000D0056,
+ PSU_HOST_SBE_MBOX7_REG = 0x000D0057,
+ PSU_SBE_DOORBELL_REG_RW = 0x000D0060,
+ PSU_SBE_DOORBELL_REG_AND = 0x000D0061,
+ PSU_SBE_DOORBELL_REG_OR = 0x000D0062,
+ PSU_HOST_DOORBELL_REG_RW = 0x000D0063,
+ PSU_HOST_DOORBELL_REG_AND = 0x000D0064,
+ PSU_HOST_DOORBELL_REG_OR = 0x000D0065,
+ };
+
+ /**
+ * @brief SBE PSU door bell register
+ */
+ enum sbeDoorbellReg
+ {
+ // Doorbell Register to trigger SBE interrupt
+ // psu_sbe_interrupt_msg_available. Set by host firmware to inform
+ // the SBE about a waiting message in the Host/SBE Mailbox Registers
+ SBE_DOORBELL =0x8000000000000000,
+ };
+ enum hostDoorbellReg
+ {
+ // Doorbell Register for Host Bridge interrupt. Set by the SBE to
+ // inform host firmware about a response message in the Host/SBE
+ // Mailbox Registers
+ HOST_RESPONSE_WAITING = 0x8000000000000000,
+ HOST_CLEAR_RESPONSE_WAITING = 0x7FFFFFFFFFFFFFFF,
+ };
+
+}
+
+#endif
OpenPOWER on IntegriCloud