xref: /rk3399_ARM-atf/lib/extensions/amu/aarch32/amu.c (revision 40daecc1be51383c806c0ac953303e47026abcac)
1ef69e1eaSDimitris Papastamos /*
2c6cc9ac3SDimitris Papastamos  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3ef69e1eaSDimitris Papastamos  *
4ef69e1eaSDimitris Papastamos  * SPDX-License-Identifier: BSD-3-Clause
5ef69e1eaSDimitris Papastamos  */
6ef69e1eaSDimitris Papastamos 
7ef69e1eaSDimitris Papastamos #include <amu.h>
8c70da546SJoel Hutton #include <amu_private.h>
9ef69e1eaSDimitris Papastamos #include <arch.h>
10ef69e1eaSDimitris Papastamos #include <arch_helpers.h>
11b6eb3932SDimitris Papastamos #include <platform.h>
12b6eb3932SDimitris Papastamos #include <pubsub_events.h>
13*40daecc1SAntonio Nino Diaz #include <stdbool.h>
14b6eb3932SDimitris Papastamos 
15b6eb3932SDimitris Papastamos #define AMU_GROUP0_NR_COUNTERS	4
16b6eb3932SDimitris Papastamos 
17b6eb3932SDimitris Papastamos struct amu_ctx {
18b6eb3932SDimitris Papastamos 	uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
19c70da546SJoel Hutton 	uint64_t group1_cnts[AMU_GROUP1_NR_COUNTERS];
20b6eb3932SDimitris Papastamos };
21b6eb3932SDimitris Papastamos 
22b6eb3932SDimitris Papastamos static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
23ef69e1eaSDimitris Papastamos 
24*40daecc1SAntonio Nino Diaz bool amu_supported(void)
25ef69e1eaSDimitris Papastamos {
26ef69e1eaSDimitris Papastamos 	uint64_t features;
27ef69e1eaSDimitris Papastamos 
28ef69e1eaSDimitris Papastamos 	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
29*40daecc1SAntonio Nino Diaz 	return (features & ID_PFR0_AMU_MASK) == 1U;
30c70da546SJoel Hutton }
31c70da546SJoel Hutton 
32*40daecc1SAntonio Nino Diaz void amu_enable(bool el2_unused)
33c70da546SJoel Hutton {
34*40daecc1SAntonio Nino Diaz 	if (!amu_supported())
350767d50eSDimitris Papastamos 		return;
360767d50eSDimitris Papastamos 
37ef69e1eaSDimitris Papastamos 	if (el2_unused) {
38ef69e1eaSDimitris Papastamos 		uint64_t v;
39ef69e1eaSDimitris Papastamos 		/*
40ef69e1eaSDimitris Papastamos 		 * Non-secure access from EL0 or EL1 to the Activity Monitor
41ef69e1eaSDimitris Papastamos 		 * registers do not trap to EL2.
42ef69e1eaSDimitris Papastamos 		 */
43ef69e1eaSDimitris Papastamos 		v = read_hcptr();
44ef69e1eaSDimitris Papastamos 		v &= ~TAM_BIT;
45ef69e1eaSDimitris Papastamos 		write_hcptr(v);
46ef69e1eaSDimitris Papastamos 	}
47ef69e1eaSDimitris Papastamos 
48ef69e1eaSDimitris Papastamos 	/* Enable group 0 counters */
49ef69e1eaSDimitris Papastamos 	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
50c70da546SJoel Hutton 
51c70da546SJoel Hutton 	/* Enable group 1 counters */
52c70da546SJoel Hutton 	write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
53c70da546SJoel Hutton }
54c70da546SJoel Hutton 
55c70da546SJoel Hutton /* Read the group 0 counter identified by the given `idx`. */
56c70da546SJoel Hutton uint64_t amu_group0_cnt_read(int idx)
57c70da546SJoel Hutton {
58*40daecc1SAntonio Nino Diaz 	assert(amu_supported());
59*40daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
60c70da546SJoel Hutton 
61c70da546SJoel Hutton 	return amu_group0_cnt_read_internal(idx);
62c70da546SJoel Hutton }
63c70da546SJoel Hutton 
64c70da546SJoel Hutton /* Write the group 0 counter identified by the given `idx` with `val`. */
65c70da546SJoel Hutton void amu_group0_cnt_write(int idx, uint64_t val)
66c70da546SJoel Hutton {
67*40daecc1SAntonio Nino Diaz 	assert(amu_supported());
68*40daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS));
69c70da546SJoel Hutton 
70c70da546SJoel Hutton 	amu_group0_cnt_write_internal(idx, val);
71c70da546SJoel Hutton 	isb();
72c70da546SJoel Hutton }
73c70da546SJoel Hutton 
74c70da546SJoel Hutton /* Read the group 1 counter identified by the given `idx`. */
75c70da546SJoel Hutton uint64_t amu_group1_cnt_read(int idx)
76c70da546SJoel Hutton {
77*40daecc1SAntonio Nino Diaz 	assert(amu_supported());
78*40daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
79c70da546SJoel Hutton 
80c70da546SJoel Hutton 	return amu_group1_cnt_read_internal(idx);
81c70da546SJoel Hutton }
82c70da546SJoel Hutton 
83c70da546SJoel Hutton /* Write the group 1 counter identified by the given `idx` with `val`. */
84c70da546SJoel Hutton void amu_group1_cnt_write(int idx, uint64_t val)
85c70da546SJoel Hutton {
86*40daecc1SAntonio Nino Diaz 	assert(amu_supported());
87*40daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
88c70da546SJoel Hutton 
89c70da546SJoel Hutton 	amu_group1_cnt_write_internal(idx, val);
90c70da546SJoel Hutton 	isb();
91c70da546SJoel Hutton }
92c70da546SJoel Hutton 
93c70da546SJoel Hutton void amu_group1_set_evtype(int idx, unsigned int val)
94c70da546SJoel Hutton {
95*40daecc1SAntonio Nino Diaz 	assert(amu_supported());
96*40daecc1SAntonio Nino Diaz 	assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS));
97c70da546SJoel Hutton 
98c70da546SJoel Hutton 	amu_group1_set_evtype_internal(idx, val);
99c70da546SJoel Hutton 	isb();
100ef69e1eaSDimitris Papastamos }
101b6eb3932SDimitris Papastamos 
102b6eb3932SDimitris Papastamos static void *amu_context_save(const void *arg)
103b6eb3932SDimitris Papastamos {
104b6eb3932SDimitris Papastamos 	struct amu_ctx *ctx;
105c70da546SJoel Hutton 	int i;
106b6eb3932SDimitris Papastamos 
107*40daecc1SAntonio Nino Diaz 	if (!amu_supported())
108b6eb3932SDimitris Papastamos 		return (void *)-1;
109b6eb3932SDimitris Papastamos 
110b6eb3932SDimitris Papastamos 	ctx = &amu_ctxs[plat_my_core_pos()];
111b6eb3932SDimitris Papastamos 
112b6eb3932SDimitris Papastamos 	/* Assert that group 0 counter configuration is what we expect */
113e6e17ee8SDimitris Papastamos 	assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK &&
114e6e17ee8SDimitris Papastamos 	       read_amcntenset1() == AMU_GROUP1_COUNTERS_MASK);
115b6eb3932SDimitris Papastamos 
116b6eb3932SDimitris Papastamos 	/*
117b6eb3932SDimitris Papastamos 	 * Disable group 0 counters to avoid other observers like SCP sampling
118b6eb3932SDimitris Papastamos 	 * counter values from the future via the memory mapped view.
119b6eb3932SDimitris Papastamos 	 */
120b6eb3932SDimitris Papastamos 	write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK);
121c70da546SJoel Hutton 	write_amcntenclr1(AMU_GROUP1_COUNTERS_MASK);
122b6eb3932SDimitris Papastamos 	isb();
123b6eb3932SDimitris Papastamos 
124c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
125c70da546SJoel Hutton 		ctx->group0_cnts[i] = amu_group0_cnt_read(i);
126c70da546SJoel Hutton 
127c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
128c70da546SJoel Hutton 		ctx->group1_cnts[i] = amu_group1_cnt_read(i);
129b6eb3932SDimitris Papastamos 
130*40daecc1SAntonio Nino Diaz 	return (void *)0;
131b6eb3932SDimitris Papastamos }
132b6eb3932SDimitris Papastamos 
133b6eb3932SDimitris Papastamos static void *amu_context_restore(const void *arg)
134b6eb3932SDimitris Papastamos {
135b6eb3932SDimitris Papastamos 	struct amu_ctx *ctx;
136c70da546SJoel Hutton 	int i;
137b6eb3932SDimitris Papastamos 
138*40daecc1SAntonio Nino Diaz 	if (!amu_supported())
139b6eb3932SDimitris Papastamos 		return (void *)-1;
140b6eb3932SDimitris Papastamos 
141b6eb3932SDimitris Papastamos 	ctx = &amu_ctxs[plat_my_core_pos()];
142b6eb3932SDimitris Papastamos 
143b6eb3932SDimitris Papastamos 	/* Counters were disabled in `amu_context_save()` */
144*40daecc1SAntonio Nino Diaz 	assert((read_amcntenset0() == 0U) && (read_amcntenset1() == 0U));
145b6eb3932SDimitris Papastamos 
146b6eb3932SDimitris Papastamos 	/* Restore group 0 counters */
147c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
148c70da546SJoel Hutton 		amu_group0_cnt_write(i, ctx->group0_cnts[i]);
149c70da546SJoel Hutton 	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
150c70da546SJoel Hutton 		amu_group1_cnt_write(i, ctx->group1_cnts[i]);
151b6eb3932SDimitris Papastamos 
152b6eb3932SDimitris Papastamos 	/* Enable group 0 counters */
153b6eb3932SDimitris Papastamos 	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
154b6eb3932SDimitris Papastamos 
155c70da546SJoel Hutton 	/* Enable group 1 counters */
156c70da546SJoel Hutton 	write_amcntenset1(AMU_GROUP1_COUNTERS_MASK);
157*40daecc1SAntonio Nino Diaz 	return (void *)0;
158b6eb3932SDimitris Papastamos }
159b6eb3932SDimitris Papastamos 
160b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
161b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);
162