summaryrefslogtreecommitdiffstats
path: root/src/usr/xscom
diff options
context:
space:
mode:
authorDoug Gilbert <dgilbert@us.ibm.com>2013-09-16 16:13:27 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-10-17 11:26:40 -0500
commit498291a1a22d35ffb27ba7d6665d9cec22d8d98e (patch)
treecd4d2efcff399b2a91858f56e6a6654d91513c21 /src/usr/xscom
parent25a68ad9643b83001dbe80120f854221e65e9585 (diff)
downloadtalos-hostboot-498291a1a22d35ffb27ba7d6665d9cec22d8d98e.tar.gz
talos-hostboot-498291a1a22d35ffb27ba7d6665d9cec22d8d98e.zip
Hostboot runtime scom support
RTC: 79407 RTC: 79406 Change-Id: I8cbf1f21e8e9e205eb0130ce96187619647cf486 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/6350 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/xscom')
-rw-r--r--src/usr/xscom/makefile2
-rw-r--r--src/usr/xscom/runtime/makefile32
-rw-r--r--src/usr/xscom/runtime/rt_xscom.C411
-rw-r--r--src/usr/xscom/runtime/test/makefile29
-rw-r--r--src/usr/xscom/runtime/test/testxscom_rt.H159
5 files changed, 632 insertions, 1 deletions
diff --git a/src/usr/xscom/makefile b/src/usr/xscom/makefile
index f879c70ec..89ead1946 100644
--- a/src/usr/xscom/makefile
+++ b/src/usr/xscom/makefile
@@ -25,6 +25,6 @@ MODULE = xscom
OBJS = xscom.o piberror.o
-SUBDIRS = test.d
+SUBDIRS = test.d runtime.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/xscom/runtime/makefile b/src/usr/xscom/runtime/makefile
new file mode 100644
index 000000000..b49e707b5
--- /dev/null
+++ b/src/usr/xscom/runtime/makefile
@@ -0,0 +1,32 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/xscom/runtime/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2013
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or otherwise
+# divested of its trade secrets, irrespective of what has been
+# deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END_TAG
+HOSTBOOT_RUNTIME = 1
+ROOTPATH = ../../../..
+MODULE = xscom_rt
+
+OBJS = rt_xscom.o
+
+SUBDIRS = test.d
+
+VPATH += ..
+include $(ROOTPATH)/config.mk
diff --git a/src/usr/xscom/runtime/rt_xscom.C b/src/usr/xscom/runtime/rt_xscom.C
new file mode 100644
index 000000000..7aa8669cb
--- /dev/null
+++ b/src/usr/xscom/runtime/rt_xscom.C
@@ -0,0 +1,411 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/xscom/runtime/rt_xscom.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <devicefw/driverif.H>
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <targeting/common/targetservice.H>
+#include <targeting/common/utilFilter.H>
+#include <xscom/xscomreasoncodes.H>
+#include "../xscom.H"
+#include <assert.h>
+#include <errl/errludlogregister.H>
+#include <runtime/interface.h>
+#include <errl/errludtarget.H>
+
+// Trace definition
+trace_desc_t* g_trac_xscom = NULL;
+TRAC_INIT(&g_trac_xscom, "XSCOM", 2*KILOBYTE, TRACE::BUFFER_SLOW);
+
+namespace XSCOM
+{
+
+enum
+{
+ CHIPID_NODE_SHIFT = 3, // CHIPID is 'NNNCCC'b, shift 3
+ MEMBUF_ID_SHIFT = 4, // CHIPID for MEMBUF is 'NNNCCCMMMM'b
+ MEMBUF_ID_FLAG = 0x80000000, // MEMBUF chip id has MSbit on
+};
+
+
+DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
+ DeviceFW::XSCOM,
+ TARGETING::TYPE_PROC,
+ xscomPerformOp);
+
+// Direct all scom calls though this interface at runtime
+DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
+ DeviceFW::FSISCOM,
+ TARGETING::TYPE_PROC,
+ xscomPerformOp);
+
+DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
+ DeviceFW::FSISCOM,
+ TARGETING::TYPE_MEMBUF,
+ xscomPerformOp);
+
+DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
+ DeviceFW::IBSCOM,
+ TARGETING::TYPE_MEMBUF,
+ xscomPerformOp);
+/**
+ * @brief Convert target into chipId that the hypervisor uses
+ * @param[in] i_target The HB TARGETING target
+ * @param[out] o_chipId 32-bit chipid
+ * @return errlHndl_t Error handle if there was an error
+ */
+errlHndl_t get_rt_target(TARGETING::Target* i_target,
+ uint32_t & o_chipId);
+
+/**
+ * @brief Internal routine that verifies the validity of input parameters
+ * for an XSCOM access.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ * @param[in] i_target XSCom target
+ * @param[in/out] i_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] i_buflen Input: size of io_buffer (in bytes)
+ * Output:
+ * Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there's only one argument,
+ * which is the MMIO XSCom address
+ * @return errlHndl_t
+ */
+errlHndl_t xscomOpSanityCheck(const DeviceFW::OperationType i_opType,
+ const TARGETING::Target* i_target,
+ const void* i_buffer,
+ const size_t& i_buflen,
+ const va_list i_args);
+
+
+
+errlHndl_t xscomOpSanityCheck(const DeviceFW::OperationType i_opType,
+ const TARGETING::Target* i_target,
+ const void* i_buffer,
+ const size_t& i_buflen,
+ const va_list i_args){
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+ // Verify data buffer
+ if ( (i_buflen < XSCOM_BUFFER_SIZE) ||
+ (i_buffer == NULL) )
+ {
+ /*@
+ * @errortype
+ * @moduleid XSCOM_RT_SANITY_CHECK
+ * @reasoncode XSCOM_INVALID_DATA_BUFFER
+ * @userdata1 Buffer size
+ * @userdata2 XSCom address
+ * @devdesc XSCOM buffer size < 8 bytes or NULL data buff
+ */
+ l_err =
+ new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ XSCOM_RT_SANITY_CHECK,
+ XSCOM_INVALID_DATA_BUFFER,
+ i_buflen,
+ va_arg(i_args,uint64_t));
+ break;
+ }
+
+ // Verify OP type
+ if ( (i_opType != DeviceFW::READ) &&
+ (i_opType != DeviceFW::WRITE) )
+ {
+ /*@
+ * @errortype
+ * @moduleid XSCOM_RT_SANITY_CHECK
+ * @reasoncode XSCOM_INVALID_OP_TYPE
+ * @userdata1 Operation type
+ * @userdata2 XSCom address
+ * @devdesc XSCOM invalid operation type
+ */
+ l_err =
+ new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ XSCOM_RT_SANITY_CHECK,
+ XSCOM_INVALID_OP_TYPE,
+ i_opType,
+ va_arg(i_args,uint64_t));
+ break;
+ }
+
+
+ } while(0);
+
+ return l_err;
+}
+
+
+errlHndl_t get_rt_target(TARGETING::Target* i_target,
+ uint32_t &o_chipId)
+{
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+ if(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ {
+ TARGETING::Target* masterProcChip = NULL;
+ TARGETING::targetService().
+ masterProcChipTargetHandle(masterProcChip);
+
+ i_target = masterProcChip;
+ }
+
+ uint32_t target_type = i_target->getAttr<TARGETING::ATTR_TYPE>();
+
+ if(target_type == TARGETING::TYPE_MEMBUF)
+ {
+ TARGETING::TargetHandleList targetList;
+
+ // need to get assoicated MC for this MEMBUF
+ getParentAffinityTargets(targetList,
+ i_target,
+ TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_MCS);
+ if( targetList.empty() )
+ {
+ uint32_t huid = get_huid(i_target);
+ TRACFCOMP(g_trac_xscom,ERR_MRK
+ "No MSC target found for MEMBUF. MEMBUF huid: %08x",
+ huid);
+ /*@
+ * @errortype
+ * @moduleid XSCOM_RT_GET_TARGET
+ * @reasoncode XSCOM_RT_NO_MCS_TARGET
+ * @userdata1 HUID of MEMBUF target
+ * @devdesc No memory controller target found for the
+ * given Memory data controller
+ */
+ l_err =
+ new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ XSCOM_RT_GET_TARGET,
+ XSCOM_RT_NO_MCS_TARGET,
+ huid,
+ 0);
+
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+
+ ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target").
+ addToLog(l_err);
+
+ break;
+ }
+
+ TARGETING::Target * mcs_target = targetList[0];
+ uint32_t mcpos = mcs_target->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+
+ // Get associated proc chip
+ targetList.clear();
+ getParentAffinityTargets(targetList,
+ mcs_target,
+ TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC);
+
+ if(targetList.empty())
+ {
+ uint32_t huid = get_huid(mcs_target);
+ TRACFCOMP(g_trac_xscom,ERR_MRK
+ "No proc target found for MSC. MSC huid: %08x",
+ huid);
+ /*@
+ * @errortype
+ * @moduleid XSCOM_RT_GET_TARGET
+ * @reasoncode XSCOM_RT_NO_PROC_TARGET
+ * @userdata1 HUID of the MSC target
+ * @devdesc No processor target found for the Memory
+ * controller.
+ */
+ l_err =
+ new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ XSCOM_RT_GET_TARGET,
+ XSCOM_RT_NO_PROC_TARGET,
+ huid,
+ 0);
+
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+
+ ERRORLOG::ErrlUserDetailsTarget(mcs_target,"SCOM Target").
+ addToLog(l_err);
+
+ break;
+ }
+
+ TARGETING::Target * proc_target = targetList[0];
+ uint32_t fabId =
+ proc_target->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
+ uint32_t procPos =
+ proc_target->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+
+ o_chipId = (fabId << CHIPID_NODE_SHIFT) + procPos;
+ o_chipId = (o_chipId << MEMBUF_ID_SHIFT) | MEMBUF_ID_FLAG;
+ o_chipId += mcpos;
+ }
+ else // must be proc
+ {
+ uint32_t fabId = i_target->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
+ uint32_t procPos = i_target->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+
+ o_chipId = (fabId << CHIPID_NODE_SHIFT) + procPos;
+ }
+ } while(0);
+
+ return l_err;
+}
+
+
+/**
+ * @brief Do the scom operation
+ */
+errlHndl_t xScomDoOp(DeviceFW::OperationType i_ioType,
+ TARGETING::Target * i_target,
+ uint32_t i_scomAddr,
+ void * io_buffer)
+{
+ errlHndl_t l_err = NULL;
+ int rc = 0;
+ uint32_t proc_id = 0;
+
+ // Convert target to something Sapphire understands
+ l_err = get_rt_target(i_target,
+ proc_id);
+
+ if(l_err)
+ {
+ return l_err;
+ }
+
+ if(g_hostInterfaces != NULL &&
+ g_hostInterfaces->scom_read != NULL &&
+ g_hostInterfaces->scom_write != NULL)
+ {
+
+ if(i_ioType == DeviceFW::READ)
+ {
+ rc =
+ g_hostInterfaces->scom_read(proc_id,
+ i_scomAddr,
+ io_buffer
+ );
+ }
+ else if (i_ioType == DeviceFW::WRITE)
+ {
+ rc =
+ g_hostInterfaces->scom_write(proc_id,
+ i_scomAddr,
+ io_buffer
+ );
+ }
+
+ if(rc)
+ {
+ // convert rc to error log
+ /*@
+ * @errortype
+ * @moduleid XSCOM_RT_DO_OP
+ * @reasoncode XSCOM_RUNTIME_ERR
+ * @userdata1 Hypervisor return code
+ * @userdata2 SCOM address
+ * @devdesc XSCOM access error
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ XSCOM_RT_DO_OP,
+ XSCOM_RUNTIME_ERR,
+ rc,
+ i_scomAddr);
+
+ // TODO - RTC 86782 need to know what kind of errors Sapphire can
+ // return - could effect callout.
+ l_err->addHwCallout(i_target,
+ HWAS::SRCI_PRIORITY_LOW,
+ HWAS::NO_DECONFIG,
+ HWAS::GARD_NULL);
+
+ // Note: no trace buffer available at runtime
+ }
+ }
+ else // Hypervisor interface not initialized
+ {
+ TRACFCOMP(g_trac_xscom,ERR_MRK"Hypervisor scom interface not linked");
+ /*@
+ * @errortype
+ * @moduleid XSCOM_RT_DO_OP
+ * @reasoncode XSCOM_RUNTIME_INTERFACE_ERR
+ * @userdata1 0
+ * @userdata2 SCOM address
+ * @devdesc XSCOM runtime interface not linked.
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ XSCOM_RT_DO_OP,
+ XSCOM_RUNTIME_INTERFACE_ERR,
+ 0,
+ i_scomAddr);
+
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ }
+
+ return l_err;
+}
+
+
+errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ TRACDCOMP(g_trac_xscom,ENTER_MRK"xscomPerformOp");
+ errlHndl_t l_err = NULL;
+ uint64_t l_addr = va_arg(i_args,uint64_t);
+
+ l_err = xscomOpSanityCheck(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ i_args);
+
+ if (!l_err)
+ {
+
+ l_err = xScomDoOp(i_opType,
+ i_target,
+ (uint32_t)l_addr,
+ io_buffer);
+ }
+
+ TRACDCOMP(g_trac_xscom,EXIT_MRK"xscomPerformOp");
+
+ return l_err;
+}
+
+}; // end namespace XSCOM
+
diff --git a/src/usr/xscom/runtime/test/makefile b/src/usr/xscom/runtime/test/makefile
new file mode 100644
index 000000000..23939761e
--- /dev/null
+++ b/src/usr/xscom/runtime/test/makefile
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/xscom/runtime/test/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2013
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or otherwise
+# divested of its trade secrets, irrespective of what has been
+# deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END_TAG
+HOSTBOOT_RUNTIME = 1
+ROOTPATH = ../../../../..
+
+MODULE = testxscom_rt
+TESTS = *.H
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/xscom/runtime/test/testxscom_rt.H b/src/usr/xscom/runtime/test/testxscom_rt.H
new file mode 100644
index 000000000..943d6381e
--- /dev/null
+++ b/src/usr/xscom/runtime/test/testxscom_rt.H
@@ -0,0 +1,159 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/xscom/runtime/test/testxscom_rt.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <devicefw/userif.H>
+#include <xscom/xscomreasoncodes.H>
+
+extern trace_desc_t* g_trac_xscom;
+
+using namespace TARGETING;
+
+// Address and data to read/write
+struct testXscomAddrData
+{
+ uint32_t addr;
+ uint64_t data;
+};
+
+// Test table values
+const testXscomAddrData g_xscomAddrTable[] =
+{
+ // Write data to be ORed with read value
+ {0x15013288, 0x0000040000000000},
+ {0x15010002, 0xC000000000000000},
+ {0x00040001, 0xE000000000000000}, //TP Chiplet
+ // TODO - more tests
+};
+const uint32_t g_xscomAddrTableSz =
+ sizeof(g_xscomAddrTable)/sizeof(testXscomAddrData);
+
+class XscomTestSuite : public CxxTest::TestSuite
+{
+ public:
+ /**
+ * @brief XSCOM test #1
+ * Write value and read back to verify
+ */
+ void testXscom1(void)
+ {
+
+ TARGETING::TargetService& l_targetService = TARGETING::targetService();
+ TARGETING::Target* l_testTarget = NULL;
+ l_targetService.masterProcChipTargetHandle( l_testTarget );
+ assert(l_testTarget != NULL);
+
+ size_t l_size = sizeof(uint64_t);
+
+ // Loop thru table
+ errlHndl_t l_err = NULL;
+ for( uint32_t l_num=0; l_num < g_xscomAddrTableSz; l_num++)
+ {
+ testXscomAddrData l_testEntry = g_xscomAddrTable[l_num];
+
+ // Perform XSComOM read
+ uint64_t l_readData = 0;
+ uint64_t l_writeData = 0;
+ uint64_t l_savedData = 0;
+ l_err = deviceRead(l_testTarget,
+ &l_readData,
+ l_size,
+ DEVICE_SCOM_ADDRESS(l_testEntry.addr));
+ if (l_err)
+ {
+ TS_FAIL("testXscom1: XSCom read: deviceRead() fails! Error committed.");
+ break;
+ }
+ else
+ {
+ TS_TRACE("testXscom1: XSCom read, Address 0x%.8X, Data %llx",
+ l_testEntry.addr,
+ (long long unsigned)l_readData);
+ }
+
+ // Perform an XSCom write
+ l_savedData = l_readData;
+ l_writeData = (l_readData | l_testEntry.data);
+ l_err = deviceWrite(l_testTarget,
+ &l_writeData,
+ l_size,
+ DeviceFW::SCOM,
+ l_testEntry.addr);
+
+ if (l_err)
+ {
+ TS_FAIL("testXscom1: XSCom write: deviceWrite() fails!");
+ break;
+ }
+ else
+ {
+ TS_TRACE("testXscom1: XSCom write, Address 0x%.8X, Data %llx",
+ l_testEntry.addr,
+ (long long unsigned)l_writeData);
+ }
+
+ // Read back
+ l_readData = 0;
+ l_err = deviceRead(l_testTarget,
+ &l_readData,
+ l_size,
+ DEVICE_SCOM_ADDRESS(l_testEntry.addr));
+ if (l_err)
+ {
+ TS_FAIL("testXscom1: XSCom read back: deviceRead() fails!");
+ break;
+ }
+
+ if( l_readData != l_writeData )
+ {
+ TS_FAIL("testXscom1: XSCom read back doesn't match write!");
+ break;
+ }
+
+ // Write back original value
+ l_err = deviceWrite(l_testTarget,
+ &l_savedData,
+ l_size,
+ DeviceFW::SCOM,
+ l_testEntry.addr);
+
+ if (l_err)
+ {
+ TS_FAIL("testXscom1: XSCom write back original fails!");
+ break;
+ }
+ }
+
+ if (l_err)
+ {
+ TS_FAIL("testXscom1 failed! Error committed.");
+ errlCommit(l_err,XSCOM_COMP_ID);
+ }
+ else
+ {
+ TS_TRACE("testXscom1 runs successfully!");
+ }
+ return;
+ }
+};
OpenPOWER on IntegriCloud