diff --git a/plat/juno/plat_topology.c b/plat/juno/plat_topology.c index 0c8c525..205791b 100644 --- a/plat/juno/plat_topology.c +++ b/plat/juno/plat_topology.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * 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: @@ -28,214 +28,32 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include #include -#include -/* TODO: Reusing psci error codes & state information. Get our own! */ -#include -/* We treat '255' as an invalid affinity instance */ -#define AFFINST_INVAL 0xff - -/******************************************************************************* - * We support 3 flavours of the FVP: Foundation, Base AEM & Base Cortex. Each - * flavour has a different topology. The common bit is that there can be a max. - * of 2 clusters (affinity 1) and 4 cpus (affinity 0) per cluster. So we define - * a tree like data structure which caters to these maximum bounds. It simply - * marks the absent affinity level instances as PSCI_AFF_ABSENT e.g. there is no - * cluster 1 on the Foundation FVP. The 'data' field is currently unused. - ******************************************************************************/ -typedef struct { - unsigned char sibling; - unsigned char child; - unsigned char state; - unsigned int data; -} affinity_info; - -/******************************************************************************* - * The following two data structures store the topology tree for the fvp. There - * is a separate array for each affinity level i.e. cpus and clusters. The child - * and sibling references allow traversal inside and in between the two arrays. - ******************************************************************************/ -static affinity_info fvp_aff1_topology_map[PLATFORM_CLUSTER_COUNT]; -static affinity_info fvp_aff0_topology_map[PLATFORM_CORE_COUNT]; - -/* Simple global variable to safeguard us from stupidity */ -static unsigned int topology_setup_done; - -/******************************************************************************* - * This function implements a part of the critical interface between the psci - * generic layer and the platform to allow the former to detect the platform - * topology. psci queries the platform to determine how many affinity instances - * are present at a particular level for a given mpidr e.g. consider a dual - * cluster platform where each cluster has 4 cpus. A call to this function with - * (0, 0x100) will return the number of cpus implemented under cluster 1 i.e. 4. - * Similarly a call with (1, 0x100) will return 2 i.e. the number of clusters. - * This is 'cause we are effectively asking how many affinity level 1 instances - * are implemented under affinity level 2 instance 0. - ******************************************************************************/ -unsigned int plat_get_aff_count(unsigned int aff_lvl, - unsigned long mpidr) +unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr) { - unsigned int aff_count = 1, ctr; - unsigned char parent_aff_id; + /* Report 1 (absent) instance at levels higher that the cluster level */ + if (aff_lvl > MPIDR_AFFLVL1) + return 1; - assert(topology_setup_done == 1); + if (aff_lvl == MPIDR_AFFLVL1) + return 2; /* We have two clusters */ - switch (aff_lvl) { - case 3: - case 2: - /* - * Assert if the parent affinity instance is not 0. - * This also takes care of level 3 in an obfuscated way - */ - parent_aff_id = (mpidr >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK; - assert(parent_aff_id == 0); - - /* - * Report that we implement a single instance of - * affinity levels 2 & 3 which are AFF_ABSENT - */ - break; - case 1: - /* Assert if the parent affinity instance is not 0. */ - parent_aff_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK; - assert(parent_aff_id == 0); - - /* Fetch the starting index in the aff1 array */ - for (ctr = 0; - fvp_aff1_topology_map[ctr].sibling != AFFINST_INVAL; - ctr = fvp_aff1_topology_map[ctr].sibling) { - aff_count++; - } - - break; - case 0: - /* Assert if the cluster id is anything apart from 0 or 1 */ - parent_aff_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; - assert(parent_aff_id < PLATFORM_CLUSTER_COUNT); - - /* Fetch the starting index in the aff0 array */ - for (ctr = fvp_aff1_topology_map[parent_aff_id].child; - fvp_aff0_topology_map[ctr].sibling != AFFINST_INVAL; - ctr = fvp_aff0_topology_map[ctr].sibling) { - aff_count++; - } - - break; - default: - assert(0); - } - - return aff_count; + return mpidr & 0x100 ? 4 : 2; /* 4 cpus in cluster 1, 2 in cluster 0 */ } -/******************************************************************************* - * This function implements a part of the critical interface between the psci - * generic layer and the platform to allow the former to detect the state of a - * affinity instance in the platform topology. psci queries the platform to - * determine whether an affinity instance is present or absent. This caters for - * topologies where an intermediate affinity level instance is missing e.g. - * consider a platform which implements a single cluster with 4 cpus and there - * is another cpu sitting directly on the interconnect along with the cluster. - * The mpidrs of the cluster would range from 0x0-0x3. The mpidr of the single - * cpu would be 0x100 to highlight that it does not belong to cluster 0. Cluster - * 1 is however missing but needs to be accounted to reach this single cpu in - * the topology tree. Hence it will be marked as PSCI_AFF_ABSENT. This is not - * applicable to the FVP but depicted as an example. - ******************************************************************************/ -unsigned int plat_get_aff_state(unsigned int aff_lvl, - unsigned long mpidr) +unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr) { - unsigned int aff_state = PSCI_AFF_ABSENT, idx; - idx = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; - - assert(topology_setup_done == 1); - - switch (aff_lvl) { - case 3: - case 2: - /* Report affinity levels 2 & 3 as absent */ - break; - case 1: - aff_state = fvp_aff1_topology_map[idx].state; - break; - case 0: - /* - * First get start index of the aff0 in its array & then add - * to it the affinity id that we want the state of - */ - idx = fvp_aff1_topology_map[idx].child; - idx += (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; - aff_state = fvp_aff0_topology_map[idx].state; - break; - default: - assert(0); - } - - return aff_state; + return aff_lvl <= MPIDR_AFFLVL1 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT; } -/******************************************************************************* - * Handy optimization to prevent the psci implementation from traversing through - * affinity levels which are not present while detecting the platform topology. - ******************************************************************************/ int plat_get_max_afflvl() { return MPIDR_AFFLVL1; } -/******************************************************************************* - * This function populates the FVP specific topology information depending upon - * the FVP flavour its running on. We construct all the mpidrs we can handle - * and rely on the PWRC.PSYSR to flag absent cpus when their status is queried. - ******************************************************************************/ int plat_setup_topology() { - unsigned char aff0, aff1, aff_state, aff0_offset = 0; - unsigned long mpidr; - - topology_setup_done = 0; - - for (aff1 = 0; aff1 < PLATFORM_CLUSTER_COUNT; aff1++) { - - fvp_aff1_topology_map[aff1].child = aff0_offset; - fvp_aff1_topology_map[aff1].sibling = aff1 + 1; - - for (aff0 = 0; aff0 < PLATFORM_MAX_CPUS_PER_CLUSTER; aff0++) { - - mpidr = aff1 << MPIDR_AFF1_SHIFT; - mpidr |= aff0 << MPIDR_AFF0_SHIFT; - - if (fvp_pwrc_read_psysr(mpidr) != PSYSR_INVALID) { - /* - * Presence of even a single aff0 indicates - * presence of parent aff1 on the FVP. - */ - aff_state = PSCI_AFF_PRESENT; - fvp_aff1_topology_map[aff1].state = - PSCI_AFF_PRESENT; - } else { - aff_state = PSCI_AFF_ABSENT; - } - - fvp_aff0_topology_map[aff0_offset].child = AFFINST_INVAL; - fvp_aff0_topology_map[aff0_offset].state = aff_state; - fvp_aff0_topology_map[aff0_offset].sibling = - aff0_offset + 1; - - /* Increment the absolute number of aff0s traversed */ - aff0_offset++; - } - - /* Tie-off the last aff0 sibling to -1 to avoid overflow */ - fvp_aff0_topology_map[aff0_offset - 1].sibling = AFFINST_INVAL; - } - - /* Tie-off the last aff1 sibling to AFFINST_INVAL to avoid overflow */ - fvp_aff1_topology_map[aff1 - 1].sibling = AFFINST_INVAL; - - topology_setup_done = 1; + /* Juno todo: Make topology configurable via SCC */ return 0; } diff --git a/plat/juno/platform.h b/plat/juno/platform.h index 465f5be..5f5af14 100644 --- a/plat/juno/platform.h +++ b/plat/juno/platform.h @@ -68,12 +68,7 @@ #define FIP_IMAGE_NAME "fip.bin" #define PLATFORM_CACHE_LINE_SIZE 64 -#define PLATFORM_CLUSTER_COUNT 2ull -#define PLATFORM_CLUSTER0_CORE_COUNT 4 -#define PLATFORM_CLUSTER1_CORE_COUNT 4 -#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ - PLATFORM_CLUSTER0_CORE_COUNT) -#define PLATFORM_MAX_CPUS_PER_CLUSTER 4 +#define PLATFORM_CORE_COUNT 6 #define PRIMARY_CPU 0x100 #define MAX_IO_DEVICES 3 #define MAX_IO_HANDLES 4