aboutsummaryrefslogtreecommitdiff
path: root/hw/occ.c
diff options
context:
space:
mode:
authorPreeti U Murthy <preeti@linux.vnet.ibm.com>2014-09-25 09:15:04 +0530
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-10-01 14:22:37 +1000
commitc0716fe5caadde0742c821ce7e7b0d3002d71314 (patch)
tree13a3c4c0e2fa884849bef83b77eb594d89f7ec8f /hw/occ.c
parentddbb18ac6d9c789092c52d8499266edb5df78f08 (diff)
downloadskiboot-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.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/hw/occ.c b/hw/occ.c
index 17fca93..e2bf0e0 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -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");