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