aboutsummaryrefslogtreecommitdiff
path: root/hw/slw.c
diff options
context:
space:
mode:
authorAkshay Adiga <akshay.adiga@linux.vnet.ibm.com>2017-03-24 20:01:49 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-03-30 19:37:48 +1100
commitc3e405b3b1e0c47efbbf31ce37ea02e9a1e005e3 (patch)
tree5f7580b592aae8f7ef8a7d2051950166c6bb4c86 /hw/slw.c
parentd95ffaa6fac5b0094cb473ad6bbc8923ce4107d7 (diff)
downloadskiboot-c3e405b3b1e0c47efbbf31ce37ea02e9a1e005e3.zip
skiboot-c3e405b3b1e0c47efbbf31ce37ea02e9a1e005e3.tar.gz
skiboot-c3e405b3b1e0c47efbbf31ce37ea02e9a1e005e3.tar.bz2
SLW: Add init for power9 power management
This patch adds new function to init core for power9 power management. SPECIAL_WKUP_* SCOM registers, if set, can hold the cores from going into idle states. Hence, clear PPM_SPECIAL_WKUP_HYP_REG scom register for each core during init. (This init are not required for MAMBO) Signed-off-by: Akshay Adiga <akshay.adiga@linux.vnet.ibm.com> Reviewed-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/slw.c')
-rw-r--r--hw/slw.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/hw/slw.c b/hw/slw.c
index a1d3eca..6503fa7 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -287,6 +287,39 @@ static bool slw_set_overrides(struct proc_chip *chip, struct cpu_thread *c)
return true;
}
+static bool slw_set_overrides_p9(struct proc_chip *chip, struct cpu_thread *c)
+{
+ uint64_t tmp;
+ int rc;
+ uint32_t core = pir_to_core_id(c->pir);
+
+ /* MAMBO does not require this init */
+ if (proc_chip_quirks & QUIRK_MAMBO_CALLOUTS) {
+ return true;
+ }
+
+ /* Clear special wakeup bits that could hold power mgt */
+ rc = xscom_write(chip->id,
+ XSCOM_ADDR_P9_EC_SLAVE(core, EC_PPM_SPECIAL_WKUP_HYP),
+ 0);
+ if (rc) {
+ log_simple_error(&e_info(OPAL_RC_SLW_SET),
+ "SLW: Failed to write EC_PPM_SPECIAL_WKUP_HYP\n");
+ return false;
+ }
+ /* Read back for debug */
+ rc = xscom_read(chip->id,
+ XSCOM_ADDR_P9_EC_SLAVE(core, EC_PPM_SPECIAL_WKUP_HYP),
+ &tmp);
+ prlog(PR_NOTICE, "SLW: EC_PPM_SPECIAL_WKUP_HYP read 0x%016llx\n", tmp);
+ rc = xscom_read(chip->id,
+ XSCOM_ADDR_P9_EC_SLAVE(core, EC_PPM_SPECIAL_WKUP_OTR),
+ &tmp);
+ if (tmp)
+ prlog(PR_WARNING, "SLW: EC_PPM_SPECIAL_WKUP_OTR read 0x%016llx\n", tmp);
+ return true;
+}
+
#ifdef __HAVE_LIBPORE__
static bool slw_unset_overrides(struct proc_chip *chip, struct cpu_thread *c)
{
@@ -1128,6 +1161,16 @@ static void slw_patch_regs(struct proc_chip *chip)
}
#endif /* __HAVE_LIBPORE__ */
+static void slw_init_chip_p9(struct proc_chip *chip)
+{
+ struct cpu_thread *c;
+
+ prlog(PR_NOTICE, "SLW: Init chip 0x%x\n", chip->id);
+
+ /* At power ON setup inits for power-mgt */
+ for_each_available_core_in_chip(c, chip->id)
+ slw_set_overrides_p9(chip, c);
+}
static void slw_init_chip(struct proc_chip *chip)
{
int64_t rc;
@@ -1493,11 +1536,12 @@ void slw_init(void)
{
struct proc_chip *chip;
- if (proc_gen != proc_gen_p8)
- return;
-
- for_each_chip(chip)
- slw_init_chip(chip);
-
- slw_init_timer();
+ if (proc_gen == proc_gen_p8) {
+ for_each_chip(chip)
+ slw_init_chip(chip);
+ slw_init_timer();
+ } else if (proc_gen == proc_gen_p9) {
+ for_each_chip(chip)
+ slw_init_chip_p9(chip);
+ }
}