/* * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include 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);