From 1862d6203cb21d1846388e8d7530612a9b98786e Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 10 Jul 2017 16:02:05 -0700 Subject: [PATCH] lib: psci: early suspend handler for platforms This patch adds an early suspend handler, that executes with SMP and data cache enabled. This handler allows platforms to perform any early actions during the CPU suspend entry sequence. This handler is optional and platforms can choose to implement it depending on their needs. The `pwr_domain_suspend` handler still exists and platforms can keep on using it without any side effects. Signed-off-by: Varun Wadekar --- docs/platform-migration-guide.rst | 13 +++++++------ docs/porting-guide.rst | 17 +++++++++++++++++ include/lib/psci/psci.h | 2 ++ lib/psci/psci_suspend.c | 11 +++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/docs/platform-migration-guide.rst b/docs/platform-migration-guide.rst index 5e8eeba18..638033e44 100644 --- a/docs/platform-migration-guide.rst +++ b/docs/platform-migration-guide.rst @@ -146,6 +146,7 @@ for the ``plat_psci_ops`` structure which is declared as : void (*cpu_standby)(plat_local_state_t cpu_state); int (*pwr_domain_on)(u_register_t mpidr); void (*pwr_domain_off)(const psci_power_state_t *target_state); + void (*pwr_domain_suspend_early)(const psci_power_state_t *target_state); void (*pwr_domain_suspend)(const psci_power_state_t *target_state); void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); void (*pwr_domain_suspend_finish)( @@ -170,12 +171,12 @@ convert the power-state parameter (possibly encoding a composite power state) passed in a PSCI ``CPU_SUSPEND`` to the ``psci_power_state`` format. This handler is now mandatory for PSCI ``CPU_SUSPEND`` support. -The ``plat_psci_ops`` handlers, ``pwr_domain_off`` and ``pwr_domain_suspend``, are -passed the target local state for each affected power domain. The platform -must execute operations specific to these target states. Similarly, -``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish`` are passed the local -states of the affected power domains before wakeup. The platform -must execute actions to restore these power domains from these specific +The ``plat_psci_ops`` handlers, ``pwr_domain_off``, ``pwr_domain_suspend_early`` +and ``pwr_domain_suspend``, are passed the target local state for each affected +power domain. The platform must execute operations specific to these target +states. Similarly, ``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish`` +are passed the local states of the affected power domains before wakeup. The +platform must execute actions to restore these power domains from these specific local states. - Difference in invocation diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 4d4cdcd6e..bf8dea7b4 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -2060,6 +2060,23 @@ power down state where as it could be either power down, retention or run state for the higher power domain levels depending on the result of state coordination. The generic code expects the handler to succeed. +plat\_psci\_ops.pwr\_domain\_suspend\_pwrdown\_early() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This optional function may be used as a performance optimization to replace +or complement pwr_domain_suspend() on some platforms. Its calling semantics +are identical to pwr_domain_suspend(), except the PSCI implementation only +calls this function when suspending to a power down state, and it guarantees +that data caches are enabled. + +When HW_ASSISTED_COHERENCY = 0, the PSCI implementation disables data caches +before calling pwr_domain_suspend(). If the target_state corresponds to a +power down state and it is safe to perform some or all of the platform +specific actions in that function with data caches enabled, it may be more +efficient to move those actions to this function. When HW_ASSISTED_COHERENCY += 1, data caches remain enabled throughout, and so there is no advantage to +moving platform specific actions to this function. + plat\_psci\_ops.pwr\_domain\_suspend() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h index fee6a24fb..0ed39c9ac 100644 --- a/include/lib/psci/psci.h +++ b/include/lib/psci/psci.h @@ -267,6 +267,8 @@ typedef struct plat_psci_ops { void (*cpu_standby)(plat_local_state_t cpu_state); int (*pwr_domain_on)(u_register_t mpidr); void (*pwr_domain_off)(const psci_power_state_t *target_state); + void (*pwr_domain_suspend_pwrdown_early)( + const psci_power_state_t *target_state); void (*pwr_domain_suspend)(const psci_power_state_t *target_state); void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); void (*pwr_domain_suspend_finish)( diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c index 0d1589ee0..40ecdeea9 100644 --- a/lib/psci/psci_suspend.c +++ b/lib/psci/psci_suspend.c @@ -80,6 +80,17 @@ static void psci_suspend_to_pwrdown_start(unsigned int end_pwrlvl, if (psci_spd_pm && psci_spd_pm->svc_suspend) psci_spd_pm->svc_suspend(max_off_lvl); +#if !HW_ASSISTED_COHERENCY + /* + * Plat. management: Allow the platform to perform any early + * actions required to power down the CPU. This might be useful for + * HW_ASSISTED_COHERENCY = 0 platforms that can safely perform these + * actions with data caches enabled. + */ + if (psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early) + psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early(state_info); +#endif + /* * Store the re-entry information for the non-secure world. */