blob: 751a1b8b5b97e4a5be1088f35f5de86014cfb5e0 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Madhukar3fd90492019-06-04 15:57:18 -05002 * Copyright (c) 2018-2019, 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
20static const struct {
21 unsigned int cluster_id;
22 unsigned int cpu_id;
23} fvp_base_aemv8a_aemv8a_cores[] = {
24 /* Cluster 0 */
25 { 0, 0 },
26 { 0, 1 },
27 { 0, 2 },
28 { 0, 3 },
Madhukar3fd90492019-06-04 15:57:18 -050029 { 0, 4 },
30 { 0, 5 },
31 { 0, 6 },
32 { 0, 7 },
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020033 /* Cluster 1 */
34 { 1, 0 },
35 { 1, 1 },
36 { 1, 2 },
37 { 1, 3 },
Madhukar3fd90492019-06-04 15:57:18 -050038 { 1, 4 },
39 { 1, 5 },
40 { 1, 6 },
41 { 1, 7 },
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020042 /* Cluster 2 */
43 { 2, 0 },
44 { 2, 1 },
45 { 2, 2 },
46 { 2, 3 },
Madhukar3fd90492019-06-04 15:57:18 -050047 { 2, 4 },
48 { 2, 5 },
49 { 2, 6 },
50 { 2, 7 },
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020051 /* Cluster 3 */
52 { 3, 0 },
53 { 3, 1 },
54 { 3, 2 },
55 { 3, 3 },
Madhukar3fd90492019-06-04 15:57:18 -050056 { 3, 4 },
57 { 3, 5 },
58 { 3, 6 },
59 { 3, 7 },
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020060};
61
62/*
63 * The FVP power domain tree descriptor. We always construct a topology
64 * with the maximum number of cluster nodes possible for FVP. During
65 * TFTF initialization, the actual number of nodes present on the model
66 * will be queried dynamically using `tftf_plat_get_mpidr()`.
67 * The FVP power domain tree does not have a single system level power domain
68 * i.e. a single root node. The first entry in the power domain descriptor
69 * specifies the number of power domains at the highest power level which
70 * is equal to FVP_CLUSTER_COUNT.
71 */
72static const unsigned char fvp_power_domain_tree_desc[] = {
73 /* Number of system nodes */
74 1,
75 /* Number of cluster nodes */
76 FVP_CLUSTER_COUNT,
77 /* Number of children for the first node */
78 FVP_MAX_CPUS_PER_CLUSTER,
79 /* Number of children for the second node */
80 FVP_MAX_CPUS_PER_CLUSTER,
81 /* Number of children for the third node */
82 FVP_MAX_CPUS_PER_CLUSTER,
83 /* Number of children for the fourth node */
84 FVP_MAX_CPUS_PER_CLUSTER
85};
86
87const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
88{
89 return fvp_power_domain_tree_desc;
90}
91
92static unsigned int fvp_pwrc_read_psysr(unsigned long mpidr)
93{
94 unsigned int rc;
95 mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr);
96 rc = mmio_read_32(PWRC_BASE + PSYSR_OFF);
97 return rc;
98}
99
100uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
101{
102 unsigned int mpid;
103
104 assert(core_pos < PLATFORM_CORE_COUNT);
105
106 mpid = make_mpid(
107 fvp_base_aemv8a_aemv8a_cores[core_pos].cluster_id,
108 fvp_base_aemv8a_aemv8a_cores[core_pos].cpu_id);
109
110 if (fvp_pwrc_read_psysr(mpid) != PSYSR_INVALID)
111 return mpid;
112
113 return INVALID_MPID;
114}