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