new file mode 100644
@@ -0,0 +1,102 @@
+///
+/// @file p10_cu.H
+/// @brief P10 chip unit definitions
+///
+/// HWP Owner: thi@us.ibm.com
+/// HWP Team: NEST
+/// HWP Level: 1
+/// HWP Consumed by: FSP/HB
+///
+
+#ifndef P10_CU_H
+#define P10_CU_H
+
+// includes
+#include <stdint.h>
+
+extern "C"
+{
+
+ /// P10 chip unit type enumeration
+ typedef enum
+ {
+ P10_NO_CU = 0, ///< P10 chip
+ PU_PERV_CHIPUNIT = 1, ///< Pervasive
+ PU_EQ_CHIPUNIT = 2, ///< Quad
+ PU_C_CHIPUNIT = 3, ///< Core
+ PU_PEC_CHIPUNIT = 4, ///< PCIe (PEC)
+ PU_PHB_CHIPUNIT = 5, ///< PCIe (PHB)
+ PU_NMMU_CHIPUNIT = 6, ///< NMMU
+ PU_IOHS_CHIPUNIT = 7, ///< IOHS (High speed IO)
+ PU_MC_CHIPUNIT = 8, ///< MC
+ PU_MI_CHIPUNIT = 9, ///< MI
+ PU_MCC_CHIPUNIT = 10, ///< MCC
+ PU_OMI_CHIPUNIT = 11, ///< OMI
+ PU_OMIC_CHIPUNIT = 12, ///< OMIC
+ PU_PAU_CHIPUNIT = 13, ///< PAU
+ PU_PAUC_CHIPUNIT = 14, ///< PAUC
+ NONE = 0xFF, ///< None/Invalid
+ } p10ChipUnits_t;
+
+ /// P10 chip unit pairing struct
+ struct p10_chipUnitPairing_t
+ {
+ /// @brief Default constructor
+ p10_chipUnitPairing_t()
+ : chipUnitType(NONE), chipUnitNum(0) {}
+ /// @brief Construct from type/instance number
+ p10_chipUnitPairing_t (p10ChipUnits_t type, uint32_t num)
+ : chipUnitType(type), chipUnitNum(num) {}
+
+ p10ChipUnits_t chipUnitType; ///< chip unit type
+ uint32_t chipUnitNum; ///< chip unit instance number
+ };
+
+ struct p10_chipUnitDescription_t
+ {
+ const char* strVal; // Chip unit string
+ const p10ChipUnits_t enumVal; // Chip unit enum value
+ const uint8_t maxChipUnitNum; // Max Chip unit num value
+ };
+
+
+ // Max chip unit positions
+ const uint8_t MAX_PU_CHIPUNIT_NUM = 0; // P10_NO_CU
+ const uint8_t MAX_PU_EQ_CHIPUNIT_NUM = 7;
+ const uint8_t MAX_PU_C_CHIPUNIT_NUM = 31;
+ const uint8_t MAX_PU_PEC_CHIPUNIT_NUM = 1;
+ const uint8_t MAX_PU_PHB_CHIPUNIT_NUM = 5;
+ const uint8_t MAX_PU_NMMU_CHIPUNIT_NUM = 1;
+ const uint8_t MAX_PU_PERV_CHIPUNIT_NUM = 39; // Special case, with gaps
+ const uint8_t MAX_PU_IOHS_CHIPUNIT_NUM = 7;
+ const uint8_t MAX_PU_PAU_CHIPUNIT_NUM = 7;
+ const uint8_t MAX_PU_MC_CHIPUNIT_NUM = 3;
+ const uint8_t MAX_PU_MI_CHIPUNIT_NUM = 3;
+ const uint8_t MAX_PU_MCC_CHIPUNIT_NUM = 7;
+ const uint8_t MAX_PU_OMIC_CHIPUNIT_NUM = 7;
+ const uint8_t MAX_PU_OMI_CHIPUNIT_NUM = 15;
+ const uint8_t MAX_PU_PAUC_CHIPUNIT_NUM = 3;
+
+ // Chip unit string/enum/max targes table
+ const p10_chipUnitDescription_t ChipUnitDescriptionTable[] =
+ {
+ { "pu" , P10_NO_CU, MAX_PU_CHIPUNIT_NUM },
+ { "eq" , PU_EQ_CHIPUNIT, MAX_PU_EQ_CHIPUNIT_NUM },
+ { "c" , PU_C_CHIPUNIT, MAX_PU_C_CHIPUNIT_NUM },
+ { "pec" , PU_PEC_CHIPUNIT, MAX_PU_PEC_CHIPUNIT_NUM },
+ { "phb" , PU_PHB_CHIPUNIT, MAX_PU_PHB_CHIPUNIT_NUM },
+ { "nmmu" , PU_NMMU_CHIPUNIT, MAX_PU_NMMU_CHIPUNIT_NUM },
+ { "perv" , PU_PERV_CHIPUNIT, MAX_PU_PERV_CHIPUNIT_NUM }, // Special case, with gaps
+ { "iohs" , PU_IOHS_CHIPUNIT, MAX_PU_IOHS_CHIPUNIT_NUM },
+ { "mc" , PU_MC_CHIPUNIT, MAX_PU_MC_CHIPUNIT_NUM },
+ { "mi" , PU_MI_CHIPUNIT, MAX_PU_MI_CHIPUNIT_NUM },
+ { "mcc" , PU_MCC_CHIPUNIT, MAX_PU_MCC_CHIPUNIT_NUM },
+ { "omi" , PU_OMI_CHIPUNIT, MAX_PU_OMI_CHIPUNIT_NUM },
+ { "omic" , PU_OMIC_CHIPUNIT, MAX_PU_OMIC_CHIPUNIT_NUM },
+ { "pau" , PU_PAU_CHIPUNIT, MAX_PU_PAU_CHIPUNIT_NUM },
+ { "pauc" , PU_PAUC_CHIPUNIT, MAX_PU_PAUC_CHIPUNIT_NUM },
+ };
+
+} // extern "C"
+
+#endif /* P10_CU_H */
new file mode 100644
@@ -0,0 +1,916 @@
+///
+/// @file p10_scom_addr.C
+/// @brief P10 chip unit SCOM address platform translation code
+///
+/// HWP HW Maintainer: Thi Tran <thi@us.ibm.com>
+/// HWP FW Maintainer:
+/// HWP Consumed by: Cronus, HB, HWSV
+///
+
+// includes
+#include "p10_scom_addr.H"
+
+#define P10_SCOM_ADDR_C
+
+extern "C"
+{
+ /// See function description in header file
+
+ // #####################################
+ bool p10_scom_addr::isEqTarget()
+ {
+ bool l_eqTarget = false;
+
+ // Must have EQ chiplet ID
+ if ( (getChipletId() >= EQ0_CHIPLET_ID) &&
+ (getChipletId() <= EQ7_CHIPLET_ID) )
+ {
+ // If endpoint is QME (0xE):
+ // QME per core (bit 20) must be 0
+ // region select (bits 16:19) must be 0
+ if ( (getEndpoint() == QME_ENDPOINT) && (!getQMEPerCore()) &&
+ (getRegionSelect() == EQ_REGION_SEL) )
+ {
+ l_eqTarget = true;
+ }
+ // associate perv target resources with EQ
+ else if (isPervTarget())
+ {
+ l_eqTarget = true;
+ }
+ }
+
+ return l_eqTarget;
+ }
+
+ // ########################################
+ uint8_t p10_scom_addr::getEqTargetInstance()
+ {
+ uint8_t l_instance = 0;
+ l_instance = (getChipletId() - EQ0_CHIPLET_ID);
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isCoreTarget()
+ {
+ bool l_coreTarget = false;
+
+ // Must have EQ chiplet ID
+ if ( (getChipletId() >= EQ0_CHIPLET_ID) &&
+ (getChipletId() <= EQ7_CHIPLET_ID) )
+ {
+ // Region select must be...
+ if ( (getRegionSelect() == MULTI_HOT_SELECT_C0) || // 0x8
+ (getRegionSelect() == MULTI_HOT_SELECT_C1) || // 0x4
+ (getRegionSelect() == MULTI_HOT_SELECT_C2) || // 0x2
+ (getRegionSelect() == MULTI_HOT_SELECT_C3) || // 0x1
+ (getRegionSelect() == EQ_REGION_SEL) ) // 0x0
+ {
+ // If QME endpoint (0xE), QME per core (bit 20) must be 1
+ if ( (getEndpoint() == QME_ENDPOINT) && getQMEPerCore() )
+ {
+ l_coreTarget = true;
+ }
+ // or must be PSCOM endpoints -- ensure that ring ID is
+ // associated with a core resource on the first PSCOM
+ // endpoint (0x1), all are core rings on the second
+ // PSCOM endpoint (0x2)
+ else if ( ((getEndpoint() == PSCOM_ENDPOINT) && // 0x1
+ ((getEQRingId() != PERV_RING_ID) && // 0x1
+ (getEQRingId() != QME_RING_ID))) || // 0x2
+ (getEndpoint() == PSCOM_2_ENDPOINT) ) // 0x2
+ {
+ l_coreTarget = true;
+ }
+ }
+ }
+
+ return l_coreTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getCoreTargetInstance()
+ {
+ uint8_t l_instance = 0;
+
+ // First core instance of the quad
+ l_instance = (getChipletId() - EQ0_CHIPLET_ID) * NUM_CORES_PER_EQ;
+
+ // Get core instance based on region select
+ if (getRegionSelect() == MULTI_HOT_SELECT_C3)
+ {
+ l_instance += 3;
+ }
+ else if (getRegionSelect() == MULTI_HOT_SELECT_C2)
+ {
+ l_instance += 2;
+ }
+ else if (getRegionSelect() == MULTI_HOT_SELECT_C1)
+ {
+ l_instance += 1;
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isPecTarget()
+ {
+ bool l_pecTarget = false;
+
+ // associate perv target resources with PCIE
+ if ( (getChipletId() >= PCI0_CHIPLET_ID) && // 0x8
+ (getChipletId() <= PCI1_CHIPLET_ID) ) // 0x9
+ {
+ l_pecTarget = isPervTarget();
+ }
+
+ // Endpoint must be PSCOM (0x1)
+ if (getEndpoint() == PSCOM_ENDPOINT) // 0x1
+ {
+ // For PEC addresses via NEST regions:
+ // Ring ID must be 0x6, sat ID must be 0
+ if ( (getChipletId() >= N0_CHIPLET_ID) && // 0x2
+ (getChipletId() <= N1_CHIPLET_ID) && // 0x3
+ (getRingId() == N0_PE1_RING_ID) && // 0x6
+ (getSatId() == PEC_SAT_ID) ) // 0x0
+
+ {
+ l_pecTarget = true;
+ }
+ // For PEC addresses via PCIE:
+ else if ( (getChipletId() >= PCI0_CHIPLET_ID) && // 0x8
+ (getChipletId() <= PCI1_CHIPLET_ID) ) // 0x9
+ {
+ // Ring IDs must be 0x4-0x5 (iopci rings) or
+ // Ring ID is 0x2 (pci ring) and sat Id = 0x0
+ if ( (getRingId() == IO_PCI0_RING_ID) || // 0x4
+ (getRingId() == IO_PCI1_RING_ID) || // 0x5
+ ((getRingId() == PCI_RING_ID) && // 0x2
+ (getSatId() == PEC_SAT_ID)) ) // 0x0
+ {
+ l_pecTarget = true;
+ }
+ }
+ }
+
+ return l_pecTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getPecTargetInstance()
+ {
+ uint8_t l_instance = 0;
+
+ // PEC addresses via NEST regions
+ l_instance = N1_CHIPLET_ID - getChipletId();
+
+ // PEC addresses via PCIE
+ if ( (getChipletId() == PCI0_CHIPLET_ID) ||
+ (getChipletId() == PCI1_CHIPLET_ID) )
+ {
+ l_instance = getChipletId() - PCI0_CHIPLET_ID;
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isPhbTarget()
+ {
+ bool l_phbTarget = false;
+
+ // Endpoint must be PSCOM (0x1)
+ if ( (getEndpoint() == PSCOM_ENDPOINT) ) // 0x1
+ {
+ // PCIE chiplet ID
+ if ( (getChipletId() >= PCI0_CHIPLET_ID) && // 0x8
+ (getChipletId() <= PCI1_CHIPLET_ID) ) // 0x9
+ {
+ // Ring ID of 0x2, Sat ID 1-6
+ if ( (getRingId() == PCI_RING_ID) && // 0x2
+ (getSatId() >= PHB0_AIB_SAT_ID) && // 0x1
+ (getSatId() <= PHB2_PHB_SAT_ID) ) // 0x6
+ {
+ l_phbTarget = true;
+ }
+ }
+
+ // N0/N1 chiplet ID
+ if ( (getChipletId() >= N0_CHIPLET_ID) && // 0x2
+ (getChipletId() <= N1_CHIPLET_ID) && // 0x3
+ (getRingId() == N0_PE1_RING_ID) && // 0x6
+ (getSatId() >= PHB0_AIB_SAT_ID) && // 0x1
+ (getSatId() <= PHB2_AIB_SAT_ID) ) // 0x3
+ {
+ l_phbTarget = true;
+ }
+ }
+
+ return l_phbTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getPhbTargetInstance()
+ {
+ uint8_t l_instance = 0;
+
+ if ( (getChipletId() == N0_CHIPLET_ID) ||
+ (getChipletId() == PCI1_CHIPLET_ID) )
+ {
+ l_instance += 3;
+ }
+
+ if ( (getRingId() == N0_PE1_RING_ID) )
+ {
+ l_instance += (getSatId() - 1);
+ }
+ else if ( (getRingId() == PCI_RING_ID ) )
+ {
+ l_instance += ((getSatId() - 1) % 3);
+ }
+ else
+ {
+ l_instance += (getRingId() - 3);
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isNmmuTarget()
+ {
+ bool l_nmmuTarget = false;
+
+ // Must have NEST chiplet ID
+ if ( (getChipletId() == N0_CHIPLET_ID) ||
+ (getChipletId() == N1_CHIPLET_ID) )
+ {
+ // Endpoint must be PSCOM, ring ID must be 0x3, Sat ID must be 0/1
+ if ( (getEndpoint() == PSCOM_ENDPOINT) && // 0x1
+ (getRingId() == N0_MM0_RING_ID) && // 0x3
+ (getSatId() >= NMMU_SAT_ID0) && // 0x0
+ (getSatId() <= NMMU_SAT_ID1) ) // 0x1
+ {
+ l_nmmuTarget = true;
+ }
+ }
+
+ return l_nmmuTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getNmmuTargetInstance()
+ {
+ return (getChipletId() - N0_CHIPLET_ID);
+ }
+
+ // #####################################
+ bool p10_scom_addr::isPervTarget()
+ {
+ bool l_pervTarget = false;
+ uint8_t l_index = 0;
+
+ // Check chiplet ID by looping through PERV chiplet ID table
+ for (l_index = 0;
+ l_index < sizeof(PervTargetChipletIdTable) / sizeof(p10ChipletId_t);
+ l_index++)
+ {
+ // See if Chiplet ID is a perv chiplet ID from table
+ if (getChipletId() == PervTargetChipletIdTable[l_index])
+ {
+ if (getEndpoint() == PSCOM_ENDPOINT) // 0x1
+ {
+ // EQ specific PSCOM endpoint logic
+ // ensure ring being accessed is EQ scoped (non-core)
+ if ( (getChipletId() >= EQ0_CHIPLET_ID) &&
+ (getChipletId() <= EQ7_CHIPLET_ID) )
+ {
+ if ( (getEQRingId() == PERV_RING_ID) || // 0x1
+ (getEQRingId() == QME_RING_ID) ) // 0x2
+ {
+ l_pervTarget = true;
+ }
+ }
+
+ // non-EQ chiplet, just match for ring ID = 0 / 1
+ else
+ {
+ if ( (getRingId() == PSCOM_RING_ID) || // 0x0
+ (getRingId() == PERV_RING_ID) ) // 0x1
+ {
+ l_pervTarget = true;
+ }
+ }
+ }
+ else if (getEndpoint() == CLOCK_CTRL_ENDPOINT) // 0x3
+ {
+ l_pervTarget = true;
+ }
+ // Check if Endpoint is a PERV endpoint
+ else if ( (getEndpoint() == CHIPLET_CTRL_ENDPOINT) || // 0x0
+ (getEndpoint() == FIR_ENDPOINT) || // 0x4
+ (getEndpoint() == THERMAL_ENDPOINT) || // 0x5
+ (getEndpoint() == PCBSLV_ENDPOINT) ) // 0xF
+ {
+ if ( getRingId() == PSCOM_RING_ID) // 0x0
+ {
+ l_pervTarget = true;
+ }
+ }
+
+ break;
+ }
+ }
+
+ return l_pervTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getPervTargetInstance()
+ {
+ return getChipletId();
+ }
+
+ // #####################################
+ bool p10_scom_addr::isIoHsTarget()
+ {
+ bool l_iohsTarget = false;
+
+ // IOHS can be targeted by AXON or PAU chiplets (indirect scom),
+
+ // Associate perv target resources with AXON
+ if ( (getChipletId() >= AXON0_CHIPLET_ID) && // 0x18
+ (getChipletId() <= AXON7_CHIPLET_ID) ) // 0x1F
+ {
+ l_iohsTarget = isPervTarget();
+
+ // If not a PERV target check for IOHS target that uses AXON chiplet
+ if (l_iohsTarget == false)
+ {
+ if ( (getEndpoint() == PSCOM_ENDPOINT) &&
+ (getRingId() == AXONE_PDL_RING_ID) && // 0x4
+ (getSatId() == DLP_SAT_ID) ) // 0x0
+ {
+ l_iohsTarget = true;
+ }
+ }
+ }
+
+ // Target via PAU chiplets
+ else if ( isIndirect() &&
+ (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ // Endpoint must be PSCOM and RingID is IOPPE
+ if ( (getEndpoint() == PSCOM_ENDPOINT) &&
+ (getRingId() == PAU_IOPPE_RING_ID) ) // 0xB
+ {
+ // Group address (bits 22:26 of upper address) must be 0b00000 or 0b00001,
+ // and indirect register address should be per-group or per-lane
+ // Group 0: IOHS[0]
+ // Group 1: IOHS[1]
+ if ( ( (getIoGroupAddr() == 0x0) ||
+ (getIoGroupAddr() == 0x1) ) &&
+ ((getIoRegAddr() & 0x1E0) != 0x1E0) )
+ {
+ l_iohsTarget = true;
+ }
+ }
+ }
+
+ return l_iohsTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getIoHsTargetInstance()
+ {
+ uint8_t l_instance = 0;
+
+ // Chiplet ID is AXON
+ if ( (getChipletId() >= AXON0_CHIPLET_ID) &&
+ (getChipletId() <= AXON7_CHIPLET_ID) )
+ {
+ l_instance = getChipletId() - AXON0_CHIPLET_ID;
+ }
+ // Chiplet ID is PAU
+ else
+ {
+ // If chiplet ID is PAU then this is indirect address.
+ // Use PAU and Group address (bits 22:26) to calculate instance.
+ // PAU0 (lower right) -> IOHS0 + IOHS1
+ // PAU1 (upper right) -> IOHS2 + IOHS3
+ // PAU2 (lower left) -> IOHS4 + IOHS5
+ // PAU3 (upper left) -> IOHS6 + IOHS7
+ //
+ // Group address bits (22:26) of upper 32-bit
+ // Group 0: IOHS[0]
+ // Group 1: IOHS[1]
+ if ( (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ l_instance = (getChipletId() - PAU0_CHIPLET_ID) * 2;
+
+ if (getIoGroupAddr() == 0x1)
+ {
+ l_instance += 1;
+ }
+ }
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isPauTarget()
+ {
+ bool l_pauTarget = false;
+
+ // Endpoint must be PSCOM
+ if ( getEndpoint() == PSCOM_ENDPOINT)
+ {
+ // Check chiplet ID
+ if ( (getChipletId() >= PAU0_CHIPLET_ID) &&
+ (getChipletId() <= PAU3_CHIPLET_ID) )
+ {
+ if ( (getRingId() == PAU0346_0_RING_ID) || // 0x02
+ (getRingId() == PAU0346_1_RING_ID) ) // 0x03
+
+ {
+ l_pauTarget = true;
+ }
+ else if ( (getChipletId() == PAU2_CHIPLET_ID) ||
+ (getChipletId() == PAU3_CHIPLET_ID) )
+ {
+ if ( (getRingId() == PAU57_0_RING_ID) || // 0x04
+ (getRingId() == PAU57_1_RING_ID) ) // 0x05
+ {
+ l_pauTarget = true;
+ }
+ }
+ }
+ }
+
+ return l_pauTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getPauTargetInstance()
+ {
+ uint8_t l_instance = 0;
+
+ if ( (getRingId() == PAU0346_0_RING_ID) || // 0x02
+ (getRingId() == PAU0346_1_RING_ID) ) // 0x03
+ {
+ if (getChipletId() == PAU0_CHIPLET_ID)
+ {
+ l_instance = 0;
+ }
+ else if (getChipletId() == PAU1_CHIPLET_ID)
+ {
+ l_instance = 3;
+ }
+ else if (getChipletId() == PAU2_CHIPLET_ID)
+ {
+ l_instance = 4;
+ }
+ else if (getChipletId() == PAU3_CHIPLET_ID)
+ {
+ l_instance = 6;
+ }
+ }
+
+ else if ( (getRingId() == PAU57_0_RING_ID) || // 0x04
+ (getRingId() == PAU57_1_RING_ID) ) // 0x05
+ {
+ if (getChipletId() == PAU2_CHIPLET_ID)
+ {
+ l_instance = 5;
+ }
+ else if (getChipletId() == PAU3_CHIPLET_ID)
+ {
+ l_instance = 7;
+ }
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isMcTarget()
+ {
+ // Same as MI
+ return isMiTarget();
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getMcTargetInstance()
+ {
+ // Same as MI
+ return getMiTargetInstance();
+ }
+
+ // #####################################
+ bool p10_scom_addr::isMiTarget()
+ {
+ bool l_miTarget = false;
+
+ // Chiplet ID must belong to MCs
+ if ( (getChipletId() >= MC0_CHIPLET_ID) && // 0x0C
+ (getChipletId() <= MC3_CHIPLET_ID) ) // 0x0F
+ {
+ // allow access to perv endpoints on MC chiplets
+ if (isPervTarget())
+ {
+ l_miTarget = true;
+ }
+ // Endpoint = PSCOM_ENDPOINT, and ringID = MC_0_RING_ID
+ else if ( (getEndpoint() == PSCOM_ENDPOINT) && // 0x1
+ (getRingId() == MC_0_RING_ID) ) // 0x3
+ {
+ // PBI satellite
+ if (getSatId() == MC_SAT_ID0) // 0x0 (PBI)
+ {
+ // avoid match on MCC register space
+ if (!(((getSatOffset() >= 0x22) &&
+ (getSatOffset() <= 0x2B)) ||
+ ((getSatOffset() >= 0x32) &&
+ (getSatOffset() <= 0x3B))))
+ {
+ l_miTarget = true;
+ }
+ }
+
+ // MCBIST satellite ID space
+ // avoid match on MCC register space in 0xD
+ if ( (getSatId() == MC_SAT_ID12) || // 0xC,0xE,0xF (MCBIST)
+ (getSatId() == MC_SAT_ID14) ||
+ (getSatId() == MC_SAT_ID15) )
+ {
+ l_miTarget = true;
+ }
+ }
+ }
+
+ return l_miTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getMiTargetInstance()
+ {
+ return getChipletId() - MC0_CHIPLET_ID;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isMccTarget()
+ {
+ bool l_mccTarget = false;
+
+ // Chiplet ID must belong to MCs, Endpoint = PSCOM_ENDPOINT,
+ // and ringID = MC_0_RING_ID
+ if ( (getChipletId() >= MC0_CHIPLET_ID) && // 0x0C
+ (getChipletId() <= MC3_CHIPLET_ID) && // 0x0F
+ (getEndpoint() == PSCOM_ENDPOINT) && // 0x1
+ (getRingId() == MC_0_RING_ID) ) // 0x3
+ {
+ // MCC Sat ID
+ if ( (getSatId() == MC_SAT_ID4) || // 0x4
+ (getSatId() == MC_SAT_ID8) || // 0x8
+ (getSatId() == MC_SAT_ID5) || // 0x5
+ (getSatId() == MC_SAT_ID9) ) // 0x9
+ {
+ l_mccTarget = true;
+ }
+
+ // MCC register space in PBI
+ if (getSatId() == MC_SAT_ID0)
+ {
+ if (((getSatOffset() >= 0x22) &&
+ (getSatOffset() <= 0x2B)) ||
+ ((getSatOffset() >= 0x32) &&
+ (getSatOffset() <= 0x3B)))
+ {
+ l_mccTarget = true;
+ }
+ }
+
+ // MCC register space in MCBIST
+ if (getSatId() == MC_SAT_ID13)
+ {
+ l_mccTarget = true;
+ }
+ }
+
+ return l_mccTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getMccTargetInstance()
+ {
+ uint8_t l_instance = (getChipletId() - MC0_CHIPLET_ID) * 2;
+
+ // MCC Sat ID
+ if ( (getSatId() == MC_SAT_ID5) || // 5
+ (getSatId() == MC_SAT_ID9) ) // 9
+ {
+ l_instance += 1;
+ }
+
+ // MCC register space in PBI
+ if ( getSatId() == MC_SAT_ID0 ) // 0
+ {
+ if ((getSatOffset() >= 0x32) &&
+ (getSatOffset() <= 0x3B))
+ {
+ l_instance += 1;
+ }
+ }
+
+ // MCC register space in MCBIST
+ if ( getSatId() == MC_SAT_ID13) // 13
+ {
+ // MSB of SatOffset denotes channel
+ if (getSatOffset() >= 0x20)
+ {
+ l_instance += 1;
+ }
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isOmiTarget()
+ {
+ bool l_omiTarget = false;
+
+ // PAU chiplet, IOPPE ringId (indirect scom)
+ if ( isIndirect() && // indirect
+ ( getChipletId() >= PAU0_CHIPLET_ID ) && // 0x10
+ ( getChipletId() <= PAU3_CHIPLET_ID ) && // 0x13
+ ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1
+ ( getRingId() == PAU_IOPPE_RING_ID) && // 0xB
+ ( getSatId() == PPE_SAT_ID0) ) // 0x0
+ {
+ // Group address (bits 22:26 of upper address)
+ // must be 0b00010 or 0b00011 (for OMI)
+ if ( (getIoGroupAddr() == 0x2 ) ||
+ (getIoGroupAddr() == 0x3 ) )
+ {
+ // Reg address must start with 0xxx (per lane)
+ uint32_t regAddr = getIoRegAddr();
+
+ if ( ( regAddr & 0x100 ) == 0x000 )
+ {
+ l_omiTarget = true;
+ }
+ }
+ }
+
+ // MC chiplet direct SCOM
+ if ( ( getChipletId() >= MC0_CHIPLET_ID ) && // 0x0C
+ ( getChipletId() <= MC3_CHIPLET_ID ) && // 0x0F
+ ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1
+ ( getRingId() >= OMI0_RING_ID ) && // 0x5
+ ( getRingId() <= OMI1_RING_ID ) && // 0x6
+ ( getSatId() == MC_SAT_ID0 ) ) // 0x0 (DL)
+ {
+ if (((getSatOffset() >= 16) && // 16:31 (subchannel 0)
+ (getSatOffset() <= 47)) || // 32:47 (subchannel 1)
+ ((getSatOffset() >= 48) && // 48:51 (subchannel 0, pm regs)
+ (getSatOffset() <= 51)) ||
+ ((getSatOffset() >= 56) && // 48:51 (subchannel 1, pm regs)
+ (getSatOffset() <= 59)))
+ {
+ l_omiTarget = true;
+ }
+ }
+
+ return l_omiTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getOmiTargetInstance()
+ {
+ uint8_t l_instance = 0;
+
+ // PAU chiplet indirect SCOM
+ if ( (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ // PAU0 --> OMI 0/1/2/3
+ // PAU1 --> OMI 8/9/10/11
+ // PAU2 --> OMI 4/5/6/7
+ // PAU3 --> OMI 12/13/14/15
+ // set basis based on direct chiplet ID
+ if (getChipletId() == PAU0_CHIPLET_ID)
+ {
+ l_instance = 0;
+ }
+ else if (getChipletId() == PAU1_CHIPLET_ID)
+ {
+ l_instance = 8;
+ }
+ else if (getChipletId() == PAU2_CHIPLET_ID)
+ {
+ l_instance = 4;
+ }
+ else
+ {
+ l_instance = 12;
+ }
+
+ // account for IO group address
+ if (getIoGroupAddr() == 0x3)
+ {
+ l_instance += 2;
+ }
+
+ // account for IO lane selection
+ if ( ( getIoLane() >= 8 ) &&
+ ( getIoLane() <= 15) )
+ {
+ l_instance += 1;
+ }
+ }
+
+ // MC direct
+ if ( (getChipletId() >= MC0_CHIPLET_ID) &&
+ (getChipletId() <= MC3_CHIPLET_ID) )
+ {
+ // Instances 0, 4, 8, 12
+ l_instance = (getChipletId() - MC0_CHIPLET_ID) * 4;
+
+ // Instances 2, 6, 10, 14
+ if ( getRingId() == OMI1_RING_ID ) // 0x6
+ {
+ l_instance += 2;
+ }
+
+ // Instances 1, 3, 5, 7, 9, 11, 13, 15
+ if ( ((getSatOffset() >= 32) &&
+ (getSatOffset() <= 47)) ||
+ ((getSatOffset() >= 56) &&
+ (getSatOffset() <= 59)) )
+ {
+ l_instance += 1;
+ }
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isOmicTarget()
+ {
+ bool l_omicTarget = false;
+
+ // PAU chiplet, IOPPE ringId (indirect scom)
+ if ( isIndirect() && // indirect
+ ( getChipletId() >= PAU0_CHIPLET_ID ) && // 0x10
+ ( getChipletId() <= PAU3_CHIPLET_ID ) && // 0x13
+ ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1
+ ( getRingId() == PAU_IOPPE_RING_ID) && // 0xB
+ ( getSatId() == PPE_SAT_ID0) ) // 0x0
+ {
+ // Group address (bits 22:26 of upper address)
+ // must be 0b00010 or 0b00011 (for OMI)
+ if ( (getIoGroupAddr() == 0x2 ) ||
+ (getIoGroupAddr() == 0x3 ) )
+ {
+ // Reg address must start with 1xxx (per group),
+ // excluding 1111 (per bus)
+ uint32_t regAddr = getIoRegAddr();
+
+ if ( ( ( regAddr & 0x1E0 ) != 0x1E0 ) &&
+ ( ( regAddr & 0x100 ) == 0x100 ) )
+ {
+ l_omicTarget = true;
+ }
+ }
+ }
+
+ // MC chiplet direct SCOM
+ if ( ( getChipletId() >= MC0_CHIPLET_ID ) && // 0x0C
+ ( getChipletId() <= MC3_CHIPLET_ID ) && // 0x0F
+ ( getEndpoint() == PSCOM_ENDPOINT ) && // 0x1
+ ( getRingId() >= OMI0_RING_ID ) && // 0x5
+ ( getRingId() <= OMI1_RING_ID ) && // 0x6
+ ( getSatId() == MC_SAT_ID0 ) && // 0x0 (DL)
+ ( getSatOffset() >= 0 ) && // shared regs 0-15
+ ( getSatOffset() <= 15 ) )
+ {
+ l_omicTarget = true;
+ }
+
+ return l_omicTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getOmicTargetInstance()
+ {
+ uint8_t l_instance = 0;
+
+ // PAU indirect
+ if ( ( getChipletId() >= PAU0_CHIPLET_ID ) && // 0x10
+ ( getChipletId() <= PAU3_CHIPLET_ID ) ) // 0x13
+ {
+ // PAU0 --> OMIC 0/1
+ // PAU1 --> OMIC 4/5
+ // PAU2 --> OMIC 2/3
+ // PAU3 --> OMIC 6/7
+ if (getChipletId() == PAU0_CHIPLET_ID)
+ {
+ l_instance = 0;
+ }
+ else if (getChipletId() == PAU1_CHIPLET_ID)
+ {
+ l_instance = 4;
+ }
+ else if (getChipletId() == PAU2_CHIPLET_ID)
+ {
+ l_instance = 2;
+ }
+ else // PAU3_CHIPLET_ID
+ {
+ l_instance = 6;
+ }
+
+ if (getIoGroupAddr() == 0x3)
+ {
+ l_instance += 1;
+ }
+ }
+
+ // MC direct
+ if ( ( getChipletId() >= MC0_CHIPLET_ID ) && // 0x0C
+ ( getChipletId() <= MC3_CHIPLET_ID ) ) // 0x0F
+ {
+ l_instance = (getChipletId() - MC0_CHIPLET_ID) * 2;
+
+ if (getRingId() == 0x6)
+ {
+ l_instance += 1;
+ }
+ }
+
+ return l_instance;
+ }
+
+ // #####################################
+ bool p10_scom_addr::isPaucTarget()
+ {
+ bool l_paucTarget = false;
+
+ if ( (getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ // allow access to perv endpoints on MC chiplets
+ if (isPervTarget())
+ {
+ l_paucTarget = true;
+ }
+ else if ( getEndpoint() == PSCOM_ENDPOINT ) // 0x1
+ {
+ // IO PPE access
+ if ( isDirect() && // direct
+ (getRingId() == PAU_IOPPE_RING_ID) && // 0xB
+ ( (getSatId() == PPE_SAT_ID0) || // 0x0
+ (getSatId() == PPE_SAT_ID1) ) ) // 0x1
+ {
+ l_paucTarget = true;
+ }
+
+ // TL access
+ if ( (getRingId() == PAU_TL_RING_ID) && // 0x6
+ ( (getSatId() == TL_SAT_ID) ) ) // 0x0
+ {
+ l_paucTarget = true;
+ }
+
+ // per-bus IO super wrapper registers
+ if ( isIndirect() && // indirect
+ ((getIoRegAddr() & 0x1E0) == 0x1E0) && // register(0:3) = 0b1111
+ (getRingId() == PAU_IOPPE_RING_ID) && // 0xB
+ (getSatId() == PPE_SAT_ID0) ) // 0x0
+ {
+ l_paucTarget = true;
+ }
+ }
+ }
+
+ return l_paucTarget;
+ }
+
+ // #####################################
+ uint8_t p10_scom_addr::getPaucTargetInstance()
+ {
+ uint8_t l_instance = (getChipletId() - PAU0_CHIPLET_ID);
+
+ return l_instance;
+ }
+
+} // extern "C"
+
+#undef P10_SCOM_ADDR_C
new file mode 100644
@@ -0,0 +1,700 @@
+///
+/// @file p10_scom_addr.H
+/// @brief P10 SCOM address class
+///
+/// HWP HW Maintainer: Thi Tran <thi@us.ibm.com>
+/// HWP FW Maintainer:
+/// HWP Consumed by: Cronus, HB, HWSV
+///
+
+#ifndef P10_SCOM_ADDR_H
+#define P10_SCOM_ADDR_H
+
+// includes
+#include <stdint.h>
+
+extern "C"
+{
+ /// Constants
+ const uint32_t NUM_CORES_PER_EQ = 4; // Num of cores in an EQ chiplet
+
+ /// P10 Chiplet ID enumeration
+ typedef enum
+ {
+ PIB_CHIPLET_ID = 0x00, ///< PIB chiplet (FSI)
+ PERV_CHIPLET_ID = 0x01, ///< TP chiplet
+
+ N0_CHIPLET_ID = 0x02, ///< Nest0 (North) chiplet
+ N1_CHIPLET_ID = 0x03, ///< Nest1 (South) chiplet
+
+ PCI0_CHIPLET_ID = 0x08, ///< PCIe0 chiplet
+ PCI1_CHIPLET_ID = 0x09, ///< PCIe1 chiplet
+
+ MC0_CHIPLET_ID = 0x0C, ///< MC0 chiplet
+ MC1_CHIPLET_ID = 0x0D, ///< MC1 chiplet
+ MC2_CHIPLET_ID = 0x0E, ///< MC2 chiplet
+ MC3_CHIPLET_ID = 0x0F, ///< MC3 chiplet
+
+ PAU0_CHIPLET_ID = 0x10, ///< PAU0 chiplet
+ PAU1_CHIPLET_ID = 0x11, ///< PAU1 chiplet
+ PAU2_CHIPLET_ID = 0x12, ///< PAU2 chiplet
+ PAU3_CHIPLET_ID = 0x13, ///< PAU3 chiplet
+
+ AXON0_CHIPLET_ID = 0x18, ///< AXON0 chiplet (high speed io)
+ AXON1_CHIPLET_ID = 0x19, ///< AXON1 chiplet (high speed io)
+ AXON2_CHIPLET_ID = 0x1A, ///< AXON2 chiplet (high speed io)
+ AXON3_CHIPLET_ID = 0x1B, ///< AXON3 chiplet (high speed io)
+ AXON4_CHIPLET_ID = 0x1C, ///< AXON4 chiplet (high speed io)
+ AXON5_CHIPLET_ID = 0x1D, ///< AXON5 chiplet (high speed io)
+ AXON6_CHIPLET_ID = 0x1E, ///< AXON6 chiplet (high speed io)
+ AXON7_CHIPLET_ID = 0x1F, ///< AXON7 chiplet (high speed io)
+
+ EQ0_CHIPLET_ID = 0x20, ///< Quad0 chiplet (super chiplet)
+ EQ1_CHIPLET_ID = 0x21, ///< Quad1 chiplet (super chiplet)
+ EQ2_CHIPLET_ID = 0x22, ///< Quad2 chiplet (super chiplet)
+ EQ3_CHIPLET_ID = 0x23, ///< Quad3 chiplet (super chiplet)
+ EQ4_CHIPLET_ID = 0x24, ///< Quad4 chiplet (super chiplet)
+ EQ5_CHIPLET_ID = 0x25, ///< Quad5 chiplet (super chiplet)
+ EQ6_CHIPLET_ID = 0x26, ///< Quad6 chiplet (super chiplet)
+ EQ7_CHIPLET_ID = 0x27, ///< Quad7 chiplet (super chiplet)
+ } p10ChipletId_t;
+
+ /// P10 SCOM Endpoint ID enumeration
+ typedef enum
+ {
+ CHIPLET_CTRL_ENDPOINT = 0x0, ///< Chiplet Control
+ PSCOM_ENDPOINT = 0x1, ///< EQ:PSCOM (L3), others: PSCOM
+ PSCOM_2_ENDPOINT = 0x2, ///< EQ:PSCOM (Core/L2), TP:ITR, Nest:TOD (Time Of Day)
+ CLOCK_CTRL_ENDPOINT = 0x3, ///< Clock controller
+ FIR_ENDPOINT = 0x4, ///< FIR
+ THERMAL_ENDPOINT = 0x5, ///< Thermal
+ DPLL_ENDPOINT = 0x6, ///< TP (only): DPLL
+ QME_ENDPOINT = 0xE, ///< EQ (only): QME
+ PCBSLV_ENDPOINT = 0xF, ///< PCB Slave registers
+ } p10EndpointID_t;
+
+ /// P10 region select (CoreId/One-hot)
+ typedef enum
+ {
+ EQ_REGION_SEL = 0x0,
+ MULTI_HOT_SELECT_C0 = 0x8,
+ MULTI_HOT_SELECT_C1 = 0x4,
+ MULTI_HOT_SELECT_C2 = 0x2,
+ MULTI_HOT_SELECT_C3 = 0x1,
+ } p10RegionSelect_t;
+
+ /// *************************************
+ /// Ring ID enums
+ /// *************************************
+
+ /// P10 N0 chiplet ring ID enumeration
+ typedef enum
+ {
+ N0_MM0_RING_ID = 0x3,
+ N0_PE1_RING_ID = 0x6,
+ } p10_N0_RingId_t;
+
+ /// P10 N1 chiplet ring ID enumeration
+ /// source: tpc_p10_n1_top.vhdl
+ typedef enum
+ {
+ N1_MM1_RING_ID = 0x3,
+ N1_PE0_RING_ID = 0x6,
+ } p10_N1_RingId_t;
+
+ /// P10 PCIe chiplet SCOM ring ID enumeration
+ typedef enum
+ {
+ PCI_RING_ID = 0x2,
+ IO_PCI0_RING_ID = 0x4,
+ IO_PCI1_RING_ID = 0x5,
+ } p10_PCI_RingId_t;
+
+ /// P10 PERV chiplet and PSCOM ring ID enumeration
+ typedef enum
+ {
+ PSCOM_RING_ID = 0x0,
+ PERV_RING_ID = 0x1,
+ } p10_PSCOM_PERV_RingId_t;
+
+ /// P10 AXONE chiplet ring ID enumeration
+ typedef enum
+ {
+ AXONE_PDL_RING_ID = 0x4,
+ } p10_AXONE_RingId_t;
+
+ /// P10 PAU chiplet ring ID enumeration
+ typedef enum
+ {
+ PAU0346_0_RING_ID = 0x2,
+ PAU0346_1_RING_ID = 0x3,
+ PAU57_0_RING_ID = 0x4,
+ PAU57_1_RING_ID = 0x5,
+ PAU_TL_RING_ID = 0x6,
+ PAU_IOPPE_RING_ID = 0xB,
+ } p10_PAU_RingId_t;
+
+ /// P10 MC chiplet ring ID enumeration
+ typedef enum
+ {
+ MC_0_RING_ID = 0x3,
+ MC_1_RING_ID = 0x4,
+ OMI0_RING_ID = 0x5,
+ OMI1_RING_ID = 0x6,
+ } p10_MC_RingId_t;
+
+ /// P10 EQ chiplet ring ID enumeration
+ typedef enum
+ {
+ QME_RING_ID = 0x2,
+ L3_RING_ID = 0x3,
+ } p10_EQ_PSCOM_RingId_t;
+
+ typedef enum
+ {
+ L2_RING_ID = 0x0,
+ C_0_RING_ID = 0x2,
+ C_1_RING_ID = 0x3,
+ C_3_RING_ID = 0x5,
+ } p10_EQ_PSCOM2_RingId_t;
+
+ /// -----------------------
+ /// Satellite ID defintions
+ /// -----------------------
+ typedef enum
+ {
+ NMMU_SAT_ID0 = 0x0,
+ NMMU_SAT_ID1 = 0x1,
+ } p10_NMMU_SatId_t;
+
+ typedef enum
+ {
+ PEC_SAT_ID = 0x0,
+ PHB0_AIB_SAT_ID = 0x1,
+ PHB1_AIB_SAT_ID = 0x2,
+ PHB2_AIB_SAT_ID = 0x3,
+ PHB0_PHB_SAT_ID = 0x4,
+ PHB1_PHB_SAT_ID = 0x5,
+ PHB2_PHB_SAT_ID = 0x6,
+ } p10_PCI_SatId_t;
+
+ typedef enum
+ {
+ MC_SAT_ID0 = 0x0,
+ MC_SAT_ID4 = 0x4,
+ MC_SAT_ID5 = 0x5,
+ MC_SAT_ID8 = 0x8,
+ MC_SAT_ID9 = 0x9,
+ MC_SAT_ID12 = 0xC,
+ MC_SAT_ID13 = 0xD,
+ MC_SAT_ID14 = 0xE,
+ MC_SAT_ID15 = 0xF,
+ } p10_MC_SatId_t;
+
+ typedef enum
+ {
+ PPE_SAT_ID0 = 0x0,
+ TL_SAT_ID = 0x0,
+ PPE_SAT_ID1 = 0x1,
+ } p10_PAU_SatId_t;
+
+ typedef enum
+ {
+ DLP_SAT_ID = 0x0,
+ } p10_AXONE_SatId_t;
+
+ /// *************************************
+ /// Perv target table
+ /// *************************************
+ const p10ChipletId_t PervTargetChipletIdTable[] =
+ {
+ PIB_CHIPLET_ID,
+ PERV_CHIPLET_ID,
+ N0_CHIPLET_ID,
+ N1_CHIPLET_ID,
+ PCI0_CHIPLET_ID,
+ PCI1_CHIPLET_ID,
+ MC0_CHIPLET_ID,
+ MC1_CHIPLET_ID,
+ MC2_CHIPLET_ID,
+ MC3_CHIPLET_ID,
+ PAU0_CHIPLET_ID,
+ PAU1_CHIPLET_ID,
+ PAU2_CHIPLET_ID,
+ PAU3_CHIPLET_ID,
+ AXON0_CHIPLET_ID,
+ AXON1_CHIPLET_ID,
+ AXON2_CHIPLET_ID,
+ AXON3_CHIPLET_ID,
+ AXON4_CHIPLET_ID,
+ AXON5_CHIPLET_ID,
+ AXON6_CHIPLET_ID,
+ AXON7_CHIPLET_ID,
+ EQ0_CHIPLET_ID,
+ EQ1_CHIPLET_ID,
+ EQ2_CHIPLET_ID,
+ EQ3_CHIPLET_ID,
+ EQ4_CHIPLET_ID,
+ EQ5_CHIPLET_ID,
+ EQ6_CHIPLET_ID,
+ EQ7_CHIPLET_ID,
+ };
+
+// ----------------------
+// For non-EQ chiplets
+// ----------------------
+// 8 7 6 5 4 3 2 1
+//
+// |0 1 2 3| |4 5 6 7| |8 9 10 11| |12 13 14 15| |16 17 18 19| |20 21 22 23| |24 25 26 27| |28 29 30 31|
+// {A}{ B } { C } 0 0 { D } { E } { F }
+//
+// A - Is multiCast if bit 1 = 0x1
+// B - Chiplet ID (6 bits) [2:7]
+// C - Endpoint ID (4 bits) [12:15]
+// D - Ring (4 bits) [18:21]
+// E - Sat ID (4 bits) [22:25]
+// F - Sat Offset (6 bits) [26:31]
+
+// ----------------------
+// For EQ/Core chiplets
+// ----------------------
+// 8 7 6 5 4 3 2 1
+//
+// |0 1 2 3| |4 5 6 7| |8 9 10 11| |12 13 14 15| |16 17 18 19| |20 21 22 23| |24 25 26 27| |28 29 30 31|
+// {A}{ B } { C } { D } E F { G } { H }
+//
+// A - Is multiCast if bit 1 = 0x1
+// B - Chiplet ID (6 bits) [2:7]
+// C - Endpoint ID (4 bits) [12:15]
+// D - Region select (4 bits) [16:19]
+// E - QME per core (1 bit) [20]
+// F - QME Sat Enable (1 bit) [21]
+// G - QME Sat sel (2 bits) [22:23]
+// H - QME reg (8 bits) [24:31]
+
+ /// P10 SCOM address class
+ class p10_scom_addr
+ {
+ public:
+
+ /// @brief Construct a SCOM address object
+ /// @param[in] i_addr 64-bit raw SCOM address
+ p10_scom_addr(const uint64_t i_addr)
+ : iv_addr(i_addr)
+ {
+ }
+
+ /// @brief Set full/raw SCOM address
+ /// @param[in] i_addr 64-bit SCOM address
+ /// @retval none
+ inline void setAddr(const uint64_t i_addr)
+ {
+ iv_addr = i_addr;
+ return;
+ }
+
+ /// @brief Retrieve full/raw SCOM address
+ /// @retval uint64_t 64-bit SCOM address
+ inline uint64_t getAddr() const
+ {
+ return (iv_addr);
+ }
+
+ /// @brief Determine if SCOM address is direct-form (bit 0)
+ /// @retval bool True if SCOM address is direct-form, false otherwise
+ inline bool isDirect() const
+ {
+ return (((iv_addr >> 63) & 0x1) == 0x0);
+ }
+
+ /// @brief Determine if SCOM address is indirect-form
+ /// @retval bool True if SCOM address is indirect-form, false otherwise
+ inline bool isIndirect() const
+ {
+ return (!isDirect());
+ }
+
+ /// @brief Determine if SCOM address is multicast (bit 1)
+ /// @retval bool True if SCOM address is multicast, false otherwise
+ inline bool isMulticast() const
+ {
+ return (((iv_addr >> 30) & 0x1) == 0x1);
+ }
+
+ /// @brief Determine if SCOM address is unicast
+ /// @retval bool True if SCOM address is unicast, false otherwise
+ inline bool isUnicast() const
+ {
+ return (!(isMulticast()));
+ }
+
+ /// @brief Extract pervasive chiplet ID from SCOM address (bits 2:7)
+ /// @retval uint8_t Pervasive chiplet ID value
+ inline uint8_t getChipletId() const
+ {
+ return ((iv_addr >> 24) & 0x3F);
+ }
+
+ /// @brief Modify SCOM address, update pervasive chiplet ID
+ /// @param[in] i_chiplet_id Chiplet ID value to write
+ /// @retval none
+ inline void setChipletId(const uint8_t i_chiplet_id)
+ {
+ iv_addr &= 0xFFFFFFFFC0FFFFFFULL;
+ iv_addr |= ((i_chiplet_id & 0x3F) << 24);
+ return;
+ }
+
+ /// @brief Extract Endpoint field from SCOM address (bits 12:15)
+ /// @retval uint8_t Endpoint field value
+ inline uint8_t getEndpoint() const
+ {
+ return ((iv_addr >> 16) & 0xF);
+ }
+
+ /// @brief Modify the Endpoint field from SCOM address
+ /// @retval none
+ inline void setEndpoint(const uint8_t i_port)
+ {
+ iv_addr &= 0xFFFFFFFFFFF0FFFFULL;
+ iv_addr |= ((i_port & 0xF) << 16);
+ return;
+ }
+
+ /// @brief Extract region select field (core id) from SCOM address (bits 16:19)
+ /// @retval uint8_t Region select value
+ inline uint8_t getRegionSelect() const
+ {
+ return ((iv_addr >> 12) & 0xF);
+ }
+
+ /// @brief Modify the region select field (core id) from SCOM address
+ /// @retval none
+ inline void setRegionSelect(const uint8_t i_regionSelect)
+ {
+ iv_addr &= 0xFFFFFFFFFFFF0FFFULL;
+ iv_addr |= ((i_regionSelect & 0xF) << 12);
+ return;
+ }
+
+ /// @brief Extract ring field from SCOM address (bits 18:21)
+ /// @retval uint8_t Ring id value
+ inline uint8_t getRingId() const
+ {
+ return ((iv_addr >> 10) & 0xF);
+ }
+
+ /// @brief Extract EQ ring field from SCOM address (bits 20:22)
+ /// @retval uint8_t Ring id value
+ inline uint8_t getEQRingId() const
+ {
+ return ((iv_addr >> 9) & 0x7);
+ }
+
+ /// @brief Modify SCOM address, update ring field value
+ /// @param[in] i_ring Ring field value to write
+ /// @retval none
+ inline void setRingId(const uint8_t i_ring)
+ {
+ iv_addr &= 0xFFFFFFFFFFFF03FFULL;
+ iv_addr |= ((i_ring & 0x3F) << 10);
+ return;
+ }
+
+ /// @brief Extract satellite ID field from SCOM address (bits 22:25)
+ /// @retval uint8_t Satellite ID field value
+ inline uint8_t getSatId() const
+ {
+ return ((iv_addr >> 6) & 0xF);
+ }
+
+ /// @brief Extract EQ satellite ID field from SCOM address (bits 23:25)
+ /// @retval uint8_t Ring id value
+ inline uint8_t getEQSatId() const
+ {
+ return ((iv_addr >> 6) & 0x7);
+ }
+
+ /// @brief Modify SCOM address, update satellite ID field
+ /// @param[in] i_sat_id Satellite ID value to write
+ /// @retval none
+ inline void setSatId(const uint8_t i_satId)
+ {
+ iv_addr &= 0xFFFFFFFFFFFFFC3FULL;
+ iv_addr |= ((i_satId & 0xF) << 6);
+ return;
+ }
+
+ /// @brief Extract satellite register offset field from SCOM address (bits 26:31)
+ /// @retval uint8_t Satellite register offset field value
+ inline uint8_t getSatOffset() const
+ {
+ return (iv_addr & 0x3F);
+ }
+
+ /// @brief Modify SCOM address, update satellite offset field
+ /// @param[in] i_sat_offset Satellite offset value to write
+ /// @retval none
+ inline void setSatOffset(const uint8_t i_sat_offset)
+ {
+ iv_addr &= 0xFFFFFFFFFFFFFFC0ULL;
+ iv_addr |= (i_sat_offset & 0x3F);
+ return;
+ }
+
+ /// @brief Get the OBUS Super Wrapper Group address (bits 22:26) of
+ /// an indirect scom address
+ /// @retval uint8_t Group address
+ inline uint8_t getIoGroupAddr() const
+ {
+ return ((iv_addr >> 37) & 0x1F);
+ }
+
+ /// @brief Set the OBUS Super Wrapper Group address (bits 22:26) of
+ /// an indirect scom address
+ /// @param[in] i_group_addr Group address value to write
+ /// @retval none
+ inline void setIoGroupAddr(const uint8_t i_group_addr)
+ {
+ iv_addr &= 0xFFFFFC1FFFFFFFFFULL;
+ iv_addr |= ( ((uint64_t)i_group_addr & 0x1F) << 37 );
+ return;
+ }
+
+ /// @brief Get Super Wrapper Register address (bits 12:20)
+ /// of an indirect scom address
+ /// @retval uint32_t Register address
+ inline uint32_t getIoRegAddr() const
+ {
+ return ((iv_addr >> 43) & 0x1FF);
+ }
+
+ /// @brief Get the OBUS Super Wrapper TX/RX bit (bit 21)
+ /// of an indirect scom address
+ /// @retval uint8_t TX/RX bit
+ inline uint32_t getIoTxRxBit() const
+ {
+ return ((iv_addr >> 42) & 0x1);
+ }
+
+ /// @brief Get the OBUS Super Wrapper Lane (bits 27:31)
+ /// of an indirect scom address
+ /// @retval uint8_t Lane
+ inline uint32_t getIoLane() const
+ {
+ return ((iv_addr >> 32) & 0x1F);
+ }
+
+ /// @brief Set the OBUS Super Wrapper Lane (bits 27:31)
+ /// of an indirect scom address
+ /// @retval uint8_t Lane
+ inline void setIoLane(const uint8_t i_lane)
+ {
+ iv_addr &= 0xFFFFFFE0FFFFFFFFULL;
+ iv_addr |= ( ((uint64_t)i_lane & 0x1F) << 32);
+ }
+
+ /// IOP indirect SCOMs
+ /// IOP0.top0.pma0 (PMA0) -> 0x8000xxxx0801113f
+ /// IOP0.top0.pma1 (PMA1) -> 0x8001xxxx0801113f
+ /// IOP0.top1.pma0 (PMA2) -> 0x8000xxxx0801153f
+ /// IOP0.top1.pma1 (PMA3) -> 0x8001xxxx0801153f
+ /// IOP1.top0.pma0 (PMA0) -> 0x8000xxxx0901113f
+ /// IOP1.top0.pma1 (PMA1) -> 0x8001xxxx0901113f
+ /// IOP1.top1.pma0 (PMA2) -> 0x8000xxxx0901153f
+ /// IOP1.top1.pma1 (PMA3) -> 0x8001xxxx0901153f
+
+ /// @brief Get PEC IOP Control Register value (bits 12:31) from
+ /// an indirect scom address
+ /// @retval uint32_t CR register
+ inline uint32_t getIopIndCRreg() const
+ {
+ return ((iv_addr >> 32) & 0xFFFFF);
+ }
+
+ /// @brief Get IOP TOP value (bit 53) from an indirect scom address
+ /// @retval uint8_t Top value (0 or 1)
+ inline uint8_t getIopTop() const
+ {
+ return ((iv_addr >> 10) & 0x1);
+ }
+
+ /// @brief Get PMA value (bit 15) from an indirect scom address
+ /// @retval uint8_t Top value (0 or 1)
+ inline uint8_t getPMA() const
+ {
+ return ( ((iv_addr >> 48) & 0x1) + (getIopTop() * 2) );
+ }
+
+ /// @brief Determine if SCOM address is valid/well-formed
+ /// @retval bool True if SCOM address is valid, false otherwise
+ inline bool isValid() const
+ {
+ return true;
+ }
+
+ /// @brief Determine if this address belongs to EQ target type
+ /// @retval true or false.
+ bool isEqTarget();
+
+ /// @brief Determine the EQ instance for this address
+ /// Function prereq: Address must belong to EQ target type
+ /// @retval uint8_t EQ target instance
+ uint8_t getEqTargetInstance();
+
+ /// @brief Determine if this address belongs to core target type
+ /// @retval true or false.
+ bool isCoreTarget();
+
+ /// @brief Determine the core instance for this address.
+ /// Function prereq: Address must belong to core target type
+ /// @retval uint8_t Core target instance
+ uint8_t getCoreTargetInstance();
+
+ /// @brief Determine if this address belongs to PEC target type
+ /// @retval true or false.
+ bool isPecTarget();
+
+ /// @brief Determine the pec instance for this address
+ /// Function prereq: Address must belong to PEC target type
+ /// @retval uint8_t PEC target instance
+ uint8_t getPecTargetInstance();
+
+ /// @brief Determine if this address belongs to PHB target type
+ /// @retval true or false.
+ bool isPhbTarget();
+
+ /// @brief Determine the PHB instance for this address
+ /// Function prereq: Address must belong to PHB target type
+ /// @retval uint8_t PHB target instance
+ uint8_t getPhbTargetInstance();
+
+ /// @brief Determine if this address belongs to NMMU target type
+ /// @retval true or false.
+ bool isNmmuTarget();
+
+ /// @brief Determine the NMMU instance for this address
+ /// Function prereq: Address must belong to NMMU target type
+ /// @retval uint8_t NMMU target instance
+ uint8_t getNmmuTargetInstance();
+
+ /// @brief Get the QME Per Core value (bit 20, EQ/Core only)
+ /// Function prereq: Address must belong to EQ or Core target type
+ /// @retval uint8_t QME Per Core value
+ inline uint8_t getQMEPerCore()
+ {
+ return (iv_addr >> 11) & 0x1;
+ }
+
+ /// @brief Get the QME Sat Enable value (bit 21, EQ/Core only)
+ /// Function prereq: Address must belong to EQ or Core target type
+ /// @retval uint8_t QME Sat Enable value
+ inline uint8_t getQMESatEn()
+ {
+ return (iv_addr >> 10) & 0x1;
+ }
+
+ /// @brief Get the QME Sat Select value (bit 22:23, EQ/Core only)
+ /// Function prereq: Address must belong to EQ or Core target type
+ /// @retval uint8_t QME Sat Sel value
+ inline uint8_t getQMESatSel()
+ {
+ return (iv_addr >> 8) & 0x3;
+ }
+
+ /// @brief Get the QME reg value (bit 24:31, EQ/Core only)
+ /// Function prereq: Address must belong to EQ or Core target type
+ /// @retval uint8_t QME reg value
+ inline uint8_t getQMEReg()
+ {
+ return (iv_addr & 0xFF);
+ }
+
+ /// @brief Determine if this address belongs to PERV target type
+ /// @retval true or false.
+ bool isPervTarget();
+
+ /// @brief Determine the PERV instance for this address
+ /// Function prereq: Address must belong to PERV target type
+ /// @retval uint8_t PERV target instance.
+ uint8_t getPervTargetInstance();
+
+ /// @brief Determine if this address belongs to IOHS target type
+ /// @retval true or false.
+ bool isIoHsTarget();
+
+ /// @brief Determine the IOHS instance for this address
+ /// Function prereq: Address must belong to IOHS target type
+ /// @retval uint8_t IOHS target instance.
+ uint8_t getIoHsTargetInstance();
+
+ /// @brief Determine if this address belongs to PAU target type
+ /// @retval true or false.
+ bool isPauTarget();
+
+ /// @brief Determine the PAU instance for this address
+ /// Function prereq: Address must belong to PAU target type
+ /// @retval uint8_t PAU target instance.
+ uint8_t getPauTargetInstance();
+
+ /// @brief Determine if this address belongs to MC target type
+ /// @retval true or false.
+ bool isMcTarget();
+
+ /// @brief Determine the MC instance for this address
+ /// Function prereq: Address must belong to MI target type
+ /// @retval uint8_t MC target instance.
+ uint8_t getMcTargetInstance();
+
+ /// @brief Determine if this address belongs to MI target type
+ /// @retval true or false.
+ bool isMiTarget();
+
+ /// @brief Determine the MI instance for this address
+ /// Function prereq: Address must belong to MI target type
+ /// @retval uint8_t MI target instance.
+ uint8_t getMiTargetInstance();
+
+ /// @brief Determine if this address belongs to MCC target type
+ /// @retval true or false.
+ bool isMccTarget();
+
+ /// @brief Determine the MCC instance for this address
+ /// Function prereq: Address must belong to MCC target type
+ /// @retval uint8_t MCC target instance.
+ uint8_t getMccTargetInstance();
+
+ /// @brief Determine if this address belongs to OMI target type
+ /// @retval true or false.
+ bool isOmiTarget();
+
+ /// @brief Determine the OMI instance for this address
+ /// Function prereq: Address must belong to OMI target type
+ /// @retval uint8_t OMI target instance.
+ uint8_t getOmiTargetInstance();
+
+ /// @brief Determine if this address belongs to OMIC target type
+ /// @retval true or false.
+ bool isOmicTarget();
+
+ /// @brief Determine the OMIC instance for this address
+ /// Function prereq: Address must belong to OMIC target type
+ /// @retval uint8_t OMIC target instance.
+ uint8_t getOmicTargetInstance();
+
+ /// @brief Determine if this address belongs to PAUC target type
+ /// @retval true or false.
+ bool isPaucTarget();
+
+ /// @brief Determine the PAUC instance for this address
+ /// Function prereq: Address must belong to PAUC target type
+ /// @retval uint8_t PAUC target instance.
+ uint8_t getPaucTargetInstance();
+
+ private:
+ uint64_t iv_addr; ///< 64-bit raw SCOM address
+ };
+
+} // extern "C"
+
+#endif /* P10_SCOM_ADDR_H */
new file mode 100644
@@ -0,0 +1,838 @@
+///
+/// @file p10_scominfo.C
+/// @brief P10 chip unit SCOM address platform translation code
+///
+/// HWP HW Maintainer: Thi Tran <thi@us.ibm.com>
+/// HWP FW Maintainer:
+/// HWP Consumed by: Cronus, HB, HWSV
+///
+
+// includes
+#include "p10_scominfo.H"
+#include "p10_scom_addr.H"
+
+#define P10_SCOMINFO_C
+
+extern "C"
+{
+
+ // ---------------------------
+ // Internal functions
+ // ---------------------------
+
+ //################################################################################
+ /// @brief Calculate the region select (core ID) value for given core
+ /// instance
+ /// @param[in] i_coreInstance Core instance number (0-31)
+ /// @retval uint8_t Region select value
+ uint8_t calcRegionSelect(uint8_t i_coreInstanceNum)
+ {
+ uint8_t l_regionSel = 0;
+
+ if (i_coreInstanceNum % NUM_CORES_PER_EQ == 0)
+ {
+ l_regionSel = 8;
+ }
+ else if (i_coreInstanceNum % NUM_CORES_PER_EQ == 1)
+ {
+ l_regionSel = 4;
+ }
+ else if (i_coreInstanceNum % NUM_CORES_PER_EQ == 2)
+ {
+ l_regionSel = 2;
+ }
+ else
+ {
+ l_regionSel = 1;
+ }
+
+ return l_regionSel;
+ }
+
+ //################################################################################
+ /// @brief Get the chiplet ID for a chip unit instance based on given
+ /// address and chip unit type
+ /// @param[in] i_addr SCOM address
+ /// @param[in] i_chipUnitNum Instance number
+ /// @param[in] i_chipUnitType Chip unit type
+ /// @param[out] o_chipletId Output chiplet id
+ /// @retval Non-zero if error
+ uint8_t getChipletId(const uint64_t i_addr,
+ const uint8_t i_chipUnitNum,
+ const p10ChipUnits_t i_chipUnitType,
+ uint8_t& o_chipletId)
+ {
+ uint8_t l_rc = 0;
+
+ do
+ {
+ p10_scom_addr l_scom(i_addr);
+
+ switch (i_chipUnitType)
+ {
+ case PU_EQ_CHIPUNIT:
+ o_chipletId = EQ0_CHIPLET_ID + i_chipUnitNum;
+ break;
+
+ case PU_C_CHIPUNIT:
+ o_chipletId = EQ0_CHIPLET_ID + (i_chipUnitNum / NUM_CORES_PER_EQ);
+ break;
+
+ case PU_PEC_CHIPUNIT:
+
+ // If input address is of Nest chiplets
+ if ( (l_scom.getChipletId() >= N0_CHIPLET_ID) &&
+ (l_scom.getChipletId() <= N1_CHIPLET_ID) )
+ {
+ o_chipletId = ((i_chipUnitNum) ? (N0_CHIPLET_ID) : (N1_CHIPLET_ID));
+ }
+ // If input address is of PCI chiplets
+ else
+ {
+ o_chipletId = PCI0_CHIPLET_ID + i_chipUnitNum;
+ }
+
+ break;
+
+ case PU_PHB_CHIPUNIT:
+
+ // If input address is of Nest chiplets
+ if ( (l_scom.getChipletId() >= N0_CHIPLET_ID) &&
+ (l_scom.getChipletId() <= N1_CHIPLET_ID) )
+ {
+ o_chipletId = ((i_chipUnitNum / 3) ? (N0_CHIPLET_ID) : (N1_CHIPLET_ID));
+ }
+ // If input address is of PCI chiplets
+ else
+ {
+ o_chipletId = (i_chipUnitNum / 3) + PCI0_CHIPLET_ID;
+ }
+
+ break;
+
+ case PU_NMMU_CHIPUNIT:
+ o_chipletId = i_chipUnitNum + N0_CHIPLET_ID;
+ break;
+
+ case PU_PERV_CHIPUNIT:
+ o_chipletId = i_chipUnitNum;
+ break;
+
+ case PU_IOHS_CHIPUNIT:
+
+ // If input address is of AXON chiplets
+ if ( (l_scom.getChipletId() >= AXON0_CHIPLET_ID) && // 0x18
+ (l_scom.getChipletId() <= AXON7_CHIPLET_ID) ) // 0x1F
+ {
+ o_chipletId = AXON0_CHIPLET_ID + i_chipUnitNum;
+ }
+ else if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) &&
+ (l_scom.getChipletId() <= PAU3_CHIPLET_ID) )
+ {
+ // PAU0 --> IOHS0, IOHS1
+ // PAU1 --> IOHS2, IOHS3
+ // PAU2 --> IOHS4, IOHS5
+ // PAU3 --> IOHS6, IOHS7
+ o_chipletId = (i_chipUnitNum / 2) + PAU0_CHIPLET_ID;
+ }
+ else
+ {
+ l_rc = 1;
+ }
+
+ break;
+
+ case PU_MI_CHIPUNIT:
+ case PU_MC_CHIPUNIT:
+ o_chipletId = i_chipUnitNum + MC0_CHIPLET_ID;
+ break;
+
+ case PU_MCC_CHIPUNIT:
+ o_chipletId = (i_chipUnitNum / 2) + MC0_CHIPLET_ID;
+ break;
+
+ case PU_OMIC_CHIPUNIT:
+
+ // PAU indirect
+ if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ // PAU0 --> OMIC 0/1
+ // PAU1 --> OMIC 4/5
+ // PAU2 --> OMIC 2/3
+ // PAU3 --> OMIC 6/7
+ if (i_chipUnitNum >= 0 && i_chipUnitNum <= 1)
+ {
+ o_chipletId = PAU0_CHIPLET_ID;
+ }
+ else if (i_chipUnitNum >= 2 && i_chipUnitNum <= 3)
+ {
+ o_chipletId = PAU2_CHIPLET_ID;
+ }
+ else if (i_chipUnitNum >= 4 && i_chipUnitNum <= 5)
+ {
+ o_chipletId = PAU1_CHIPLET_ID;
+ }
+ else if (i_chipUnitNum >= 6 && i_chipUnitNum <= 7)
+ {
+ o_chipletId = PAU3_CHIPLET_ID;
+ }
+ else
+ {
+ l_rc = 1;
+ }
+ }
+ // MC direct
+ else
+ {
+ o_chipletId = (i_chipUnitNum / 2) + MC0_CHIPLET_ID;
+ }
+
+ break;
+
+ case PU_OMI_CHIPUNIT:
+
+ // PAU indirect
+ if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ // PAU0 --> OMI 0/1/2/3
+ // PAU1 --> OMI 8/9/10/11
+ // PAU2 --> OMI 4/5/6/7
+ // PAU3 --> OMI 12/13/14/15
+ if (i_chipUnitNum >= 0 && i_chipUnitNum <= 3)
+ {
+ o_chipletId = PAU0_CHIPLET_ID;
+ }
+ else if (i_chipUnitNum >= 4 && i_chipUnitNum <= 7)
+ {
+ o_chipletId = PAU2_CHIPLET_ID;
+ }
+ else if (i_chipUnitNum >= 8 && i_chipUnitNum <= 11)
+ {
+ o_chipletId = PAU1_CHIPLET_ID;
+ }
+ else if (i_chipUnitNum >= 12 && i_chipUnitNum <= 15)
+ {
+ o_chipletId = PAU3_CHIPLET_ID;
+ }
+ else
+ {
+ l_rc = 1;
+ }
+ }
+ // MC direct
+ else
+ {
+ o_chipletId = (i_chipUnitNum / 4) + MC0_CHIPLET_ID;
+ }
+
+ break;
+
+ case PU_PAUC_CHIPUNIT:
+ o_chipletId = i_chipUnitNum + PAU0_CHIPLET_ID;
+ break;
+
+ case PU_PAU_CHIPUNIT:
+ o_chipletId = (i_chipUnitNum / 2) + PAU0_CHIPLET_ID;
+ break;
+
+ default:
+ l_rc = 1;
+ break;
+ };
+
+ }
+ while (0);
+
+ return (l_rc);
+ }
+
+ // See header file for function description
+ uint64_t p10_scominfo_createChipUnitScomAddr(
+ const p10ChipUnits_t i_p10CU,
+ const uint8_t i_ecLevel,
+ const uint8_t i_chipUnitNum,
+ const uint64_t i_scomAddr,
+ const uint32_t i_mode)
+ {
+ uint8_t l_rc = 0;
+ p10_scom_addr l_scom(i_scomAddr);
+ uint8_t l_chipletId = 0;
+
+ do
+ {
+ // Make sure i_chipUnitNum is within range
+ l_rc = validateChipUnitNum(i_chipUnitNum, i_p10CU);
+
+ if (l_rc)
+ {
+ break;
+ }
+
+ // If chip unit type is a chip, return input address
+ if (i_p10CU == P10_NO_CU)
+ {
+ l_scom.setAddr(i_scomAddr);
+ break;
+ }
+
+ // Set the chiplet ID
+ l_rc = getChipletId(i_scomAddr, i_chipUnitNum, i_p10CU, l_chipletId);
+
+ if (l_rc)
+ {
+ break;
+ }
+
+ l_scom.setChipletId(l_chipletId);
+
+ // Set other address fields (ringId, satId, etc...)
+ // for Chip unit types that are needed.
+ switch (i_p10CU)
+ {
+ case PU_C_CHIPUNIT:
+ // Set the core's region select (core ID)
+ l_scom.setRegionSelect(calcRegionSelect(i_chipUnitNum));
+ break;
+
+ case PU_PHB_CHIPUNIT:
+
+ // If input address is of Nest chiplets
+ if ( (l_scom.getChipletId() >= N0_CHIPLET_ID) &&
+ (l_scom.getChipletId() <= N1_CHIPLET_ID) )
+ {
+ l_scom.setSatId(1 + (i_chipUnitNum % 3));
+ }
+ // If input address is of PCI chiplets
+ else
+ {
+ if (l_scom.getRingId() == 2)
+ {
+ if ((l_scom.getSatId() >= 1) &&
+ (l_scom.getSatId() <= 3))
+ {
+ l_scom.setSatId(1 + (i_chipUnitNum % 3));
+ }
+ else
+ {
+ l_scom.setSatId(4 + (i_chipUnitNum % 3));
+ }
+ }
+ }
+
+ break;
+
+ case PU_MCC_CHIPUNIT:
+
+ // Set Sat ID
+ if (i_chipUnitNum % 2)
+ {
+ uint8_t l_offset = l_scom.getSatOffset();
+
+ // MCC Sat ID
+ // For odd MCC instance, Sat Id is to be set to 5, or 9
+ // If input address is an even instance that has:
+ // SatId = 0x4 --> set translated SatId to 0x5
+ // = 0x8 --> set translated SatId to 0x9
+ // If input address is an odd instance, leave the SatId
+ // as input address.
+ if (l_scom.getSatId() == 0x4)
+ {
+ l_scom.setSatId(0x5);
+ }
+ else if (l_scom.getSatId() == 0x8)
+ {
+ l_scom.setSatId(0x9);
+ }
+ // PBI Sat ID
+ else if (l_scom.getSatId() == 0x0)
+ {
+ if ((l_offset >= 0x22) &&
+ (l_offset <= 0x2B))
+ {
+ l_scom.setSatOffset(l_offset + 0x10);
+ }
+ }
+ // MCBIST Sat ID
+ else if (l_scom.getSatId() == 0xD)
+ {
+ if ((l_offset >= 0x00) &&
+ (l_offset <= 0x1F))
+ {
+ l_scom.setSatOffset(l_offset + 0x20);
+ }
+ }
+ }
+ else
+ {
+ uint8_t l_offset = l_scom.getSatOffset();
+
+ // For even MCC instance, Sat Id is to be set to 4, or 8
+ // If input address is an odd instance that has:
+ // SatId = 0x5 --> set translated SatId to 0x4
+ // = 0x9 --> set translated SatId to 0x8
+ // If input address is an even instance, leave the SatId
+ // as input address.
+ if (l_scom.getSatId() == 0x5)
+ {
+ l_scom.setSatId(0x4);
+ }
+ else if (l_scom.getSatId() == 0x9)
+ {
+ l_scom.setSatId(0x8);
+ }
+ // PBI Sat ID
+ else if (l_scom.getSatId() == 0x0)
+ {
+ if ((l_offset >= 0x32) &&
+ (l_offset <= 0x3B))
+ {
+ l_scom.setSatOffset(l_offset - 0x10);
+ }
+ }
+ // MCBIST Sat ID
+ else if (l_scom.getSatId() == 0xD)
+ {
+ if ((l_offset >= 0x20) &&
+ (l_offset <= 0x3F))
+ {
+ l_scom.setSatOffset(l_offset - 0x20);
+ }
+ }
+ }
+
+ break;
+
+
+ case PU_IOHS_CHIPUNIT:
+
+ // PAU indirect
+ if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ // for odd IOHS instances, set IO group = 1
+ if ( i_chipUnitNum % 2 )
+ {
+ l_scom.setIoGroupAddr(0x1);
+ }
+ // for even IOHS instances, set IO group = 0
+ else
+ {
+ l_scom.setIoGroupAddr(0x0);
+ }
+ }
+
+ break;
+
+ case PU_OMI_CHIPUNIT:
+
+ // PAU indirect
+ if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ // for odd OMI instances, set IO lane between 8-15
+ if ( i_chipUnitNum % 2 )
+ {
+ l_scom.setIoLane(8 + (l_scom.getIoLane() % 8));
+ }
+ // for even OMI instances, set IO lane between 0-7
+ else
+ {
+ l_scom.setIoLane(0 + (l_scom.getIoLane() % 8));
+ }
+
+ // for odd OMI instances after dividing by 2, set IO group = 3
+ if ( (i_chipUnitNum / 2) % 2 )
+ {
+ l_scom.setIoGroupAddr(0x3);
+ }
+ // for even OMI instances after dividing by 2, set IO group = 2
+ else
+ {
+ l_scom.setIoGroupAddr(0x2);
+ }
+ }
+ // MC direct
+ else
+ {
+ // non-PM regs
+ if ((l_scom.getSatOffset() >= 16) && (l_scom.getSatOffset() <= 47))
+ {
+ // for odd OMI instances, set sat reg ID between 32-47
+ if ( i_chipUnitNum % 2 )
+ {
+ l_scom.setSatOffset(32 + (l_scom.getSatOffset() % 16));
+ }
+ // for even OMI instances, set sat reg ID between 16-31
+ else
+ {
+ l_scom.setSatOffset(16 + (l_scom.getSatOffset() % 16));
+ }
+ }
+ // PM regs
+ else
+ {
+ // for odd OMI instances, set sat reg ID between 56-59
+ if ( i_chipUnitNum % 2 )
+ {
+ l_scom.setSatOffset(56 + (l_scom.getSatOffset() % 4));
+ }
+ // for even OMI instances, set sat reg ID between 48-51
+ else
+ {
+ l_scom.setSatOffset(48 + (l_scom.getSatOffset() % 4));
+ }
+
+ }
+
+ // for odd OMI instances after dividing by 2, set ring ID = 6
+ if ( (i_chipUnitNum / 2) % 2 )
+ {
+ l_scom.setRingId(0x6);
+ }
+ // for even OMI instances after dividing by 2, set ring ID = 5
+ else
+ {
+ l_scom.setRingId(0x5);
+ }
+ }
+
+ break;
+
+ case PU_OMIC_CHIPUNIT:
+
+ // PAU indirect
+ if ( (l_scom.getChipletId() >= PAU0_CHIPLET_ID) && // 0x10
+ (l_scom.getChipletId() <= PAU3_CHIPLET_ID) ) // 0x13
+ {
+ if (i_chipUnitNum % 2)
+ {
+ // For odd OMIC instance, set IO group ID=3
+ l_scom.setIoGroupAddr(0x3);
+ }
+ else
+ {
+ // For even OMIC instance, set IO group ID=2
+ l_scom.setIoGroupAddr(0x2);
+ }
+ }
+ // MC direct
+ else
+ {
+ if (i_chipUnitNum % 2)
+ {
+ // For odd OMIC instance, set ring ID=6
+ l_scom.setRingId(0x6);
+ }
+ else
+ {
+ // For even OMIC instance, set ring ID=5
+ l_scom.setRingId(0x5);
+ }
+ }
+
+ break;
+
+ case PU_PAU_CHIPUNIT:
+
+ // Setting RingId for instances 0, 3, 4, and 6
+ // If input address has:
+ // RingId = 0x4 --> set translated RingId to 0x2
+ // 0x5 --> set translated RingId to 0x3
+ // Leave RingId as is otherwise
+ if ( (i_chipUnitNum == 0) ||
+ (i_chipUnitNum == 3) ||
+ (i_chipUnitNum == 4) ||
+ (i_chipUnitNum == 6) )
+ {
+ if (l_scom.getRingId() == 0x4)
+ {
+ l_scom.setRingId(0x2);
+ }
+ else if (l_scom.getRingId() == 0x5)
+ {
+ l_scom.setRingId(0x3);
+ }
+ }
+
+ // Setting RingId for instances 1, 2, 5, and 7
+ // If input address has:
+ // RingId = 0x2 --> set translated RingId to 0x4
+ // 0x3 --> set translated RingId to 0x5
+ // Leave RingId as is otherwise
+ else if ( (i_chipUnitNum == 1) ||
+ (i_chipUnitNum == 2) ||
+ (i_chipUnitNum == 5) ||
+ (i_chipUnitNum == 7) )
+ {
+ if (l_scom.getRingId() == 0x2)
+ {
+ l_scom.setRingId(0x4);
+ }
+ else if (l_scom.getRingId() == 0x3)
+ {
+ l_scom.setRingId(0x5);
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ // Break out if error
+ if (l_rc)
+ {
+ break;
+ }
+
+ }
+ while(0);
+
+ if (l_rc)
+ {
+ l_scom.setAddr(FAILED_TRANSLATION);
+ }
+
+ return l_scom.getAddr();
+ }
+
+ // See header file for function description
+ uint32_t p10_scominfo_isChipUnitScom(const p10ChipUnits_t i_p10CU,
+ const uint8_t i_ecLevel,
+ const uint64_t i_scomAddr,
+ bool& o_chipUnitRelated,
+ std::vector<p10_chipUnitPairing_t>& o_chipUnitPairing,
+ const p10TranslationMode_t i_mode)
+ {
+ p10_scom_addr l_scom(i_scomAddr);
+ o_chipUnitRelated = false;
+ o_chipUnitPairing.clear();
+
+ // Quad registers which can be addressed by EQ target type
+ // eq: 0..7
+ if (l_scom.isEqTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_EQ_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_EQ_CHIPUNIT,
+ l_scom.getEqTargetInstance()));
+ }
+
+ // Core, L2, L3 registers which can be addressed by core target type
+ // c: 0..31
+ if (l_scom.isCoreTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_C_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_C_CHIPUNIT,
+ l_scom.getCoreTargetInstance()));
+ }
+
+ // PEC registers which can be addressed by pec target type
+ // pec: 0..1
+ if (l_scom.isPecTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_PEC_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PEC_CHIPUNIT,
+ l_scom.getPecTargetInstance()));
+ }
+
+ // PHB registers
+ // phb: 0..5
+ if (l_scom.isPhbTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_PHB_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PHB_CHIPUNIT,
+ l_scom.getPhbTargetInstance()));
+ }
+
+ // NMMU registers
+ // nmmu: 0..1
+ if (l_scom.isNmmuTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_NMMU_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_NMMU_CHIPUNIT,
+ l_scom.getNmmuTargetInstance()));
+ }
+
+ // IOHS registers
+ if (l_scom.isIoHsTarget() &&
+ // prevent matching on IOHS SCOMs in ENGD build mode
+ (i_mode != P10_ENGD_BUILD_MODE))
+ {
+ o_chipUnitRelated = true;
+ // PU_IOHS_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_IOHS_CHIPUNIT,
+ l_scom.getIoHsTargetInstance()));
+ }
+
+ // PAU registers
+ if (l_scom.isPauTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_PAU_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PAU_CHIPUNIT,
+ l_scom.getPauTargetInstance()));
+ }
+
+ // MC registers
+ if (l_scom.isMcTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_MC_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_MC_CHIPUNIT,
+ l_scom.getMcTargetInstance()));
+ }
+
+ // MI registers
+ if (l_scom.isMiTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_MI_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_MI_CHIPUNIT,
+ l_scom.getMiTargetInstance()));
+ }
+
+ // MCC registers
+ if (l_scom.isMccTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_MCC_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_MCC_CHIPUNIT,
+ l_scom.getMccTargetInstance()));
+ }
+
+ // OMI registers
+ if (l_scom.isOmiTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_OMI_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_OMI_CHIPUNIT,
+ l_scom.getOmiTargetInstance()));
+ }
+
+ // OMIC registers
+ if (l_scom.isOmicTarget())
+ {
+ o_chipUnitRelated = true;
+ // PU_OMIC_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_OMIC_CHIPUNIT,
+ l_scom.getOmicTargetInstance()));
+ }
+
+ // PAUC registers
+ if (l_scom.isPaucTarget() &&
+ // prevent matching on indirect SCOMs (physically targeting IOHS
+ // scan latches) in ENGD build mode
+ ((i_mode != P10_ENGD_BUILD_MODE) ||
+ (l_scom.isDirect())))
+ {
+ o_chipUnitRelated = true;
+ // PU_PAUC_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PAUC_CHIPUNIT,
+ l_scom.getPaucTargetInstance()));
+ }
+
+ // PERV registers
+ if (l_scom.isPervTarget())
+ {
+ // if running in engineering data build flow context, do not
+ // emit associations for registers which would have only
+ // a single association of type PERV
+ if (!((o_chipUnitPairing.size() == 0) &&
+ (i_mode == P10_ENGD_BUILD_MODE)))
+ {
+ o_chipUnitRelated = true;
+ // PU_PERV_CHIPUNIT
+ o_chipUnitPairing.push_back(p10_chipUnitPairing_t(PU_PERV_CHIPUNIT,
+ l_scom.getPervTargetInstance()));
+ }
+ }
+
+ /// Address may be of a chip, let it pass through
+ return (!l_scom.isValid());
+ }
+
+ uint32_t p10_scominfo_fixChipUnitScomAddrOrTarget(const p10ChipUnits_t i_p10CU,
+ const uint8_t i_ecLevel,
+ const uint32_t i_targetChipUnitNum,
+ const uint64_t i_scomaddr,
+ uint64_t& o_modifiedScomAddr,
+ p10ChipUnits_t& o_p10CU,
+ uint32_t& o_modifiedChipUnitNum,
+ const uint32_t i_mode)
+ {
+ uint32_t rc = 0;
+
+ o_modifiedScomAddr = i_scomaddr;
+ o_p10CU = i_p10CU;
+ o_modifiedChipUnitNum = i_targetChipUnitNum;
+
+ return rc;
+ }
+
+ //################################################################################
+ uint8_t validateChipUnitNum(const uint8_t i_chipUnitNum,
+ const p10ChipUnits_t i_chipUnitType)
+ {
+ uint8_t l_rc = 0;
+ uint8_t l_index;
+
+ for (l_index = 0;
+ l_index < (sizeof(ChipUnitDescriptionTable) / sizeof(p10_chipUnitDescription_t));
+ l_index++)
+ {
+ // Looking for input chip unit type in table
+ if (i_chipUnitType == ChipUnitDescriptionTable[l_index].enumVal)
+ {
+ // Found a match, check input i_chipUnitNum to be <= max chip unit num
+ // for this unit type
+ if (i_chipUnitNum > ChipUnitDescriptionTable[l_index].maxChipUnitNum)
+ {
+ l_rc = 1;
+ }
+
+ // Additional check for PERV targets, where there are gaps between instances
+ else if (i_chipUnitType == PU_PERV_CHIPUNIT)
+ {
+ // Note: We allow content in chiplet ID = 0x00 to be referenced with a perv target instance,
+ // so do not check for instance = 0 here.
+ if ( ((i_chipUnitNum > 3) && (i_chipUnitNum < 8)) ||
+ ((i_chipUnitNum > 9) && (i_chipUnitNum < 12)) ||
+ ((i_chipUnitNum > 19) && (i_chipUnitNum < 24)) )
+ {
+ l_rc = 1;
+ }
+ }
+
+ // Additional check for PAU targets, where instance 1 and 2 are not valid
+ else if (i_chipUnitType == PU_PAU_CHIPUNIT)
+ {
+ if ( (i_chipUnitNum == 1) || (i_chipUnitNum == 2) )
+ {
+ l_rc = 1;
+ }
+ }
+
+ break;
+ }
+ }
+
+ // Can't find i_chipUnitType in table
+ if ( l_index >= (sizeof(ChipUnitDescriptionTable) / sizeof(p10_chipUnitDescription_t)) )
+ {
+ l_rc = 1;
+ }
+
+ return (l_rc);
+ }
+
+} // extern "C"
+
+#undef P10_SCOMINFO_C
new file mode 100644
@@ -0,0 +1,89 @@
+///
+/// @file p10_scominfo.H
+/// @brief P10 chip unit SCOM address platform translation code
+///
+/// HWP HW Maintainer: Thi Tran <thi@us.ibm.com>
+/// HWP FW Maintainer:
+/// HWP Consumed by: Cronus, HB, HWSV
+///
+
+#ifndef P10_SCOMINFO_H
+#define P10_SCOMINFO_H
+
+// includes
+#include <stdint.h>
+#include <vector>
+#include "p10_cu.H"
+
+extern "C"
+{
+ // Modes of translation
+ typedef enum
+ {
+ P10_DEFAULT_MODE = 0, // Default platform behavior
+ P10_ENGD_BUILD_MODE = 1, // Apply customization for ENGD build
+ } p10TranslationMode_t;
+
+ typedef enum
+ {
+ FAILED_TRANSLATION = 0xFFFFFFFFFFFFFFF1ull
+ } p10TranslationResult_t;
+
+ /// @brief Creates the actual SCOM address based on the chip unit type, instance, and the input SCOM address (relative to chip unit instance 0)
+ /// @param[in] i_p10CU Enumeration of the chip unit type
+ /// @param[in] i_ecLevel Chip EC level represented in HEX digit value. Example: i_ecLevel = 0x12 --> EC level 1.2
+ /// @param[in] i_chipUnitNum Instance number of the chip unit
+ /// @param[in] i_scomAddr The input SCOM address associated with the chip unit type
+ /// @param[in] i_mode Translation mode, specifying different addr translation methods.
+ /// @retval uint64_t Actual SCOM address for the chip unit instance passed in
+ uint64_t p10_scominfo_createChipUnitScomAddr(const p10ChipUnits_t i_p10CU,
+ const uint8_t i_ecLevel,
+ const uint8_t i_chipUnitNum,
+ const uint64_t i_scomAddr,
+ const uint32_t i_mode = 0);
+
+ /// @brief Determine if the provided SCOM address correlates to any chip units (if so creates a list of chipUnitPairing structures which correspond)
+ /// @param[in] i_p10CU Enumeration of the chip unit type
+ /// @param[in] i_ecLevel Chip EC level represented in HEX digit value. Example: i_ecLevel = 0x12 --> EC level 1.2
+ /// @param[in] i_scomAddr SCOM address to be tested
+ /// @param[out] o_chipUnitRelated Returns true if SCOM address is associated with any chip units
+ /// @param[out] o_chipUnitPairing Collection of chipUnitPairing enums
+ /// @param[in] i_mode Translation mode, specifying different addr translation methods.
+ /// @retval uint32_t Return non-zero for error
+ uint32_t p10_scominfo_isChipUnitScom(const p10ChipUnits_t i_p10CU,
+ const uint8_t i_ecLevel,
+ const uint64_t i_scomAddr,
+ bool& o_chipUnitRelated,
+ std::vector<p10_chipUnitPairing_t>& o_chipUnitPairing,
+ const p10TranslationMode_t i_mode = P10_DEFAULT_MODE);
+
+ /// @brief Alter the unit/unitnum of a target for spys where the clocks-on vs clocks-off targets are different.
+ /// @param[in] i_p10CU Target used for the spy request
+ /// @param[in] i_ecLevel Chip EC level represented in HEX digit value. Example: i_ecLevel = 0x12 --> EC level 1.2
+ /// @param[in] i_targetChipUnitNum The instance number of the target used for the spy request
+ /// @param[in] i_scomaddr The scom from the clocks-on portion of the spy
+ /// @param[out] o_modifiedScomAddr The translated scom address (none may be needed)
+ /// @param[out] o_p10CU The translated target type
+ /// @param[out] o_modifiedChipUnitNum The translated target instance number
+ /// @param[in] i_mode Translation mode, specifying different addr translation methods.
+ /// @retval uint32_t Return non-zero for error
+ uint32_t p10_scominfo_fixChipUnitScomAddrOrTarget(const p10ChipUnits_t i_p10CU,
+ const uint8_t i_ecLevel,
+ const uint32_t i_targetChipUnitNum,
+ const uint64_t i_scomaddr,
+ uint64_t& o_modifiedScomAddr,
+ p10ChipUnits_t& o_p10CU,
+ uint32_t& o_modifiedChipUnitNum,
+ const uint32_t i_mode = 0);
+
+ /// @brief Validate the chip unit number to be within range
+ /// of a chip unit type.
+ /// @param[in] i_chipUnitNum Value of chip unit number (instance)
+ /// @param[in] i_chipUnitType Chip unit type
+ /// @retval Non-zero if error
+ uint8_t validateChipUnitNum(const uint8_t i_chipUnitNum,
+ const p10ChipUnits_t i_chipUnitType);
+
+} // extern "C"
+
+#endif /* P10_SCOMINFO_H */
Signed-off-by: Amitay Isaacs <amitay@ozlabs.org> --- src/tests/p10_cu.H | 102 +++++ src/tests/p10_scom_addr.C | 916 ++++++++++++++++++++++++++++++++++++++ src/tests/p10_scom_addr.H | 700 +++++++++++++++++++++++++++++ src/tests/p10_scominfo.C | 838 ++++++++++++++++++++++++++++++++++ src/tests/p10_scominfo.H | 89 ++++ 5 files changed, 2645 insertions(+) create mode 100644 src/tests/p10_cu.H create mode 100644 src/tests/p10_scom_addr.C create mode 100644 src/tests/p10_scom_addr.H create mode 100644 src/tests/p10_scominfo.C create mode 100644 src/tests/p10_scominfo.H