From e2b18771fc2a0528dda18dbdaac08dd8530df25a Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 22 Jan 2022 23:37:12 -0600 Subject: [PATCH] feat(allwinner): provide CPU idle states to the rich OS When using SCPI as the PSCI backend, firmware can wake up the CPUs and cluster from sleep, so CPU idle states are available for the rich OS to use. In that case, advertise them to the rich OS via the DTB. Change-Id: I718ef6ef41212fe5213b11b4799613adbbe6e0eb Signed-off-by: Samuel Holland --- plat/allwinner/common/allwinner-common.mk | 1 + plat/allwinner/common/include/sunxi_private.h | 9 +++++++ plat/allwinner/common/sunxi_pm.c | 11 ++++++++ plat/allwinner/common/sunxi_prepare_dtb.c | 7 +++++ plat/allwinner/sun50i_a64/sunxi_idle_states.c | 27 +++++++++++++++++++ plat/allwinner/sun50i_h6/sunxi_idle_states.c | 11 ++++++++ .../allwinner/sun50i_h616/sunxi_idle_states.c | 11 ++++++++ .../allwinner/sun50i_r329/sunxi_idle_states.c | 11 ++++++++ 8 files changed, 88 insertions(+) create mode 100644 plat/allwinner/sun50i_a64/sunxi_idle_states.c create mode 100644 plat/allwinner/sun50i_h6/sunxi_idle_states.c create mode 100644 plat/allwinner/sun50i_h616/sunxi_idle_states.c create mode 100644 plat/allwinner/sun50i_r329/sunxi_idle_states.c diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk index cf559fbc8..61c1dbe3e 100644 --- a/plat/allwinner/common/allwinner-common.mk +++ b/plat/allwinner/common/allwinner-common.mk @@ -27,6 +27,7 @@ BL31_SOURCES += drivers/allwinner/axp/common.c \ plat/common/plat_gicv2.c \ plat/common/plat_psci_common.c \ ${AW_PLAT}/common/sunxi_bl31_setup.c \ + ${AW_PLAT}/${PLAT}/sunxi_idle_states.c \ ${AW_PLAT}/common/sunxi_pm.c \ ${AW_PLAT}/${PLAT}/sunxi_power.c \ ${AW_PLAT}/common/sunxi_security.c \ diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h index efea736b3..6a3865745 100644 --- a/plat/allwinner/common/include/sunxi_private.h +++ b/plat/allwinner/common/include/sunxi_private.h @@ -7,8 +7,12 @@ #ifndef SUNXI_PRIVATE_H #define SUNXI_PRIVATE_H +#include + #include +extern const struct psci_cpu_idle_state sunxi_idle_states[]; + void sunxi_configure_mmu_el3(int flags); void sunxi_cpu_on(u_register_t mpidr); @@ -24,8 +28,13 @@ static inline void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops) } #endif #if SUNXI_PSCI_USE_SCPI +bool sunxi_psci_is_scpi(void); int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops); #else +static inline bool sunxi_psci_is_scpi(void) +{ + return false; +} static inline int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops) { return -1; diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c index eb1b7e7b8..3772b4a57 100644 --- a/plat/allwinner/common/sunxi_pm.c +++ b/plat/allwinner/common/sunxi_pm.c @@ -9,12 +9,22 @@ #include #include +#include #include #include #include #include +static bool psci_is_scpi; + +#if SUNXI_PSCI_USE_SCPI +bool sunxi_psci_is_scpi(void) +{ + return psci_is_scpi; +} +#endif + int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint) { /* The non-secure entry point must be in DRAM */ @@ -40,6 +50,7 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint, if (sunxi_set_scpi_psci_ops(psci_ops) == 0) { INFO("PSCI: Suspend is available via SCPI\n"); + psci_is_scpi = true; } else { INFO("PSCI: Suspend is unavailable\n"); sunxi_set_native_psci_ops(psci_ops); diff --git a/plat/allwinner/common/sunxi_prepare_dtb.c b/plat/allwinner/common/sunxi_prepare_dtb.c index fc2e561fb..66af35ab8 100644 --- a/plat/allwinner/common/sunxi_prepare_dtb.c +++ b/plat/allwinner/common/sunxi_prepare_dtb.c @@ -34,6 +34,13 @@ void sunxi_prepare_dtb(void *fdt) } #endif + if (sunxi_psci_is_scpi()) { + ret = fdt_add_cpu_idle_states(fdt, sunxi_idle_states); + if (ret < 0) { + WARN("Failed to add idle states to DT: %d\n", ret); + } + } + ret = fdt_pack(fdt); if (ret < 0) { ERROR("Failed to pack devicetree at %p: error %d\n", diff --git a/plat/allwinner/sun50i_a64/sunxi_idle_states.c b/plat/allwinner/sun50i_a64/sunxi_idle_states.c new file mode 100644 index 000000000..2918bb71b --- /dev/null +++ b/plat/allwinner/sun50i_a64/sunxi_idle_states.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const struct psci_cpu_idle_state sunxi_idle_states[] = { + { + .name = "cpu-sleep", + .power_state = 0x00010003, + .local_timer_stop = true, + .entry_latency_us = 800, + .exit_latency_us = 1500, + .min_residency_us = 25000 + }, + { + .name = "cluster-sleep", + .power_state = 0x01010013, + .local_timer_stop = true, + .entry_latency_us = 850, + .exit_latency_us = 1500, + .min_residency_us = 50000 + }, + {} +}; diff --git a/plat/allwinner/sun50i_h6/sunxi_idle_states.c b/plat/allwinner/sun50i_h6/sunxi_idle_states.c new file mode 100644 index 000000000..4339bcd77 --- /dev/null +++ b/plat/allwinner/sun50i_h6/sunxi_idle_states.c @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const struct psci_cpu_idle_state sunxi_idle_states[] = { + {} +}; diff --git a/plat/allwinner/sun50i_h616/sunxi_idle_states.c b/plat/allwinner/sun50i_h616/sunxi_idle_states.c new file mode 100644 index 000000000..4339bcd77 --- /dev/null +++ b/plat/allwinner/sun50i_h616/sunxi_idle_states.c @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const struct psci_cpu_idle_state sunxi_idle_states[] = { + {} +}; diff --git a/plat/allwinner/sun50i_r329/sunxi_idle_states.c b/plat/allwinner/sun50i_r329/sunxi_idle_states.c new file mode 100644 index 000000000..4339bcd77 --- /dev/null +++ b/plat/allwinner/sun50i_r329/sunxi_idle_states.c @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const struct psci_cpu_idle_state sunxi_idle_states[] = { + {} +};