[Skiboot] [PATCH v5 6/9] hw/slw: split P8 specific code into its own file

Nicholas Piggin npiggin at gmail.com
Mon Dec 20 23:22:49 AEDT 2021


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>
---
 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 */
-- 
2.23.0



More information about the Skiboot mailing list