summaryrefslogtreecommitdiffstats
path: root/src/hwpf/plat_hw_access.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/hwpf/plat_hw_access.C')
-rw-r--r--src/hwpf/plat_hw_access.C357
1 files changed, 357 insertions, 0 deletions
diff --git a/src/hwpf/plat_hw_access.C b/src/hwpf/plat_hw_access.C
new file mode 100644
index 00000000..d1112533
--- /dev/null
+++ b/src/hwpf/plat_hw_access.C
@@ -0,0 +1,357 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/hwpf/plat_hw_access.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <fapi2.H>
+#include "hw_access.H"
+#include "plat_hw_access.H"
+#include "p9_perv_scom_addresses.H"
+#include <p9_putRingUtils.H>
+
+namespace fapi2
+{
+
+struct restoreOpcgRegisters g_opcgData;
+
+uint64_t decodeScanRegionData(const uint32_t i_ringAddress)
+{
+ uint32_t l_scan_region = (i_ringAddress & 0x0000FFF0) << 13;
+
+ uint32_t l_scan_type = 0x00008000 >> (i_ringAddress & 0x0000000F);
+
+ // This is special case if encoded type is 0xF
+
+ if ( (i_ringAddress & 0x0000000F) == 0xF)
+ {
+ l_scan_type = 0x00008000 | (l_scan_type << 12);
+ }
+ uint64_t l_value = l_scan_region;
+ l_value = (l_value << 32) | l_scan_type;
+
+ return l_value;
+}
+
+ReturnCode getRing_setup(const uint32_t i_ringAddress,
+ const RingMode i_ringMode)
+{
+ fapi2::ReturnCode l_rc = FAPI2_RC_SUCCESS;
+ uint64_t l_scanRegion = 0;
+ uint32_t l_chipletId = i_ringAddress >> 24;
+
+ Target<fapi2::TARGET_TYPE_PROC_CHIP> l_proc = plat_getChipTarget();
+
+ do
+ {
+ l_scanRegion = decodeScanRegionData(i_ringAddress);
+
+ if (i_ringMode & fapi2::RING_MODE_SET_PULSE_SL)
+ {
+ l_rc = storeOPCGRegData (l_proc, g_opcgData, l_chipletId);
+ if(l_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+
+ l_rc = setupScanRegionForSetPulse(l_proc, l_scanRegion,
+ i_ringMode,l_chipletId);
+ if(l_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+ }
+ else
+ {
+ // Set up the scan region for the ring.
+ l_rc = setupScanRegion(l_proc, l_scanRegion, l_chipletId);
+ if(l_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+ }
+ // Write a 64 bit value for header.
+ const uint64_t l_header = 0xa5a5a5a5a5a5a5a5;
+ uint32_t l_scomAddress = 0x0003E000 | (i_ringAddress & 0xFF000000);
+ l_rc = fapi2::putScom(l_proc, l_scomAddress, l_header);
+ if(l_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+
+ }while(0);
+
+ return l_rc;
+}
+
+ReturnCode getRing_verifyAndcleanup(const uint32_t i_ringAddress,
+ const RingMode i_ringMode)
+{
+ fapi2::ReturnCode l_rc = FAPI2_RC_SUCCESS;
+ uint32_t l_chipletId = i_ringAddress >> 24;
+
+ fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_proc;
+
+ do
+ {
+ // Verify header
+ uint64_t l_header = 0xa5a5a5a5a5a5a5a5;
+ l_rc = verifyHeader(l_proc, l_header, l_chipletId,i_ringMode);
+ if(l_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+
+ l_rc = cleanScanRegionandTypeData(l_proc, l_chipletId);
+ if(l_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+
+ if (i_ringMode & fapi2::RING_MODE_SET_PULSE_SL)
+ {
+ l_rc = restoreOPCGRegData(l_proc, g_opcgData, l_chipletId);
+ if(l_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ }while(0);
+
+ return l_rc;
+}
+
+static uint32_t getEffectiveAddress(const plat_target_handle_t &i_target, const uint32_t i_addr)
+{
+ ScomAddr l_addr(i_addr);
+ switch(i_target.getTargetType())
+ {
+ case PPE_TARGET_TYPE_EX:
+ if((EQ_CHIPLET_OFFSET <= l_addr.iv_chiplet) &&
+ ((EQ_CHIPLET_OFFSET + EQ_TARGET_COUNT) > l_addr.iv_chiplet))
+ {
+ l_addr.iv_chiplet = i_target.fields.chiplet_num;
+ l_addr.iv_ring = (l_addr.iv_ring - (l_addr.iv_ring % 2)) +
+ (i_target.getTargetInstance() % 2);
+ }
+ else if ((CORE_CHIPLET_OFFSET <= l_addr.iv_chiplet) &&
+ ((CORE_CHIPLET_OFFSET + CORE_TARGET_COUNT) > l_addr.iv_chiplet))
+ {
+ l_addr.iv_chiplet = CORE_CHIPLET_OFFSET + (l_addr.iv_chiplet % 2) +
+ (i_target.getTargetInstance() * 2);
+ }
+ else
+ {
+ assert(false);
+ }
+ break;
+ case PPE_TARGET_TYPE_MCS:
+ l_addr.iv_chiplet = i_target.fields.chiplet_num;
+ l_addr.iv_satId = (2 * (i_target.getTargetInstance() % 2));
+ break;
+ case PPE_TARGET_TYPE_PHB:
+ if(l_addr.iv_chiplet == N2_CHIPLET)
+ {
+ if (i_target.getTargetInstance() == 0)
+ {
+ l_addr.iv_ring = 0x3;
+ l_addr.iv_satId = ((l_addr.iv_satId < 4) ? (1) : (4));
+ }
+ else
+ {
+ l_addr.iv_ring = (0x3 + (i_target.getTargetInstance() / 3) + 1) & 0xF;
+ l_addr.iv_satId = ((l_addr.iv_satId < 4) ? (1) : (4)) +
+ ((i_target.getTargetInstance() % 2) ? (0) : (1)) +
+ (2 * (i_target.getTargetInstance() / 5));
+ }
+ }
+ else
+ {
+ l_addr.iv_chiplet = i_target.fields.chiplet_num;
+ if (i_target.getTargetInstance() == 0)
+ {
+ l_addr.iv_satId = ((l_addr.iv_satId < 4) ? (1) : (4));
+ }
+ else
+ {
+ l_addr.iv_satId = (((l_addr.iv_satId < 4) ? (1) : (4)) +
+ ((i_target.getTargetInstance() % 2) ? (0) : (1)) +
+ (2 * (i_target.getTargetInstance() / 5)));
+ }
+ }
+ break;
+ default:
+ if(0 != i_target.getAddressOverlay())
+ {
+ l_addr.iv_chiplet = i_target.fields.chiplet_num;
+ }
+ break;
+ }
+ return l_addr;
+}
+
+static fapi2::ReturnCode pibRcToFapiRc(const uint32_t i_pibRc)
+{
+ fapi2::ReturnCode l_fapiRc = FAPI2_RC_SUCCESS;
+ switch(i_pibRc)
+ {
+ case PIB_XSCOM_ERROR:
+ l_fapiRc = RC_SBE_PIB_XSCOM_ERROR;
+ break;
+ case PIB_OFFLINE_ERROR:
+ l_fapiRc = RC_SBE_PIB_OFFLINE_ERROR;
+ break;
+ case PIB_PARTIAL_ERROR:
+ l_fapiRc = RC_SBE_PIB_PARTIAL_ERROR;
+ break;
+ case PIB_ADDRESS_ERROR:
+ l_fapiRc = RC_SBE_PIB_ADDRESS_ERROR;
+ break;
+ case PIB_CLOCK_ERROR:
+ l_fapiRc = RC_SBE_PIB_CLOCK_ERROR;
+ break;
+ case PIB_PARITY_ERROR:
+ l_fapiRc = RC_SBE_PIB_PARITY_ERROR;
+ break;
+ case PIB_TIMEOUT_ERROR:
+ l_fapiRc = RC_SBE_PIB_TIMEOUT_ERROR;
+ break;
+ case PIB_NO_ERROR:
+ default:
+ break;
+ }
+ return l_fapiRc;
+}
+
+fapi2::ReturnCode getscom_abs_wrap(const void *i_target,
+ const uint32_t i_addr, uint64_t *o_data)
+{
+ uint32_t l_pibRc = 0;
+ uint32_t l_addr = getEffectiveAddress(*(plat_target_handle_t*)i_target, i_addr);
+ FAPI_INF("getScom: address: 0x%08X", l_addr);
+ l_pibRc = getscom_abs(l_addr, o_data);
+ if( PIB_NO_ERROR != l_pibRc )
+ {
+ l_pibRc = p9_pibErrRetry( l_addr, o_data, l_pibRc, true);
+ }
+ FAPI_INF("getScom: returned pibRc: 0x%08X, data HI: 0x%08X, "
+ "data LO: 0x%08X", l_pibRc, (*o_data >> 32),
+ static_cast<uint32_t>(*o_data & 0xFFFFFFFF));
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ // Setting 64bit address in ffdc package as the parsers are
+ // hard coded to read 64bit address
+ const uint64_t ffdcAddr = l_addr;
+ PLAT_FAPI_ASSERT( PIB_NO_ERROR == l_pibRc,
+ SBE_SCOM_FAILURE().
+ set_address(ffdcAddr).
+ set_pcb_pib_rc(l_pibRc),
+ "getScom:pcb pib error, pibRc[0x%08X] Scom_Addr[0x%08X]",
+ l_pibRc,l_addr);
+fapi_try_exit:
+ if(PIB_NO_ERROR != l_pibRc)
+ {
+ // Override FAPI RC based on PIB RC
+ fapi2::current_err = pibRcToFapiRc(l_pibRc);
+ fapi2::g_FfdcData.fapiRc = fapi2::current_err;
+ }
+ return fapi2::current_err;
+}
+
+fapi2::ReturnCode putscom_abs_wrap(const void *i_target,
+ const uint32_t i_addr, uint64_t i_data)
+{
+ uint32_t l_pibRc = 0;
+ uint32_t l_addr = getEffectiveAddress(*(plat_target_handle_t*)i_target,
+ i_addr);
+ FAPI_INF("putScom: address: 0x%08X, data HI: 0x%08X, data LO: 0x%08X",
+ l_addr, (i_data >> 32),
+ static_cast<uint32_t>(i_data & 0xFFFFFFFF));
+ l_pibRc = putscom_abs(l_addr, i_data);
+ if( PIB_NO_ERROR != l_pibRc )
+ {
+ l_pibRc = p9_pibErrRetry( l_addr, &i_data, l_pibRc, false);
+ }
+ FAPI_INF("putScom: returned pibRc: 0x%08X", l_pibRc);
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ // Setting 64bit address in ffdc package as the parsers are
+ // hard coded to read 64bit address
+ const uint64_t ffdcAddr = l_addr;
+ PLAT_FAPI_ASSERT( PIB_NO_ERROR == l_pibRc,
+ SBE_SCOM_FAILURE().
+ set_address(ffdcAddr).
+ set_pcb_pib_rc(l_pibRc),
+ "putScom:pcb pib error, pibRc[0x%08X] Scom_Addr[0x%08X] "
+ "Scom_Data[0x%08X%08X]",
+ l_pibRc,l_addr,(i_data >> 32),
+ static_cast<uint32_t>(i_data & 0xFFFFFFFF));
+fapi_try_exit:
+ if(PIB_NO_ERROR != l_pibRc)
+ {
+ // Override FAPI RC based on PIB RC
+ fapi2::current_err = pibRcToFapiRc(l_pibRc);
+ fapi2::g_FfdcData.fapiRc = fapi2::current_err;
+ }
+ return fapi2::current_err;
+}
+
+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;
+ 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++)
+ {
+ 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;
+}
+
+};
OpenPOWER on IntegriCloud