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[] = { + {} +};