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