Add standby state support in PSCI cpu_suspend api
authorVikram Kanigiri <vikram.kanigiri@arm.com>
Fri, 21 Mar 2014 11:57:10 +0000 (11:57 +0000)
committerDan Handley <dan.handley@arm.com>
Wed, 26 Mar 2014 17:36:35 +0000 (17:36 +0000)
This patch adds support in the generic PSCI implementation to call a
platform specific function to enter a standby state using an example
implementation in ARM FVP port

Fixes ARM-software/tf-issues#94
Change-Id: Ic1263fcf25f28e09162ad29dca954125f9aa8cc9

include/psci.h
plat/fvp/plat_pm.c
services/std_svc/psci/psci_main.c

index 6fe1d8af375ef39349123244dd83add10e1b1067..5c66789ee9ac1a363b2b21e3b4a34fc86d272639 100644 (file)
@@ -74,6 +74,9 @@
 #define PSTATE_TYPE_MASK       0x1
 #define PSTATE_AFF_LVL_MASK    0x3
 
+#define PSTATE_TYPE_STANDBY    0x0
+#define PSTATE_TYPE_POWERDOWN  0x1
+
 #define psci_get_pstate_id(pstate)     (pstate >> PSTATE_ID_SHIFT) & \
                                        PSTATE_ID_MASK
 #define psci_get_pstate_type(pstate)   (pstate >> PSTATE_TYPE_SHIFT) & \
index dd7a4b3611021429bab493cb0c0d80261ca89b87..7b51476e03075958d0300429d51247d66c58628d 100644 (file)
 /* Only included for error codes */
 #include <psci.h>
 
+/*******************************************************************************
+ * FVP handler called when an affinity instance is about to enter standby.
+ ******************************************************************************/
+int fvp_affinst_standby(unsigned int power_state)
+{
+       unsigned int target_afflvl;
+
+       /* Sanity check the requested state */
+       target_afflvl = psci_get_pstate_afflvl(power_state);
+
+       /*
+        * It's possible to enter standby only on affinity level 0 i.e. a cpu
+        * on the FVP. Ignore any other affinity level.
+        */
+       if (target_afflvl != MPIDR_AFFLVL0)
+               return PSCI_E_INVALID_PARAMS;
+
+       /* Enter standby state */
+       wfi();
+
+       return PSCI_E_SUCCESS;
+}
+
 /*******************************************************************************
  * FVP handler called when an affinity instance is about to be turned on. The
  * level and mpidr determine the affinity instance.
@@ -372,7 +395,7 @@ int fvp_affinst_suspend_finish(unsigned long mpidr,
  * Export the platform handlers to enable psci to invoke them
  ******************************************************************************/
 static plat_pm_ops fvp_plat_pm_ops = {
-       0,
+       fvp_affinst_standby,
        fvp_affinst_on,
        fvp_affinst_off,
        fvp_affinst_suspend,
index 6bf05830411f2e721dbecca3f8a88b95ffeb4e5f..2d61ec0896ab564b92f4ebcbb1ff260460260c11 100644 (file)
@@ -85,31 +85,28 @@ int psci_cpu_suspend(unsigned int power_state,
        unsigned long mpidr;
        unsigned int target_afflvl, pstate_type;
 
-       /* TODO: Standby states are not supported at the moment */
-       pstate_type = psci_get_pstate_type(power_state);
-       if (pstate_type == 0) {
-               rc = PSCI_E_INVALID_PARAMS;
-               goto exit;
-       }
-
        /* Sanity check the requested state */
        target_afflvl = psci_get_pstate_afflvl(power_state);
-       if (target_afflvl > MPIDR_MAX_AFFLVL) {
-               rc = PSCI_E_INVALID_PARAMS;
-               goto exit;
-       }
+       if (target_afflvl > MPIDR_MAX_AFFLVL)
+               return PSCI_E_INVALID_PARAMS;
 
-       mpidr = read_mpidr();
-       rc = psci_afflvl_suspend(mpidr,
-                                entrypoint,
-                                context_id,
-                                power_state,
-                                MPIDR_AFFLVL0,
-                                target_afflvl);
+       pstate_type = psci_get_pstate_type(power_state);
+       if (pstate_type == PSTATE_TYPE_STANDBY) {
+               if  (psci_plat_pm_ops->affinst_standby)
+                       rc = psci_plat_pm_ops->affinst_standby(power_state);
+               else
+                       return PSCI_E_INVALID_PARAMS;
+       } else {
+               mpidr = read_mpidr();
+               rc = psci_afflvl_suspend(mpidr,
+                                        entrypoint,
+                                        context_id,
+                                        power_state,
+                                        MPIDR_AFFLVL0,
+                                        target_afflvl);
+       }
 
-exit:
-       if (rc != PSCI_E_SUCCESS)
-               assert(rc == PSCI_E_INVALID_PARAMS);
+       assert(rc == PSCI_E_INVALID_PARAMS || rc == PSCI_E_SUCCESS);
        return rc;
 }