summaryrefslogtreecommitdiff
path: root/lib/cpus/aarch64/cortex_a75_pubsub.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cpus/aarch64/cortex_a75_pubsub.c')
-rw-r--r--lib/cpus/aarch64/cortex_a75_pubsub.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/cpus/aarch64/cortex_a75_pubsub.c b/lib/cpus/aarch64/cortex_a75_pubsub.c
new file mode 100644
index 00000000..c1089a60
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_a75_pubsub.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cortex_a75.h>
+#include <pubsub_events.h>
+#include <platform.h>
+
+struct amu_ctx {
+ uint64_t cnts[CORTEX_A75_AMU_NR_COUNTERS];
+ uint16_t mask;
+};
+
+static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
+
+static void *cortex_a75_context_save(const void *arg)
+{
+ struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
+ unsigned int midr;
+ unsigned int midr_mask;
+ int i;
+
+ midr = read_midr();
+ midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) |
+ (MIDR_PN_MASK << MIDR_PN_SHIFT);
+ if ((midr & midr_mask) != (CORTEX_A75_MIDR & midr_mask))
+ return 0;
+
+ /* Save counter configuration */
+ ctx->mask = cortex_a75_amu_read_cpuamcntenset_el0();
+
+ /* Ensure counters are disabled */
+ cortex_a75_amu_write_cpuamcntenclr_el0(ctx->mask);
+ isb();
+
+ /* Save counters */
+ for (i = 0; i < CORTEX_A75_AMU_NR_COUNTERS; i++)
+ ctx->cnts[i] = cortex_a75_amu_cnt_read(i);
+
+ return 0;
+}
+
+static void *cortex_a75_context_restore(const void *arg)
+{
+ struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
+ unsigned int midr;
+ unsigned int midr_mask;
+ int i;
+
+ midr = read_midr();
+ midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) |
+ (MIDR_PN_MASK << MIDR_PN_SHIFT);
+ if ((midr & midr_mask) != (CORTEX_A75_MIDR & midr_mask))
+ return 0;
+
+ ctx = &amu_ctxs[plat_my_core_pos()];
+
+ /* Counters were disabled in `cortex_a75_context_save()` */
+ assert(cortex_a75_amu_read_cpuamcntenset_el0() == 0);
+
+ /* Restore counters */
+ for (i = 0; i < CORTEX_A75_AMU_NR_COUNTERS; i++)
+ cortex_a75_amu_cnt_write(i, ctx->cnts[i]);
+ isb();
+
+ /* Restore counter configuration */
+ cortex_a75_amu_write_cpuamcntenset_el0(ctx->mask);
+
+ return 0;
+}
+
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_a75_context_save);
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, cortex_a75_context_restore);