[Skiboot] [PATCH] hw/npu2-hw-procedures.c: Add nvram option to override zcal calculations

Alistair Popple alistair at popple.id.au
Thu Jun 8 16:10:24 AEST 2017


In some rare cases the zcal state machine may fail and flag an error. According
to hardware designers it is sometimes ok to ignore this failure and use nominal
values for the calculations. In this case we add a nvram variable
(nv_zcal_override) which will cause skiboot to ignore the failure and use the
nominal value specified in nvram.

Signed-off-by: Alistair Popple <alistair at popple.id.au>
---
 hw/npu2-hw-procedures.c | 28 ++++++++++++++++++++--------
 hw/npu2.c               |  9 +++++++++
 include/npu2.h          |  2 +-
 3 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/hw/npu2-hw-procedures.c b/hw/npu2-hw-procedures.c
index ee1ade6..07eb551 100644
--- a/hw/npu2-hw-procedures.c
+++ b/hw/npu2-hw-procedures.c
@@ -23,6 +23,10 @@
 #include <npu2-regs.h>
 #include <xscom.h>
 
+/* Set in npu2.c if there is an nvram override for the zcal settings on this
+ * machine */
+int nv_zcal_nominal = -1;
+
 /* PHY Registers. The documentation for the PHY training is written in
  * terms of bits within an actual register so we use that
  * representation here. */
@@ -316,12 +320,15 @@ static uint32_t phy_tx_zcal_wait(struct npu2_dev *ndev)
 	done = phy_read(ndev, &NPU2_PHY_TX_ZCAL_DONE);
 	error = phy_read(ndev, &NPU2_PHY_TX_ZCAL_ERROR);
 
-	/* We have never seen this in the field and it is not
-	 * expected. Therefore it's best to error out which will
-	 * complain loudly in the logs than to continue with nominal
-	 * values which wont work well. */
-	if (error)
+	/* We have never seen this in the field and it is not expected.
+	 * Therefore it's best to error out which will complain loudly. Nominal
+	 * vaules may be set in nvram to ignore this error. */
+	if (error && nv_zcal_nominal < 0) {
+		NPU2DEVERR(ndev, "ZCAL failed. Nominal values may be used by"
+			   " setting nvram variable nv_zcal_override = 50\n");
+		NPU2DEVERR(ndev, "However this may impact link performance\n");
 		return PROCEDURE_COMPLETE | PROCEDURE_FAILED;
+	}
 
 	if (!done)
 		return PROCEDURE_INPROGRESS;
@@ -380,9 +387,14 @@ static uint32_t phy_tx_zcal_calculate(struct npu2_dev *ndev)
 	uint32_t margin_pd_select;
 	uint32_t margin_select;
 
-	/* Convert the value from 8R to 2R by / 4 */
-	zcal_n = phy_read(ndev, &NPU2_PHY_TX_ZCAL_N) / 4;
-	zcal_p = phy_read(ndev, &NPU2_PHY_TX_ZCAL_P) / 4;
+	if (nv_zcal_nominal < 0) {
+		/* Convert the value from 8R to 2R by / 4 */
+		zcal_n = phy_read(ndev, &NPU2_PHY_TX_ZCAL_N) / 4;
+		zcal_p = phy_read(ndev, &NPU2_PHY_TX_ZCAL_P) / 4;
+	} else {
+		zcal_n = zcal_p = nv_zcal_nominal;
+		NPU2DEVINF(ndev, "Using nominal values for zcal, performance may be impacted\n");
+	}
 
 	/* Again, if the hardware detects an unexpected condition it's
 	 * better just to fail loudly. */
diff --git a/hw/npu2.c b/hw/npu2.c
index 73e9841..4cc0bc6 100644
--- a/hw/npu2.c
+++ b/hw/npu2.c
@@ -35,6 +35,7 @@
 #include <bitutils.h>
 #include <chip.h>
 #include <phys-map.h>
+#include <nvram.h>
 
 /*
  * NPU2 BAR layout definition. We have 3 stacks and each of them
@@ -1613,6 +1614,14 @@ static void npu2_create_phb(struct dt_node *dn)
 void probe_npu2(void)
 {
 	struct dt_node *np;
+	const char *zcal;
+
+	/* Check for a zcal override */
+	zcal = nvram_query("nv_zcal_override");
+	if (zcal) {
+		nv_zcal_nominal = atoi(zcal);
+		prlog(PR_WARNING, "NPU2: Using ZCAL impedance override = %d\n", nv_zcal_nominal);
+	}
 
 	/* Scan NPU XSCOM nodes */
 	dt_for_each_compatible(dt_root, np, "ibm,power9-npu")
diff --git a/include/npu2.h b/include/npu2.h
index d15b2c9..7778f6e 100644
--- a/include/npu2.h
+++ b/include/npu2.h
@@ -147,5 +147,5 @@ void npu2_write_mask(struct npu2 *p, uint64_t reg, uint64_t val, uint64_t mask);
 int64_t npu2_dev_procedure(void *dev, struct pci_cfg_reg_filter *pcrf,
 			   uint32_t offset, uint32_t len, uint32_t *data,
 			   bool write);
-
+extern int nv_zcal_nominal;
 #endif /* __NPU2_H */
-- 
2.1.4



More information about the Skiboot mailing list