aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2015-06-05 23:40:52 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-07-09 16:28:15 +1000
commita524c05983e36ab0a29cd2e3c979dff672d0eb6b (patch)
treecd56177168b5666f76761b3f1cf6a9259c51d72f /hw
parent645984621bc2cb60a181026434401f7d72ae702b (diff)
downloadskiboot-a524c05983e36ab0a29cd2e3c979dff672d0eb6b.zip
skiboot-a524c05983e36ab0a29cd2e3c979dff672d0eb6b.tar.gz
skiboot-a524c05983e36ab0a29cd2e3c979dff672d0eb6b.tar.bz2
opal: Recover from TOD register parity errors.
This patch implements recovery from parity errors on below listed TOD control registers: - Master Path control register (0x00040000) - Primary Port-0 control register (0x00040001) - Primary Port-1 control register (0x00040002) - Secondary Port-0 control register (0x00040003) - Secondary Port-1 control register (0x00040004) - Slave Path control register (0x00040005) - Internal Path control register (0x00040006) - Primary/secondary master/slave control register (0x00040007) - Chip control register (0x00040010) To inject TOD register parity error issue: putscom pu 40031 8000000000000000 -pall # (00040000) putscom pu 40031 1000000000000000 -pall # (00040001) putscom pu 40031 0800000000000000 -pall # (00040002) putscom pu 40031 0400000000000000 -pall # (00040003) putscom pu 40031 0200000000000000 -pall # (00040004) putscom pu 40031 0100000000000000 -pall # (00040005) putscom pu 40031 0080000000000000 -pall # (00040006) putscom pu 40031 0040000000000000 -pall # (00040007) putscom pu 40031 0000000080000000 -pall # (00040010) Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/chiptod.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/hw/chiptod.c b/hw/chiptod.c
index 99847cc..b09f378 100644
--- a/hw/chiptod.c
+++ b/hw/chiptod.c
@@ -957,6 +957,9 @@ bool chiptod_wakeup_resync(void)
static int chiptod_recover_tod_errors(void)
{
uint64_t terr;
+ uint64_t treset = 0;
+ int i;
+ int32_t chip_id = this_cpu()->chip_id;
/* Read TOD error register */
if (xscom_readme(TOD_ERROR, &terr) != 0) {
@@ -971,9 +974,41 @@ static int chiptod_recover_tod_errors(void)
(terr & TOD_ERR_DELAY_COMPL_PARITY) ||
(terr & TOD_ERR_TOD_REGISTER_PARITY)) {
chiptod_reset_tod_errors();
- return 1;
}
- return 0;
+
+ /*
+ * Check for TOD control register parity errors and restore those
+ * registers with last saved valid values.
+ */
+ for (i = 0; i < ARRAY_SIZE(chiptod_tod_regs); i++) {
+ if (!(terr & chiptod_tod_regs[i].error_bit))
+ continue;
+
+ /* Check if we have valid last saved register value. */
+ if (!chiptod_tod_regs[i].val[chip_id].valid) {
+ prerror("CHIPTOD: Failed to restore TOD register: "
+ "%08llx", chiptod_tod_regs[i].xscom_addr);
+ return 0;
+ }
+
+ prlog(PR_DEBUG, "CHIPTOD: parity error, "
+ "Restoring TOD register: %08llx\n",
+ chiptod_tod_regs[i].xscom_addr);
+ if (xscom_writeme(chiptod_tod_regs[i].xscom_addr,
+ chiptod_tod_regs[i].val[chip_id].data) != 0) {
+ prerror("CHIPTOD: XSCOM error writing 0x%08llx reg.\n",
+ chiptod_tod_regs[i].xscom_addr);
+ return 0;
+ }
+ treset |= chiptod_tod_regs[i].error_bit;
+ }
+
+ if (treset && (xscom_writeme(TOD_ERROR, treset) != 0)) {
+ prerror("CHIPTOD: XSCOM error writing TOD_ERROR !\n");
+ return 0;
+ }
+ /* We have handled all the TOD errors routed to hypervisor */
+ return 1;
}
static int32_t chiptod_get_active_master(void)