[Skiboot] [PATCH v4 04/10] p9-adu: Implement update sequence for PowerBus Hotplug Mode Control
Andrew Donnellan
andrew.donnellan at au1.ibm.com
Wed Feb 7 17:41:54 AEDT 2018
The PowerBus Hotplug Mode Control register is used to control various
things about the PowerBus.
Due to hardware timing constraints, updating this register requires
more than just a simple SCOM write. There are two sets of pb_hp_mode
registers, current (B) and next (A). Updating is done by a SCOM write
to the next registers, followed by a SWITCH_AB pulse from the
Alter/Display Unit, which triggers a hardware sequence to swap
between the current and next registers.
The sequence used in this code was derived from the hardware
procedures used by Hostboot.
This will be used in a subsequent patch as part of the
OpenCAPI/NVLink init sequence.
Signed-off-by: Andrew Donnellan <andrew.donnellan at au1.ibm.com>
---
v1->v2:
- assert if we don't find master chip (Fred)
- make sure we don't accidentally send a SWITCH_CD, per hostboot (Fred)
---
hw/Makefile.inc | 2 +-
hw/npu2.c | 1 +-
hw/p9-adu.c | 184 +++++++++++++++++++++++++++++++++++++++++++++-
include/npu2-regs.h | 2 +-
include/p9-adu.h | 59 ++++++++++++++-
5 files changed, 245 insertions(+), 3 deletions(-)
create mode 100644 hw/p9-adu.c
create mode 100644 include/p9-adu.h
diff --git a/hw/Makefile.inc b/hw/Makefile.inc
index cf8649d00270..27d8a382d784 100644
--- a/hw/Makefile.inc
+++ b/hw/Makefile.inc
@@ -7,7 +7,7 @@ HW_OBJS += p7ioc.o p7ioc-inits.o p7ioc-phb.o
HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o prd.o
HW_OBJS += dts.o lpc-rtc.o npu.o npu-hw-procedures.o xive.o phb4.o
HW_OBJS += fake-nvram.o lpc-mbox.o npu2.o npu2-hw-procedures.o
-HW_OBJS += npu2-common.o phys-map.o sbe-p9.o capp.o occ-sensor.o vas.o
+HW_OBJS += npu2-common.o phys-map.o sbe-p9.o capp.o occ-sensor.o vas.o p9-adu.o
HW=hw/built-in.o
# FIXME hack this for now
diff --git a/hw/npu2.c b/hw/npu2.c
index 3162bb613e7a..b6eff9cb40c8 100644
--- a/hw/npu2.c
+++ b/hw/npu2.c
@@ -37,6 +37,7 @@
#include <phys-map.h>
#include <nvram.h>
#include <xive.h>
+#include <p9-adu.h>
#define NPU2_IRQ_BASE_SHIFT 13
#define NPU2_N_DL_IRQS 23
diff --git a/hw/p9-adu.c b/hw/p9-adu.c
new file mode 100644
index 000000000000..d2117d184551
--- /dev/null
+++ b/hw/p9-adu.c
@@ -0,0 +1,184 @@
+/* Copyright 2013-2018 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Support code for POWER9 Fabric Alter/Display Unit (ADU) hotplug functionality
+ *
+ * The ADU acts as a bridge between the PowerBus and the Pervasive Interconnect
+ * Bus (PIB).
+ *
+ * Among other things, the ADU is used to support PowerBus Hotplug. Skiboot
+ * needs to set the PowerBus Hotplug Mode Control register as part of OpenCAPI
+ * and NVLink initialisation.
+ */
+
+#include <skiboot.h>
+#include <timebase.h>
+#include <xscom.h>
+#include <chip.h>
+#include <p9-adu.h>
+
+/*
+ * Lock or unlock ADU
+ */
+static int p9_adu_manage_lock(bool lock)
+{
+ int rc;
+ uint64_t val = 0;
+ struct proc_chip *chip = NULL;
+ if (lock) {
+ val |= PU_ALTD_CMD_REG_FBC_LOCKED;
+ val |= PU_ALTD_CMD_REG_FBC_ALTD_RESET_FSM;
+ val |= PU_ALTD_CMD_REG_FBC_ALTD_CLEAR_STATUS;
+ }
+
+ while ((chip = next_chip(chip))) {
+ rc = xscom_write(chip->id, PU_ALTD_CMD_REG, val);
+ if (rc != OPAL_SUCCESS) {
+ /* TODO: Lock picking support */
+ prlog(PR_ERR,
+ "ADU: Error %d writing command (chip %d)\n",
+ rc, chip->id);
+ return OPAL_HARDWARE;
+ }
+ }
+ return OPAL_SUCCESS;
+}
+
+static uint32_t find_master_chip(void)
+{
+ uint64_t reg;
+ struct proc_chip *chip = NULL;
+ while ((chip = next_chip(chip))) {
+ xscom_read(chip->id, PB_CENT_HP_MODE_CURR, ®);
+ if (reg & PB_CFG_MASTER_CHIP)
+ return chip->id;
+ }
+ assert(false);
+}
+
+/*
+ * Trigger a SWITCH_AB pulse to switch the current PowerBus Hotplug Mode Control
+ * register set.
+ *
+ * Overview of sequence:
+ *
+ * - acquire lock and reset all ADUs
+ * - configure all ADUs for AB switch
+ * - configure one ADU (on the fabric master chip) to issue a
+ * quiesce/switch/reinit
+ * - check status
+ * - clear switch selectors
+ * - reset all ADUs
+ * - unlock
+ */
+static void p9_adu_switch_ab(void)
+{
+ uint32_t gcid = find_master_chip();
+ struct proc_chip *chip = NULL;
+ uint64_t reg;
+ uint64_t val;
+ int rc = OPAL_SUCCESS;
+
+ /*
+ * There's a performance issue on P9DD1 that requires a workaround:
+ * see IBM defect HW397129. However, this code isn't expected to be
+ * used on DD1 machines.
+ */
+
+ rc = p9_adu_manage_lock(true);
+ if (rc)
+ goto err;
+
+ /* Set PB_SWITCH_AB on all ADUs */
+ while ((chip = next_chip(chip))) {
+ xscom_read(chip->id, PU_SND_MODE_REG, ®);
+ reg |= PU_SND_MODE_REG_ENABLE_PB_SWITCH_AB;
+ reg &= ~PU_SND_MODE_REG_ENABLE_PB_SWITCH_CD;
+ rc = xscom_write(chip->id, PU_SND_MODE_REG, reg);
+ if (rc)
+ goto err_switch;
+ }
+
+ /* Set address 0 */
+ rc = xscom_write(gcid, PU_ALTD_ADDR_REG, 0);
+ if (rc)
+ goto err_switch;
+
+ /* Configure ADU to issue quiesce + switch + reinit */
+ val = PU_ALTD_OPTION_REG_FBC_ALTD_WITH_PRE_QUIESCE;
+ val = SETFIELD(PU_ALTD_OPTION_REG_FBC_ALTD_AFTER_QUIESCE_WAIT_COUNT,
+ val, QUIESCE_SWITCH_WAIT_COUNT);
+ val |= PU_ALTD_OPTION_REG_FBC_ALTD_WITH_POST_INIT;
+ val = SETFIELD(PU_ALTD_OPTION_REG_FBC_ALTD_BEFORE_INIT_WAIT_COUNT,
+ val, INIT_SWITCH_WAIT_COUNT);
+ val |= PU_ALTD_OPTION_REG_FBC_ALTD_WITH_FAST_PATH; /* see HW397129, DD2 */
+ rc = xscom_write(gcid, PU_ALTD_OPTION_REG, val);
+ if (rc)
+ goto err_switch;
+
+ /* Set up command */
+ val = PU_ALTD_CMD_REG_FBC_LOCKED;
+ val |= PU_ALTD_CMD_REG_FBC_ALTD_START_OP;
+ val = SETFIELD(PU_ALTD_CMD_REG_FBC_ALTD_SCOPE, val,
+ PU_ALTD_CMD_REG_FBC_ALTD_SCOPE_SYSTEM);
+ val |= PU_ALTD_CMD_REG_FBC_ALTD_DROP_PRIORITY;
+ val |= PU_ALTD_CMD_REG_FBC_ALTD_AXTYPE;
+ val = SETFIELD(PU_ALTD_CMD_REG_FBC_ALTD_TTYPE, val,
+ PU_ALTD_CMD_REG_FBC_ALTD_TTYPE_PMISC_OPER);
+ val |= PU_ALTD_CMD_REG_FBC_ALTD_WITH_TM_QUIESCE;
+ val = SETFIELD(PU_ALTD_CMD_REG_FBC_ALTD_TSIZE, val,
+ PU_ALTD_CMD_REG_FBC_ALTD_TSIZE_PMISC_1);
+ xscom_write(gcid, PU_ALTD_CMD_REG, val);
+
+ /*
+ * TODO: check ADU status is consistent, see
+ * p9_build_smp_adu_check_status() in hostboot
+ */
+
+err_switch:
+ /* Reset switch controls */
+ chip = NULL;
+ while ((chip = next_chip(chip))) {
+ xscom_read(chip->id, PU_SND_MODE_REG, ®);
+ reg &= ~PU_SND_MODE_REG_ENABLE_PB_SWITCH_AB;
+ reg &= ~PU_SND_MODE_REG_ENABLE_PB_SWITCH_CD;
+ xscom_write(chip->id, PU_SND_MODE_REG, reg);
+ }
+
+ /* Reset ADUs */
+ p9_adu_manage_lock(true);
+
+err:
+ /* Unlock */
+ p9_adu_manage_lock(false);
+}
+
+void p9_adu_set_pb_hp_mode(uint32_t gcid, uint64_t val)
+{
+ /* Write next value */
+ xscom_write(gcid, PB_WEST_HP_MODE_NEXT, val);
+ xscom_write(gcid, PB_CENT_HP_MODE_NEXT, val);
+ xscom_write(gcid, PB_EAST_HP_MODE_NEXT, val);
+
+ /* Send switch pulse */
+ p9_adu_switch_ab();
+
+ /* Now that switch is complete, overwrite old value */
+ xscom_write(gcid, PB_WEST_HP_MODE_NEXT, val);
+ xscom_write(gcid, PB_CENT_HP_MODE_NEXT, val);
+ xscom_write(gcid, PB_EAST_HP_MODE_NEXT, val);
+}
diff --git a/include/npu2-regs.h b/include/npu2-regs.h
index b190d0f0767a..b6dae7bb13fd 100644
--- a/include/npu2-regs.h
+++ b/include/npu2-regs.h
@@ -36,8 +36,6 @@ void npu2_scom_write(uint64_t gcid, uint64_t scom_base,
#define MCD_BANK_CN_VALID PPC_BIT(0)
#define MCD_BANK_CN_SIZE PPC_BITMASK(13,29)
#define MCD_BANK_CN_ADDR PPC_BITMASK(33,63)
-#define PB_CENT_HP_MODE_CURR 0x5011c0c
-#define PB_CFG_CHG_RATE_GP_MASTER PPC_BIT(2)
#define PB_CENT_MODE 0x5011c0a
#define PB_CFG_CHIP_ADDR_EXTENSION_MASK_CENT PPC_BITMASK(42,48)
diff --git a/include/p9-adu.h b/include/p9-adu.h
new file mode 100644
index 000000000000..a418a23cb293
--- /dev/null
+++ b/include/p9-adu.h
@@ -0,0 +1,59 @@
+/* Copyright 2013-2018 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+void p9_adu_set_pb_hp_mode(uint32_t gcid, uint64_t val);
+
+#define PU_ALTD_ADDR_REG 0x0090000
+
+#define PU_ALTD_CMD_REG 0x0090001
+#define PU_ALTD_CMD_REG_FBC_ALTD_START_OP PPC_BIT(2)
+#define PU_ALTD_CMD_REG_FBC_ALTD_CLEAR_STATUS PPC_BIT(3)
+#define PU_ALTD_CMD_REG_FBC_ALTD_RESET_FSM PPC_BIT(4)
+#define PU_ALTD_CMD_REG_FBC_ALTD_AXTYPE PPC_BIT(6)
+#define PU_ALTD_CMD_REG_FBC_LOCKED PPC_BIT(11)
+#define PU_ALTD_CMD_REG_FBC_LOCK_ID PPC_BITMASK(12, 15)
+#define PU_ALTD_CMD_REG_FBC_ALTD_SCOPE PPC_BITMASK(16, 18)
+#define PU_ALTD_CMD_REG_FBC_ALTD_SCOPE_SYSTEM 0b101
+#define PU_ALTD_CMD_REG_FBC_ALTD_DROP_PRIORITY PPC_BIT(20)
+#define PU_ALTD_CMD_REG_FBC_ALTD_WITH_TM_QUIESCE PPC_BIT(24)
+#define PU_ALTD_CMD_REG_FBC_ALTD_TTYPE PPC_BITMASK(25, 31)
+#define PU_ALTD_CMD_REG_FBC_ALTD_TTYPE_PMISC_OPER 0b0110001
+#define PU_ALTD_CMD_REG_FBC_ALTD_TSIZE PPC_BITMASK(32, 39)
+#define PU_ALTD_CMD_REG_FBC_ALTD_TSIZE_PMISC_1 0b00000010
+
+#define PU_ALTD_OPTION_REG 0x0090002
+#define PU_ALTD_OPTION_REG_FBC_ALTD_WITH_PRE_QUIESCE PPC_BIT(23)
+#define PU_ALTD_OPTION_REG_FBC_ALTD_AFTER_QUIESCE_WAIT_COUNT PPC_BITMASK(28, 47)
+#define PU_ALTD_OPTION_REG_FBC_ALTD_WITH_POST_INIT PPC_BIT(51)
+#define PU_ALTD_OPTION_REG_FBC_ALTD_WITH_FAST_PATH PPC_BIT(52)
+#define PU_ALTD_OPTION_REG_FBC_ALTD_BEFORE_INIT_WAIT_COUNT PPC_BITMASK(54, 63)
+
+#define QUIESCE_SWITCH_WAIT_COUNT 128
+#define INIT_SWITCH_WAIT_COUNT 128
+
+#define PU_SND_MODE_REG 0x0090021
+#define PU_SND_MODE_REG_ENABLE_PB_SWITCH_AB PPC_BIT(30)
+#define PU_SND_MODE_REG_ENABLE_PB_SWITCH_CD PPC_BIT(31)
+
+/* Hotplug mode registers */
+#define PB_WEST_HP_MODE_NEXT 0x501180B
+#define PB_CENT_HP_MODE_NEXT 0x5011C0B
+#define PB_EAST_HP_MODE_NEXT 0x501200B
+#define PB_WEST_HP_MODE_CURR 0x501180C
+#define PB_CENT_HP_MODE_CURR 0x5011C0C
+#define PB_EAST_HP_MODE_CURR 0x501200C
+#define PB_CFG_MASTER_CHIP PPC_BIT(0)
+#define PB_CFG_CHG_RATE_GP_MASTER PPC_BIT(2)
--
git-series 0.9.1
More information about the Skiboot
mailing list