diff options
author | Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> | 2014-07-29 10:53:30 +0530 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-07-30 10:56:17 +1000 |
commit | d5aed5be5a63f991b80458b3a8eedaa26e203639 (patch) | |
tree | d8a0629f9e3419478acbcb204fe2a49bce96221f /hw | |
parent | a02875504d6c182ec27fd29638f0451bfa13b969 (diff) | |
download | skiboot-d5aed5be5a63f991b80458b3a8eedaa26e203639.zip skiboot-d5aed5be5a63f991b80458b3a8eedaa26e203639.tar.gz skiboot-d5aed5be5a63f991b80458b3a8eedaa26e203639.tar.bz2 |
sleep: Add workarounds for fast sleep
Add OPAL calls to setup xscom before and after sleep
V1:https://w3-01.ibm.com/stg/linux/ltc/mailinglists/pipermail/sapphire/2014-July/003170.html
Changes in V2:
1.Store L2 Fir Action register contents in primary thread's pointer
2.Enable secondary threads also to call opal, now that the synchronization
across threads of a core will be taken care of by the kernel. We can
hence safely call fastsleep in smt on mode.
Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/slw.c | 89 |
1 files changed, 88 insertions, 1 deletions
@@ -527,7 +527,7 @@ void add_cpu_idle_state_properties(void) /* Check if hostboot say we can sleep */ if (p && !dt_prop_find_string(p, "fastsleep")) - can_sleep = false; + can_sleep = true; /* Clip to NAP only on Murano DD1.x */ if (chip->type == PROC_CHIP_P8_MURANO && @@ -874,3 +874,90 @@ void slw_init(void) slw_init_chip(chip); } +/* 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) { + printf("fast_sleep_enter XSCOM failed\n"); + return; + } + + primary_thread->save_l2_fir_action1 = tmp; + tmp = tmp & ~0x0200000000000000ULL; + rc = xscom_write(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1), + tmp); + if (rc) { + printf("fast_sleep_enter XSCOM failed\n"); + return; + } + rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1), + &tmp); + printf("fastsleep: core %d: l2 fir before %016llx, after %016llx\n", + this_cpu()->pir, primary_thread->save_l2_fir_action1, tmp); + if (rc) { + printf("fast_sleep_enter XSCOM failed\n"); + return; + } + +} + +/* Workarounds while exiting fast-sleep */ + +static 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; + + rc = xscom_write(chip_id, XSCOM_ADDR_P8_EX(core, L2_FIR_ACTION1), + primary_thread->save_l2_fir_action1); + if (rc) { + printf("fast_sleep_exit XSCOM failed\n"); + return; + } + printf("fastsleep: core %d: l2 fir restored %016llx\n", + this_cpu()->pir, primary_thread->save_l2_fir_action1); +} + +/* + * 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); |