xref: /rk3399_ARM-atf/lib/extensions/amu/aarch32/amu.c (revision b6eb39327c5b009bc0bbecdb6867d8bf7c05f2fd)
1ef69e1eaSDimitris Papastamos /*
2ef69e1eaSDimitris Papastamos  * Copyright (c) 2017, 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>
8ef69e1eaSDimitris Papastamos #include <arch.h>
9ef69e1eaSDimitris Papastamos #include <arch_helpers.h>
100767d50eSDimitris Papastamos #include <debug.h>
11*b6eb3932SDimitris Papastamos #include <platform.h>
12*b6eb3932SDimitris Papastamos #include <pubsub_events.h>
13*b6eb3932SDimitris Papastamos 
14*b6eb3932SDimitris Papastamos #define AMU_GROUP0_NR_COUNTERS	4
15*b6eb3932SDimitris Papastamos 
16*b6eb3932SDimitris Papastamos struct amu_ctx {
17*b6eb3932SDimitris Papastamos 	uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
18*b6eb3932SDimitris Papastamos };
19*b6eb3932SDimitris Papastamos 
20*b6eb3932SDimitris Papastamos static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
21ef69e1eaSDimitris Papastamos 
22ef69e1eaSDimitris Papastamos void amu_enable(int el2_unused)
23ef69e1eaSDimitris Papastamos {
24ef69e1eaSDimitris Papastamos 	uint64_t features;
25ef69e1eaSDimitris Papastamos 
26ef69e1eaSDimitris Papastamos 	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
270767d50eSDimitris Papastamos 	if ((features & ID_PFR0_AMU_MASK) != 1) {
280767d50eSDimitris Papastamos 		WARN("Cannot enable AMU - not supported\n");
290767d50eSDimitris Papastamos 		return;
300767d50eSDimitris Papastamos 	}
310767d50eSDimitris Papastamos 
32ef69e1eaSDimitris Papastamos 	if (el2_unused) {
33ef69e1eaSDimitris Papastamos 		uint64_t v;
34ef69e1eaSDimitris Papastamos 
35ef69e1eaSDimitris Papastamos 		/*
36ef69e1eaSDimitris Papastamos 		 * Non-secure access from EL0 or EL1 to the Activity Monitor
37ef69e1eaSDimitris Papastamos 		 * registers do not trap to EL2.
38ef69e1eaSDimitris Papastamos 		 */
39ef69e1eaSDimitris Papastamos 		v = read_hcptr();
40ef69e1eaSDimitris Papastamos 		v &= ~TAM_BIT;
41ef69e1eaSDimitris Papastamos 		write_hcptr(v);
42ef69e1eaSDimitris Papastamos 	}
43ef69e1eaSDimitris Papastamos 
44ef69e1eaSDimitris Papastamos 	/* Enable group 0 counters */
45ef69e1eaSDimitris Papastamos 	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
46ef69e1eaSDimitris Papastamos }
47*b6eb3932SDimitris Papastamos 
48*b6eb3932SDimitris Papastamos static void *amu_context_save(const void *arg)
49*b6eb3932SDimitris Papastamos {
50*b6eb3932SDimitris Papastamos 	struct amu_ctx *ctx;
51*b6eb3932SDimitris Papastamos 	uint64_t features;
52*b6eb3932SDimitris Papastamos 
53*b6eb3932SDimitris Papastamos 	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
54*b6eb3932SDimitris Papastamos 	if ((features & ID_PFR0_AMU_MASK) != 1)
55*b6eb3932SDimitris Papastamos 		return (void *)-1;
56*b6eb3932SDimitris Papastamos 
57*b6eb3932SDimitris Papastamos 	ctx = &amu_ctxs[plat_my_core_pos()];
58*b6eb3932SDimitris Papastamos 
59*b6eb3932SDimitris Papastamos 	/* Assert that group 0 counter configuration is what we expect */
60*b6eb3932SDimitris Papastamos 	assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK);
61*b6eb3932SDimitris Papastamos 
62*b6eb3932SDimitris Papastamos 	/*
63*b6eb3932SDimitris Papastamos 	 * Disable group 0 counters to avoid other observers like SCP sampling
64*b6eb3932SDimitris Papastamos 	 * counter values from the future via the memory mapped view.
65*b6eb3932SDimitris Papastamos 	 */
66*b6eb3932SDimitris Papastamos 	write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK);
67*b6eb3932SDimitris Papastamos 	isb();
68*b6eb3932SDimitris Papastamos 
69*b6eb3932SDimitris Papastamos 	ctx->group0_cnts[0] = read64_amevcntr00();
70*b6eb3932SDimitris Papastamos 	ctx->group0_cnts[1] = read64_amevcntr01();
71*b6eb3932SDimitris Papastamos 	ctx->group0_cnts[2] = read64_amevcntr02();
72*b6eb3932SDimitris Papastamos 	ctx->group0_cnts[3] = read64_amevcntr03();
73*b6eb3932SDimitris Papastamos 
74*b6eb3932SDimitris Papastamos 	return 0;
75*b6eb3932SDimitris Papastamos }
76*b6eb3932SDimitris Papastamos 
77*b6eb3932SDimitris Papastamos static void *amu_context_restore(const void *arg)
78*b6eb3932SDimitris Papastamos {
79*b6eb3932SDimitris Papastamos 	struct amu_ctx *ctx;
80*b6eb3932SDimitris Papastamos 	uint64_t features;
81*b6eb3932SDimitris Papastamos 
82*b6eb3932SDimitris Papastamos 	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
83*b6eb3932SDimitris Papastamos 	if ((features & ID_PFR0_AMU_MASK) != 1)
84*b6eb3932SDimitris Papastamos 		return (void *)-1;
85*b6eb3932SDimitris Papastamos 
86*b6eb3932SDimitris Papastamos 	ctx = &amu_ctxs[plat_my_core_pos()];
87*b6eb3932SDimitris Papastamos 
88*b6eb3932SDimitris Papastamos 	/* Counters were disabled in `amu_context_save()` */
89*b6eb3932SDimitris Papastamos 	assert(read_amcntenset0() == 0);
90*b6eb3932SDimitris Papastamos 
91*b6eb3932SDimitris Papastamos 	/* Restore group 0 counters */
92*b6eb3932SDimitris Papastamos 	if (AMU_GROUP0_COUNTERS_MASK & (1U << 0))
93*b6eb3932SDimitris Papastamos 		write64_amevcntr00(ctx->group0_cnts[0]);
94*b6eb3932SDimitris Papastamos 	if (AMU_GROUP0_COUNTERS_MASK & (1U << 1))
95*b6eb3932SDimitris Papastamos 		write64_amevcntr01(ctx->group0_cnts[1]);
96*b6eb3932SDimitris Papastamos 	if (AMU_GROUP0_COUNTERS_MASK & (1U << 2))
97*b6eb3932SDimitris Papastamos 		write64_amevcntr02(ctx->group0_cnts[2]);
98*b6eb3932SDimitris Papastamos 	if (AMU_GROUP0_COUNTERS_MASK & (1U << 3))
99*b6eb3932SDimitris Papastamos 		write64_amevcntr03(ctx->group0_cnts[3]);
100*b6eb3932SDimitris Papastamos 	isb();
101*b6eb3932SDimitris Papastamos 
102*b6eb3932SDimitris Papastamos 	/* Enable group 0 counters */
103*b6eb3932SDimitris Papastamos 	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
104*b6eb3932SDimitris Papastamos 
105*b6eb3932SDimitris Papastamos 	return 0;
106*b6eb3932SDimitris Papastamos }
107*b6eb3932SDimitris Papastamos 
108*b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
109*b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);
110