Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
39fa81bc
Commit
39fa81bc
authored
11 years ago
by
Jon Medhurst
Committed by
Sandrine Bailleux
11 years ago
Browse files
Options
Download
Email Patches
Plain Diff
juno: Port plat_topology.c
Signed-off-by:
Jon Medhurst
<
tixy@linaro.org
>
parent
1100a4f1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
plat/juno/plat_topology.c
+11
-193
plat/juno/plat_topology.c
plat/juno/platform.h
+1
-6
plat/juno/platform.h
with
12 additions
and
199 deletions
+12
-199
plat/juno/plat_topology.c
View file @
39fa81bc
/*
* 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 <string.h>
#include <assert.h>
#include <platform.h>
#include <fvp_pwrc.h>
/* TODO: Reusing psci error codes & state information. Get our own! */
#include <psci.h>
/* 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
;
assert
(
topology_setup_done
==
1
);
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 1 (absent) instance at levels higher that the cluster level */
if
(
aff_lvl
>
MPIDR_AFFLVL1
)
return
1
;
/*
* 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
);
if
(
aff_lvl
==
MPIDR_AFFLVL1
)
return
2
;
/* We have two clusters */
/* 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
;
}
This diff is collapsed.
Click to expand it.
plat/juno/platform.h
View file @
39fa81bc
...
...
@@ -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
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help