blob: e13e801448fb5cd730233b4161cd4840c8918d8c [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 }
25
26#else
27#define CPU_DEF(cluster, cpu) \
28 { cluster, cpu }
29#endif
30
31/* 8 CPUs per cluster */
32#define CLUSTER_DEF(cluster) \
33 CPU_DEF(cluster, 0), \
34 CPU_DEF(cluster, 1), \
35 CPU_DEF(cluster, 2), \
36 CPU_DEF(cluster, 3), \
37 CPU_DEF(cluster, 4), \
38 CPU_DEF(cluster, 5), \
39 CPU_DEF(cluster, 6), \
40 CPU_DEF(cluster, 7)
41
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020042static const struct {
43 unsigned int cluster_id;
44 unsigned int cpu_id;
Alexei Fedorov0f305472019-10-29 14:06:54 +000045#if FVP_MAX_PE_PER_CPU > 1
46 unsigned int thread_id;
47#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020048} fvp_base_aemv8a_aemv8a_cores[] = {
Alexei Fedorov0f305472019-10-29 14:06:54 +000049 /* Clusters 0...3 */
50 CLUSTER_DEF(0),
51 CLUSTER_DEF(1),
52 CLUSTER_DEF(2),
53 CLUSTER_DEF(3)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020054};
55
56/*
57 * The FVP power domain tree descriptor. We always construct a topology
58 * with the maximum number of cluster nodes possible for FVP. During
59 * TFTF initialization, the actual number of nodes present on the model
60 * will be queried dynamically using `tftf_plat_get_mpidr()`.
61 * The FVP power domain tree does not have a single system level power domain
62 * i.e. a single root node. The first entry in the power domain descriptor
63 * specifies the number of power domains at the highest power level which
64 * is equal to FVP_CLUSTER_COUNT.
65 */
66static const unsigned char fvp_power_domain_tree_desc[] = {
67 /* Number of system nodes */
68 1,
69 /* Number of cluster nodes */
70 FVP_CLUSTER_COUNT,
71 /* Number of children for the first node */
Imre Kis8da87ad2019-12-17 17:41:34 +010072 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020073 /* Number of children for the second node */
Imre Kis8da87ad2019-12-17 17:41:34 +010074 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020075 /* Number of children for the third node */
Imre Kis8da87ad2019-12-17 17:41:34 +010076 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU,
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020077 /* Number of children for the fourth node */
Imre Kis8da87ad2019-12-17 17:41:34 +010078 FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020079};
80
81const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
82{
83 return fvp_power_domain_tree_desc;
84}
85
86static unsigned int fvp_pwrc_read_psysr(unsigned long mpidr)
87{
88 unsigned int rc;
89 mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr);
90 rc = mmio_read_32(PWRC_BASE + PSYSR_OFF);
91 return rc;
92}
93
94uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
95{
96 unsigned int mpid;
97
98 assert(core_pos < PLATFORM_CORE_COUNT);
99
100 mpid = make_mpid(
101 fvp_base_aemv8a_aemv8a_cores[core_pos].cluster_id,
Alexei Fedorov0f305472019-10-29 14:06:54 +0000102#if FVP_MAX_PE_PER_CPU > 1
103 fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id,
104 fvp_base_aemv8a_aemv8a_cores[core_pos].thread_id);
105#else
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200106 fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id);
Alexei Fedorov0f305472019-10-29 14:06:54 +0000107#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200108
109 if (fvp_pwrc_read_psysr(mpid) != PSYSR_INVALID)
110 return mpid;
111
112 return INVALID_MPID;
113}