blob: 0da0b5ee75da64bb39749617c40801959cd7a4c6 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef __PLAT_TOPOLOGY_H__
8#define __PLAT_TOPOLOGY_H__
9
10#include <arch.h>
11#include <platform_def.h>
12#include <stdint.h>
13
14/*
15 * This is the initial value of the power domain index when used
16 * as argument to the tftf topology helpers. They are also used
17 * to indicate the end of iterative topology navigation when returned
18 * by the tftf topology helpers.
19 */
20#define PWR_DOMAIN_INIT ((unsigned int) -1)
21
22/*
23 * Return the total number of clusters in the system.
24 * Currently there is correspondence between power level and affinity
25 * level and hence cluster power level corresponds to affinity level 1.
26 */
27#define tftf_get_total_clusters_count() tftf_get_total_aff_count(1)
28
29/*
30 * Return the total number of CPUs in the system (across all clusters).
31 * Currently there is correspondence between power level and affinity
32 * level and hence CPU power level correspond to affinity level 0.
33 */
34#define tftf_get_total_cpus_count() tftf_get_total_aff_count(0)
35
36/*
37 * Converts a 'core_pos' into an MPIDR. The 'core_pos' is a unique number
38 * corresponding to a CPU as returned by platform_get_core_pos() API
39 */
40#define tftf_core_pos_to_mpidr(core_pos) \
41 tftf_get_mpidr_from_node(core_pos + tftf_pwr_domain_start_idx[0])
42
43/*
44 * The following array stores the start index of each level in the power
45 * domain topology tree.
46 */
47extern unsigned int tftf_pwr_domain_start_idx[PLATFORM_MAX_AFFLVL + 1];
48
49/*
50 * The following data structure represents a TFTF power domain node.
51 */
52typedef struct tftf_pwr_domain_node {
53 /*
54 * Array index of the first CPU in the topology array for which this
55 * power domain is the parent. If this power domain is a CPU, then
56 * `cpu_start_node` will be its own index in the power domain
57 * topology array.
58 */
59 unsigned int cpu_start_node;
60
61 /*
62 * Number of CPU power domains which belong to this power domain.
63 * i.e. all the CPUs in the range 'cpu_start_node
64 * -> cpu_start_node + ncpus - 1 ' will belong to this power domain.
65 * If this power domain is a CPU then 'ncpus' will be 1.
66 */
67 unsigned int ncpus;
68
69 /* Valid only for CPU power domains */
70 unsigned int mpidr;
71
72 /* Index of the parent power domain node */
73 unsigned int parent_node;
74
75 /*
76 * The level of this power domain node in the power domain topology
77 * tree. It could correspond to the affinity level but the platform
78 * could have power levels which do not match affinity levels.
79 */
80 unsigned int level;
81
82 /*
83 * The 'is_present' field is used to cater for power domains
84 * which are absent.
85 */
86 unsigned char is_present;
87} tftf_pwr_domain_node_t;
88
89/*
90 * Detect and store the platform topology so that test cases can query it later.
91 */
92void tftf_init_topology(void);
93
94/*
95 * Return the number of affinity instances implemented at the affinity level
96 * passed as an argument. This function returns 0 for any other affinity
97 * level higher than that supported by the platform.
98 */
99unsigned int tftf_get_total_aff_count(unsigned int aff_lvl);
100
101/*
102 * Returns the index of the next power domain after `pwr_domain_idx`
103 * in the topology tree at the same `aff_lvl`. The `pwr_domain_idx`
104 * has to be initialized to PWR_DOMAIN_INIT to get the first entry.
105 * It returns PWR_DOMAIN_INIT if none is found.
106 */
107unsigned int tftf_get_next_peer_domain(unsigned int pwr_domain_idx,
108 unsigned int pwr_lvl);
109
110/*
111 * Returns the index of the next CPU after the current CPU `cpu_node`
112 * which belongs to the power domain `pwr_domain_idx`. The `cpu_node`
113 * has to be initialized to PWR_DOMAIN_INIT to get the first entry.
114 * It returns PWR_DOMAIN_INIT if none is found.
115 */
116unsigned int tftf_get_next_cpu_in_pwr_domain(unsigned int pwr_domain_idx,
117 unsigned int cpu_node);
118
119/*
120 * Return the node index of the next CPU after 'cpu_node' in the topology tree.
121 * Skip absent CPUs.
122 * cpu_node: Node index of the current CPU.
123 */
124unsigned int tftf_topology_next_cpu(unsigned int cpu_node);
125
126/*
127 * Iterate over every CPU. Skip absent CPUs.
128 * cpu: unsigned integer corresponding to the index of the cpu in
John Tsichritzis941fab42018-10-30 14:49:31 +0000129 * the topology array.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200130 */
John Tsichritzis941fab42018-10-30 14:49:31 +0000131#define for_each_cpu(cpu) \
132 for (cpu = tftf_topology_next_cpu(PWR_DOMAIN_INIT); \
133 cpu != PWR_DOMAIN_INIT; \
134 cpu = tftf_topology_next_cpu(cpu))
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200135
136/*
137 * Iterate over every power domain idx for a given level.
John Tsichritzis941fab42018-10-30 14:49:31 +0000138 * - idx: unsigned integer corresponding to the power domain index.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200139 * - lvl: level
140 */
John Tsichritzis941fab42018-10-30 14:49:31 +0000141#define for_each_power_domain_idx(idx, lvl) \
142 for (idx = tftf_get_next_peer_domain(PWR_DOMAIN_INIT, (lvl)); \
143 idx != PWR_DOMAIN_INIT; \
144 idx = tftf_get_next_peer_domain(idx, (lvl)))
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200145
146/*
147 * Iterate over every CPU in a power domain idx.
John Tsichritzis941fab42018-10-30 14:49:31 +0000148 * - cpu_idx: CPU index.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200149 * - pwr_domain_idx: unsigned integer corresponding to the power domain index.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200150 */
John Tsichritzis941fab42018-10-30 14:49:31 +0000151#define for_each_cpu_in_power_domain(cpu_idx, pwr_domain_idx) \
152 for (cpu_idx = tftf_get_next_cpu_in_pwr_domain( \
153 (pwr_domain_idx), PWR_DOMAIN_INIT); \
154 cpu_idx != PWR_DOMAIN_INIT; \
155 cpu_idx = tftf_get_next_cpu_in_pwr_domain( \
156 (pwr_domain_idx), cpu_idx))
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200157
158/*
159 * Returns the MPIDR of the CPU power domain node indexed by `cpu_node`
160 * or INVALID_MPID if it is absent.
161 */
162unsigned int tftf_get_mpidr_from_node(unsigned int cpu_node);
163
164/*
165 * Query the platform topology to find another CPU than the one specified
166 * as an argument.
167 * Return the MPID of this other CPU, or INVALID_MPID if none could be found.
168 */
169unsigned int tftf_find_any_cpu_other_than(unsigned int exclude_mpid);
170
171/*
172 * Query the platform topology to find a random CPU other than the one specified
173 * as an argument.
174 * The difference between this function and tftf_find_any_cpu_other_than is
175 * the randomness in selecting a CPU.
176 * Return the MPID of this other CPU, or INVALID_MPID if none could be found.
177 */
178unsigned int tftf_find_random_cpu_other_than(unsigned int exclude_mpid);
179
180#endif /* __PLAT_TOPOLOGY_H__ */