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