Tegra: introduce plat_enable_console()

This patch introduces the 'plat_enable_console' handler to allow
the platform to enable the right console. Tegra194 platform supports
multiple console, while all the previous platforms support only one
console.

For Tegra194 platforms, the previous bootloader checks the platform
config and sets the uart-id boot parameter, to 0xFE. On seeing this
boot parameter, the platform port uses the proper memory aperture
base address to communicate with the SPE. This functionality is
currently protected by a platform macro, ENABLE_CONSOLE_SPE.

Change-Id: I3972aa376d66bd10d868495f561dc08fe32fcb10
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index f89e77a..a665276 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -129,10 +129,8 @@
 	struct tegra_bl31_params *arg_from_bl2 = (struct tegra_bl31_params *) arg0;
 	plat_params_from_bl2_t *plat_params = (plat_params_from_bl2_t *)arg1;
 	image_info_t bl32_img_info = { {0} };
-	uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end, console_base;
-	uint32_t console_clock;
+	uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end;
 	int32_t ret;
-	static console_16550_t console;
 
 	/*
 	 * For RESET_TO_BL31 systems, BL31 is the first bootloader to run so
@@ -182,31 +180,9 @@
 	}
 
 	/*
-	 * Reference clock used by the FPGAs is a lot slower.
+	 * Enable console for the platform
 	 */
-	if (tegra_platform_is_fpga()) {
-		console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
-	} else {
-		console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
-	}
-
-	/*
-	 * Get the base address of the UART controller to be used for the
-	 * console
-	 */
-	console_base = plat_get_console_from_id(plat_params->uart_id);
-
-	if (console_base != 0U) {
-		/*
-		 * Configure the UART port to be used as the console
-		 */
-		(void)console_16550_register(console_base,
-					     console_clock,
-					     TEGRA_CONSOLE_BAUDRATE,
-					     &console);
-		console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
-			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
-	}
+	plat_enable_console(plat_params->uart_id);
 
 	/*
 	 * The previous bootloader passes the base address of the shared memory
diff --git a/plat/nvidia/tegra/include/t194/tegra_def.h b/plat/nvidia/tegra/include/t194/tegra_def.h
index ca2a6ed..bedf268 100644
--- a/plat/nvidia/tegra/include/t194/tegra_def.h
+++ b/plat/nvidia/tegra/include/t194/tegra_def.h
@@ -144,6 +144,12 @@
 #define  RNG1_MUTEX_WATCHDOG_NS_LIMIT	U(0xFE0)
 
 /*******************************************************************************
+ * Tegra hardware synchronization primitives for the SPE engine
+ ******************************************************************************/
+#define TEGRA_AON_HSP_SM_6_7_BASE	U(0x0c190000)
+#define TEGRA_CONSOLE_SPE_BASE		(TEGRA_AON_HSP_SM_6_7_BASE + U(0x8000))
+
+/*******************************************************************************
  * Tegra micro-seconds timer constants
  ******************************************************************************/
 #define TEGRA_TMRUS_BASE		U(0x0C2E0000)
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index fab0eaf..cd2f773 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -76,7 +76,7 @@
 
 /* Declarations for plat_setup.c */
 const mmap_region_t *plat_get_mmio_map(void);
-uint32_t plat_get_console_from_id(int32_t id);
+void plat_enable_console(int32_t id);
 void plat_gic_setup(void);
 struct tegra_bl31_params *plat_get_bl31_params(void);
 plat_params_from_bl2_t *plat_get_bl31_plat_params(void);
diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c
index 570acd9..df62678 100644
--- a/plat/nvidia/tegra/soc/t132/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t132/plat_setup.c
@@ -6,9 +6,11 @@
 
 #include <arch_helpers.h>
 #include <common/bl_common.h>
+#include <drivers/console.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <tegra_def.h>
+#include <tegra_platform.h>
 #include <tegra_private.h>
 
 /* sets of MMIO ranges setup */
@@ -85,14 +87,30 @@
 };
 
 /*******************************************************************************
- * Retrieve the UART controller base to be used as the console
+ * Enable console corresponding to the console ID
  ******************************************************************************/
-uint32_t plat_get_console_from_id(int id)
+void plat_enable_console(int32_t id)
 {
-	if (id > TEGRA132_MAX_UART_PORTS)
-		return 0;
+	static console_16550_t uart_console;
+	uint32_t console_clock;
+
+	if ((id > 0) && (id < TEGRA132_MAX_UART_PORTS)) {
+		/*
+		 * Reference clock used by the FPGAs is a lot slower.
+		 */
+		if (tegra_platform_is_fpga()) {
+			console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
+		} else {
+			console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
+		}
 
-	return tegra132_uart_addresses[id];
+		(void)console_16550_register(tegra132_uart_addresses[id],
+					     console_clock,
+					     TEGRA_CONSOLE_BAUDRATE,
+					     &uart_console);
+		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+	}
 }
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index ef0ba4e..1018caa 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -141,19 +141,30 @@
 };
 
 /*******************************************************************************
- * Retrieve the UART controller base to be used as the console
+ * Enable console corresponding to the console ID
  ******************************************************************************/
-uint32_t plat_get_console_from_id(int32_t id)
+void plat_enable_console(int32_t id)
 {
-	uint32_t ret;
+	static console_16550_t uart_console;
+	uint32_t console_clock;
 
-	if (id > TEGRA186_MAX_UART_PORTS) {
-		ret = 0;
-	} else {
-		ret = tegra186_uart_addresses[id];
-	}
+	if ((id > 0) && (id < TEGRA186_MAX_UART_PORTS)) {
+		/*
+		 * Reference clock used by the FPGAs is a lot slower.
+		 */
+		if (tegra_platform_is_fpga()) {
+			console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
+		} else {
+			console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
+		}
 
-	return ret;
+		(void)console_16550_register(tegra186_uart_addresses[id],
+					     console_clock,
+					     TEGRA_CONSOLE_BAUDRATE,
+					     &uart_console);
+		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+	}
 }
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
index 278dabe..8c57105 100644
--- a/plat/nvidia/tegra/soc/t194/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -21,12 +21,16 @@
 #include <mce.h>
 #include <mce_private.h>
 #include <plat/common/platform.h>
+#include <spe.h>
 #include <tegra_def.h>
 #include <tegra_mc_def.h>
 #include <tegra_platform.h>
 #include <tegra_private.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
+/* ID for spe-console */
+#define TEGRA_CONSOLE_SPE_ID		0xFE
+
 /*******************************************************************************
  * 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
@@ -68,12 +72,14 @@
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000U, /* 64KB */
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#if !ENABLE_CONSOLE_SPE
 	MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000U, /* 128KB - UART A, B*/
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000U, /* 192KB - UART D, E, F */
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#endif
 	MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000U, /* 64KB */
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000U, /* 128KB */
@@ -84,6 +90,10 @@
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000U, /* 64KB */
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#if ENABLE_CONSOLE_SPE
+	MAP_REGION_FLAT(TEGRA_AON_HSP_SM_6_7_BASE, 0x10000U, /* 64KB */
+			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#endif
 	MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000U, /* 256KB */
@@ -120,6 +130,7 @@
 	return 31250000;
 }
 
+#if !ENABLE_CONSOLE_SPE
 /*******************************************************************************
  * Maximum supported UART controllers
  ******************************************************************************/
@@ -138,21 +149,47 @@
 	TEGRA_UARTF_BASE,
 	TEGRA_UARTG_BASE
 };
+#endif
 
 /*******************************************************************************
- * Retrieve the UART controller base to be used as the console
+ * Enable console corresponding to the console ID
  ******************************************************************************/
-uint32_t plat_get_console_from_id(int32_t id)
+void plat_enable_console(int32_t id)
 {
-	uint32_t ret;
+	uint32_t console_clock = 0U;
 
-	if (id > TEGRA194_MAX_UART_PORTS) {
-		ret = 0;
-	} else {
-		ret = tegra194_uart_addresses[id];
+#if ENABLE_CONSOLE_SPE
+	static console_spe_t spe_console;
+
+	if (id == TEGRA_CONSOLE_SPE_ID) {
+		(void)console_spe_register(TEGRA_CONSOLE_SPE_BASE,
+					   console_clock,
+					   TEGRA_CONSOLE_BAUDRATE,
+					   &spe_console);
+		console_set_scope(&spe_console.console, CONSOLE_FLAG_BOOT |
+			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
+#else
+	static console_16550_t uart_console;
 
-	return ret;
+	if ((id > 0) && (id < TEGRA194_MAX_UART_PORTS)) {
+		/*
+		 * Reference clock used by the FPGAs is a lot slower.
+		 */
+		if (tegra_platform_is_fpga()) {
+			console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
+		} else {
+			console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
+		}
+
+		(void)console_16550_register(tegra194_uart_addresses[id],
+					     console_clock,
+					     TEGRA_CONSOLE_BAUDRATE,
+					     &uart_console);
+		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+	}
+#endif
 }
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t194/platform_t194.mk b/plat/nvidia/tegra/soc/t194/platform_t194.mk
index ea171bd..5ec1af2 100644
--- a/plat/nvidia/tegra/soc/t194/platform_t194.mk
+++ b/plat/nvidia/tegra/soc/t194/platform_t194.mk
@@ -5,6 +5,9 @@
 #
 
 # platform configs
+ENABLE_CONSOLE_SPE			:= 0
+$(eval $(call add_define,ENABLE_CONSOLE_SPE))
+
 ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS	:= 0
 $(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS))
 
@@ -42,7 +45,7 @@
 # platform files
 PLAT_INCLUDES		+=	-I${SOC_DIR}/drivers/include
 
-BL31_SOURCES		+=	drivers/ti/uart/aarch64/16550_console.S	\
+BL31_SOURCES		+=	drivers/ti/uart/aarch64/16550_console.S \
 				lib/cpus/aarch64/denver.S		\
 				${COMMON_DIR}/drivers/memctrl/memctrl_v2.c	\
 				${COMMON_DIR}/drivers/smmu/smmu.c	\
@@ -57,3 +60,7 @@
 				${SOC_DIR}/plat_sip_calls.c		\
 				${SOC_DIR}/plat_smmu.c			\
 				${SOC_DIR}/plat_trampoline.S
+
+ifeq (${ENABLE_CONSOLE_SPE},1)
+BL31_SOURCES		+=	${COMMON_DIR}/drivers/spe/shared_console.S
+endif
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index 2a2d102..bfa8184 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -114,14 +114,30 @@
 };
 
 /*******************************************************************************
- * Retrieve the UART controller base to be used as the console
+ * Enable console corresponding to the console ID
  ******************************************************************************/
-uint32_t plat_get_console_from_id(int id)
+void plat_enable_console(int32_t id)
 {
-	if (id > TEGRA210_MAX_UART_PORTS)
-		return 0;
+	static console_16550_t uart_console;
+	uint32_t console_clock;
+
+	if ((id > 0) && (id < TEGRA210_MAX_UART_PORTS)) {
+		/*
+		 * Reference clock used by the FPGAs is a lot slower.
+		 */
+		if (tegra_platform_is_fpga()) {
+			console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
+		} else {
+			console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
+		}
 
-	return tegra210_uart_addresses[id];
+		(void)console_16550_register(tegra210_uart_addresses[id],
+					     console_clock,
+					     TEGRA_CONSOLE_BAUDRATE,
+					     &uart_console);
+		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+	}
 }
 
 /*******************************************************************************