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