pmaports/temp/arm-trusted-firmware/2002-allwinner-Simplify-CPU_SUSPEND-power-state-encoding.patch

85 lines
2.9 KiB
Diff

From 75ddf133e308f7ce15af9ecd899079a22c59dcfc Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Thu, 18 Mar 2021 23:15:28 -0500
Subject: [PATCH] allwinner: Simplify CPU_SUSPEND power state encoding
Use the encoding recommended by the PSCI specification: four bits for
the power state at each power level.
Since SCPI provides no way to handshake an exit from a standby state,
the only possible standby state is the architectural WFI state. Since
WFI can be used without PSCI, we do not allow passing in standby states.
Signed-off-by: Samuel Holland <samuel@sholland.org>
Change-Id: I4b3b84e5c255ee58a25255a0cab5d7623425086e
---
plat/allwinner/common/sunxi_scpi_pm.c | 36 ++++++++++++---------------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/plat/allwinner/common/sunxi_scpi_pm.c b/plat/allwinner/common/sunxi_scpi_pm.c
index 89c834aa9..8dcc54b16 100644
--- a/plat/allwinner/common/sunxi_scpi_pm.c
+++ b/plat/allwinner/common/sunxi_scpi_pm.c
@@ -33,6 +33,9 @@
*/
#define SCP_FIRMWARE_MAGIC 0xb4400012
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
#define CPU_PWR_LVL MPIDR_AFFLVL0
#define CLUSTER_PWR_LVL MPIDR_AFFLVL1
#define SYSTEM_PWR_LVL MPIDR_AFFLVL2
@@ -126,7 +129,9 @@ static int sunxi_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
unsigned int power_level = psci_get_pstate_pwrlvl(power_state);
+ unsigned int state_id = psci_get_pstate_id(power_state);
unsigned int type = psci_get_pstate_type(power_state);
+ unsigned int i;
assert(req_state != NULL);
@@ -135,28 +140,19 @@ static int sunxi_validate_power_state(unsigned int power_state,
}
if (type == PSTATE_TYPE_STANDBY) {
- /* Only one retention power state is supported. */
- if (psci_get_pstate_id(power_state) > 0) {
- return PSCI_E_INVALID_PARAMS;
- }
- /* The SoC cannot be suspended without losing state */
- if (power_level == SYSTEM_PWR_LVL) {
- return PSCI_E_INVALID_PARAMS;
- }
- for (unsigned int i = 0; i <= power_level; ++i) {
- req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
- }
- } else {
- /* Only one off power state is supported. */
- if (psci_get_pstate_id(power_state) > 0) {
- return PSCI_E_INVALID_PARAMS;
- }
- for (unsigned int i = 0; i <= power_level; ++i) {
- req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
- }
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ /* Pass through the requested PSCI state as-is. */
+ for (i = 0; i <= power_level; ++i) {
+ unsigned int local_pstate = state_id & PLAT_LOCAL_PSTATE_MASK;
+
+ req_state->pwr_domain_state[i] = local_pstate;
+ state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
}
+
/* Higher power domain levels should all remain running */
- for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) {
+ for (; i <= PLAT_MAX_PWR_LVL; ++i) {
req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
}
--
2.33.1