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