summaryrefslogtreecommitdiffstats
path: root/src/usr/xscom
diff options
context:
space:
mode:
authorDan Crowell <dcrowell@us.ibm.com>2016-04-29 11:30:47 -0500
committerMatthew A. Ploetz <maploetz@us.ibm.com>2016-05-04 14:50:33 -0400
commitae304eed80b3e440f7fce5f5bafac5b357e9f7c4 (patch)
tree92b37b24a8f8d7e6c5c90f68fbf91a2eee02cc36 /src/usr/xscom
parent0b163c19b9950b1df51af5b128083f3a9edf071d (diff)
downloadtalos-hostboot-ae304eed80b3e440f7fce5f5bafac5b357e9f7c4.tar.gz
talos-hostboot-ae304eed80b3e440f7fce5f5bafac5b357e9f7c4.zip
Good path xscom support for multiple P9 chips
Necessary changes to handle new MMIO map for P9 Change-Id: I105114030d02c6baccb4732fe9597d67f24b263c RTC: 128077 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/23862 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Reviewed-by: Andrew J. Geissler <andrewg@us.ibm.com> Reviewed-by: Thi N. Tran <thi@us.ibm.com> Reviewed-by: Matthew A. Ploetz <maploetz@us.ibm.com>
Diffstat (limited to 'src/usr/xscom')
-rw-r--r--src/usr/xscom/xscom.C102
-rw-r--r--src/usr/xscom/xscom.H60
2 files changed, 62 insertions, 100 deletions
diff --git a/src/usr/xscom/xscom.C b/src/usr/xscom/xscom.C
index 5eaad2237..b4f4c3aa6 100644
--- a/src/usr/xscom/xscom.C
+++ b/src/usr/xscom/xscom.C
@@ -58,17 +58,15 @@ namespace XSCOM
// Master processor virtual address
uint64_t* g_masterProcVirtAddr = NULL;
-// Max chip per node in this system
-extern uint8_t getMaxChipsPerNode();
-static uint8_t g_xscomMaxChipsPerNode = getMaxChipsPerNode();
-
// Register XSCcom access functions to DD framework
DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
DeviceFW::XSCOM,
TARGETING::TYPE_PROC,
xscomPerformOp);
-uint64_t* getCpuIdVirtualAddress();
+// Helper function to map in the master proc's XSCOM space
+uint64_t* getCpuIdVirtualAddress( XSComBase_t& o_mmioAddr );
+
/**
* @brief Internal routine that reset XSCOM status bits
* of HMER register before an XSCOM operation
@@ -187,32 +185,6 @@ errlHndl_t xscomOpSanityCheck(const DeviceFW::OperationType i_opType,
}
/**
- * @brief Returns maximum processors chip per node
- * base on system type
- *
- * @return uint8_t
- */
-uint8_t getMaxChipsPerNode()
-{
- uint8_t l_numOfChips = 0;
-
- ProcessorCoreType l_coreType = cpu_core_type();
- switch (l_coreType)
- {
- case CORE_POWER8_MURANO:
- case CORE_POWER8_VENICE:
- case CORE_POWER8_NAPLES:
- case CORE_POWER9_NIMBUS:
- case CORE_POWER9_CUMULUS:
- case CORE_UNKNOWN:
- default:
- l_numOfChips = 8;
- break;
- }
- return l_numOfChips;
-}
-
-/**
* @brief Get the virtual address of the input target
* for an XSCOM access.
*
@@ -291,7 +263,8 @@ errlHndl_t getTargetVirtualAddress(TARGETING::Target* i_target,
{
// Note: can't call TARGETING code prior to PNOR being
// brought up.
- uint64_t* l_tempVirtAddr = getCpuIdVirtualAddress();
+ uint64_t l_mmioAddr = 0;
+ uint64_t* l_tempVirtAddr = getCpuIdVirtualAddress(l_mmioAddr);
if (!__sync_bool_compare_and_swap(&g_masterProcVirtAddr,
NULL, l_tempVirtAddr))
{
@@ -323,6 +296,14 @@ errlHndl_t getTargetVirtualAddress(TARGETING::Target* i_target,
break;
}
}
+ else
+ {
+ TRACFCOMP(g_trac_xscom,
+ "Master Proc : pir=%.8X, mmio=0x%0.16llX, virt=0x%llX",
+ task_getcpuid(),
+ l_mmioAddr,
+ reinterpret_cast<uint64_t>(l_tempVirtAddr));
+ }
}
// Set virtual address to sentinel's value
@@ -343,35 +324,25 @@ errlHndl_t getTargetVirtualAddress(TARGETING::Target* i_target,
// the virtual address and save it in the xscom address attribute.
if (o_virtAddr == NULL)
{
- uint64_t xscomNodeId = 0;
+ uint64_t xscomGroupId = 0;
uint64_t xscomChipId = 0;
- // Get the target Node Id
- xscomNodeId =
+ // Get the target Group Id
+ xscomGroupId =
i_target->getAttr<TARGETING::ATTR_FABRIC_GROUP_ID>();
// Get the target Chip Id
xscomChipId =
i_target->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
- // Get system XSCOM base address
- TARGETING::TargetService& l_targetService =
- TARGETING::targetService();
- TARGETING::Target* l_pTopLevel = NULL;
- (void) l_targetService.getTopLevelTarget(l_pTopLevel);
- assert(l_pTopLevel != NULL);
- XSComBase_t l_systemBaseAddr =
- l_pTopLevel->getAttr<TARGETING::ATTR_XSCOM_BASE_ADDRESS>();
-
- // Target's XSCOM Base address
- l_XSComBaseAddr = l_systemBaseAddr +
- ( ( (g_xscomMaxChipsPerNode * xscomNodeId) +
- xscomChipId ) * THIRTYTWO_GB);
+ // Get assigned XSCOM base address
+ l_XSComBaseAddr =
+ i_target->getAttr<TARGETING::ATTR_XSCOM_BASE_ADDRESS>();
TRACFCOMP(g_trac_xscom,
- "Target %.8X :: Node:%d Chip:%d :: XscomBase:0x%llX",
+ "Target %.8X :: Group:%d Chip:%d :: XscomBase:0x%llX",
TARGETING::get_huid(i_target),
- xscomNodeId,
+ xscomGroupId,
xscomChipId,
l_XSComBaseAddr);
@@ -390,7 +361,7 @@ errlHndl_t getTargetVirtualAddress(TARGETING::Target* i_target,
// logic. So there is possibility that this same thread is running
// on another thread at the exact same time. We can use atomic
// update instructions here.
- // Comment for Nick: This is a good candidate for having a way
+ // Future note : This is a good candidate for having a way
// to return a reference to the attribute instead of requiring
// to call setAttr. We currently have no way to SMP-safely update
// this attribute, where as if we had a reference to it we could use
@@ -438,8 +409,8 @@ errlHndl_t xScomDoOp(DeviceFW::OperationType i_opType,
HMER &io_hmer)
{
- // Build the XSCom address (relative to node 0, chip 0)
- XSComP8Address l_mmioAddr(i_xscomAddr);
+ // Build the XSCom address (relative to group 0, chip 0)
+ XSComP9Address l_mmioAddr(i_xscomAddr);
// Get the offset
uint64_t l_offset = l_mmioAddr.offset();
@@ -488,7 +459,7 @@ errlHndl_t xScomDoOp(DeviceFW::OperationType i_opType,
// an obscene amount of time
if( l_retryCtr > 500000 )
{
- TRACFCOMP( g_trac_xscom, "Giving up, we're still locked..." );
+ TRACFCOMP( g_trac_xscom, "Giving up, we're still locked on 0x%.16llX...", l_offset );
break;
}
}
@@ -542,32 +513,24 @@ errlHndl_t xScomDoOp(DeviceFW::OperationType i_opType,
* @brief Get the Virtual Address of the XSCOM space for the processor
* associated with this thread (the source chip)
*
+ * @param[out] o_mmioAddr Physical mmio address that was mapped in
* @return uint64_t* virtualAddress
*/
-uint64_t* getCpuIdVirtualAddress()
+uint64_t* getCpuIdVirtualAddress( XSComBase_t& o_mmioAddr )
{
uint64_t* o_virtAddr = 0;
// Get the CPU core this thread is running on
PIR_t cpuid = task_getcpuid();
- // Can change the above hardcoded values to either a macro or use
- // the info below to do the masking and shifting.
- // uint64_t max_threads = cpu_thread_count();
- // for the number of Chips - use g_xscomMaxChipsPerNode instead..
- // For the number of Procs.. MAX_PROCS_RSV = P8_MAX_PROCS*2
- // P8_MAX_PROCS = 8 -- space left for 2* that.
-
- XSComBase_t l_systemBaseAddr = MASTER_PROC_XSCOM_BASE_ADDR;
-
// Target's XSCOM Base address
- XSComBase_t l_XSComBaseAddr = l_systemBaseAddr +
- ( ( (g_xscomMaxChipsPerNode * cpuid.groupId) +
- cpuid.chipId ) * THIRTYTWO_GB);
+ o_mmioAddr = MASTER_PROC_XSCOM_BASE_ADDR +
+ (MMIO_OFFSET_PER_GROUP * cpuid.groupId) +
+ (MMIO_OFFSET_PER_GROUP * cpuid.chipId);
// Target's virtual address
o_virtAddr = static_cast<uint64_t*>
- (mmio_dev_map(reinterpret_cast<void*>(l_XSComBaseAddr),
+ (mmio_dev_map(reinterpret_cast<void*>(o_mmioAddr),
THIRTYTWO_GB));
TRACDCOMP(g_trac_xscom, "getCpuIdVirtualAddress: o_Virtual Address = 0x%llX\n",o_virtAddr);
@@ -611,7 +574,8 @@ void resetScomEngine(TARGETING::Target* i_target,
// running on. Need to find the virtAddr for that CPU.
if (XscomAddr[i].target_type == CurThreadCpu)
{
- l_virtAddr = getCpuIdVirtualAddress();
+ XSComBase_t l_ignored = 0;
+ l_virtAddr = getCpuIdVirtualAddress(l_ignored);
}
// The rest are xscoms are to the target cpu.
else
diff --git a/src/usr/xscom/xscom.H b/src/usr/xscom/xscom.H
index 0cd7e60a8..9472f39d9 100644
--- a/src/usr/xscom/xscom.H
+++ b/src/usr/xscom/xscom.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -33,22 +33,20 @@
#include <limits.h>
/**
- * @brief Max number of retries if XSCOM fails with certain errors
+ * @brief The (fixed) base address value for master proc
*/
-#define MAX_XSCOM_RETRY 1
+constexpr uint64_t MASTER_PROC_XSCOM_BASE_ADDR = 0x000603FC00000000;
/**
- * @brief The (fixed) base address value for master proc
+ * @brief Static offsets into other chips
*/
-// @todo-RTC:128077 XSCOM support for P9
-#define MASTER_PROC_XSCOM_BASE_ADDR 0x000603FC00000000
+constexpr uint64_t MMIO_OFFSET_PER_CHIP = (4*TERABYTE);
+constexpr uint64_t MMIO_OFFSET_PER_GROUP = (32*TERABYTE);
/**
- * @brief Type definition for XSCom address and Chip ID
+ * @brief Type definition for XSCom address and Base
*/
typedef uint32_t XSComAddress_t;
-typedef uint16_t XSComChipId_t;
-typedef uint16_t XSComNodeId_t;
typedef uint64_t XSComBase_t;
namespace XSCOM
@@ -99,7 +97,7 @@ errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType,
va_list i_args);
/**
- * @brief Abstracts HMER register of a P8 (Murano/Venice) chip
+ * @brief Abstracts HMER register of a POWER9 chip
*/
class HMER
{
@@ -157,38 +155,38 @@ public:
/**
* @brief This class contains necessary information to build an XSCOM
- * address for a P8/Salerno chip.
+ * address for a POWER9 chip.
*/
-class XSComP8Address
+class XSComP9Address
{
public:
/**
- * @brief Constructor of XSComP8Address class
+ * @brief Constructor of XSComP9Address class
*
* @param[in] i_addr PCB address of the register being accessed
*
* @return None
*/
- ALWAYS_INLINE inline XSComP8Address(const XSComAddress_t i_addr);
+ ALWAYS_INLINE inline XSComP9Address(const XSComAddress_t i_addr);
/**
- * @brief Conversion operator
- */
- ALWAYS_INLINE inline operator uint64_t() const;
+ * @brief Conversion operator
+ */
+ ALWAYS_INLINE inline operator uint64_t() const;
/**
- * @brief Return the address' 64-bit full offset
- *
- * @return uint64_t
- */
- ALWAYS_INLINE inline uint64_t offset(void) const;
+ * @brief Return the address' 64-bit full offset
+ *
+ * @return uint64_t
+ */
+ ALWAYS_INLINE inline uint64_t offset(void) const;
private:
/**
* @brief Disabled copy constructor and assignment operator
*/
- XSComP8Address(const XSComP8Address& i_right);
- XSComP8Address& operator=(const XSComP8Address& right);
+ XSComP9Address(const XSComP9Address& i_right);
+ XSComP9Address& operator=(const XSComP9Address& right);
// Layout of XSCOM address parts
union
@@ -198,7 +196,7 @@ class XSComP8Address
{
uint64_t mReserved1:8; // Not currently used (0:7)
uint64_t mBaseAddrHi:7; // Base address [8:14] (8:14)
- uint64_t mNodeId:4; // Node where target resides (15:18)
+ uint64_t mGroupId:4; // Group where target resides (15:18)
uint64_t mChipId:3; // Targeted chip ID (19:21)
uint64_t mBaseAddrLo:8; // Base address [22:29] (22:29)
uint64_t mSComAddr:31; // PIB Address (30:60)
@@ -206,7 +204,7 @@ class XSComP8Address
} mAddressParts;
};
-}; // End XSComP8Address class
+}; // End XSComP9Address class
//-----------------------------------------------------------------------
// In-line functions
@@ -214,25 +212,25 @@ class XSComP8Address
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
-XSComP8Address::XSComP8Address(const XSComAddress_t i_addr)
+XSComP9Address::XSComP9Address(const XSComAddress_t i_addr)
:mMmioAddress(0)
{
- // Relative address of Node 0, chip 0
- // The chip's nodeId and chip id will be taken into account
+ // Relative address of Group 0, chip 0
+ // The chip's groupId and chip id will be taken into account
// when calculating its XSCOM base address
mAddressParts.mSComAddr = i_addr;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
-XSComP8Address::operator uint64_t() const
+XSComP9Address::operator uint64_t() const
{
return mMmioAddress;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
-uint64_t XSComP8Address::offset(void) const
+uint64_t XSComP9Address::offset(void) const
{
return (mMmioAddress / sizeof(uint64_t));
}
OpenPOWER on IntegriCloud