Tegra: allow platforms to override plat_core_pos_by_mpidr()

This patch makes the default implementation of plat_core_pos_by_mpidr()
as weakly linked, so that platforms can override it with their own.

Tegra186, for one, does not have CPU IDs 2 and 3, so it has its own
implementation of plat_core_pos_by_mpidr().

Change-Id: I7a5319869c01ede3775386cb95af1431792f74b3
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/common/tegra_topology.c b/plat/nvidia/tegra/common/tegra_topology.c
index 0431d98..f4c5661 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 <psci.h>
 
 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 @@
 {
 	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 7108723..13f867e 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -50,6 +50,13 @@
 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
  * the number of power domains at the highest power level.
@@ -256,3 +263,40 @@
 
 	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;
+}