1ef69e1eaSDimitris Papastamos /* 2873d4241Sjohpow01 * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. 3ef69e1eaSDimitris Papastamos * 4ef69e1eaSDimitris Papastamos * SPDX-License-Identifier: BSD-3-Clause 5ef69e1eaSDimitris Papastamos */ 6ef69e1eaSDimitris Papastamos 7f3ccf036SAlexei Fedorov #include <assert.h> 833b9be6dSChris Kay #include <cdefs.h> 909d40e0eSAntonio Nino Diaz #include <stdbool.h> 1009d40e0eSAntonio Nino Diaz 11e747a59bSChris Kay #include "../amu_private.h" 12ef69e1eaSDimitris Papastamos #include <arch.h> 13ef69e1eaSDimitris Papastamos #include <arch_helpers.h> 14*742ca230SChris Kay #include <common/debug.h> 1509d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/pubsub_events.h> 1609d40e0eSAntonio Nino Diaz #include <lib/extensions/amu.h> 17f3ccf036SAlexei Fedorov 1809d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 19b6eb3932SDimitris Papastamos 20e747a59bSChris Kay struct amu_ctx { 21e747a59bSChris Kay uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS]; 22e747a59bSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 23e747a59bSChris Kay uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS]; 24e747a59bSChris Kay #endif 25e747a59bSChris Kay 26e747a59bSChris Kay uint16_t group0_enable; 27e747a59bSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 28e747a59bSChris Kay uint16_t group1_enable; 29e747a59bSChris Kay #endif 30e747a59bSChris Kay }; 31e747a59bSChris Kay 32e747a59bSChris Kay static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT]; 33e747a59bSChris Kay 34e747a59bSChris Kay CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS, 35e747a59bSChris Kay amu_ctx_group0_enable_cannot_represent_all_group0_counters); 36e747a59bSChris Kay 37e747a59bSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 38e747a59bSChris Kay CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS, 39e747a59bSChris Kay amu_ctx_group1_enable_cannot_represent_all_group1_counters); 40e747a59bSChris Kay #endif 41ef69e1eaSDimitris Papastamos 4233b9be6dSChris Kay static inline __unused uint32_t read_id_pfr0_amu(void) 43ef69e1eaSDimitris Papastamos { 4433b9be6dSChris Kay return (read_id_pfr0() >> ID_PFR0_AMU_SHIFT) & 45873d4241Sjohpow01 ID_PFR0_AMU_MASK; 46c70da546SJoel Hutton } 47c70da546SJoel Hutton 4833b9be6dSChris Kay static inline __unused void write_hcptr_tam(uint32_t value) 4933b9be6dSChris Kay { 5033b9be6dSChris Kay write_hcptr((read_hcptr() & ~TAM_BIT) | 5133b9be6dSChris Kay ((value << TAM_SHIFT) & TAM_BIT)); 5233b9be6dSChris Kay } 5333b9be6dSChris Kay 5433b9be6dSChris Kay static inline __unused void write_amcr_cg1rz(uint32_t value) 5533b9be6dSChris Kay { 5633b9be6dSChris Kay write_amcr((read_amcr() & ~AMCR_CG1RZ_BIT) | 5733b9be6dSChris Kay ((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT)); 5833b9be6dSChris Kay } 5933b9be6dSChris Kay 6033b9be6dSChris Kay static inline __unused uint32_t read_amcfgr_ncg(void) 6133b9be6dSChris Kay { 6233b9be6dSChris Kay return (read_amcfgr() >> AMCFGR_NCG_SHIFT) & 6333b9be6dSChris Kay AMCFGR_NCG_MASK; 6433b9be6dSChris Kay } 6533b9be6dSChris Kay 6681e2ff1fSChris Kay static inline __unused uint32_t read_amcgcr_cg0nc(void) 6781e2ff1fSChris Kay { 6881e2ff1fSChris Kay return (read_amcgcr() >> AMCGCR_CG0NC_SHIFT) & 6981e2ff1fSChris Kay AMCGCR_CG0NC_MASK; 7081e2ff1fSChris Kay } 7181e2ff1fSChris Kay 7233b9be6dSChris Kay static inline __unused uint32_t read_amcgcr_cg1nc(void) 7333b9be6dSChris Kay { 7433b9be6dSChris Kay return (read_amcgcr() >> AMCGCR_CG1NC_SHIFT) & 7533b9be6dSChris Kay AMCGCR_CG1NC_MASK; 7633b9be6dSChris Kay } 7733b9be6dSChris Kay 7833b9be6dSChris Kay static inline __unused uint32_t read_amcntenset0_px(void) 7933b9be6dSChris Kay { 8033b9be6dSChris Kay return (read_amcntenset0() >> AMCNTENSET0_Pn_SHIFT) & 8133b9be6dSChris Kay AMCNTENSET0_Pn_MASK; 8233b9be6dSChris Kay } 8333b9be6dSChris Kay 8433b9be6dSChris Kay static inline __unused uint32_t read_amcntenset1_px(void) 8533b9be6dSChris Kay { 8633b9be6dSChris Kay return (read_amcntenset1() >> AMCNTENSET1_Pn_SHIFT) & 8733b9be6dSChris Kay AMCNTENSET1_Pn_MASK; 8833b9be6dSChris Kay } 8933b9be6dSChris Kay 9033b9be6dSChris Kay static inline __unused void write_amcntenset0_px(uint32_t px) 9133b9be6dSChris Kay { 9233b9be6dSChris Kay uint32_t value = read_amcntenset0(); 9333b9be6dSChris Kay 9433b9be6dSChris Kay value &= ~AMCNTENSET0_Pn_MASK; 9533b9be6dSChris Kay value |= (px << AMCNTENSET0_Pn_SHIFT) & 9633b9be6dSChris Kay AMCNTENSET0_Pn_MASK; 9733b9be6dSChris Kay 9833b9be6dSChris Kay write_amcntenset0(value); 9933b9be6dSChris Kay } 10033b9be6dSChris Kay 10133b9be6dSChris Kay static inline __unused void write_amcntenset1_px(uint32_t px) 10233b9be6dSChris Kay { 10333b9be6dSChris Kay uint32_t value = read_amcntenset1(); 10433b9be6dSChris Kay 10533b9be6dSChris Kay value &= ~AMCNTENSET1_Pn_MASK; 10633b9be6dSChris Kay value |= (px << AMCNTENSET1_Pn_SHIFT) & 10733b9be6dSChris Kay AMCNTENSET1_Pn_MASK; 10833b9be6dSChris Kay 10933b9be6dSChris Kay write_amcntenset1(value); 11033b9be6dSChris Kay } 11133b9be6dSChris Kay 11233b9be6dSChris Kay static inline __unused void write_amcntenclr0_px(uint32_t px) 11333b9be6dSChris Kay { 11433b9be6dSChris Kay uint32_t value = read_amcntenclr0(); 11533b9be6dSChris Kay 11633b9be6dSChris Kay value &= ~AMCNTENCLR0_Pn_MASK; 11733b9be6dSChris Kay value |= (px << AMCNTENCLR0_Pn_SHIFT) & AMCNTENCLR0_Pn_MASK; 11833b9be6dSChris Kay 11933b9be6dSChris Kay write_amcntenclr0(value); 12033b9be6dSChris Kay } 12133b9be6dSChris Kay 12233b9be6dSChris Kay static inline __unused void write_amcntenclr1_px(uint32_t px) 12333b9be6dSChris Kay { 12433b9be6dSChris Kay uint32_t value = read_amcntenclr1(); 12533b9be6dSChris Kay 12633b9be6dSChris Kay value &= ~AMCNTENCLR1_Pn_MASK; 12733b9be6dSChris Kay value |= (px << AMCNTENCLR1_Pn_SHIFT) & AMCNTENCLR1_Pn_MASK; 12833b9be6dSChris Kay 12933b9be6dSChris Kay write_amcntenclr1(value); 13033b9be6dSChris Kay } 13133b9be6dSChris Kay 132e747a59bSChris Kay static __unused bool amu_supported(void) 13333b9be6dSChris Kay { 13433b9be6dSChris Kay return read_id_pfr0_amu() >= ID_PFR0_AMU_V1; 13533b9be6dSChris Kay } 13633b9be6dSChris Kay 13733b9be6dSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 138e747a59bSChris Kay static __unused bool amu_group1_supported(void) 139f3ccf036SAlexei Fedorov { 14033b9be6dSChris Kay return read_amcfgr_ncg() > 0U; 141f3ccf036SAlexei Fedorov } 142f3ccf036SAlexei Fedorov #endif 143f3ccf036SAlexei Fedorov 144f3ccf036SAlexei Fedorov /* 145e747a59bSChris Kay * Enable counters. This function is meant to be invoked by the context 146e747a59bSChris Kay * management library before exiting from EL3. 147f3ccf036SAlexei Fedorov */ 14840daecc1SAntonio Nino Diaz void amu_enable(bool el2_unused) 149c70da546SJoel Hutton { 150e747a59bSChris Kay uint32_t id_pfr0_amu; /* AMU version */ 151e747a59bSChris Kay 152e747a59bSChris Kay uint32_t amcfgr_ncg; /* Number of counter groups */ 153e747a59bSChris Kay uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ 154e747a59bSChris Kay 155e747a59bSChris Kay uint32_t amcntenset0_px = 0x0; /* Group 0 enable mask */ 156e747a59bSChris Kay uint32_t amcntenset1_px = 0x0; /* Group 1 enable mask */ 157e747a59bSChris Kay 158e747a59bSChris Kay id_pfr0_amu = read_id_pfr0_amu(); 159e747a59bSChris Kay if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { 160e747a59bSChris Kay /* 161e747a59bSChris Kay * If the AMU is unsupported, nothing needs to be done. 162e747a59bSChris Kay */ 163e747a59bSChris Kay 1640767d50eSDimitris Papastamos return; 165f3ccf036SAlexei Fedorov } 166f3ccf036SAlexei Fedorov 167ef69e1eaSDimitris Papastamos if (el2_unused) { 168ef69e1eaSDimitris Papastamos /* 169e747a59bSChris Kay * HCPTR.TAM: Set to zero so any accesses to the Activity 170e747a59bSChris Kay * Monitor registers do not trap to EL2. 171ef69e1eaSDimitris Papastamos */ 17233b9be6dSChris Kay write_hcptr_tam(0U); 173ef69e1eaSDimitris Papastamos } 174ef69e1eaSDimitris Papastamos 175e747a59bSChris Kay /* 176e747a59bSChris Kay * Retrieve the number of architected counters. All of these counters 177e747a59bSChris Kay * are enabled by default. 178e747a59bSChris Kay */ 179c70da546SJoel Hutton 180e747a59bSChris Kay amcgcr_cg0nc = read_amcgcr_cg0nc(); 181e747a59bSChris Kay amcntenset0_px = (UINT32_C(1) << (amcgcr_cg0nc)) - 1U; 182e747a59bSChris Kay 183e747a59bSChris Kay assert(amcgcr_cg0nc <= AMU_AMCGCR_CG0NC_MAX); 184e747a59bSChris Kay 185e747a59bSChris Kay /* 186*742ca230SChris Kay * The platform may opt to enable specific auxiliary counters. This can 187*742ca230SChris Kay * be done via the common FCONF getter, or via the platform-implemented 188*742ca230SChris Kay * function. 189*742ca230SChris Kay */ 190*742ca230SChris Kay 191*742ca230SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 192*742ca230SChris Kay const struct amu_topology *topology; 193*742ca230SChris Kay 194*742ca230SChris Kay #if ENABLE_AMU_FCONF 195*742ca230SChris Kay topology = FCONF_GET_PROPERTY(amu, config, topology); 196*742ca230SChris Kay #else 197*742ca230SChris Kay topology = plat_amu_topology(); 198*742ca230SChris Kay #endif /* ENABLE_AMU_FCONF */ 199*742ca230SChris Kay 200*742ca230SChris Kay if (topology != NULL) { 201*742ca230SChris Kay unsigned int core_pos = plat_my_core_pos(); 202*742ca230SChris Kay 203*742ca230SChris Kay amcntenset1_el0_px = topology->cores[core_pos].enable; 204*742ca230SChris Kay } else { 205*742ca230SChris Kay ERROR("AMU: failed to generate AMU topology\n"); 206*742ca230SChris Kay } 207*742ca230SChris Kay #endif /* ENABLE_AMU_AUXILIARY_COUNTERS */ 208*742ca230SChris Kay 209*742ca230SChris Kay /* 210e747a59bSChris Kay * Enable the requested counters. 211e747a59bSChris Kay */ 212e747a59bSChris Kay 213e747a59bSChris Kay write_amcntenset0_px(amcntenset0_px); 214e747a59bSChris Kay 215e747a59bSChris Kay amcfgr_ncg = read_amcfgr_ncg(); 216e747a59bSChris Kay if (amcfgr_ncg > 0U) { 217e747a59bSChris Kay write_amcntenset1_px(amcntenset1_px); 218*742ca230SChris Kay 219*742ca230SChris Kay #if !ENABLE_AMU_AUXILIARY_COUNTERS 220*742ca230SChris Kay VERBOSE("AMU: auxiliary counters detected but support is disabled\n"); 221*742ca230SChris Kay #endif 2221fd685a7SChris Kay } 223873d4241Sjohpow01 224873d4241Sjohpow01 /* Initialize FEAT_AMUv1p1 features if present. */ 225e747a59bSChris Kay if (id_pfr0_amu < ID_PFR0_AMU_V1P1) { 226873d4241Sjohpow01 return; 227873d4241Sjohpow01 } 228873d4241Sjohpow01 229873d4241Sjohpow01 #if AMU_RESTRICT_COUNTERS 230873d4241Sjohpow01 /* 231873d4241Sjohpow01 * FEAT_AMUv1p1 adds a register field to restrict access to group 1 232873d4241Sjohpow01 * counters at all but the highest implemented EL. This is controlled 233873d4241Sjohpow01 * with the AMU_RESTRICT_COUNTERS compile time flag, when set, system 234873d4241Sjohpow01 * register reads at lower ELs return zero. Reads from the memory 235873d4241Sjohpow01 * mapped view are unaffected. 236873d4241Sjohpow01 */ 237873d4241Sjohpow01 VERBOSE("AMU group 1 counter access restricted.\n"); 23833b9be6dSChris Kay write_amcr_cg1rz(1U); 239873d4241Sjohpow01 #else 24033b9be6dSChris Kay write_amcr_cg1rz(0U); 241873d4241Sjohpow01 #endif 242c70da546SJoel Hutton } 243c70da546SJoel Hutton 244c70da546SJoel Hutton /* Read the group 0 counter identified by the given `idx`. */ 245b4b726eaSChris Kay static uint64_t amu_group0_cnt_read(unsigned int idx) 246c70da546SJoel Hutton { 24733b9be6dSChris Kay assert(amu_supported()); 24881e2ff1fSChris Kay assert(idx < read_amcgcr_cg0nc()); 249c70da546SJoel Hutton 250c70da546SJoel Hutton return amu_group0_cnt_read_internal(idx); 251c70da546SJoel Hutton } 252c70da546SJoel Hutton 253f3ccf036SAlexei Fedorov /* Write the group 0 counter identified by the given `idx` with `val` */ 254b4b726eaSChris Kay static void amu_group0_cnt_write(unsigned int idx, uint64_t val) 255c70da546SJoel Hutton { 25633b9be6dSChris Kay assert(amu_supported()); 25781e2ff1fSChris Kay assert(idx < read_amcgcr_cg0nc()); 258c70da546SJoel Hutton 259c70da546SJoel Hutton amu_group0_cnt_write_internal(idx, val); 260c70da546SJoel Hutton isb(); 261c70da546SJoel Hutton } 262c70da546SJoel Hutton 2631fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 264f3ccf036SAlexei Fedorov /* Read the group 1 counter identified by the given `idx` */ 265b4b726eaSChris Kay static uint64_t amu_group1_cnt_read(unsigned int idx) 266c70da546SJoel Hutton { 26733b9be6dSChris Kay assert(amu_supported()); 268f3ccf036SAlexei Fedorov assert(amu_group1_supported()); 26931d3cc25SChris Kay assert(idx < read_amcgcr_cg1nc()); 270c70da546SJoel Hutton 271c70da546SJoel Hutton return amu_group1_cnt_read_internal(idx); 272c70da546SJoel Hutton } 273c70da546SJoel Hutton 274f3ccf036SAlexei Fedorov /* Write the group 1 counter identified by the given `idx` with `val` */ 275b4b726eaSChris Kay static void amu_group1_cnt_write(unsigned int idx, uint64_t val) 276c70da546SJoel Hutton { 27733b9be6dSChris Kay assert(amu_supported()); 278f3ccf036SAlexei Fedorov assert(amu_group1_supported()); 27931d3cc25SChris Kay assert(idx < read_amcgcr_cg1nc()); 280c70da546SJoel Hutton 281c70da546SJoel Hutton amu_group1_cnt_write_internal(idx, val); 282c70da546SJoel Hutton isb(); 283c70da546SJoel Hutton } 2841fd685a7SChris Kay #endif 285b6eb3932SDimitris Papastamos 286b6eb3932SDimitris Papastamos static void *amu_context_save(const void *arg) 287b6eb3932SDimitris Papastamos { 288e747a59bSChris Kay uint32_t i; 289b6eb3932SDimitris Papastamos 290e747a59bSChris Kay unsigned int core_pos; 291e747a59bSChris Kay struct amu_ctx *ctx; 292b6eb3932SDimitris Papastamos 293e747a59bSChris Kay uint32_t id_pfr0_amu; /* AMU version */ 294e747a59bSChris Kay uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ 295b6eb3932SDimitris Papastamos 2961fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 297e747a59bSChris Kay uint32_t amcfgr_ncg; /* Number of counter groups */ 298e747a59bSChris Kay uint32_t amcgcr_cg1nc; /* Number of group 1 counters */ 299f3ccf036SAlexei Fedorov #endif 300e747a59bSChris Kay 301e747a59bSChris Kay id_pfr0_amu = read_id_pfr0_amu(); 302e747a59bSChris Kay if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { 303e747a59bSChris Kay return (void *)0; 304e747a59bSChris Kay } 305e747a59bSChris Kay 306e747a59bSChris Kay core_pos = plat_my_core_pos(); 307e747a59bSChris Kay ctx = &amu_ctxs_[core_pos]; 308e747a59bSChris Kay 309e747a59bSChris Kay amcgcr_cg0nc = read_amcgcr_cg0nc(); 310e747a59bSChris Kay 311e747a59bSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 312e747a59bSChris Kay amcfgr_ncg = read_amcfgr_ncg(); 313e747a59bSChris Kay amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U; 314e747a59bSChris Kay #endif 315e747a59bSChris Kay 316b6eb3932SDimitris Papastamos /* 317e747a59bSChris Kay * Disable all AMU counters. 318b6eb3932SDimitris Papastamos */ 319e747a59bSChris Kay 320e747a59bSChris Kay ctx->group0_enable = read_amcntenset0_px(); 321e747a59bSChris Kay write_amcntenclr0_px(ctx->group0_enable); 322f3ccf036SAlexei Fedorov 3231fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 324e747a59bSChris Kay if (amcfgr_ncg > 0U) { 325e747a59bSChris Kay ctx->group1_enable = read_amcntenset1_px(); 326e747a59bSChris Kay write_amcntenclr1_px(ctx->group1_enable); 3271fd685a7SChris Kay } 328f3ccf036SAlexei Fedorov #endif 3291fd685a7SChris Kay 330e747a59bSChris Kay /* 331e747a59bSChris Kay * Save the counters to the local context. 332e747a59bSChris Kay */ 333b6eb3932SDimitris Papastamos 334e747a59bSChris Kay isb(); /* Ensure counters have been stopped */ 335e747a59bSChris Kay 336e747a59bSChris Kay for (i = 0U; i < amcgcr_cg0nc; i++) { 337c70da546SJoel Hutton ctx->group0_cnts[i] = amu_group0_cnt_read(i); 338f3ccf036SAlexei Fedorov } 339c70da546SJoel Hutton 3401fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 341e747a59bSChris Kay for (i = 0U; i < amcgcr_cg1nc; i++) { 342c70da546SJoel Hutton ctx->group1_cnts[i] = amu_group1_cnt_read(i); 343f3ccf036SAlexei Fedorov } 344f3ccf036SAlexei Fedorov #endif 3451fd685a7SChris Kay 34640daecc1SAntonio Nino Diaz return (void *)0; 347b6eb3932SDimitris Papastamos } 348b6eb3932SDimitris Papastamos 349b6eb3932SDimitris Papastamos static void *amu_context_restore(const void *arg) 350b6eb3932SDimitris Papastamos { 351e747a59bSChris Kay uint32_t i; 352b6eb3932SDimitris Papastamos 353e747a59bSChris Kay unsigned int core_pos; 354e747a59bSChris Kay struct amu_ctx *ctx; 355b6eb3932SDimitris Papastamos 356e747a59bSChris Kay uint32_t id_pfr0_amu; /* AMU version */ 357e747a59bSChris Kay 358e747a59bSChris Kay uint32_t amcfgr_ncg; /* Number of counter groups */ 359e747a59bSChris Kay uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ 360b6eb3932SDimitris Papastamos 3611fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 362e747a59bSChris Kay uint32_t amcgcr_cg1nc; /* Number of group 1 counters */ 363f3ccf036SAlexei Fedorov #endif 364f3ccf036SAlexei Fedorov 365e747a59bSChris Kay id_pfr0_amu = read_id_pfr0_amu(); 366e747a59bSChris Kay if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { 367e747a59bSChris Kay return (void *)0; 368e747a59bSChris Kay } 369e747a59bSChris Kay 370e747a59bSChris Kay core_pos = plat_my_core_pos(); 371e747a59bSChris Kay ctx = &amu_ctxs_[core_pos]; 372e747a59bSChris Kay 373e747a59bSChris Kay amcfgr_ncg = read_amcfgr_ncg(); 374e747a59bSChris Kay amcgcr_cg0nc = read_amcgcr_cg0nc(); 375e747a59bSChris Kay 376e747a59bSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 377e747a59bSChris Kay amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U; 378e747a59bSChris Kay #endif 379e747a59bSChris Kay 380e747a59bSChris Kay /* 381e747a59bSChris Kay * Sanity check that all counters were disabled when the context was 382e747a59bSChris Kay * previously saved. 383e747a59bSChris Kay */ 384e747a59bSChris Kay 385e747a59bSChris Kay assert(read_amcntenset0_px() == 0U); 386e747a59bSChris Kay 387e747a59bSChris Kay if (amcfgr_ncg > 0U) { 388e747a59bSChris Kay assert(read_amcntenset1_px() == 0U); 389e747a59bSChris Kay } 390e747a59bSChris Kay 391e747a59bSChris Kay /* 392e747a59bSChris Kay * Restore the counter values from the local context. 393e747a59bSChris Kay */ 394e747a59bSChris Kay 395e747a59bSChris Kay for (i = 0U; i < amcgcr_cg0nc; i++) { 396c70da546SJoel Hutton amu_group0_cnt_write(i, ctx->group0_cnts[i]); 397f3ccf036SAlexei Fedorov } 398b6eb3932SDimitris Papastamos 3991fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 400e747a59bSChris Kay for (i = 0U; i < amcgcr_cg1nc; i++) { 401f3ccf036SAlexei Fedorov amu_group1_cnt_write(i, ctx->group1_cnts[i]); 402f3ccf036SAlexei Fedorov } 403e747a59bSChris Kay #endif 404f3ccf036SAlexei Fedorov 405e747a59bSChris Kay /* 406e747a59bSChris Kay * Re-enable counters that were disabled during context save. 407e747a59bSChris Kay */ 408e747a59bSChris Kay 409e747a59bSChris Kay write_amcntenset0_px(ctx->group0_enable); 410e747a59bSChris Kay 411e747a59bSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS 412e747a59bSChris Kay if (amcfgr_ncg > 0U) { 413e747a59bSChris Kay write_amcntenset1_px(ctx->group1_enable); 4141fd685a7SChris Kay } 415f3ccf036SAlexei Fedorov #endif 416f3ccf036SAlexei Fedorov 41740daecc1SAntonio Nino Diaz return (void *)0; 418b6eb3932SDimitris Papastamos } 419b6eb3932SDimitris Papastamos 420b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); 421b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore); 422