diff options
author | Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> | 2015-06-05 23:40:52 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-07-09 16:28:15 +1000 |
commit | a524c05983e36ab0a29cd2e3c979dff672d0eb6b (patch) | |
tree | cd56177168b5666f76761b3f1cf6a9259c51d72f /hw | |
parent | 645984621bc2cb60a181026434401f7d72ae702b (diff) | |
download | skiboot-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.c | 39 |
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) |