[Skiboot] [PATCH 4/9] p9-adu: Implement update sequence for PowerBus Hotplug Mode Control
Andrew Donnellan
andrew.donnellan at au1.ibm.com
Thu Jan 11 14:37:36 AEDT 2018
On 11/01/18 05:39, Frederic Barrat wrote:
>
> Le 18/12/2017 à 08:07, Andrew Donnellan a écrit :
>> 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>
>> ---
>> hw/Makefile.inc | 2 +-
>> hw/npu2.c | 1 +-
>> hw/p9-adu.c | 182
>> +++++++++++++++++++++++++++++++++++++++++++++-
>> include/npu2-regs.h | 2 +-
>> include/p9-adu.h | 58 ++++++++++++++-
>> 5 files changed, 242 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 cf8649d..27d8a38 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 1d7b936..12d239a 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 0000000..b2b6287
>> --- /dev/null
>> +++ b/hw/p9-adu.c
>> @@ -0,0 +1,182 @@
>> +/* Copyright 2013-2017 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)
>> + break;
>> + }
>> + return chip->id;
>
>
> We may want to assert if we don't find the master chip.
Good point
>
>
>> +}
>> +
>> +/*
>> + * 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;
>
> I found the cronus sequence we're supposed to mimic in an old email and
> this should match:
>
> # configure all chips for AB switch
> putscom pu 090021 30 2 10 -ib -all
>
> However, here we are not clearing bit 31?
>
> Hostboot also seems to always define both bits (to 0b01 in our case), so
> it should be safer (see p9_build_smp_adu_set_switch_action())
>
> The meaning of the bits is in the big scom list, but doesn't help me much.
>
> Same comment applies on the reset a few lines below. The rest of the
> function looks good.
I don't think we'll ever run into a problem here but I'll clear that
just in case. We only need a SWITCH_AB, no idea what a SWITCH_CD does...
Andrew
>
> Fred
>
>
>> + 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;
>> + 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 cf74431..27956f2 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 0000000..1505704
>> --- /dev/null
>> +++ b/include/p9-adu.h
>> @@ -0,0 +1,58 @@
>> +/* Copyright 2013-2017 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)
>> +
>> +/* 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)
>>
--
Andrew Donnellan OzLabs, ADL Canberra
andrew.donnellan at au1.ibm.com IBM Australia Limited
More information about the Skiboot
mailing list