diff options
-rw-r--r-- | src/hwpf/include/plat/plat_hw_access.H | 26 | ||||
-rw-r--r-- | src/hwpf/src/plat/plat_hw_access.C | 61 |
2 files changed, 87 insertions, 0 deletions
diff --git a/src/hwpf/include/plat/plat_hw_access.H b/src/hwpf/include/plat/plat_hw_access.H index 89c02f2a..c7c73325 100644 --- a/src/hwpf/include/plat/plat_hw_access.H +++ b/src/hwpf/include/plat/plat_hw_access.H @@ -6,6 +6,7 @@ /* OpenPOWER sbe Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* [+] International Business Machines Corp. */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -34,6 +35,18 @@ #include "hw_access_def.H" #include <return_code.H> +// PIB errors +enum PCB_ERRORS +{ + PIB_NO_ERROR = 0x0, + PIB_XSCOM_ERROR = 0x1, + PIB_OFFLINE_ERROR = 0x2, + PIB_PARTIAL_ERROR = 0x3, + PIB_ADDRESS_ERROR = 0x4, + PIB_CLOCK_ERROR = 0x5, + PIB_PARITY_ERROR = 0x6, + PIB_TIMEOUT_ERROR = 0x7 +}; /// PIB Error Mask @@ -141,6 +154,19 @@ namespace fapi2 /// @return PCB-PIB return code /// uint32_t putscom_abs_wrap(const uint32_t i_addr, uint64_t i_data); + + /// + /// @brief Platform wrapper to retry scom for parity/timeout errors + /// + /// @param [in] i_addr The SCOM address + /// @param [io] io_data The data pointer + /// @param [in] i_pibErr PIB error code + /// @param [in] i_isRead True if read operation, false otherwise + /// + /// @return PCB-PIB return code + /// + uint32_t p9_pibErrRetry( const uint32_t i_addr, uint64_t *io_data, + const uint8_t i_pibErr, const bool i_isRead); } diff --git a/src/hwpf/src/plat/plat_hw_access.C b/src/hwpf/src/plat/plat_hw_access.C index 5c2af1a8..01fedc96 100644 --- a/src/hwpf/src/plat/plat_hw_access.C +++ b/src/hwpf/src/plat/plat_hw_access.C @@ -6,6 +6,7 @@ /* OpenPOWER sbe Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -24,6 +25,7 @@ #include <fapi2.H> #include "plat_hw_access.H" +#include "p9_perv_scom_addresses.H" namespace fapi2 { @@ -53,6 +55,10 @@ namespace fapi2 uint32_t l_rc = 0; FAPI_INF("getScom: address: 0x%08X", i_addr); l_rc = getscom_abs(i_addr, o_data); + if( PIB_NO_ERROR != l_rc ) + { + l_rc = p9_pibErrRetry( i_addr, o_data, l_rc, true); + } FAPI_INF("getScom: returned rc: 0x%08X, data HI: 0x%08X, " "data LO: 0x%08X", l_rc, (*o_data >> 32), static_cast<uint32_t>(*o_data & 0xFFFFFFFF)); @@ -66,7 +72,62 @@ namespace fapi2 i_addr, (i_data >> 32), static_cast<uint32_t>(i_data & 0xFFFFFFFF)); l_rc = putscom_abs(i_addr, i_data); + if( PIB_NO_ERROR != l_rc ) + { + l_rc = p9_pibErrRetry( i_addr, &i_data, l_rc, false); + } FAPI_INF("putScom: returned rc: 0x%08X", l_rc); return l_rc; } + +uint32_t p9_pibErrRetry( const uint32_t i_addr, uint64_t *io_data, + const uint8_t i_pibErr, const bool i_isRead) +{ + FAPI_INF("Entering p9_pibErrRetry"); + static const uint8_t MAX_RETRIES = 2; + static const uint64_t REG_BIT0 = (uint64_t)(0x1)<<63; + uint8_t l_retryCount = 0; + uint32_t pibErr = i_pibErr; + + do + { + // Only retry for parity and timeout errors + if (( i_pibErr != PIB_PARITY_ERROR ) + && ( i_pibErr != PIB_TIMEOUT_ERROR )) + { + break; + } + for(l_retryCount = 0; l_retryCount < MAX_RETRIES; l_retryCount++) + { + // RESET_PCB: Reset all PCB elements outside of the standby domain + pibErr = putscom_abs( PERV_PIB_RESET_REG, REG_BIT0 ); + if( pibErr ) break; + // RESET_PCB: clear it again + pibErr = putscom_abs( PERV_PIB_RESET_REG, 0); + if( pibErr ) break; + + FAPI_DBG( "*** Retry %i ***", l_retryCount ); + + if ( i_isRead ) + { + pibErr = getscom_abs(i_addr, io_data); + } + else + { + pibErr = putscom_abs(i_addr, *io_data); + } + + if( PIB_NO_ERROR == pibErr ) + { + FAPI_INF("Read/Write Retry Successful"); + break; + } + if ( pibErr != i_pibErr ) break; + } + }while(0); + FAPI_INF("Exiting p9_pibErrRetry"); + return pibErr; +} + + }; |