summaryrefslogtreecommitdiffstats
path: root/src/usr/sio/siodd.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/sio/siodd.C')
-rwxr-xr-xsrc/usr/sio/siodd.C85
1 files changed, 64 insertions, 21 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
OpenPOWER on IntegriCloud