From ae8ac2d233f21fa8c1f7b7329559f75726de8e4d Mon Sep 17 00:00:00 2001
From: Varun Wadekar <vwadekar@nvidia.com>
Date: Tue, 31 Jan 2017 14:53:37 -0800
Subject: [PATCH] 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>
---
 plat/nvidia/tegra/common/tegra_topology.c | 12 +++----
 plat/nvidia/tegra/soc/t186/plat_setup.c   | 44 +++++++++++++++++++++++
 2 files changed, 48 insertions(+), 8 deletions(-)

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 <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 @@ 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;
+}
-- 
GitLab