xref: /rk3399_ARM-atf/lib/extensions/amu/aarch64/amu.c (revision 0767d50e699d3d9cb827172dd7742618d37aabe0)
1380559c1SDimitris Papastamos /*
2380559c1SDimitris Papastamos  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3380559c1SDimitris Papastamos  *
4380559c1SDimitris Papastamos  * SPDX-License-Identifier: BSD-3-Clause
5380559c1SDimitris Papastamos  */
6380559c1SDimitris Papastamos 
7380559c1SDimitris Papastamos #include <amu.h>
8*0767d50eSDimitris Papastamos #include <amu_private.h>
9380559c1SDimitris Papastamos #include <arch.h>
10380559c1SDimitris Papastamos #include <arch_helpers.h>
11*0767d50eSDimitris Papastamos #include <assert.h>
12*0767d50eSDimitris Papastamos #include <debug.h>
13380559c1SDimitris Papastamos 
14*0767d50eSDimitris Papastamos #define AMU_GROUP0_NR_COUNTERS	4
15*0767d50eSDimitris Papastamos 
16*0767d50eSDimitris Papastamos int amu_supported(void)
17380559c1SDimitris Papastamos {
18380559c1SDimitris Papastamos 	uint64_t features;
19380559c1SDimitris Papastamos 
20380559c1SDimitris Papastamos 	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT;
21*0767d50eSDimitris Papastamos 	return (features & ID_AA64PFR0_AMU_MASK) == 1;
22*0767d50eSDimitris Papastamos }
23*0767d50eSDimitris Papastamos 
24*0767d50eSDimitris Papastamos /*
25*0767d50eSDimitris Papastamos  * Enable counters.  This function is meant to be invoked
26*0767d50eSDimitris Papastamos  * by the context management library before exiting from EL3.
27*0767d50eSDimitris Papastamos  */
28*0767d50eSDimitris Papastamos void amu_enable(int el2_unused)
29*0767d50eSDimitris Papastamos {
30380559c1SDimitris Papastamos 	uint64_t v;
31380559c1SDimitris Papastamos 
32*0767d50eSDimitris Papastamos 	if (!amu_supported()) {
33*0767d50eSDimitris Papastamos 		WARN("Cannot enable AMU - not supported\n");
34*0767d50eSDimitris Papastamos 		return;
35*0767d50eSDimitris Papastamos 	}
36*0767d50eSDimitris Papastamos 
37380559c1SDimitris Papastamos 	if (el2_unused) {
38380559c1SDimitris Papastamos 		/*
39380559c1SDimitris Papastamos 		 * CPTR_EL2.TAM: Set to zero so any accesses to
40380559c1SDimitris Papastamos 		 * the Activity Monitor registers do not trap to EL2.
41380559c1SDimitris Papastamos 		 */
42380559c1SDimitris Papastamos 		v = read_cptr_el2();
43380559c1SDimitris Papastamos 		v &= ~CPTR_EL2_TAM_BIT;
44380559c1SDimitris Papastamos 		write_cptr_el2(v);
45380559c1SDimitris Papastamos 	}
46380559c1SDimitris Papastamos 
47380559c1SDimitris Papastamos 	/*
48380559c1SDimitris Papastamos 	 * CPTR_EL3.TAM: Set to zero so that any accesses to
49380559c1SDimitris Papastamos 	 * the Activity Monitor registers do not trap to EL3.
50380559c1SDimitris Papastamos 	 */
51380559c1SDimitris Papastamos 	v = read_cptr_el3();
52380559c1SDimitris Papastamos 	v &= ~TAM_BIT;
53380559c1SDimitris Papastamos 	write_cptr_el3(v);
54380559c1SDimitris Papastamos 
55380559c1SDimitris Papastamos 	/* Enable group 0 counters */
56380559c1SDimitris Papastamos 	write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
5759902b7cSDimitris Papastamos 	/* Enable group 1 counters */
5859902b7cSDimitris Papastamos 	write_amcntenset1_el0(AMU_GROUP1_COUNTERS_MASK);
59380559c1SDimitris Papastamos }
60*0767d50eSDimitris Papastamos 
61*0767d50eSDimitris Papastamos /* Read the group 0 counter identified by the given `idx`. */
62*0767d50eSDimitris Papastamos uint64_t amu_group0_cnt_read(int idx)
63*0767d50eSDimitris Papastamos {
64*0767d50eSDimitris Papastamos 	assert(amu_supported());
65*0767d50eSDimitris Papastamos 	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
66*0767d50eSDimitris Papastamos 
67*0767d50eSDimitris Papastamos 	return amu_group0_cnt_read_internal(idx);
68*0767d50eSDimitris Papastamos }
69*0767d50eSDimitris Papastamos 
70*0767d50eSDimitris Papastamos /* Write the group 0 counter identified by the given `idx` with `val`. */
71*0767d50eSDimitris Papastamos void amu_group0_cnt_write(int idx, uint64_t val)
72*0767d50eSDimitris Papastamos {
73*0767d50eSDimitris Papastamos 	assert(amu_supported());
74*0767d50eSDimitris Papastamos 	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
75*0767d50eSDimitris Papastamos 
76*0767d50eSDimitris Papastamos 	amu_group0_cnt_write_internal(idx, val);
77*0767d50eSDimitris Papastamos 	isb();
78*0767d50eSDimitris Papastamos }
79*0767d50eSDimitris Papastamos 
80*0767d50eSDimitris Papastamos /* Read the group 1 counter identified by the given `idx`. */
81*0767d50eSDimitris Papastamos uint64_t amu_group1_cnt_read(int idx)
82*0767d50eSDimitris Papastamos {
83*0767d50eSDimitris Papastamos 	assert(amu_supported());
84*0767d50eSDimitris Papastamos 	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
85*0767d50eSDimitris Papastamos 
86*0767d50eSDimitris Papastamos 	return amu_group1_cnt_read_internal(idx);
87*0767d50eSDimitris Papastamos }
88*0767d50eSDimitris Papastamos 
89*0767d50eSDimitris Papastamos /* Write the group 1 counter identified by the given `idx` with `val`. */
90*0767d50eSDimitris Papastamos void amu_group1_cnt_write(int idx, uint64_t val)
91*0767d50eSDimitris Papastamos {
92*0767d50eSDimitris Papastamos 	assert(amu_supported());
93*0767d50eSDimitris Papastamos 	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
94*0767d50eSDimitris Papastamos 
95*0767d50eSDimitris Papastamos 	amu_group1_cnt_write_internal(idx, val);
96*0767d50eSDimitris Papastamos 	isb();
97*0767d50eSDimitris Papastamos }
98*0767d50eSDimitris Papastamos 
99*0767d50eSDimitris Papastamos /*
100*0767d50eSDimitris Papastamos  * Program the event type register for the given `idx` with
101*0767d50eSDimitris Papastamos  * the event number `val`.
102*0767d50eSDimitris Papastamos  */
103*0767d50eSDimitris Papastamos void amu_group1_set_evtype(int idx, unsigned int val)
104*0767d50eSDimitris Papastamos {
105*0767d50eSDimitris Papastamos 	assert(amu_supported());
106*0767d50eSDimitris Papastamos 	assert (idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
107*0767d50eSDimitris Papastamos 
108*0767d50eSDimitris Papastamos 	amu_group1_set_evtype_internal(idx, val);
109*0767d50eSDimitris Papastamos 	isb();
110380559c1SDimitris Papastamos }
111