summaryrefslogtreecommitdiffstats
path: root/plat/qti/msm8916/msm8916_pm.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 17:43:51 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 17:43:51 +0000
commitbe58c81aff4cd4c0ccf43dbd7998da4a6a08c03b (patch)
tree779c248fb61c83f65d1f0dc867f2053d76b4e03a /plat/qti/msm8916/msm8916_pm.c
parentInitial commit. (diff)
downloadarm-trusted-firmware-be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b.tar.xz
arm-trusted-firmware-be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b.zip
Adding upstream version 2.10.0+dfsg.upstream/2.10.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plat/qti/msm8916/msm8916_pm.c')
-rw-r--r--plat/qti/msm8916/msm8916_pm.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/plat/qti/msm8916/msm8916_pm.c b/plat/qti/msm8916/msm8916_pm.c
new file mode 100644
index 0000000..fd44f04
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_pm.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021-2022, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <msm8916_mmap.h>
+#include "msm8916_pm.h"
+
+/*
+ * On platforms with two clusters the index of the APCS memory region is swapped
+ * compared to the MPIDR cluster affinity level: APCS cluster 0 manages CPUs
+ * with cluster affinity level 1, while APCS cluster 1 manages CPUs with level 0.
+ *
+ * On platforms with a single cluster there is only one APCS memory region.
+ */
+#if PLATFORM_CLUSTER_COUNT == 2
+#define MPIDR_APCS_CLUSTER(mpidr) !MPIDR_AFFLVL1_VAL(mpidr)
+#else
+#define MPIDR_APCS_CLUSTER(mpidr) 0
+#endif
+
+#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+
+static int msm8916_pwr_domain_on(u_register_t mpidr)
+{
+ /* Should be never called on single-core platforms */
+ if (PLATFORM_CORE_COUNT == 1) {
+ assert(false);
+ return PSCI_E_ALREADY_ON;
+ }
+
+ /* Power on L2 cache and secondary CPU core for the first time */
+ if (PLATFORM_CLUSTER_COUNT > 1) {
+ msm8916_l2_boot(APCS_GLB(MPIDR_APCS_CLUSTER(mpidr)));
+ }
+ msm8916_cpu_boot(APCS_ALIAS_ACS(MPIDR_APCS_CLUSTER(mpidr),
+ MPIDR_AFFLVL0_VAL(mpidr)));
+ return PSCI_E_SUCCESS;
+}
+
+static void msm8916_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* Should be never called on single-core platforms */
+ if (PLATFORM_CORE_COUNT == 1) {
+ assert(false);
+ return;
+ }
+
+ if (PLATFORM_CLUSTER_COUNT > 1 &&
+ CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+ }
+
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static void __dead2 msm8916_system_reset(void)
+{
+ mmio_write_32(MPM_PS_HOLD, 0);
+ mdelay(1000);
+
+ ERROR("PSCI: System reset failed\n");
+ panic();
+}
+
+static const plat_psci_ops_t msm8916_psci_ops = {
+ .pwr_domain_on = msm8916_pwr_domain_on,
+ .pwr_domain_on_finish = msm8916_pwr_domain_on_finish,
+ .system_off = msm8916_system_reset,
+ .system_reset = msm8916_system_reset,
+};
+
+/* Defined and used in msm8916_helpers.S */
+extern uintptr_t msm8916_entry_point;
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ /*
+ * The entry point is read with caches off (and even from two different
+ * physical addresses when read through the "boot remapper"), so make
+ * sure it is flushed to memory.
+ */
+ msm8916_entry_point = sec_entrypoint;
+ flush_dcache_range((uintptr_t)&msm8916_entry_point, sizeof(uintptr_t));
+
+ *psci_ops = &msm8916_psci_ops;
+ return 0;
+}