blob: 0a1e65384a280bacfd419babf9edceed27834dcb [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
johpow01b7d752a2020-10-08 17:29:11 -05002 * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <amu.h>
8#include <amu_private.h>
9#include <arch.h>
10#include <arch_helpers.h>
11#include <assert.h>
12
johpow01b7d752a2020-10-08 17:29:11 -050013/*
14 * Get AMU version value from aa64pfr0.
15 * Return values
16 * ID_AA64PFR0_AMU_V1: FEAT_AMUv1 supported (introduced in ARM v8.4)
17 * ID_AA64PFR0_AMU_V1P1: FEAT_AMUv1p1 supported (introduced in ARM v8.6)
18 * ID_AA64PFR0_AMU_NOT_SUPPORTED: not supported
19 */
20unsigned int amu_get_version(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020021{
johpow01b7d752a2020-10-08 17:29:11 -050022 return (unsigned int)(read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
23 ID_AA64PFR0_AMU_MASK;
24}
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020025
johpow01b7d752a2020-10-08 17:29:11 -050026/* Check if group 1 counters is implemented */
27int amu_group1_supported(void)
28{
29 uint64_t features = read_amcfgr_el0() >> AMCFGR_EL0_NCG_SHIFT;
30
31 return (features & AMCFGR_EL0_NCG_MASK) == 1U;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020032}
33
34/* Read the group 0 counter identified by the given `idx`. */
johpow01b7d752a2020-10-08 17:29:11 -050035uint64_t amu_group0_cnt_read(unsigned int idx)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020036{
johpow01b7d752a2020-10-08 17:29:11 -050037 assert(amu_get_version() != ID_AA64PFR0_AMU_NOT_SUPPORTED);
38 assert(idx < AMU_GROUP0_NR_COUNTERS);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020039
40 return amu_group0_cnt_read_internal(idx);
41}
42
johpow01b7d752a2020-10-08 17:29:11 -050043/*
44 * Read the group 0 offset register for a given index. Index must be 0, 2, or
45 * 3, the register for 1 does not exist.
46 *
47 * Using this function requires v8.6 FEAT_AMUv1p1 support.
48 */
49uint64_t amu_group0_voffset_read(unsigned int idx)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020050{
johpow01b7d752a2020-10-08 17:29:11 -050051 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
52 assert(idx < AMU_GROUP0_NR_COUNTERS);
53 assert(idx != 1U);
54
55 return amu_group0_voffset_read_internal(idx);
56}
57
58/*
59 * Write the group 0 offset register for a given index. Index must be 0, 2, or
60 * 3, the register for 1 does not exist.
61 *
62 * Using this function requires v8.6 FEAT_AMUv1p1 support.
63 */
64void amu_group0_voffset_write(unsigned int idx, uint64_t val)
65{
66 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
67 assert(idx < AMU_GROUP0_NR_COUNTERS);
68 assert(idx != 1U);
69
70 amu_group0_voffset_write_internal(idx, val);
71 isb();
72}
73
74/* Read the group 1 counter identified by the given `idx`. */
75uint64_t amu_group1_cnt_read(unsigned int idx)
76{
77 assert(amu_get_version() != ID_AA64PFR0_AMU_NOT_SUPPORTED);
78 assert(idx < AMU_GROUP1_NR_COUNTERS);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020079
80 return amu_group1_cnt_read_internal(idx);
81}
johpow01b7d752a2020-10-08 17:29:11 -050082
83/*
84 * Read the group 1 offset register for a given index.
85 *
86 * Using this function requires v8.6 FEAT_AMUv1p1 support.
87 */
88uint64_t amu_group1_voffset_read(unsigned int idx)
89{
90 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
91 assert(amu_group1_supported());
92 assert(idx < AMU_GROUP1_NR_COUNTERS);
93 assert(((read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) &
94 (1U << idx)) != 0U);
95
96 return amu_group1_voffset_read_internal(idx);
97}
98
99/*
100 * Write the group 1 offset register for a given index.
101 *
102 * Using this function requires v8.6 FEAT_AMUv1p1 support.
103 */
104void amu_group1_voffset_write(unsigned int idx, uint64_t val)
105{
106 assert(amu_get_version() >= ID_AA64PFR0_AMU_V1P1);
107 assert(amu_group1_supported());
108 assert(idx < AMU_GROUP1_NR_COUNTERS);
109 assert(((read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) &
110 (1U << idx)) != 0U);
111
112 amu_group1_voffset_write_internal(idx, val);
113 isb();
114}