diff --git a/plat/nvidia/tegra/common/tegra_topology.c b/plat/nvidia/tegra/common/tegra_topology.c index 0431d98a2..f4c56617b 100644 --- a/plat/nvidia/tegra/common/tegra_topology.c +++ b/plat/nvidia/tegra/common/tegra_topology.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, 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: @@ -33,6 +33,7 @@ #include extern const unsigned char tegra_power_domain_tree_desc[]; +#pragma weak plat_core_pos_by_mpidr /******************************************************************************* * This function returns the Tegra default topology tree information. @@ -52,23 +53,18 @@ int plat_core_pos_by_mpidr(u_register_t mpidr) { unsigned int cluster_id, cpu_id; - mpidr &= MPIDR_AFFINITY_MASK; - - if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) - return -1; - cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; if (cluster_id >= PLATFORM_CLUSTER_COUNT) - return -1; + return PSCI_E_NOT_PRESENT; /* * Validate cpu_id by checking whether it represents a CPU in * one of the two clusters present on the platform. */ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) - return -1; + return PSCI_E_NOT_PRESENT; return (cpu_id + (cluster_id * 4)); } diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index 71087231f..13f867e21 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -49,6 +49,13 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, L2CTLR_EL1) extern uint64_t tegra_enable_l2_ecc_parity_prot; +/******************************************************************************* + * Tegra186 CPU numbers in cluster #0 + ******************************************************************************* + */ +#define TEGRA186_CLUSTER0_CORE2 2 +#define TEGRA186_CLUSTER0_CORE3 3 + /******************************************************************************* * The Tegra power domain tree has a single system level power domain i.e. a * single root node. The first entry in the power domain descriptor specifies @@ -256,3 +263,40 @@ plat_params_from_bl2_t *plat_get_bl31_plat_params(void) return (plat_params_from_bl2_t *)(uintptr_t)val; } + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id, pos; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + /* + * Validate cluster_id by checking whether it represents + * one of the two clusters present on the platform. + */ + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return PSCI_E_NOT_PRESENT; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) + return PSCI_E_NOT_PRESENT; + + /* calculate the core position */ + pos = cpu_id + (cluster_id << 2); + + /* check for non-existent CPUs */ + if (pos == TEGRA186_CLUSTER0_CORE2 || pos == TEGRA186_CLUSTER0_CORE3) + return PSCI_E_NOT_PRESENT; + + return pos; +}