summaryrefslogtreecommitdiffstats
path: root/src/usr/sio
diff options
context:
space:
mode:
authorAndrew Jeffery <andrewrj@au1.ibm.com>2018-10-15 15:35:07 +1030
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-10-15 16:11:08 -0500
commit55ff29accb8313232e5a1a6cf5d7a54681579073 (patch)
treef8c20018033b639d1864df3f7a5d33bb3512977b /src/usr/sio
parent95165ec1e1116f5675c8410f230ecce95af86c6d (diff)
downloadblackbird-hostboot-55ff29accb8313232e5a1a6cf5d7a54681579073.tar.gz
blackbird-hostboot-55ff29accb8313232e5a1a6cf5d7a54681579073.zip
sio: Add test for availability
Some components can continue to operate in the face of the SuperIO controller being unavailable on the LPC bus (specifically, the UART and boot flag processing). Other components require it present (AST-based SFC implementations and the AST mailbox). Components in the latter category can just fail with an errl when they attempt to access the controller, but for those in the former category we add an isAvailable() function in the SIO namespace to sidestep dealing with errors. Specifically, isAvailable() tests for the expected error when the SuperIO controller is disabled, and returns an errlHndl_t if any other error occurs. This way true LPC errors are propagated to the caller to commit as desired. For the moment *all* errors produced by the SIO::isAvailable() LPC bus access will result in the SIO code assuming the device is absent. We should be more precise about this, but the hardware behaviour seen under hostboot currently prevents us from being more specific. This problem is highlighted by a FIXME block in the implementation of SIO::isAvailable(). Change-Id: Id30a09b48586d2054e0cdae625ee23df68ac2aa3 Signed-off-by: Andrew Jeffery <andrewrj@au1.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/67460 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Corey V. Swenson <cswenson@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/sio')
-rwxr-xr-xsrc/usr/sio/siodd.C85
-rw-r--r--src/usr/sio/siodd.H4
2 files changed, 67 insertions, 22 deletions
diff --git a/src/usr/sio/siodd.C b/src/usr/sio/siodd.C
index 5301d9e1c..8bbc59f5b 100755
--- a/src/usr/sio/siodd.C
+++ b/src/usr/sio/siodd.C
@@ -37,6 +37,9 @@
#include <hbotcompid.H>
#include <stdarg.h>
#include <targeting/common/target.H>
+#include <lpc/lpc_reasoncodes.H>
+
+#include <console/consoleif.H>
// Trace definition
trace_desc_t* g_trac_sio = NULL;
@@ -191,32 +194,64 @@ DEVICE_REGISTER_ROUTE( DeviceFW::WRITE,
TARGETING::TYPE_PROC,
ahbSioWriteDD );
-//function to unlock superIO password register
-void SioDD::unlock_SIO(TARGETING::Target* i_target)
+errlHndl_t SIO::isAvailable(bool& available)
{
uint8_t l_byte = SIO::SIO_PASSWORD_REG;
- errlHndl_t l_err = NULL;
- do
- {
- // Unlock the SIO registers
- // (write 0xA5 password to offset 0x2E two times)
size_t l_len = sizeof(uint8_t);
- l_err = deviceWrite(i_target,
- &l_byte,
- l_len,
- DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_ADDR_REG_2E));
- if(l_err) { break; }
- l_err = deviceWrite(i_target,
- &l_byte,
- l_len,
+ errlHndl_t l_err = NULL;
+
+ l_err = deviceWrite(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &l_byte, l_len,
DEVICE_LPC_ADDRESS(LPC::TRANS_IO, SIO::SIO_ADDR_REG_2E));
- } while(0);
if (l_err)
{
- TRACFCOMP(g_trac_sio,"Error in unlocking SIO password register\n");
- errlCommit(l_err, SIO_COMP_ID);
+ /* FIXME: The implementation assumes that any error indicates that the
+ * SIO device is not available. This, generally, is a terribe
+ * assumption. We should instead look for the specific failure, which
+ * is a LPC SYNC No Response (and this is what we see in skiboot).
+ * Currently there are open questions about the hardware behaviour as
+ * observed by hostboot: We see an OPBM Error Acknowledge state when we
+ * try to access an absent SIO device, but no error state is present in
+ * the LPCHC status register.
+ *
+ * We retain the interface of returning an errlHndl_t to future-proof
+ * the code. The caller should commit the errl if it is valid.
+ */
+ TRACFCOMP(g_trac_sio,
+ "Received error during SIO availability test, assuming "
+ "absent. Reason code: 0x%x, user data: [0x%8x, 0x%8x]",
+ l_err->reasonCode(), l_err->getUserData1(),
+ l_err->getUserData2());
+ available = false;
+ delete l_err;
+ l_err = NULL;
+ }
+ else
+ {
+ available = true;
}
+
+ return l_err;
+}
+
+//function to unlock superIO password register
+errlHndl_t SioDD::unlock_SIO(TARGETING::Target* i_target)
+{
+ uint8_t l_byte = SIO::SIO_PASSWORD_REG;
+ size_t l_len = sizeof(uint8_t);
+ errlHndl_t l_err = NULL;
+ int again = 1;
+
+ do
+ {
+ // Unlock the SIO registers (write 0xA5 password to offset 0x2E two times)
+ l_err = deviceWrite(i_target, &l_byte, l_len,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_IO,
+ SIO::SIO_ADDR_REG_2E));
+ } while(!l_err && again--);
+
+ return l_err;
}
//SioDD constructor
@@ -225,7 +260,16 @@ SioDD::SioDD(TARGETING::Target* i_target)
assert(i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
mutex_init(&iv_sio_mutex);
iv_prev_dev = 0x00;
- unlock_SIO(i_target);
+
+ errlHndl_t err = unlock_SIO(i_target);
+ bool failed = (err != NULL);
+ delete err;
+
+ /* Unlocked very early, so make some noise if we fail */
+ if (failed)
+ {
+ printk("SuperIO unlock failed! Expect future errors\n");
+ }
}
//SioDD destructor
@@ -279,8 +323,7 @@ errlHndl_t SioDD::_readSIO(TARGETING::Target* i_target,
//function to change logical device in SIO
errlHndl_t SioDD::changeDevice(TARGETING::Target* i_target, uint8_t i_dev)
{
- uint8_t l_reg = SIO::SIO_DEVICE_SELECT_REG;
- return _writeSIO(i_target, l_reg, &i_dev);
+ return _writeSIO(i_target, SIO::SIO_DEVICE_SELECT_REG, &i_dev);
}
//function to read from SIO register
diff --git a/src/usr/sio/siodd.H b/src/usr/sio/siodd.H
index 664935921..86821d466 100644
--- a/src/usr/sio/siodd.H
+++ b/src/usr/sio/siodd.H
@@ -167,8 +167,10 @@ class SioDD
/**
* @brief Unlock SIO password register
* @param[in] i_target: SIO target
+ *
+ * @return Error from operation
*/
- void unlock_SIO(TARGETING::Target* i_target);
+ errlHndl_t unlock_SIO(TARGETING::Target* i_target);
/**
* @brief Previous device accessed by SIO
OpenPOWER on IntegriCloud