xref: /rk3399_ARM-atf/drivers/arm/dsu/dsu.c (revision 1e8b5354574ac389bb3d29fdfcb9631cc8108ccb)
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