diff mbox

[1/4] phb4: Implement diag data

Message ID 20170410015737.9487-2-ruscur@russell.cc
State Superseded
Headers show

Commit Message

Russell Currey April 10, 2017, 1:57 a.m. UTC
Implement PHB4 diagnostic data, similar to PHB3.  There are a few
registers that have changed, but everything is largely the same.

Signed-off-by: Russell Currey <ruscur@russell.cc>
---
 hw/phb4.c           | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/opal-api.h  |  58 ++++++++++++++++++++++++++-
 include/phb4-regs.h |  86 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 253 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/hw/phb4.c b/hw/phb4.c
index 571f7037..6c7bb9fe 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -1526,12 +1526,123 @@  static void phb4_err_ER_clear(struct phb4 *p)
 static void phb4_read_phb_status(struct phb4 *p,
 				 struct OpalIoPhb4ErrorData *stat)
 {
+	uint16_t val = 0;
+	uint32_t i;
+	uint64_t val64 = 0;
+	uint64_t *pPEST;
+
 	memset(stat, 0, sizeof(struct OpalIoPhb4ErrorData));
 
 	/* Error data common part */
 	stat->common.version = OPAL_PHB_ERROR_DATA_VERSION_1;
 	stat->common.ioType  = OPAL_PHB_ERROR_DATA_TYPE_PHB4;
 	stat->common.len     = sizeof(struct OpalIoPhb4ErrorData);
+
+	/*
+	 * TODO: investigate reading registers through ASB instead of AIB.
+	 *
+	 * Until this is implemented, some registers may be unreadable through
+	 * a fence.
+	 */
+
+	/* Grab RC bridge control, make it 32-bit */
+	phb4_pcicfg_read16(&p->phb, 0, PCI_CFG_BRCTL, &val);
+	stat->brdgCtl = val;
+
+	/* XXX: No UTL registers on PHB4? */
+
+	/*
+	 * Grab various RC PCIe capability registers. All device, slot
+	 * and link status are 16-bit, so we grab the pair control+status
+	 * for each of them
+	 */
+	phb4_pcicfg_read32(&p->phb, 0, p->ecap + PCICAP_EXP_DEVCTL,
+			   &stat->deviceStatus);
+	phb4_pcicfg_read32(&p->phb, 0, p->ecap + PCICAP_EXP_SLOTCTL,
+			   &stat->slotStatus);
+	phb4_pcicfg_read32(&p->phb, 0, p->ecap + PCICAP_EXP_LCTL,
+			   &stat->linkStatus);
+
+	/*
+	 * I assume those are the standard config space header, cmd & status
+	 * together makes 32-bit. Secondary status is 16-bit so I'll clear
+	 * the top on that one
+	 */
+	phb4_pcicfg_read32(&p->phb, 0, PCI_CFG_CMD, &stat->devCmdStatus);
+	phb4_pcicfg_read16(&p->phb, 0, PCI_CFG_SECONDARY_STATUS, &val);
+	stat->devSecStatus = val;
+
+	/* Grab a bunch of AER regs */
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_RERR_STA,
+			   &stat->rootErrorStatus);
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_UE_STATUS,
+			   &stat->uncorrErrorStatus);
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_CE_STATUS,
+			   &stat->corrErrorStatus);
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG0,
+			   &stat->tlpHdr1);
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG1,
+			   &stat->tlpHdr2);
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG2,
+			   &stat->tlpHdr3);
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG3,
+			   &stat->tlpHdr4);
+	phb4_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_SRCID,
+			   &stat->sourceId);
+
+	/* PEC NFIR, same as P8/PHB3 */
+	xscom_read(p->chip_id, p->pe_stk_xscom + 0x0, &stat->nFir);
+	xscom_read(p->chip_id, p->pe_stk_xscom + 0x3, &stat->nFirMask);
+	xscom_read(p->chip_id, p->pe_stk_xscom + 0x8, &stat->nFirWOF);
+
+	/* PHB4 inbound and outbound error Regs */
+	stat->phbPlssr = phb4_read_reg_asb(p, PHB_CPU_LOADSTORE_STATUS);
+	stat->phbCsr = phb4_read_reg_asb(p, PHB_DMA_CHAN_STATUS);
+	stat->lemFir = phb4_read_reg_asb(p, PHB_LEM_FIR_ACCUM);
+	stat->lemErrorMask = phb4_read_reg_asb(p, PHB_LEM_ERROR_MASK);
+	stat->lemWOF = phb4_read_reg_asb(p, PHB_LEM_WOF);
+	stat->phbErrorStatus = phb4_read_reg_asb(p, PHB_ERR_STATUS);
+	stat->phbFirstErrorStatus = phb4_read_reg_asb(p, PHB_ERR1_STATUS);
+	stat->phbErrorLog0 = phb4_read_reg_asb(p, PHB_ERR_LOG_0);
+	stat->phbErrorLog1 = phb4_read_reg_asb(p, PHB_ERR_LOG_1);
+	stat->mmioErrorStatus = phb4_read_reg_asb(p, PHB_TXE_ERR_STATUS);
+	stat->mmioFirstErrorStatus = phb4_read_reg_asb(p, PHB_TXE_ERR1_STATUS);
+	stat->mmioErrorLog0 = phb4_read_reg_asb(p, PHB_TXE_ERR_LOG_0);
+	stat->mmioErrorLog1 = phb4_read_reg_asb(p, PHB_TXE_ERR_LOG_1);
+	stat->dma0ErrorStatus = phb4_read_reg_asb(p, PHB_RXE_ARB_ERR_STATUS);
+	stat->dma0FirstErrorStatus = phb4_read_reg_asb(p, PHB_RXE_ARB_ERR1_STATUS);
+	stat->dma0ErrorLog0 = phb4_read_reg_asb(p, PHB_RXE_ARB_ERR_LOG_0);
+	stat->dma0ErrorLog1 = phb4_read_reg_asb(p, PHB_RXE_ARB_ERR_LOG_1);
+	stat->dma1ErrorStatus = phb4_read_reg_asb(p, PHB_RXE_MRG_ERR_STATUS);
+	stat->dma1FirstErrorStatus = phb4_read_reg_asb(p, PHB_RXE_MRG_ERR1_STATUS);
+	stat->dma1ErrorLog0 = phb4_read_reg_asb(p, PHB_RXE_MRG_ERR_LOG_0);
+	stat->dma1ErrorLog1 = phb4_read_reg_asb(p, PHB_RXE_MRG_ERR_LOG_1);
+	stat->dma2ErrorStatus = phb4_read_reg_asb(p, PHB_RXE_TCE_ERR_STATUS);
+	stat->dma2FirstErrorStatus = phb4_read_reg_asb(p, PHB_RXE_TCE_ERR1_STATUS);
+	stat->dma2ErrorLog0 = phb4_read_reg_asb(p, PHB_RXE_TCE_ERR_LOG_0);
+	stat->dma2ErrorLog1 = phb4_read_reg_asb(p, PHB_RXE_TCE_ERR_LOG_1);
+
+	/*
+	 * Grab PESTA & B content. The error bit (bit#0) should
+	 * be fetched from IODA and the left content from memory
+	 * resident tables.
+	 */
+	 pPEST = (uint64_t *)p->tbl_pest;
+	 val64 = PHB_IODA_AD_AUTOINC;
+	 val64 = SETFIELD(PHB_IODA_AD_TSEL, val64, IODA3_TBL_PESTA);
+	 phb4_write_reg_asb(p, PHB_IODA_ADDR, val64);
+	 for (i = 0; i < OPAL_PHB4_NUM_PEST_REGS; i++) {
+		 stat->pestA[i] = phb4_read_reg_asb(p, PHB_IODA_DATA0);
+		 stat->pestA[i] |= pPEST[2 * i];
+	 }
+
+	 val64 = PHB_IODA_AD_AUTOINC;
+	 val64 = SETFIELD(PHB_IODA_AD_TSEL, val64, IODA3_TBL_PESTB);
+	 phb4_write_reg_asb(p, PHB_IODA_ADDR, val64);
+	 for (i = 0; i < OPAL_PHB4_NUM_PEST_REGS; i++) {
+		 stat->pestB[i] = phb4_read_reg_asb(p, PHB_IODA_DATA0);
+		 stat->pestB[i] |= pPEST[2 * i + 1];
+	 }
 }
 
 static int64_t phb4_set_pe(struct phb *phb,
diff --git a/include/opal-api.h b/include/opal-api.h
index 7966200e..101e4be7 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -809,7 +809,8 @@  enum {
 
 enum {
 	OPAL_P7IOC_NUM_PEST_REGS = 128,
-	OPAL_PHB3_NUM_PEST_REGS = 256
+	OPAL_PHB3_NUM_PEST_REGS = 256,
+	OPAL_PHB4_NUM_PEST_REGS = 512
 };
 
 struct OpalIoPhbErrorCommon {
@@ -941,7 +942,60 @@  struct OpalIoPhb3ErrorData {
 
 struct OpalIoPhb4ErrorData {
 	struct OpalIoPhbErrorCommon common;
-	// FIXME add phb4 specific stuff
+
+	__be32 brdgCtl;
+
+	/* XXX missing UTL registers? */
+
+	/* PHB4 cfg regs */
+	__be32 deviceStatus;
+	__be32 slotStatus;
+	__be32 linkStatus;
+	__be32 devCmdStatus;
+	__be32 devSecStatus;
+
+	/* cfg AER regs */
+	__be32 rootErrorStatus;
+	__be32 uncorrErrorStatus;
+	__be32 corrErrorStatus;
+	__be32 tlpHdr1;
+	__be32 tlpHdr2;
+	__be32 tlpHdr3;
+	__be32 tlpHdr4;
+	__be32 sourceId;
+
+	/* PHB4 MMIO Error Regs */
+	__be64 nFir;			/* 000 */
+	__be64 nFirMask;		/* 003 */
+	__be64 nFirWOF;			/* 008 */
+	__be64 phbPlssr;		/* 120 */
+	__be64 phbCsr;			/* 110 */
+	__be64 lemFir;			/* C00 */
+	__be64 lemErrorMask;		/* C18 */
+	__be64 lemWOF;			/* C40 */
+	__be64 phbErrorStatus;		/* C80 */
+	__be64 phbFirstErrorStatus;	/* C88 */
+	__be64 phbErrorLog0;		/* CC0 */
+	__be64 phbErrorLog1;		/* CC8 */
+	__be64 mmioErrorStatus;		/* D00 */
+	__be64 mmioFirstErrorStatus;	/* D08 */
+	__be64 mmioErrorLog0;		/* D40 */
+	__be64 mmioErrorLog1;		/* D48 */
+	__be64 dma0ErrorStatus;		/* D80 */
+	__be64 dma0FirstErrorStatus;	/* D88 */
+	__be64 dma0ErrorLog0;		/* DC0 */
+	__be64 dma0ErrorLog1;		/* DC8 */
+	__be64 dma1ErrorStatus;		/* E00 */
+	__be64 dma1FirstErrorStatus;	/* E08 */
+	__be64 dma1ErrorLog0;		/* E40 */
+	__be64 dma1ErrorLog1;		/* E48 */
+	__be64 dma2ErrorStatus;		/* E80 */
+	__be64 dma2FirstErrorStatus;	/* E88 */
+	__be64 dma2ErrorLog0;		/* EC0 */
+	__be64 dma2ErrorLog1;		/* EC8 */
+
+	__be64 pestA[OPAL_PHB4_NUM_PEST_REGS];
+	__be64 pestB[OPAL_PHB4_NUM_PEST_REGS];
 };
 
 enum {
diff --git a/include/phb4-regs.h b/include/phb4-regs.h
index 48953e40..2ae95801 100644
--- a/include/phb4-regs.h
+++ b/include/phb4-regs.h
@@ -187,6 +187,92 @@ 
 #define PHB_PCIE_LANE_EQ_CNTL22		0x1B00 /* DD1 only */
 #define PHB_PCIE_LANE_EQ_CNTL23		0x1B08 /* DD1 only */
 
+/* Fundamental register set B - some missing from PHB3 */
+#define PHB_VERSION			0x800
+#define PHB_CONTROL			0x810
+#define PHB_AIB_FENCE_CTRL		0x860
+#define PHB_TCE_TAG_ENABLE		0x868
+#define PHB_TCE_WATERMARK		0x870
+#define PHB_TIMEOUT_CTRL1		0x878
+#define PHB_TIMEOUT_CTRL2		0x880
+#define PHB_QUIESCE_DMA_G		0x888
+#define PHB_TCE_TAG_STATUS		0x908
+
+/* FIR & Error registers - identical to PHB3 */
+#define PHB_LEM_FIR_ACCUM		0xc00
+#define PHB_LEM_FIR_AND_MASK		0xc08
+#define PHB_LEM_FIR_OR_MASK		0xc10
+#define PHB_LEM_ERROR_MASK		0xc18
+#define PHB_LEM_ERROR_AND_MASK		0xc20
+#define PHB_LEM_ERROR_OR_MASK		0xc28
+#define PHB_LEM_ACTION0			0xc30
+#define PHB_LEM_ACTION1			0xc38
+#define PHB_LEM_WOF			0xc40
+#define PHB_ERR_STATUS			0xc80
+#define PHB_ERR1_STATUS			0xc88
+#define PHB_ERR_INJECT			0xc90
+#define PHB_ERR_LEM_ENABLE		0xc98
+#define PHB_ERR_IRQ_ENABLE		0xca0
+#define PHB_ERR_FREEZE_ENABLE		0xca8
+#define PHB_ERR_AIB_FENCE_ENABLE	0xcb0
+#define PHB_ERR_LOG_0			0xcc0
+#define PHB_ERR_LOG_1			0xcc8
+#define PHB_ERR_STATUS_MASK		0xcd0
+#define PHB_ERR1_STATUS_MASK		0xcd8
+
+/*
+ * Instead of MMIO outbound, inboundA and inboundB in PHB3,
+ * PHB4 has TXE (outbound), RXE_ARB, RXE_MRG and RXE_TCE.
+ */
+
+#define PHB_TXE_ERR_STATUS			0xd00
+#define PHB_TXE_ERR1_STATUS			0xd08
+#define PHB_TXE_ERR_INJECT			0xd10
+#define PHB_TXE_ERR_LEM_ENABLE			0xd18
+#define PHB_TXE_ERR_IRQ_ENABLE			0xd20
+#define PHB_TXE_ERR_FREEZE_ENABLE		0xd28
+#define PHB_TXE_ERR_AIB_FENCE_ENABLE		0xd30
+#define PHB_TXE_ERR_LOG_0			0xd40
+#define PHB_TXE_ERR_LOG_1			0xd48
+#define PHB_TXE_ERR_STATUS_MASK			0xd50
+#define PHB_TXE_ERR1_STATUS_MASK		0xd58
+
+#define PHB_RXE_ARB_ERR_STATUS			0xd80
+#define PHB_RXE_ARB_ERR1_STATUS			0xd88
+#define PHB_RXE_ARB_ERR_INJECT			0xd90
+#define PHB_RXE_ARB_ERR_LEM_ENABLE      	0xd98
+#define PHB_RXE_ARB_ERR_IRQ_ENABLE		0xda0
+#define PHB_RXE_ARB_ERR_FREEZE_ENABLE		0xda8
+#define PHB_RXE_ARB_ERR_AIB_FENCE_ENABLE	0xdb0
+#define PHB_RXE_ARB_ERR_LOG_0			0xdc0
+#define PHB_RXE_ARB_ERR_LOG_1			0xdc8
+#define PHB_RXE_ARB_ERR_STATUS_MASK		0xdd0
+#define PHB_RXE_ARB_ERR1_STATUS_MASK		0xdd8
+
+#define PHB_RXE_MRG_ERR_STATUS			0xe00
+#define PHB_RXE_MRG_ERR1_STATUS			0xe08
+#define PHB_RXE_MRG_ERR_INJECT			0xe10
+#define PHB_RXE_MRG_ERR_LEM_ENABLE		0xe18
+#define PHB_RXE_MRG_ERR_IRQ_ENABLE		0xe20
+#define PHB_RXE_MRG_ERR_FREEZE_ENABLE		0xe28
+#define PHB_RXE_MRG_ERR_AIB_FENCE_ENABLE	0xe30
+#define PHB_RXE_MRG_ERR_LOG_0			0xe40
+#define PHB_RXE_MRG_ERR_LOG_1			0xe48
+#define PHB_RXE_MRG_ERR_STATUS_MASK		0xe50
+#define PHB_RXE_MRG_ERR1_STATUS_MASK		0xe58
+
+#define PHB_RXE_TCE_ERR_STATUS			0xe80
+#define PHB_RXE_TCE_ERR1_STATUS			0xe88
+#define PHB_RXE_TCE_ERR_INJECT			0xe90
+#define PHB_RXE_TCE_ERR_LEM_ENABLE		0xe98
+#define PHB_RXE_TCE_ERR_IRQ_ENABLE		0xea0
+#define PHB_RXE_TCE_ERR_FREEZE_ENABLE		0xea8
+#define PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE	0xeb0
+#define PHB_RXE_TCE_ERR_LOG_0			0xec0
+#define PHB_RXE_TCE_ERR_LOG_1			0xec8
+#define PHB_RXE_TCE_ERR_STATUS_MASK		0xed0
+#define PHB_RXE_TCE_ERR1_STATUS_MASK		0xed8
+
 /*
  * PHB4 xscom address defines
  */