blob: 6dece2865e17f90be8ef77e65fc828a92fcf1cb4 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Imre Kis8da87ad2019-12-17 17:41:34 +01002 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <assert.h>
9#include <mmio.h>
10#include <plat_topology.h>
11#include <platform_def.h>
12#include <stddef.h>
13#include <tftf_lib.h>
14
15/* FVP Power controller based defines */
16#define PWRC_BASE 0x1c100000
17#define PSYSR_OFF 0x10
18#define PSYSR_INVALID 0xffffffff
19
Alexei Fedorov0f305472019-10-29 14:06:54 +000020#if FVP_MAX_PE_PER_CPU == 2
21/* SMT: 2 threads per CPU */
22#define CPU_DEF(cluster, cpu) \
23 { cluster, cpu, 0 }, \
24 { cluster, cpu, 1 }
Alexei Fedorov0f305472019-10-29 14:06:54 +000025#else
Alexei Fedorov7cc25872020-06-02 16:35:36 +010026/* ST: 1 thread per CPU */
Alexei Fedorov0f305472019-10-29 14:06:54 +000027#define CPU_DEF(cluster, cpu) \
28 { cluster, cpu }
Alexei Fedorov7cc25872020-06-02 16:35:36 +010029#endif /* FVP_MAX_PE_PER_CPU */
Alexei Fedorov0f305472019-10-29 14:06:54 +000030
Alexei Fedorov7cc25872020-06-02 16:35:36 +010031/*
32 * Max CPUs per cluster:
33 * ST: 4
34 * SMT: 8
35 */
36#if (FVP_MAX_CPUS_PER_CLUSTER == 1)
37#define CLUSTER_DEF(cluster) \
38 CPU_DEF(cluster, 0)
39#elif (FVP_MAX_CPUS_PER_CLUSTER == 2)
40#define CLUSTER_DEF(cluster) \
41 CPU_DEF(cluster, 0), \
42 CPU_DEF(cluster, 1)
43#elif (FVP_MAX_CPUS_PER_CLUSTER == 3)
44#define CLUSTER_DEF(cluster) \
45 CPU_DEF(cluster, 0), \
46 CPU_DEF(cluster, 1), \
47 CPU_DEF(cluster, 2)
48#elif (FVP_MAX_CPUS_PER_CLUSTER == 4)
49#define CLUSTER_DEF(cluster) \
50 CPU_DEF(cluster, 0), \
51 CPU_DEF(cluster, 1), \
52 CPU_DEF(cluster, 2), \
53 CPU_DEF(cluster, 3)
54#elif (FVP_MAX_CPUS_PER_CLUSTER == 5)
55#define CLUSTER_DEF(cluster) \
56 CPU_DEF(cluster, 0), \
57 CPU_DEF(cluster, 1), \
58 CPU_DEF(cluster, 2), \
59 CPU_DEF(cluster, 3), \
60 CPU_DEF(cluster, 4)
61#elif (FVP_MAX_CPUS_PER_CLUSTER == 6)
62#define CLUSTER_DEF(cluster) \
63 CPU_DEF(cluster, 0), \
64 CPU_DEF(cluster, 1), \
65 CPU_DEF(cluster, 2), \
66 CPU_DEF(cluster, 3), \
67 CPU_DEF(cluster, 4), \
68 CPU_DEF(cluster, 5)
69#elif (FVP_MAX_CPUS_PER_CLUSTER == 7)
70#define CLUSTER_DEF(cluster) \
71 CPU_DEF(cluster, 0), \
72 CPU_DEF(cluster, 1), \
73 CPU_DEF(cluster, 2), \
74 CPU_DEF(cluster, 3), \
75 CPU_DEF(cluster, 4), \
76 CPU_DEF(cluster, 5), \
77 CPU_DEF(cluster, 6)
78#else
Alexei Fedorov0f305472019-10-29 14:06:54 +000079#define CLUSTER_DEF(cluster) \
80 CPU_DEF(cluster, 0), \
81 CPU_DEF(cluster, 1), \
82 CPU_DEF(cluster, 2), \
83 CPU_DEF(cluster, 3), \
84 CPU_DEF(cluster, 4), \
85 CPU_DEF(cluster, 5), \
86 CPU_DEF(cluster, 6), \
87 CPU_DEF(cluster, 7)
Alexei Fedorov7cc25872020-06-02 16:35:36 +010088#endif /* FVP_MAX_CPUS_PER_CLUSTER */
Alexei Fedorov0f305472019-10-29 14:06:54 +000089
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020090static const struct {
91 unsigned int cluster_id;
92 unsigned int cpu_id;
Alexei Fedorov0f305472019-10-29 14:06:54 +000093#if FVP_MAX_PE_PER_CPU > 1
94 unsigned int thread_id;
95#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020096} fvp_base_aemv8a_aemv8a_cores[] = {
Alexei Fedorov0f305472019-10-29 14:06:54 +000097 /* Clusters 0...3 */
98 CLUSTER_DEF(0),
Alexei Fedorov7cc25872020-06-02 16:35:36 +010099#if (FVP_CLUSTER_COUNT > 1)
Alexei Fedorov0f305472019-10-29 14:06:54 +0000100 CLUSTER_DEF(1),
Alexei Fedorov7cc25872020-06-02 16:35:36 +0100101#if (FVP_CLUSTER_COUNT > 2)
Alexei Fedorov0f305472019-10-29 14:06:54 +0000102 CLUSTER_DEF(2),
Alexei Fedorov7cc25872020-06-02 16:35:36 +0100103#if (FVP_CLUSTER_COUNT > 3)
Alexei Fedorov0f305472019-10-29 14:06:54 +0000104 CLUSTER_DEF(3)
Alexei Fedorov7cc25872020-06-02 16:35:36 +0100105#endif
106#endif
107#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200108};
109
110/*
111 * The FVP power domain tree descriptor. We always construct a topology
112 * with the maximum number of cluster nodes possible for FVP. During
113 * TFTF initialization, the actual number of nodes present on the model
114 * will be queried dynamically using `tftf_plat_get_mpidr()`.
115 * The FVP power domain tree does not have a single system level power domain
116 * i.e. a single root node. The first entry in the power domain descriptor
117 * specifies the number of power domains at the highest power level which
118 * is equal to FVP_CLUSTER_COUNT.
119 */
120static const unsigned char fvp_power_domain_tree_desc[] = {
121 /* Number of system nodes */
122 1,
123 /* Number of cluster nodes */
124 FVP_CLUSTER_COUNT,
125 /* Number of children for the first node */
Imre Kis8da87ad2019-12-17 17:41:34 +0100126 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
Alexei Fedorov7cc25872020-06-02 16:35:36 +0100127#if (FVP_CLUSTER_COUNT > 1)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200128 /* Number of children for the second node */
Imre Kis8da87ad2019-12-17 17:41:34 +0100129 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
Alexei Fedorov7cc25872020-06-02 16:35:36 +0100130#if (FVP_CLUSTER_COUNT > 2)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200131 /* Number of children for the third node */
Imre Kis8da87ad2019-12-17 17:41:34 +0100132 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
Alexei Fedorov7cc25872020-06-02 16:35:36 +0100133#if (FVP_CLUSTER_COUNT > 3)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200134 /* Number of children for the fourth node */
Imre Kis8da87ad2019-12-17 17:41:34 +0100135 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU
Alexei Fedorov7cc25872020-06-02 16:35:36 +0100136#endif
137#endif
138#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200139};
140
141const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
142{
143 return fvp_power_domain_tree_desc;
144}
145
146static unsigned int fvp_pwrc_read_psysr(unsigned long mpidr)
147{
148 unsigned int rc;
149 mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr);
150 rc = mmio_read_32(PWRC_BASE + PSYSR_OFF);
151 return rc;
152}
153
154uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
155{
156 unsigned int mpid;
157
158 assert(core_pos < PLATFORM_CORE_COUNT);
159
160 mpid = make_mpid(
161 fvp_base_aemv8a_aemv8a_cores[core_pos].cluster_id,
Alexei Fedorov0f305472019-10-29 14:06:54 +0000162#if FVP_MAX_PE_PER_CPU > 1
163 fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id,
164 fvp_base_aemv8a_aemv8a_cores[core_pos].thread_id);
165#else
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200166 fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id);
Alexei Fedorov0f305472019-10-29 14:06:54 +0000167#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200168
169 if (fvp_pwrc_read_psysr(mpid) != PSYSR_INVALID)
170 return mpid;
171
172 return INVALID_MPID;
173}