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