[4/9] p9-adu: Implement update sequence for PowerBus Hotplug Mode Control

Message ID a9bc6a76329778aadf7b7188c8d4b71342e16e24.1513579137.git-series.andrew.donnellan@au1.ibm.com
State Changes Requested
Headers show
Series
  • Initial OpenCAPI 3.0 Support for P9
Related show

Commit Message

Andrew Donnellan Dec. 18, 2017, 7:07 a.m.
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@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

Comments

Frederic Barrat Jan. 10, 2018, 6:39 p.m. | #1
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@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, &reg);
> +		if (reg & PB_CFG_MASTER_CHIP)
> +			break;
> +	}
> +	return chip->id;


We may want to assert if we don't find the master chip.


> +}
> +
> +/*
> + * 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);
> +		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.

   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);
> +		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 Jan. 11, 2018, 3:37 a.m. | #2
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@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, &reg);
>> +        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);
>> +        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);
>> +        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)
>>

Patch

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, &reg);
+		if (reg & PB_CFG_MASTER_CHIP)
+			break;
+	}
+	return chip->id;
+}
+
+/*
+ * 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);
+		reg |= PU_SND_MODE_REG_ENABLE_PB_SWITCH_AB;
+		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);
+		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)