summaryrefslogtreecommitdiff
path: root/plat/common
diff options
context:
space:
mode:
authorSandrine Bailleux <sandrine.bailleux@arm.com>2014-10-30 14:38:00 +0000
committerSandrine Bailleux <sandrine.bailleux@arm.com>2014-11-04 17:32:46 +0000
commite4296c455e1158d68a4b1749afb1523395ee2ceb (patch)
treed48f071d218d176deee94e5b7acf0393f5525ac4 /plat/common
parentdc51e22565ddb784f39e1638a144c83f021fc080 (diff)
Move FVP platform topology code to generic layer
At the moment, only the FVP port uses a topology tree to store the platform topology information. The Juno port just returns hard-coded values in the mandatory platform APIs. Actually any platform topology can be described using the data structures used in the FVP port. Then, if all platforms share the same way to represent the system topology, the code to query this topology becomes common and generic. This reduces the porting effort. The only responsibility of the platform code is to detect the system topology and populate the topology tree accordingly. Therefore, this patch pulls in the FVP topology code to the generic layer. It also reworks the Juno topology code to populate the topology tree. The porting guide is updated to reflect these changes. Change-Id: I63e0eee25985c6449b07faac4ac51f9e0349b7fc
Diffstat (limited to 'plat/common')
-rw-r--r--plat/common/plat_topology.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/plat/common/plat_topology.c b/plat/common/plat_topology.c
new file mode 100644
index 0000000..7edd15c
--- /dev/null
+++ b/plat/common/plat_topology.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <plat_topology.h>
+#include <platform.h>
+#include <psci.h>
+#include <stdio.h>
+
+affinity_info_t plat_aff1_topology_map[PLATFORM_CLUSTER_COUNT];
+affinity_info_t plat_aff0_topology_map[PLATFORM_CORE_COUNT];
+
+/*
+ * Global variable to check that the platform topology is not queried until it
+ * has been setup.
+ */
+static unsigned int topology_setup_done;
+
+/* Read accessors for CPUs and clusters topology maps */
+static uint8_t cpu_sibling(uint8_t cpu_idx)
+{
+ return plat_aff0_topology_map[cpu_idx].sibling;
+}
+
+static unsigned int cpu_has_sibling(uint8_t cpu_idx)
+{
+ return plat_aff0_topology_map[cpu_idx].sibling != AFFINST_INVAL;
+}
+
+static uint8_t cpu_state(uint8_t cpu_idx)
+{
+ return plat_aff0_topology_map[cpu_idx].state;
+}
+
+static uint8_t cluster_sibling(uint8_t cluster_idx)
+{
+ return plat_aff1_topology_map[cluster_idx].sibling;
+}
+
+static unsigned int cluster_has_sibling(uint8_t cluster_idx)
+{
+ return plat_aff1_topology_map[cluster_idx].sibling != AFFINST_INVAL;
+}
+
+static uint8_t cluster_child(uint8_t cluster_idx)
+{
+ return plat_aff1_topology_map[cluster_idx].child;
+}
+
+static uint8_t cluster_state(uint8_t cluster_idx)
+{
+ return plat_aff1_topology_map[cluster_idx].state;
+}
+
+unsigned int tftf_topology_get_aff_count(unsigned int aff_lvl,
+ unsigned long mpidr)
+{
+ unsigned int aff_count = 1, ctr;
+ uint8_t parent_aff_id;
+
+ assert(topology_setup_done == 1);
+ assert(aff_lvl <= MPIDR_MAX_AFFLVL);
+
+ switch (aff_lvl) {
+ case 3:
+ case 2:
+ parent_aff_id = MPIDR_AFF_ID(mpidr, MPIDR_AFFLVL3);
+ assert(parent_aff_id == 0);
+
+ /*
+ * Report that we implement a single instance of
+ * affinity levels 2 & 3 which are absent
+ */
+ break;
+ case 1:
+ parent_aff_id = MPIDR_AFF_ID(mpidr, MPIDR_AFFLVL2);
+ assert(parent_aff_id == 0);
+
+ for (ctr = 0;
+ cluster_has_sibling(ctr);
+ ctr = cluster_sibling(ctr)) {
+ aff_count++;
+ }
+
+ break;
+ case 0:
+ parent_aff_id = MPIDR_CLUSTER_ID(mpidr);
+ assert(parent_aff_id < PLATFORM_CLUSTER_COUNT);
+
+ for (ctr = cluster_child(parent_aff_id);
+ cpu_has_sibling(ctr);
+ ctr = cpu_sibling(ctr)) {
+ aff_count++;
+ }
+
+ break;
+ default:
+ return 0;
+ }
+
+ return aff_count;
+}
+
+unsigned int tftf_topology_get_aff_state(unsigned int aff_lvl,
+ unsigned long mpidr)
+{
+ uint8_t idx;
+
+ assert(topology_setup_done == 1);
+ assert(aff_lvl <= MPIDR_MAX_AFFLVL);
+
+ idx = MPIDR_CLUSTER_ID(mpidr);
+
+ switch (aff_lvl) {
+ case 3:
+ case 2:
+ return PSCI_AFF_ABSENT;
+ case 1:
+ return cluster_state(idx);
+ case 0:
+ idx = cluster_child(idx) + MPIDR_CPU_ID(mpidr);
+ return cpu_state(idx);
+ default:
+ return PSCI_AFF_ABSENT;
+ }
+}
+
+void tftf_init_topology(void)
+{
+ tftf_plat_init_topology();
+ topology_setup_done = 1;
+}