diff options
author | Preeti U Murthy <preeti@linux.vnet.ibm.com> | 2014-09-25 09:15:04 +0530 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-10-01 14:22:37 +1000 |
commit | c0716fe5caadde0742c821ce7e7b0d3002d71314 (patch) | |
tree | 13a3c4c0e2fa884849bef83b77eb594d89f7ec8f /hw/occ.c | |
parent | ddbb18ac6d9c789092c52d8499266edb5df78f08 (diff) | |
download | skiboot-c0716fe5caadde0742c821ce7e7b0d3002d71314.zip skiboot-c0716fe5caadde0742c821ce7e7b0d3002d71314.tar.gz skiboot-c0716fe5caadde0742c821ce7e7b0d3002d71314.tar.bz2 |
occ/slw: Fix OCC/SLW initialization for power management
When the fast/deep power management modes for the cpu idle states
is initialized, bits which are not relevant in this context are also
being set. Fix this.
Besides this, the EX_PM_GP1 register will be read/written into by the
OCC as well. We touch this register during initialization of fast/deep
cpuidle modes and during initialization of pstate transitions. The register
contents can thus get messed up due to potential race conditions between
the OCC and sapphire settings.
Hence make use of the AND and OR scoms to do the settings and hence
let the hardware take care of the necessary synchronization.
We can also get rid of the setting of deep mode during slw_reinit since
we enable the required deep winkle mode during slw_init itself. This means
effectively removing the slw_prepare_chip() and its children functions.
They are no longer useful.
Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw/occ.c')
-rw-r--r-- | hw/occ.c | 20 |
1 files changed, 13 insertions, 7 deletions
@@ -197,10 +197,13 @@ static bool cpu_pstates_prepare_core(struct proc_chip *chip, struct cpu_thread * * Need to ensure only relevant bits are inited */ - /* Init PM GP1 for SCOM based PSTATE control to set nominal freq */ - rc = xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP1), &tmp); - tmp = tmp | EX_PM_SETUP_GP1_PM_SPR_OVERRIDE_EN; - rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP1), tmp); + /* Init PM GP1 for SCOM based PSTATE control to set nominal freq + * + * Use the OR SCOM to set the required bits in PM_GP1 register + * since the OCC might be mainpulating the PM_GP1 register as well. + */ + rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_SET_GP1), + EX_PM_SETUP_GP1_PM_SPR_OVERRIDE_EN); if (rc) { log_simple_error(&e_info(OPAL_RC_OCC_PSTATE_INIT), "OCC: Failed to write PM_GP1 in pstates init\n"); @@ -225,10 +228,13 @@ static bool cpu_pstates_prepare_core(struct proc_chip *chip, struct cpu_thread * * cleared by OCC. Sapphire need not clear. * However wait for DVFS state machine to become idle after min->nominal * transition initiated above. If not switch over to SPR control could fail. + * + * Use the AND SCOM to clear the required bits in PM_GP1 register + * since the OCC might be mainpulating the PM_GP1 register as well. */ - rc = xscom_read(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP1), &tmp); - tmp = tmp & ~EX_PM_SETUP_GP1_PM_SPR_OVERRIDE_EN; - rc = xscom_write(chip->id, XSCOM_ADDR_P8_EX_SLAVE(core, EX_PM_GP1), tmp); + tmp = ~EX_PM_SETUP_GP1_PM_SPR_OVERRIDE_EN; + 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_OCC_PSTATE_INIT), "OCC: Failed to write PM_GP1 in pstates init\n"); |