1*d52ff2b3SArvind Ram Prakash /* 2*d52ff2b3SArvind Ram Prakash * Copyright (c) 2025, Arm Limited. All rights reserved. 3*d52ff2b3SArvind Ram Prakash * 4*d52ff2b3SArvind Ram Prakash * SPDX-License-Identifier: BSD-3-Clause 5*d52ff2b3SArvind Ram Prakash */ 6*d52ff2b3SArvind Ram Prakash 7*d52ff2b3SArvind Ram Prakash #include <assert.h> 8*d52ff2b3SArvind Ram Prakash 9*d52ff2b3SArvind Ram Prakash #include <arch.h> 10*d52ff2b3SArvind Ram Prakash #include <arch_helpers.h> 11*d52ff2b3SArvind Ram Prakash #include <common/bl_common.h> 12*d52ff2b3SArvind Ram Prakash #include <common/debug.h> 13*d52ff2b3SArvind Ram Prakash #include <drivers/arm/dsu.h> 14*d52ff2b3SArvind Ram Prakash #include <dsu_def.h> 15*d52ff2b3SArvind Ram Prakash #include <lib/utils_def.h> 16*d52ff2b3SArvind Ram Prakash 17*d52ff2b3SArvind Ram Prakash #include <plat/arm/common/plat_arm.h> 18*d52ff2b3SArvind Ram Prakash #include <plat/common/platform.h> 19*d52ff2b3SArvind Ram Prakash 20*d52ff2b3SArvind Ram Prakash /* 21*d52ff2b3SArvind Ram Prakash * Context structure that saves the state of DSU PMU registers 22*d52ff2b3SArvind Ram Prakash */ 23*d52ff2b3SArvind Ram Prakash cluster_pmu_state_t cluster_pmu_context[PLAT_ARM_CLUSTER_COUNT]; 24*d52ff2b3SArvind Ram Prakash 25*d52ff2b3SArvind Ram Prakash /**************************************************************************** 26*d52ff2b3SArvind Ram Prakash * This function, save_dsu_pmu_state, is designed to save the 27*d52ff2b3SArvind Ram Prakash * current state of the Performance Monitoring Unit (PMU) for a cluster. 28*d52ff2b3SArvind Ram Prakash * 29*d52ff2b3SArvind Ram Prakash * The function performs the following operations: 30*d52ff2b3SArvind Ram Prakash * 1. Saves the current values of several PMU registers 31*d52ff2b3SArvind Ram Prakash * (CLUSTERPMCR_EL1, CLUSTERPMCNTENSET_EL1, CLUSTERPMCCNTR_EL1, 32*d52ff2b3SArvind Ram Prakash * CLUSTERPMOVSSET_EL1, and CLUSTERPMSELR_EL1) into the cluster_pmu_state 33*d52ff2b3SArvind Ram Prakash * structure. 34*d52ff2b3SArvind Ram Prakash * 35*d52ff2b3SArvind Ram Prakash * 2. Disables the PMU event counting by 36*d52ff2b3SArvind Ram Prakash * clearing the E bit in the clusterpmcr_el1 register. 37*d52ff2b3SArvind Ram Prakash * 38*d52ff2b3SArvind Ram Prakash * 3. Iterates over the available PMU counters as 39*d52ff2b3SArvind Ram Prakash * determined by the read_cluster_eventctr_num() function. 40*d52ff2b3SArvind Ram Prakash * For each counter, it: 41*d52ff2b3SArvind Ram Prakash * a. Selects the counter by writing its index to CLUSTERPMSELR_EL1. 42*d52ff2b3SArvind Ram Prakash * b. Reads the current counter value (event count) and 43*d52ff2b3SArvind Ram Prakash * the event type being counted from CLUSTERPMXEVCNTR_EL1 and 44*d52ff2b3SArvind Ram Prakash * CLUSTERPMXEVTYPER_EL1 registers, respectively. 45*d52ff2b3SArvind Ram Prakash * 46*d52ff2b3SArvind Ram Prakash * This function is useful for preserving the DynamIQ Shared Unit's (DSU) 47*d52ff2b3SArvind Ram Prakash * PMU registers over a power cycle. 48*d52ff2b3SArvind Ram Prakash ***************************************************************************/ 49*d52ff2b3SArvind Ram Prakash 50*d52ff2b3SArvind Ram Prakash void save_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_state) 51*d52ff2b3SArvind Ram Prakash { 52*d52ff2b3SArvind Ram Prakash unsigned int idx = 0U; 53*d52ff2b3SArvind Ram Prakash unsigned int cluster_eventctr_num = read_cluster_eventctr_num(); 54*d52ff2b3SArvind Ram Prakash 55*d52ff2b3SArvind Ram Prakash assert(cluster_pmu_state != 0); 56*d52ff2b3SArvind Ram Prakash 57*d52ff2b3SArvind Ram Prakash save_pmu_reg(cluster_pmu_state, clusterpmcr); 58*d52ff2b3SArvind Ram Prakash 59*d52ff2b3SArvind Ram Prakash write_clusterpmcr(cluster_pmu_state->clusterpmcr & 60*d52ff2b3SArvind Ram Prakash ~(CLUSTERPMCR_E_BIT)); 61*d52ff2b3SArvind Ram Prakash 62*d52ff2b3SArvind Ram Prakash save_pmu_reg(cluster_pmu_state, clusterpmcntenset); 63*d52ff2b3SArvind Ram Prakash 64*d52ff2b3SArvind Ram Prakash save_pmu_reg(cluster_pmu_state, clusterpmccntr); 65*d52ff2b3SArvind Ram Prakash 66*d52ff2b3SArvind Ram Prakash save_pmu_reg(cluster_pmu_state, clusterpmovsset); 67*d52ff2b3SArvind Ram Prakash 68*d52ff2b3SArvind Ram Prakash save_pmu_reg(cluster_pmu_state, clusterpmselr); 69*d52ff2b3SArvind Ram Prakash 70*d52ff2b3SArvind Ram Prakash for (idx = 0U ; idx < cluster_eventctr_num ; idx++) { 71*d52ff2b3SArvind Ram Prakash write_clusterpmselr(idx); 72*d52ff2b3SArvind Ram Prakash cluster_pmu_state->counter_val[idx] = read_clusterpmxevcntr(); 73*d52ff2b3SArvind Ram Prakash cluster_pmu_state->counter_type[idx] = read_clusterpmxevtyper(); 74*d52ff2b3SArvind Ram Prakash } 75*d52ff2b3SArvind Ram Prakash } 76*d52ff2b3SArvind Ram Prakash 77*d52ff2b3SArvind Ram Prakash void cluster_off_dsu_pmu_context_save(void) 78*d52ff2b3SArvind Ram Prakash { 79*d52ff2b3SArvind Ram Prakash unsigned int cluster_pos; 80*d52ff2b3SArvind Ram Prakash 81*d52ff2b3SArvind Ram Prakash cluster_pos = (unsigned int) plat_cluster_id_by_mpidr(read_mpidr_el1()); 82*d52ff2b3SArvind Ram Prakash 83*d52ff2b3SArvind Ram Prakash save_dsu_pmu_state(&cluster_pmu_context[cluster_pos]); 84*d52ff2b3SArvind Ram Prakash } 85*d52ff2b3SArvind Ram Prakash 86*d52ff2b3SArvind Ram Prakash /***************************************************************************** 87*d52ff2b3SArvind Ram Prakash * This function, restore_dsu_pmu_state, restores the state of the 88*d52ff2b3SArvind Ram Prakash * Performance Monitoring Unit (PMU) from a previously saved state. 89*d52ff2b3SArvind Ram Prakash * 90*d52ff2b3SArvind Ram Prakash * The function performs the following operations: 91*d52ff2b3SArvind Ram Prakash * 1. Restores the CLUSTERPMCR_EL1 register with the 92*d52ff2b3SArvind Ram Prakash * saved value from the cluster_pmu_state structure. 93*d52ff2b3SArvind Ram Prakash * 2. Iterates over the available PMU counters as determined 94*d52ff2b3SArvind Ram Prakash * by the read_cluster_eventctr_num() function. For each counter, it: 95*d52ff2b3SArvind Ram Prakash * a. Selects the counter by writing its index to CLUSTERPMSELR_EL1. 96*d52ff2b3SArvind Ram Prakash * b. Restores the counter value (event count) and the event type to 97*d52ff2b3SArvind Ram Prakash * CLUSTERPMXEVCNTR_EL1 and CLUSTERPMXEVTYPER_EL1 registers, respectively 98*d52ff2b3SArvind Ram Prakash * 3. Restores several other PMU registers (CLUSTERPMSELR_EL1, 99*d52ff2b3SArvind Ram Prakash * CLUSTERPMOVSCLR_EL1, CLUSTERPMOVSSET_EL1, CLUSTERPMCCNTR_EL1, 100*d52ff2b3SArvind Ram Prakash * and CLUSTERPMCNTENSET_EL1) with their saved values. 101*d52ff2b3SArvind Ram Prakash * 102*d52ff2b3SArvind Ram Prakash *****************************************************************************/ 103*d52ff2b3SArvind Ram Prakash void restore_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_state) 104*d52ff2b3SArvind Ram Prakash { 105*d52ff2b3SArvind Ram Prakash unsigned int idx = 0U; 106*d52ff2b3SArvind Ram Prakash unsigned int cluster_eventctr_num = read_cluster_eventctr_num(); 107*d52ff2b3SArvind Ram Prakash 108*d52ff2b3SArvind Ram Prakash assert(cluster_pmu_state != 0); 109*d52ff2b3SArvind Ram Prakash 110*d52ff2b3SArvind Ram Prakash for (idx = 0U ; idx < cluster_eventctr_num ; idx++) { 111*d52ff2b3SArvind Ram Prakash write_clusterpmselr(idx); 112*d52ff2b3SArvind Ram Prakash write_clusterpmxevcntr(cluster_pmu_state->counter_val[idx]); 113*d52ff2b3SArvind Ram Prakash write_clusterpmxevtyper(cluster_pmu_state->counter_type[idx]); 114*d52ff2b3SArvind Ram Prakash } 115*d52ff2b3SArvind Ram Prakash 116*d52ff2b3SArvind Ram Prakash restore_pmu_reg(cluster_pmu_state, clusterpmselr); 117*d52ff2b3SArvind Ram Prakash 118*d52ff2b3SArvind Ram Prakash write_clusterpmovsclr(~(uint32_t)cluster_pmu_state->clusterpmovsset); 119*d52ff2b3SArvind Ram Prakash 120*d52ff2b3SArvind Ram Prakash restore_pmu_reg(cluster_pmu_state, clusterpmovsset); 121*d52ff2b3SArvind Ram Prakash 122*d52ff2b3SArvind Ram Prakash restore_pmu_reg(cluster_pmu_state, clusterpmccntr); 123*d52ff2b3SArvind Ram Prakash 124*d52ff2b3SArvind Ram Prakash restore_pmu_reg(cluster_pmu_state, clusterpmcntenset); 125*d52ff2b3SArvind Ram Prakash 126*d52ff2b3SArvind Ram Prakash write_clusterpmcr(cluster_pmu_state->clusterpmcr); 127*d52ff2b3SArvind Ram Prakash } 128*d52ff2b3SArvind Ram Prakash 129*d52ff2b3SArvind Ram Prakash void cluster_on_dsu_pmu_context_restore(void) 130*d52ff2b3SArvind Ram Prakash { 131*d52ff2b3SArvind Ram Prakash unsigned int cluster_pos; 132*d52ff2b3SArvind Ram Prakash 133*d52ff2b3SArvind Ram Prakash cluster_pos = (unsigned int) plat_cluster_id_by_mpidr(read_mpidr_el1()); 134*d52ff2b3SArvind Ram Prakash 135*d52ff2b3SArvind Ram Prakash restore_dsu_pmu_state(&cluster_pmu_context[cluster_pos]); 136*d52ff2b3SArvind Ram Prakash } 137*d52ff2b3SArvind Ram Prakash 138*d52ff2b3SArvind Ram Prakash void dsu_driver_init(const dsu_driver_data_t *plat_driver_data) 139*d52ff2b3SArvind Ram Prakash { 140*d52ff2b3SArvind Ram Prakash uint64_t actlr_el3 = read_actlr_el3(); 141*d52ff2b3SArvind Ram Prakash uint64_t pwrctlr = read_clusterpwrctlr_el1(); 142*d52ff2b3SArvind Ram Prakash uint64_t pwrdn = read_clusterpwrdn_el1(); 143*d52ff2b3SArvind Ram Prakash 144*d52ff2b3SArvind Ram Prakash /* enable access to power control registers. */ 145*d52ff2b3SArvind Ram Prakash actlr_el3 |= ACTLR_EL3_PWREN_BIT; 146*d52ff2b3SArvind Ram Prakash write_actlr_el3(actlr_el3); 147*d52ff2b3SArvind Ram Prakash 148*d52ff2b3SArvind Ram Prakash UPDATE_REG_FIELD(CLUSTERPWRCTLR_FUNCRET, pwrctlr, 149*d52ff2b3SArvind Ram Prakash plat_driver_data->clusterpwrctlr_funcret); 150*d52ff2b3SArvind Ram Prakash 151*d52ff2b3SArvind Ram Prakash UPDATE_REG_FIELD(CLUSTERPWRCTLR_CACHEPWR, pwrctlr, 152*d52ff2b3SArvind Ram Prakash plat_driver_data->clusterpwrctlr_cachepwr); 153*d52ff2b3SArvind Ram Prakash 154*d52ff2b3SArvind Ram Prakash write_clusterpwrctlr_el1(pwrctlr); 155*d52ff2b3SArvind Ram Prakash 156*d52ff2b3SArvind Ram Prakash UPDATE_REG_FIELD(CLUSTERPWRDN_PWRDN, pwrdn, 157*d52ff2b3SArvind Ram Prakash plat_driver_data->clusterpwrdwn_pwrdn); 158*d52ff2b3SArvind Ram Prakash 159*d52ff2b3SArvind Ram Prakash UPDATE_REG_FIELD(CLUSTERPWRDN_MEMRET, pwrdn, 160*d52ff2b3SArvind Ram Prakash plat_driver_data->clusterpwrdwn_memret); 161*d52ff2b3SArvind Ram Prakash 162*d52ff2b3SArvind Ram Prakash write_clusterpwrdn_el1(pwrdn); 163*d52ff2b3SArvind Ram Prakash } 164*d52ff2b3SArvind Ram Prakash 165