[Skiboot] [PATCH v5 6/9] hw/slw: split P8 specific code into its own file
Cédric Le Goater
clg at kaod.org
Tue Jan 4 02:32:55 AEDT 2022
On 12/20/21 13:22, Nicholas Piggin wrote:
> POWER8 support is large and significantly different than P9/10 code.
> This change prepares to make P8 support configurable.
>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
Thanks for doing this cleanup. Looks good to me.
C.
> ---
> core/fast-reboot.c | 1 +
> core/init.c | 1 +
> hw/Makefile.inc | 2 +-
> hw/imc.c | 1 +
> hw/nx.c | 1 +
> hw/slw-p8.c | 508 +++++++++++++++++++++++++++++++++++++++++++++
> hw/slw.c | 491 +------------------------------------------
> hw/xive.c | 1 +
> hw/xive2.c | 1 +
> include/skiboot.h | 12 --
> include/slw.h | 48 +++++
> 11 files changed, 574 insertions(+), 493 deletions(-)
> create mode 100644 hw/slw-p8.c
> create mode 100644 include/slw.h
>
> diff --git a/core/fast-reboot.c b/core/fast-reboot.c
> index 2696348af..fedfa88cc 100644
> --- a/core/fast-reboot.c
> +++ b/core/fast-reboot.c
> @@ -6,6 +6,7 @@
> */
>
> #include <skiboot.h>
> +#include <slw.h>
> #include <cpu.h>
> #include <console.h>
> #include <fsp.h>
> diff --git a/core/init.c b/core/init.c
> index c3e0c494d..deead5ecc 100644
> --- a/core/init.c
> +++ b/core/init.c
> @@ -6,6 +6,7 @@
> */
>
> #include <skiboot.h>
> +#include <slw.h>
> #include <psi.h>
> #include <chiptod.h>
> #include <nx.h>
> diff --git a/hw/Makefile.inc b/hw/Makefile.inc
> index 8f509739d..7327cec35 100644
> --- a/hw/Makefile.inc
> +++ b/hw/Makefile.inc
> @@ -10,7 +10,7 @@ HW_OBJS += npu2-common.o npu2-opencapi.o phys-map.o sbe-p9.o capp.o
> HW_OBJS += occ-sensor.o vas.o dio-p9.o lpc-port80h.o cache-p9.o
> HW_OBJS += npu-opal.o ocmb.o xive2.o pau.o pau-hw-procedures.o
> ifeq ($(CONFIG_P8),1)
> -HW_OBJS += phb3.o sbe-p8.o
> +HW_OBJS += phb3.o sbe-p8.o slw-p8.o
> endif
> HW=hw/built-in.a
>
> diff --git a/hw/imc.c b/hw/imc.c
> index cbd68edc4..97e0809f0 100644
> --- a/hw/imc.c
> +++ b/hw/imc.c
> @@ -8,6 +8,7 @@
>
> #define pr_fmt(fmt) "IMC: " fmt
> #include <skiboot.h>
> +#include <slw.h>
> #include <xscom.h>
> #include <imc.h>
> #include <chip.h>
> diff --git a/hw/nx.c b/hw/nx.c
> index fdadf53c7..13c681b2c 100644
> --- a/hw/nx.c
> +++ b/hw/nx.c
> @@ -6,6 +6,7 @@
> */
>
> #include <skiboot.h>
> +#include <slw.h>
> #include <xscom.h>
> #include <io.h>
> #include <cpu.h>
> diff --git a/hw/slw-p8.c b/hw/slw-p8.c
> new file mode 100644
> index 000000000..0a27a8fcc
> --- /dev/null
> +++ b/hw/slw-p8.c
> @@ -0,0 +1,508 @@
> +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
> +
> +#include <skiboot.h>
> +#include <slw.h>
> +#include <xscom.h>
> +#include <xscom-p8-regs.h>
> +#include <cpu.h>
> +#include <chip.h>
> +#include <interrupts.h>
> +#include <timebase.h>
> +#include <errorlog.h>
> +#include <libfdt/libfdt.h>
> +#include <opal-api.h>
> +#include <sbe-p8.h>
> +
> +#include <p8_pore_table_gen_api.H>
> +#include <sbe_xip_image.h>
> +
> +/*
> + * It would be nice to be able to define non-static log entry types and share
> + * these with slw.c
> + */
> +DEFINE_LOG_ENTRY(OPAL_RC_SLW_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> + OPAL_PLATFORM_FIRMWARE, OPAL_PREDICTIVE_ERR_GENERAL,
> + OPAL_NA);
> +
> +DEFINE_LOG_ENTRY(OPAL_RC_SLW_SET, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> + OPAL_PLATFORM_FIRMWARE, OPAL_INFO,
> + OPAL_NA);
> +
> +DEFINE_LOG_ENTRY(OPAL_RC_SLW_GET, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> + OPAL_PLATFORM_FIRMWARE, OPAL_INFO,
> + OPAL_NA);
> +
> +DEFINE_LOG_ENTRY(OPAL_RC_SLW_REG, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> + OPAL_PLATFORM_FIRMWARE, OPAL_INFO,
> + OPAL_NA);
> +
> +static bool slw_general_init(struct proc_chip *chip, struct cpu_thread *c)
> +{
> + uint32_t core = pir_to_core_id(c->pir);
> + uint64_t tmp;
> + int rc;
> +
> + /* PowerManagement GP0 clear PM_DISABLE */
> + rc = xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP0), &tmp);
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> + "SLW: Failed to read PM_GP0\n");
> + return false;
> + }
> + tmp = tmp & ~0x8000000000000000ULL;
> + rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP0), tmp);
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> + "SLW: Failed to write PM_GP0\n");
> + return false;
> + }
> + prlog(PR_TRACE, "SLW: PMGP0 set to 0x%016llx\n", tmp);
> +
> + /* Read back for debug */
> + rc = xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP0), &tmp);
> + if (rc)
> + log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> + "SLW: Failed to re-read PM_GP0. Continuing...\n");
> +
> + prlog(PR_TRACE, "SLW: PMGP0 read 0x%016llx\n", tmp);
> +
> + return true;
> +}
> +
> +static bool slw_set_overrides(struct proc_chip *chip, struct cpu_thread *c)
> +{
> + uint32_t core = pir_to_core_id(c->pir);
> + int rc;
> +
> + rc = xscom_write(chip->id,
> + XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_SPECIAL_WAKEUP_PHYP),
> + 0);
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_SET),
> + "SLW: Failed to write PM_SPECIAL_WAKEUP_PHYP\n");
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static bool slw_set_idle_mode(struct proc_chip *chip, struct cpu_thread *c)
> +{
> + uint32_t core = pir_to_core_id(c->pir);
> + uint64_t tmp;
> + int rc;
> +
> + /*
> + * PM GP1 allows fast/deep mode to be selected independently for sleep
> + * and winkle. Init PM GP1 so that sleep happens in fast mode and
> + * winkle happens in deep mode.
> + * Make use of the OR XSCOM for this since the OCC might be manipulating
> + * the PM_GP1 register as well. Before doing this ensure that the bits
> + * managing idle states are cleared so as to override any bits set at
> + * init time.
> + */
> +
> + tmp = ~EX_PM_GP1_SLEEP_WINKLE_MASK;
> + rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_CLEAR_GP1),
> + tmp);
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_SET),
> + "SLW: Failed to write PM_GP1\n");
> + return false;
> + }
> +
> + rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_SET_GP1),
> + EX_PM_SETUP_GP1_FAST_SLEEP_DEEP_WINKLE);
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_SET),
> + "SLW: Failed to write PM_GP1\n");
> + return false;
> + }
> +
> + /* Read back for debug */
> + xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP1), &tmp);
> + prlog(PR_TRACE, "SLW: PMGP1 read 0x%016llx\n", tmp);
> + return true;
> +}
> +
> +static bool slw_get_idle_state_history(struct proc_chip *chip, struct cpu_thread *c)
> +{
> + uint32_t core = pir_to_core_id(c->pir);
> + uint64_t tmp;
> + int rc;
> +
> + /* Cleanup history */
> + rc = xscom_read(chip->id,
> + XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_IDLE_STATE_HISTORY_PHYP),
> + &tmp);
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_GET),
> + "SLW: Failed to read PM_IDLE_STATE_HISTORY\n");
> + return false;
> + }
> +
> + prlog(PR_TRACE, "SLW: core %x:%x history: 0x%016llx (old1)\n",
> + chip->id, core, tmp);
> +
> + rc = xscom_read(chip->id,
> + XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_IDLE_STATE_HISTORY_PHYP),
> + &tmp);
> +
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_GET),
> + "SLW: Failed to read PM_IDLE_STATE_HISTORY\n");
> + return false;
> + }
> +
> + prlog(PR_TRACE, "SLW: core %x:%x history: 0x%016llx (old2)\n",
> + chip->id, core, tmp);
> +
> + return true;
> +}
> +
> +static bool idle_prepare_core(struct proc_chip *chip, struct cpu_thread *c)
> +{
> + prlog(PR_TRACE, "FASTSLEEP: Prepare core %x:%x\n",
> + chip->id, pir_to_core_id(c->pir));
> +
> + if(!slw_general_init(chip, c))
> + return false;
> + if(!slw_set_overrides(chip, c))
> + return false;
> + if(!slw_set_idle_mode(chip, c))
> + return false;
> + if(!slw_get_idle_state_history(chip, c))
> + return false;
> +
> + return true;
> +
> +}
> +
> +static struct cpu_idle_states nap_only_cpu_idle_states[] = {
> + { /* nap */
> + .name = "nap",
> + .latency_ns = 4000,
> + .residency_ns = 100000,
> + .flags = 0*OPAL_PM_DEC_STOP \
> + | 0*OPAL_PM_TIMEBASE_STOP \
> + | 1*OPAL_PM_LOSE_USER_CONTEXT \
> + | 0*OPAL_PM_LOSE_HYP_CONTEXT \
> + | 0*OPAL_PM_LOSE_FULL_CONTEXT \
> + | 1*OPAL_PM_NAP_ENABLED \
> + | 0*OPAL_PM_SLEEP_ENABLED \
> + | 0*OPAL_PM_WINKLE_ENABLED \
> + | 0*OPAL_USE_PMICR,
> + .pm_ctrl_reg_val = 0,
> + .pm_ctrl_reg_mask = 0 },
> +};
> +
> +static struct cpu_idle_states power8_cpu_idle_states[] = {
> + { /* nap */
> + .name = "nap",
> + .latency_ns = 4000,
> + .residency_ns = 100000,
> + .flags = 0*OPAL_PM_DEC_STOP \
> + | 0*OPAL_PM_TIMEBASE_STOP \
> + | 1*OPAL_PM_LOSE_USER_CONTEXT \
> + | 0*OPAL_PM_LOSE_HYP_CONTEXT \
> + | 0*OPAL_PM_LOSE_FULL_CONTEXT \
> + | 1*OPAL_PM_NAP_ENABLED \
> + | 0*OPAL_USE_PMICR,
> + .pm_ctrl_reg_val = 0,
> + .pm_ctrl_reg_mask = 0 },
> + { /* fast sleep (with workaround) */
> + .name = "fastsleep_",
> + .latency_ns = 40000,
> + .residency_ns = 300000000,
> + .flags = 1*OPAL_PM_DEC_STOP \
> + | 1*OPAL_PM_TIMEBASE_STOP \
> + | 1*OPAL_PM_LOSE_USER_CONTEXT \
> + | 0*OPAL_PM_LOSE_HYP_CONTEXT \
> + | 0*OPAL_PM_LOSE_FULL_CONTEXT \
> + | 1*OPAL_PM_SLEEP_ENABLED_ER1 \
> + | 0*OPAL_USE_PMICR, /* Not enabled until deep
> + states are available */
> + .pm_ctrl_reg_val = OPAL_PM_FASTSLEEP_PMICR,
> + .pm_ctrl_reg_mask = OPAL_PM_SLEEP_PMICR_MASK },
> + { /* Winkle */
> + .name = "winkle",
> + .latency_ns = 10000000,
> + .residency_ns = 1000000000, /* Educated guess (not measured).
> + * Winkle is not currently used by
> + * linux cpuidle subsystem so we
> + * don't have real world user.
> + * However, this should be roughly
> + * accurate for when linux does
> + * use it. */
> + .flags = 1*OPAL_PM_DEC_STOP \
> + | 1*OPAL_PM_TIMEBASE_STOP \
> + | 1*OPAL_PM_LOSE_USER_CONTEXT \
> + | 1*OPAL_PM_LOSE_HYP_CONTEXT \
> + | 1*OPAL_PM_LOSE_FULL_CONTEXT \
> + | 1*OPAL_PM_WINKLE_ENABLED \
> + | 0*OPAL_USE_PMICR, /* Currently choosing deep vs
> + fast via EX_PM_GP1 reg */
> + .pm_ctrl_reg_val = 0,
> + .pm_ctrl_reg_mask = 0 },
> +};
> +
> +void find_cpu_idle_state_properties_p8(struct cpu_idle_states **states,
> + int *nr_states, bool *can_sleep)
> +{
> + struct proc_chip *chip;
> +
> + chip = next_chip(NULL);
> + assert(chip);
> +
> + *can_sleep = true;
> +
> + if (chip->type == PROC_CHIP_P8_MURANO ||
> + chip->type == PROC_CHIP_P8_VENICE ||
> + chip->type == PROC_CHIP_P8_NAPLES) {
> + const struct dt_property *p;
> +
> + p = dt_find_property(dt_root, "ibm,enabled-idle-states");
> + if (p)
> + prlog(PR_NOTICE,
> + "SLW: HB-provided idle states property found\n");
> + *states = power8_cpu_idle_states;
> + *nr_states = ARRAY_SIZE(power8_cpu_idle_states);
> +
> + /* Check if hostboot say we can sleep */
> + if (!p || !dt_prop_find_string(p, "fast-sleep")) {
> + prlog(PR_WARNING, "SLW: Sleep not enabled by HB"
> + " on this platform\n");
> + *can_sleep = false;
> + }
> +
> + /* Clip to NAP only on Murano and Venice DD1.x */
> + if ((chip->type == PROC_CHIP_P8_MURANO ||
> + chip->type == PROC_CHIP_P8_VENICE) &&
> + chip->ec_level < 0x20) {
> + prlog(PR_NOTICE, "SLW: Sleep not enabled on P8 DD1.x\n");
> + *can_sleep = false;
> + }
> +
> + } else {
> + *states = nap_only_cpu_idle_states;
> + *nr_states = ARRAY_SIZE(nap_only_cpu_idle_states);
> + }
> +}
> +
> +static void slw_patch_regs(struct proc_chip *chip)
> +{
> + struct cpu_thread *c;
> + void *image = (void *)chip->slw_base;
> + int rc;
> +
> + for_each_available_cpu(c) {
> + if (c->chip_id != chip->id)
> + continue;
> +
> + /* Clear HRMOR */
> + rc = p8_pore_gen_cpureg_fixed(image, P8_SLW_MODEBUILD_SRAM,
> + P8_SPR_HRMOR, 0,
> + cpu_get_core_index(c),
> + cpu_get_thread_index(c));
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_REG),
> + "SLW: Failed to set HRMOR for CPU %x\n",
> + c->pir);
> + }
> +
> + /* XXX Add HIDs etc... */
> + }
> +}
> +
> +static bool slw_image_check_p8(struct proc_chip *chip)
> +{
> + int64_t rc;
> +
> + prlog(PR_DEBUG, "SLW: slw_check chip 0x%x\n", chip->id);
> + if (!chip->slw_base) {
> + prerror("SLW: No image found !\n");
> + return false;
> + }
> +
> + /* Check actual image size */
> + rc = sbe_xip_get_scalar((void *)chip->slw_base, "image_size",
> + &chip->slw_image_size);
> + if (rc != 0) {
> + log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> + "SLW: Error %lld reading SLW image size\n", rc);
> + /* XXX Panic ? */
> + chip->slw_base = 0;
> + chip->slw_bar_size = 0;
> + chip->slw_image_size = 0;
> + return false;
> + }
> + prlog(PR_DEBUG, "SLW: Image size from image: 0x%llx\n",
> + chip->slw_image_size);
> +
> + if (chip->slw_image_size > chip->slw_bar_size) {
> + log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> + "SLW: Built-in image size larger than BAR size !\n");
> + /* XXX Panic ? */
> + return false;
> + }
> + return true;
> +
> +}
> +
> +static void slw_late_init_p8(struct proc_chip *chip)
> +{
> +
> + prlog(PR_DEBUG, "SLW: late Init chip 0x%x\n", chip->id);
> +
> + /* Patch SLW image */
> + slw_patch_regs(chip);
> +
> +}
> +static void slw_init_chip_p8(struct proc_chip *chip)
> +{
> + struct cpu_thread *c;
> +
> + prlog(PR_DEBUG, "SLW: Init chip 0x%x\n", chip->id);
> + /* At power ON setup inits for fast-sleep */
> + for_each_available_core_in_chip(c, chip->id) {
> + idle_prepare_core(chip, c);
> + }
> +}
> +
> +/* Workarounds while entering fast-sleep */
> +
> +static void fast_sleep_enter(void)
> +{
> + uint32_t core = pir_to_core_id(this_cpu()->pir);
> + uint32_t chip_id = this_cpu()->chip_id;
> + struct cpu_thread *primary_thread;
> + uint64_t tmp;
> + int rc;
> +
> + primary_thread = this_cpu()->primary;
> +
> + rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> + &tmp);
> + if (rc) {
> + prlog(PR_WARNING, "fast_sleep_enter XSCOM failed(1):"
> + " rc=%d chip_id=%d core=%d\n",
> + rc, chip_id, core);
> + return;
> + }
> +
> + primary_thread->save_l2_fir_action1 = tmp;
> + primary_thread->in_fast_sleep = true;
> +
> + tmp = tmp & ~0x0200000000000000ULL;
> + rc = xscom_write(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> + tmp);
> + if (rc) {
> + prlog(PR_WARNING, "fast_sleep_enter XSCOM failed(2):"
> + " rc=%d chip_id=%d core=%d\n",
> + rc, chip_id, core);
> + return;
> + }
> + rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> + &tmp);
> + if (rc) {
> + prlog(PR_WARNING, "fast_sleep_enter XSCOM failed(3):"
> + " rc=%d chip_id=%d core=%d\n",
> + rc, chip_id, core);
> + return;
> + }
> +
> +}
> +
> +/* Workarounds while exiting fast-sleep */
> +
> +void fast_sleep_exit(void)
> +{
> + uint32_t core = pir_to_core_id(this_cpu()->pir);
> + uint32_t chip_id = this_cpu()->chip_id;
> + struct cpu_thread *primary_thread;
> + int rc;
> +
> + primary_thread = this_cpu()->primary;
> + primary_thread->in_fast_sleep = false;
> +
> + rc = xscom_write(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> + primary_thread->save_l2_fir_action1);
> + if (rc) {
> + prlog(PR_WARNING, "fast_sleep_exit XSCOM failed:"
> + " rc=%d chip_id=%d core=%d\n",
> + rc, chip_id, core);
> + return;
> + }
> +}
> +
> +/*
> + * Setup and cleanup method for fast-sleep workarounds
> + * state = 1 fast-sleep
> + * enter = 1 Enter state
> + * exit = 0 Exit state
> + */
> +
> +static int64_t opal_config_cpu_idle_state(uint64_t state, uint64_t enter)
> +{
> + /* Only fast-sleep for now */
> + if (state != 1)
> + return OPAL_PARAMETER;
> +
> + switch(enter) {
> + case 1:
> + fast_sleep_enter();
> + break;
> + case 0:
> + fast_sleep_exit();
> + break;
> + default:
> + return OPAL_PARAMETER;
> + }
> +
> + return OPAL_SUCCESS;
> +}
> +
> +opal_call(OPAL_CONFIG_CPU_IDLE_STATE, opal_config_cpu_idle_state, 2);
> +
> +int64_t opal_slw_set_reg_p8(struct cpu_thread *c, struct proc_chip *chip,
> + uint64_t sprn, uint64_t val)
> +{
> + int spr_is_supported = 0;
> + void *image;
> + int i;
> + int rc;
> +
> + /* Check of the SPR is supported by libpore */
> + for (i = 0; i < SLW_SPR_REGS_SIZE ; i++) {
> + if (sprn == SLW_SPR_REGS[i].value) {
> + spr_is_supported = 1;
> + break;
> + }
> + }
> + if (!spr_is_supported) {
> + log_simple_error(&e_info(OPAL_RC_SLW_REG),
> + "SLW: Trying to set unsupported spr for CPU %x\n",
> + c->pir);
> + return OPAL_UNSUPPORTED;
> + }
> + image = (void *)chip->slw_base;
> + rc = p8_pore_gen_cpureg_fixed(image, P8_SLW_MODEBUILD_SRAM,
> + sprn, val,
> + cpu_get_core_index(c),
> + cpu_get_thread_index(c));
> + return rc;
> +}
> +
> +void slw_p8_init(void)
> +{
> + struct proc_chip *chip;
> +
> + for_each_chip(chip) {
> + slw_init_chip_p8(chip);
> + if (slw_image_check_p8(chip))
> + wakeup_engine_state = WAKEUP_ENGINE_PRESENT;
> + if (wakeup_engine_state == WAKEUP_ENGINE_PRESENT)
> + slw_late_init_p8(chip);
> + }
> + p8_sbe_init_timer();
> +}
> diff --git a/hw/slw.c b/hw/slw.c
> index bc53960b7..6d7c8619c 100644
> --- a/hw/slw.c
> +++ b/hw/slw.c
> @@ -7,8 +7,8 @@
> */
>
> #include <skiboot.h>
> +#include <slw.h>
> #include <xscom.h>
> -#include <xscom-p8-regs.h>
> #include <xscom-p9-regs.h>
> #include <xscom-p10-regs.h>
> #include <io.h>
> @@ -22,12 +22,10 @@
> #include <libfdt/libfdt.h>
> #include <opal-api.h>
> #include <nvram.h>
> -#include <sbe-p8.h>
> #include <xive.h>
>
> #include <p10_stop_api.H>
> -#include <p8_pore_table_gen_api.H>
> -#include <sbe_xip_image.h>
> +//#include <sbe_xip_image.h>
>
> enum wakeup_engine_states wakeup_engine_state = WAKEUP_ENGINE_NOT_PRESENT;
> bool has_deep_states = false;
> @@ -40,158 +38,6 @@ DEFINE_LOG_ENTRY(OPAL_RC_SLW_REG, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> OPAL_PLATFORM_FIRMWARE, OPAL_INFO,
> OPAL_NA);
>
> -#ifdef CONFIG_P8
> -DEFINE_LOG_ENTRY(OPAL_RC_SLW_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> - OPAL_PLATFORM_FIRMWARE, OPAL_PREDICTIVE_ERR_GENERAL,
> - OPAL_NA);
> -
> -DEFINE_LOG_ENTRY(OPAL_RC_SLW_GET, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> - OPAL_PLATFORM_FIRMWARE, OPAL_INFO,
> - OPAL_NA);
> -
> -static bool slw_general_init(struct proc_chip *chip, struct cpu_thread *c)
> -{
> - uint32_t core = pir_to_core_id(c->pir);
> - uint64_t tmp;
> - int rc;
> -
> - /* PowerManagement GP0 clear PM_DISABLE */
> - rc = xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP0), &tmp);
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> - "SLW: Failed to read PM_GP0\n");
> - return false;
> - }
> - tmp = tmp & ~0x8000000000000000ULL;
> - rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP0), tmp);
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> - "SLW: Failed to write PM_GP0\n");
> - return false;
> - }
> - prlog(PR_TRACE, "SLW: PMGP0 set to 0x%016llx\n", tmp);
> -
> - /* Read back for debug */
> - rc = xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP0), &tmp);
> - if (rc)
> - log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> - "SLW: Failed to re-read PM_GP0. Continuing...\n");
> -
> - prlog(PR_TRACE, "SLW: PMGP0 read 0x%016llx\n", tmp);
> -
> - return true;
> -}
> -
> -static bool slw_set_overrides(struct proc_chip *chip, struct cpu_thread *c)
> -{
> - uint32_t core = pir_to_core_id(c->pir);
> - int rc;
> -
> - rc = xscom_write(chip->id,
> - XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_SPECIAL_WAKEUP_PHYP),
> - 0);
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_SET),
> - "SLW: Failed to write PM_SPECIAL_WAKEUP_PHYP\n");
> - return false;
> - }
> -
> - return true;
> -}
> -
> -static bool slw_set_idle_mode(struct proc_chip *chip, struct cpu_thread *c)
> -{
> - uint32_t core = pir_to_core_id(c->pir);
> - uint64_t tmp;
> - int rc;
> -
> - /*
> - * PM GP1 allows fast/deep mode to be selected independently for sleep
> - * and winkle. Init PM GP1 so that sleep happens in fast mode and
> - * winkle happens in deep mode.
> - * Make use of the OR XSCOM for this since the OCC might be manipulating
> - * the PM_GP1 register as well. Before doing this ensure that the bits
> - * managing idle states are cleared so as to override any bits set at
> - * init time.
> - */
> -
> - tmp = ~EX_PM_GP1_SLEEP_WINKLE_MASK;
> - rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_CLEAR_GP1),
> - tmp);
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_SET),
> - "SLW: Failed to write PM_GP1\n");
> - return false;
> - }
> -
> - rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_SET_GP1),
> - EX_PM_SETUP_GP1_FAST_SLEEP_DEEP_WINKLE);
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_SET),
> - "SLW: Failed to write PM_GP1\n");
> - return false;
> - }
> -
> - /* Read back for debug */
> - xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP1), &tmp);
> - prlog(PR_TRACE, "SLW: PMGP1 read 0x%016llx\n", tmp);
> - return true;
> -}
> -
> -static bool slw_get_idle_state_history(struct proc_chip *chip, struct cpu_thread *c)
> -{
> - uint32_t core = pir_to_core_id(c->pir);
> - uint64_t tmp;
> - int rc;
> -
> - /* Cleanup history */
> - rc = xscom_read(chip->id,
> - XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_IDLE_STATE_HISTORY_PHYP),
> - &tmp);
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_GET),
> - "SLW: Failed to read PM_IDLE_STATE_HISTORY\n");
> - return false;
> - }
> -
> - prlog(PR_TRACE, "SLW: core %x:%x history: 0x%016llx (old1)\n",
> - chip->id, core, tmp);
> -
> - rc = xscom_read(chip->id,
> - XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_IDLE_STATE_HISTORY_PHYP),
> - &tmp);
> -
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_GET),
> - "SLW: Failed to read PM_IDLE_STATE_HISTORY\n");
> - return false;
> - }
> -
> - prlog(PR_TRACE, "SLW: core %x:%x history: 0x%016llx (old2)\n",
> - chip->id, core, tmp);
> -
> - return true;
> -}
> -
> -static bool idle_prepare_core(struct proc_chip *chip, struct cpu_thread *c)
> -{
> - prlog(PR_TRACE, "FASTSLEEP: Prepare core %x:%x\n",
> - chip->id, pir_to_core_id(c->pir));
> -
> - if(!slw_general_init(chip, c))
> - return false;
> - if(!slw_set_overrides(chip, c))
> - return false;
> - if(!slw_set_idle_mode(chip, c))
> - return false;
> - if(!slw_get_idle_state_history(chip, c))
> - return false;
> -
> - return true;
> -
> -}
> -#endif
> -
> static bool slw_set_overrides_p10(struct proc_chip *chip, struct cpu_thread *c)
> {
> uint64_t tmp;
> @@ -245,89 +91,6 @@ static bool slw_set_overrides_p9(struct proc_chip *chip, struct cpu_thread *c)
> return true;
> }
>
> -/* Define device-tree fields */
> -#define MAX_NAME_LEN 16
> -struct cpu_idle_states {
> - char name[MAX_NAME_LEN];
> - u32 latency_ns;
> - u32 residency_ns;
> - /*
> - * Register value/mask used to select different idle states.
> - * PMICR in POWER8 and PSSCR in POWER9
> - */
> - u64 pm_ctrl_reg_val;
> - u64 pm_ctrl_reg_mask;
> - u32 flags;
> -};
> -
> -static struct cpu_idle_states nap_only_cpu_idle_states[] = {
> - { /* nap */
> - .name = "nap",
> - .latency_ns = 4000,
> - .residency_ns = 100000,
> - .flags = 0*OPAL_PM_DEC_STOP \
> - | 0*OPAL_PM_TIMEBASE_STOP \
> - | 1*OPAL_PM_LOSE_USER_CONTEXT \
> - | 0*OPAL_PM_LOSE_HYP_CONTEXT \
> - | 0*OPAL_PM_LOSE_FULL_CONTEXT \
> - | 1*OPAL_PM_NAP_ENABLED \
> - | 0*OPAL_PM_SLEEP_ENABLED \
> - | 0*OPAL_PM_WINKLE_ENABLED \
> - | 0*OPAL_USE_PMICR,
> - .pm_ctrl_reg_val = 0,
> - .pm_ctrl_reg_mask = 0 },
> -};
> -
> -static struct cpu_idle_states power8_cpu_idle_states[] = {
> - { /* nap */
> - .name = "nap",
> - .latency_ns = 4000,
> - .residency_ns = 100000,
> - .flags = 0*OPAL_PM_DEC_STOP \
> - | 0*OPAL_PM_TIMEBASE_STOP \
> - | 1*OPAL_PM_LOSE_USER_CONTEXT \
> - | 0*OPAL_PM_LOSE_HYP_CONTEXT \
> - | 0*OPAL_PM_LOSE_FULL_CONTEXT \
> - | 1*OPAL_PM_NAP_ENABLED \
> - | 0*OPAL_USE_PMICR,
> - .pm_ctrl_reg_val = 0,
> - .pm_ctrl_reg_mask = 0 },
> - { /* fast sleep (with workaround) */
> - .name = "fastsleep_",
> - .latency_ns = 40000,
> - .residency_ns = 300000000,
> - .flags = 1*OPAL_PM_DEC_STOP \
> - | 1*OPAL_PM_TIMEBASE_STOP \
> - | 1*OPAL_PM_LOSE_USER_CONTEXT \
> - | 0*OPAL_PM_LOSE_HYP_CONTEXT \
> - | 0*OPAL_PM_LOSE_FULL_CONTEXT \
> - | 1*OPAL_PM_SLEEP_ENABLED_ER1 \
> - | 0*OPAL_USE_PMICR, /* Not enabled until deep
> - states are available */
> - .pm_ctrl_reg_val = OPAL_PM_FASTSLEEP_PMICR,
> - .pm_ctrl_reg_mask = OPAL_PM_SLEEP_PMICR_MASK },
> - { /* Winkle */
> - .name = "winkle",
> - .latency_ns = 10000000,
> - .residency_ns = 1000000000, /* Educated guess (not measured).
> - * Winkle is not currently used by
> - * linux cpuidle subsystem so we
> - * don't have real world user.
> - * However, this should be roughly
> - * accurate for when linux does
> - * use it. */
> - .flags = 1*OPAL_PM_DEC_STOP \
> - | 1*OPAL_PM_TIMEBASE_STOP \
> - | 1*OPAL_PM_LOSE_USER_CONTEXT \
> - | 1*OPAL_PM_LOSE_HYP_CONTEXT \
> - | 1*OPAL_PM_LOSE_FULL_CONTEXT \
> - | 1*OPAL_PM_WINKLE_ENABLED \
> - | 0*OPAL_USE_PMICR, /* Currently choosing deep vs
> - fast via EX_PM_GP1 reg */
> - .pm_ctrl_reg_val = 0,
> - .pm_ctrl_reg_mask = 0 },
> -};
> -
> /*
> * cpu_idle_states for key idle states of POWER9 that we want to
> * exploit.
> @@ -796,9 +559,9 @@ static void slw_late_init_p10(struct proc_chip *chip)
> void add_cpu_idle_state_properties(void)
> {
> struct dt_node *power_mgt;
> - struct cpu_idle_states *states;
> + struct cpu_idle_states *states = NULL;
> struct proc_chip *chip;
> - int nr_states;
> + int nr_states = 0;
>
> bool can_sleep = true;
> bool has_stop_inst = false;
> @@ -897,39 +660,12 @@ void add_cpu_idle_state_properties(void)
> }
> if (wakeup_engine_state != WAKEUP_ENGINE_PRESENT)
> has_deep_states = false;
> - } else if (chip->type == PROC_CHIP_P8_MURANO ||
> - chip->type == PROC_CHIP_P8_VENICE ||
> - chip->type == PROC_CHIP_P8_NAPLES) {
> - const struct dt_property *p;
> -
> - p = dt_find_property(dt_root, "ibm,enabled-idle-states");
> - if (p)
> - prlog(PR_NOTICE,
> - "SLW: HB-provided idle states property found\n");
> - states = power8_cpu_idle_states;
> - nr_states = ARRAY_SIZE(power8_cpu_idle_states);
> -
> - /* Check if hostboot say we can sleep */
> - if (!p || !dt_prop_find_string(p, "fast-sleep")) {
> - prlog(PR_WARNING, "SLW: Sleep not enabled by HB"
> - " on this platform\n");
> - can_sleep = false;
> - }
> -
> - /* Clip to NAP only on Murano and Venice DD1.x */
> - if ((chip->type == PROC_CHIP_P8_MURANO ||
> - chip->type == PROC_CHIP_P8_VENICE) &&
> - chip->ec_level < 0x20) {
> - prlog(PR_NOTICE, "SLW: Sleep not enabled on P8 DD1.x\n");
> - can_sleep = false;
> - }
> -
> +#ifdef CONFIG_P8
> } else {
> - states = nap_only_cpu_idle_states;
> - nr_states = ARRAY_SIZE(nap_only_cpu_idle_states);
> + find_cpu_idle_state_properties_p8(&states, &nr_states, &can_sleep);
> +#endif
> }
>
> -
> /*
> * Currently we can't append strings and cells to dt properties.
> * So create buffers to which you can append values, then create
> @@ -1112,183 +848,6 @@ static bool slw_image_check_p9(struct proc_chip *chip)
>
> }
>
> -#ifdef CONFIG_P8
> -static void slw_patch_regs(struct proc_chip *chip)
> -{
> - struct cpu_thread *c;
> - void *image = (void *)chip->slw_base;
> - int rc;
> -
> - for_each_available_cpu(c) {
> - if (c->chip_id != chip->id)
> - continue;
> -
> - /* Clear HRMOR */
> - rc = p8_pore_gen_cpureg_fixed(image, P8_SLW_MODEBUILD_SRAM,
> - P8_SPR_HRMOR, 0,
> - cpu_get_core_index(c),
> - cpu_get_thread_index(c));
> - if (rc) {
> - log_simple_error(&e_info(OPAL_RC_SLW_REG),
> - "SLW: Failed to set HRMOR for CPU %x\n",
> - c->pir);
> - }
> -
> - /* XXX Add HIDs etc... */
> - }
> -}
> -
> -static bool slw_image_check_p8(struct proc_chip *chip)
> -{
> - int64_t rc;
> -
> - prlog(PR_DEBUG, "SLW: slw_check chip 0x%x\n", chip->id);
> - if (!chip->slw_base) {
> - prerror("SLW: No image found !\n");
> - return false;
> - }
> -
> - /* Check actual image size */
> - rc = sbe_xip_get_scalar((void *)chip->slw_base, "image_size",
> - &chip->slw_image_size);
> - if (rc != 0) {
> - log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> - "SLW: Error %lld reading SLW image size\n", rc);
> - /* XXX Panic ? */
> - chip->slw_base = 0;
> - chip->slw_bar_size = 0;
> - chip->slw_image_size = 0;
> - return false;
> - }
> - prlog(PR_DEBUG, "SLW: Image size from image: 0x%llx\n",
> - chip->slw_image_size);
> -
> - if (chip->slw_image_size > chip->slw_bar_size) {
> - log_simple_error(&e_info(OPAL_RC_SLW_INIT),
> - "SLW: Built-in image size larger than BAR size !\n");
> - /* XXX Panic ? */
> - return false;
> - }
> - return true;
> -
> -}
> -
> -static void slw_late_init_p8(struct proc_chip *chip)
> -{
> -
> - prlog(PR_DEBUG, "SLW: late Init chip 0x%x\n", chip->id);
> -
> - /* Patch SLW image */
> - slw_patch_regs(chip);
> -
> -}
> -static void slw_init_chip_p8(struct proc_chip *chip)
> -{
> - struct cpu_thread *c;
> -
> - prlog(PR_DEBUG, "SLW: Init chip 0x%x\n", chip->id);
> - /* At power ON setup inits for fast-sleep */
> - for_each_available_core_in_chip(c, chip->id) {
> - idle_prepare_core(chip, c);
> - }
> -}
> -
> -/* Workarounds while entering fast-sleep */
> -
> -static void fast_sleep_enter(void)
> -{
> - uint32_t core = pir_to_core_id(this_cpu()->pir);
> - uint32_t chip_id = this_cpu()->chip_id;
> - struct cpu_thread *primary_thread;
> - uint64_t tmp;
> - int rc;
> -
> - primary_thread = this_cpu()->primary;
> -
> - rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> - &tmp);
> - if (rc) {
> - prlog(PR_WARNING, "fast_sleep_enter XSCOM failed(1):"
> - " rc=%d chip_id=%d core=%d\n",
> - rc, chip_id, core);
> - return;
> - }
> -
> - primary_thread->save_l2_fir_action1 = tmp;
> - primary_thread->in_fast_sleep = true;
> -
> - tmp = tmp & ~0x0200000000000000ULL;
> - rc = xscom_write(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> - tmp);
> - if (rc) {
> - prlog(PR_WARNING, "fast_sleep_enter XSCOM failed(2):"
> - " rc=%d chip_id=%d core=%d\n",
> - rc, chip_id, core);
> - return;
> - }
> - rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> - &tmp);
> - if (rc) {
> - prlog(PR_WARNING, "fast_sleep_enter XSCOM failed(3):"
> - " rc=%d chip_id=%d core=%d\n",
> - rc, chip_id, core);
> - return;
> - }
> -
> -}
> -
> -/* Workarounds while exiting fast-sleep */
> -
> -void fast_sleep_exit(void)
> -{
> - uint32_t core = pir_to_core_id(this_cpu()->pir);
> - uint32_t chip_id = this_cpu()->chip_id;
> - struct cpu_thread *primary_thread;
> - int rc;
> -
> - primary_thread = this_cpu()->primary;
> - primary_thread->in_fast_sleep = false;
> -
> - rc = xscom_write(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1),
> - primary_thread->save_l2_fir_action1);
> - if (rc) {
> - prlog(PR_WARNING, "fast_sleep_exit XSCOM failed:"
> - " rc=%d chip_id=%d core=%d\n",
> - rc, chip_id, core);
> - return;
> - }
> -}
> -
> -/*
> - * Setup and cleanup method for fast-sleep workarounds
> - * state = 1 fast-sleep
> - * enter = 1 Enter state
> - * exit = 0 Exit state
> - */
> -
> -static int64_t opal_config_cpu_idle_state(uint64_t state, uint64_t enter)
> -{
> - /* Only fast-sleep for now */
> - if (state != 1)
> - return OPAL_PARAMETER;
> -
> - switch(enter) {
> - case 1:
> - fast_sleep_enter();
> - break;
> - case 0:
> - fast_sleep_exit();
> - break;
> - default:
> - return OPAL_PARAMETER;
> - }
> -
> - return OPAL_SUCCESS;
> -}
> -
> -opal_call(OPAL_CONFIG_CPU_IDLE_STATE, opal_config_cpu_idle_state, 2);
> -#endif
> -
> int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val)
> {
>
> @@ -1330,28 +889,7 @@ int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val)
>
> #ifdef CONFIG_P8
> } else if (proc_gen == proc_gen_p8) {
> - int spr_is_supported = 0;
> - void *image;
> - int i;
> -
> - /* Check of the SPR is supported by libpore */
> - for (i = 0; i < SLW_SPR_REGS_SIZE ; i++) {
> - if (sprn == SLW_SPR_REGS[i].value) {
> - spr_is_supported = 1;
> - break;
> - }
> - }
> - if (!spr_is_supported) {
> - log_simple_error(&e_info(OPAL_RC_SLW_REG),
> - "SLW: Trying to set unsupported spr for CPU %x\n",
> - c->pir);
> - return OPAL_UNSUPPORTED;
> - }
> - image = (void *)chip->slw_base;
> - rc = p8_pore_gen_cpureg_fixed(image, P8_SLW_MODEBUILD_SRAM,
> - sprn, val,
> - cpu_get_core_index(c),
> - cpu_get_thread_index(c));
> + rc = opal_slw_set_reg_p8(c, chip, sprn, val);
> #endif
> } else {
> log_simple_error(&e_info(OPAL_RC_SLW_REG),
> @@ -1386,18 +924,11 @@ void slw_init(void)
> return;
> }
>
> - if (proc_gen == proc_gen_p8) {
> #ifdef CONFIG_P8
> - for_each_chip(chip) {
> - slw_init_chip_p8(chip);
> - if(slw_image_check_p8(chip))
> - wakeup_engine_state = WAKEUP_ENGINE_PRESENT;
> - if (wakeup_engine_state == WAKEUP_ENGINE_PRESENT)
> - slw_late_init_p8(chip);
> - }
> - p8_sbe_init_timer();
> + if (proc_gen == proc_gen_p8)
> + slw_p8_init();
> #endif
> - } else if (proc_gen == proc_gen_p9) {
> + if (proc_gen == proc_gen_p9) {
> for_each_chip(chip) {
> slw_init_chip_p9(chip);
> if(slw_image_check_p9(chip))
> diff --git a/hw/xive.c b/hw/xive.c
> index 51b03549a..34b92f1e9 100644
> --- a/hw/xive.c
> +++ b/hw/xive.c
> @@ -7,6 +7,7 @@
> */
>
> #include <skiboot.h>
> +#include <slw.h>
> #include <xscom.h>
> #include <chip.h>
> #include <io.h>
> diff --git a/hw/xive2.c b/hw/xive2.c
> index 30293cdf1..ea55423bb 100644
> --- a/hw/xive2.c
> +++ b/hw/xive2.c
> @@ -9,6 +9,7 @@
> #define pr_fmt(fmt) "XIVE: " fmt
>
> #include <skiboot.h>
> +#include <slw.h>
> #include <xscom.h>
> #include <chip.h>
> #include <io.h>
> diff --git a/include/skiboot.h b/include/skiboot.h
> index e2a1b5fc6..db08f45f4 100644
> --- a/include/skiboot.h
> +++ b/include/skiboot.h
> @@ -216,7 +216,6 @@ extern void uart_init(void);
> extern void mbox_init(void);
> extern void early_uart_init(void);
> extern void homer_init(void);
> -extern void slw_init(void);
> extern void add_cpu_idle_state_properties(void);
> extern void lpc_rtc_init(void);
>
> @@ -303,19 +302,8 @@ extern int prd_hbrt_fsp_msg_notify(void *data, u32 dsize);
> /* Flatten device-tree */
> extern void *create_dtb(const struct dt_node *root, bool exclusive);
>
> -/* Track failure in Wakup engine */
> -enum wakeup_engine_states {
> - WAKEUP_ENGINE_NOT_PRESENT,
> - WAKEUP_ENGINE_PRESENT,
> - WAKEUP_ENGINE_FAILED
> -};
> -extern enum wakeup_engine_states wakeup_engine_state;
> -extern bool has_deep_states;
> extern void nx_p9_rng_late_init(void);
>
> -/* Patch SPR in SLW image */
> -extern int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
> -
> extern void fast_sleep_exit(void);
>
> /* Fallback fake RTC */
> diff --git a/include/slw.h b/include/slw.h
> new file mode 100644
> index 000000000..299cbf191
> --- /dev/null
> +++ b/include/slw.h
> @@ -0,0 +1,48 @@
> +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
> +
> +#ifndef __SLW_H
> +#define __SLW_H
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +#include <ccan/short_types/short_types.h>
> +
> +/* Define device-tree fields */
> +#define MAX_NAME_LEN 16
> +struct cpu_idle_states {
> + char name[MAX_NAME_LEN];
> + u32 latency_ns;
> + u32 residency_ns;
> + /*
> + * Register value/mask used to select different idle states.
> + * PMICR in POWER8 and PSSCR in POWER9
> + */
> + u64 pm_ctrl_reg_val;
> + u64 pm_ctrl_reg_mask;
> + u32 flags;
> +};
> +
> +/* Track failure in Wakup engine */
> +enum wakeup_engine_states {
> + WAKEUP_ENGINE_NOT_PRESENT,
> + WAKEUP_ENGINE_PRESENT,
> + WAKEUP_ENGINE_FAILED
> +};
> +extern enum wakeup_engine_states wakeup_engine_state;
> +extern bool has_deep_states;
> +
> +/* Patch SPR in SLW image */
> +extern int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
> +
> +extern void slw_init(void);
> +
> +/* P8 specific */
> +struct cpu_thread;
> +struct proc_chip;
> +extern int64_t opal_slw_set_reg_p8(struct cpu_thread *c, struct proc_chip *chip,
> + uint64_t sprn, uint64_t val);
> +extern void slw_p8_init(void);
> +extern void find_cpu_idle_state_properties_p8(struct cpu_idle_states **states, int *nr_states, bool *can_sleep);
> +
> +#endif /* __SKIBOOT_H */
>
More information about the Skiboot
mailing list