xref: /rk3399_ARM-atf/drivers/arm/dsu/dsu.c (revision 084b886495ee167a3601e43ea9a25ace8e4c74d5)
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 
save_dsu_pmu_state(cluster_pmu_state_t * cluster_pmu_state)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 
cluster_off_dsu_pmu_context_save(void)77 void cluster_off_dsu_pmu_context_save(void)
78 {
79 	unsigned int cluster_pos = plat_cluster_id_by_mpidr(read_mpidr_el1());
80 
81 	assert(cluster_pos < ARRAY_SIZE(cluster_pmu_context));
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  *****************************************************************************/
restore_dsu_pmu_state(cluster_pmu_state_t * cluster_pmu_state)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 
cluster_on_dsu_pmu_context_restore(void)129 void cluster_on_dsu_pmu_context_restore(void)
130 {
131 	unsigned int cluster_pos = plat_cluster_id_by_mpidr(read_mpidr_el1());
132 
133 	assert(cluster_pos < ARRAY_SIZE(cluster_pmu_context));
134 
135 	restore_dsu_pmu_state(&cluster_pmu_context[cluster_pos]);
136 }
137 
dsu_driver_init(const dsu_driver_data_t * plat_driver_data)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 actlr_el2 = read_actlr_el2();
142 	uint64_t pwrctlr = read_clusterpwrctlr_el1();
143 	uint64_t pwrdn = read_clusterpwrdn_el1();
144 	unsigned int pmmdcr_el3 = read_clusterpmmdcr_el3();
145 
146 	/* Prohibit PMU event counting in secure state */
147 	pmmdcr_el3 &= ~CLUSTERPMMDCR_SPME;
148 	write_clusterpmmdcr_el3(pmmdcr_el3);
149 
150 	/* enable access to power control and PMU registers. */
151 	actlr_el3 |= ACTLR_EL3_PWREN_BIT | ACTLR_CLUSTERPMUEN;
152 	write_actlr_el3(actlr_el3);
153 	actlr_el2 |= ACTLR_CLUSTERPMUEN;
154 	write_actlr_el2(actlr_el2);
155 
156 	UPDATE_REG_FIELD(CLUSTERPWRCTLR_FUNCRET, pwrctlr,
157 			plat_driver_data->clusterpwrctlr_funcret);
158 
159 	UPDATE_REG_FIELD(CLUSTERPWRCTLR_CACHEPWR, pwrctlr,
160 			plat_driver_data->clusterpwrctlr_cachepwr);
161 
162 	write_clusterpwrctlr_el1(pwrctlr);
163 
164 	UPDATE_REG_FIELD(CLUSTERPWRDN_PWRDN, pwrdn,
165 			plat_driver_data->clusterpwrdwn_pwrdn);
166 
167 	UPDATE_REG_FIELD(CLUSTERPWRDN_MEMRET, pwrdn,
168 			plat_driver_data->clusterpwrdwn_memret);
169 
170 	write_clusterpwrdn_el1(pwrdn);
171 }
172 
173