feat(msm8916): allow selecting which UART to use

At the moment the msm8916 platform port always uses UART number 2 for
debug output. In some situations it is necessary to change this, either
because only the other UART is exposed on the board or for runtime
debugging, to avoid conflicting with the normal world.

Make the UART to use configurable using QTI_UART_NUM on the make
command line and also add QTI_RUNTIME_UART as an option to keep using
the UART after early boot. The latter is disabled by default since it
requires reserving the UART and related clocks inside the normal world.

Change-Id: I14725f954bbcecebcf317e8601922a3d00f2ec28
Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
diff --git a/plat/qti/msm8916/aarch32/msm8916_helpers.S b/plat/qti/msm8916/aarch32/msm8916_helpers.S
index 3664ff1..ea39663 100644
--- a/plat/qti/msm8916/aarch32/msm8916_helpers.S
+++ b/plat/qti/msm8916/aarch32/msm8916_helpers.S
@@ -30,7 +30,7 @@
 	 * -------------------------------------------------
 	 */
 func plat_crash_console_init
-	ldr	r1, =BLSP_UART2_BASE
+	ldr	r1, =BLSP_UART_BASE
 	mov	r0, #1
 	b	console_uartdm_core_init
 endfunc plat_crash_console_init
@@ -44,7 +44,7 @@
 	 * -------------------------------------------------
 	 */
 func plat_crash_console_putc
-	ldr	r1, =BLSP_UART2_BASE
+	ldr	r1, =BLSP_UART_BASE
 	b	console_uartdm_core_putc
 endfunc plat_crash_console_putc
 
@@ -56,7 +56,7 @@
 	 * -------------------------------------------------
 	 */
 func plat_crash_console_flush
-	ldr	r1, =BLSP_UART2_BASE
+	ldr	r1, =BLSP_UART_BASE
 	b	console_uartdm_core_flush
 endfunc plat_crash_console_flush
 
diff --git a/plat/qti/msm8916/aarch64/msm8916_helpers.S b/plat/qti/msm8916/aarch64/msm8916_helpers.S
index 4bed215..bccc5e5 100644
--- a/plat/qti/msm8916/aarch64/msm8916_helpers.S
+++ b/plat/qti/msm8916/aarch64/msm8916_helpers.S
@@ -30,7 +30,7 @@
 	 * -------------------------------------------------
 	 */
 func plat_crash_console_init
-	mov	x1, #BLSP_UART2_BASE
+	mov_imm	x1, BLSP_UART_BASE
 	mov	x0, #1
 	b	console_uartdm_core_init
 endfunc plat_crash_console_init
@@ -44,7 +44,7 @@
 	 * -------------------------------------------------
 	 */
 func plat_crash_console_putc
-	mov	x1, #BLSP_UART2_BASE
+	mov_imm	x1, BLSP_UART_BASE
 	b	console_uartdm_core_putc
 endfunc plat_crash_console_putc
 
@@ -56,7 +56,7 @@
 	 * -------------------------------------------------
 	 */
 func plat_crash_console_flush
-	mov	x1, #BLSP_UART2_BASE
+	mov_imm	x1, BLSP_UART_BASE
 	b	console_uartdm_core_flush
 endfunc plat_crash_console_flush
 
diff --git a/plat/qti/msm8916/include/msm8916_mmap.h b/plat/qti/msm8916/include/msm8916_mmap.h
index d201536..35e3b86 100644
--- a/plat/qti/msm8916/include/msm8916_mmap.h
+++ b/plat/qti/msm8916/include/msm8916_mmap.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net>
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -23,8 +23,9 @@
 #define APPS_SMMU_BASE		(PCNOC_BASE + 0x1e00000)
 #define APPS_SMMU_QCOM		(APPS_SMMU_BASE + 0xf0000)
 
-#define BLSP_UART1_BASE		(PCNOC_BASE + 0x78af000)
-#define BLSP_UART2_BASE		(PCNOC_BASE + 0x78b0000)
+#define BLSP1_BASE		(PCNOC_BASE + 0x7880000)
+#define BLSP1_UART_BASE(n)	(BLSP1_BASE + 0x2f000 + (((n) - 1) * 0x1000))
+#define BLSP_UART_BASE		BLSP1_UART_BASE(QTI_UART_NUM)
 
 #define APCS_QGIC2_BASE		(APCS_BASE + 0x00000)
 #define APCS_QGIC2_GICD		(APCS_QGIC2_BASE + 0x0000)
diff --git a/plat/qti/msm8916/msm8916_setup.c b/plat/qti/msm8916/msm8916_setup.c
index 50c6c0a..26039a9 100644
--- a/plat/qti/msm8916/msm8916_setup.c
+++ b/plat/qti/msm8916/msm8916_setup.c
@@ -31,46 +31,64 @@
 	return PLAT_SYSCNT_FREQ;
 }
 
-#define GPIO_BLSP_UART2_TX		4
-#define GPIO_BLSP_UART2_RX		5
-#define GPIO_CFG_FUNC_BLSP_UART2	(U(0x2) << 2)
-#define GPIO_CFG_DRV_STRENGTH_16MA	(U(0x7) << 6)
+#define GPIO_CFG_FUNC(n)		((n) << 2)
+#define GPIO_CFG_DRV_STRENGTH_MA(ma)	(((ma) / 2 - 1) << 6)
 
 #define CLK_ENABLE			BIT_32(0)
 #define CLK_OFF				BIT_32(31)
 #define GCC_BLSP1_AHB_CBCR		(GCC_BASE + 0x01008)
-#define GCC_BLSP1_UART2_APPS_CBCR	(GCC_BASE + 0x0302c)
+#define GCC_BLSP1_UART_APPS_CBCR(n)	(GCC_BASE + \
+	(((n) == 2) ? (0x0302c) : (0x0203c + (((n) - 1) * 0x1000))))
 #define GCC_APCS_CLOCK_BRANCH_ENA_VOTE	(GCC_BASE + 0x45004)
 #define BLSP1_AHB_CLK_ENA		BIT_32(10)
 
+struct uartdm_gpios {
+	unsigned int tx, rx, func;
+};
+
+static const struct uartdm_gpios uartdm_gpio_map[] = {
+	{0, 1, 0x2}, {4, 5, 0x2},
+};
+
 /*
  * The previous boot stage seems to disable most of the UART setup before exit
  * so it must be enabled here again before the UART console can be used.
  */
-static void msm8916_enable_blsp_uart2(void)
+static void msm8916_enable_blsp_uart(void)
 {
-	/* Route GPIOs to BLSP UART2 */
-	mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_TX),
-		      GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA);
-	mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_RX),
-		      GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA);
+	const struct uartdm_gpios *gpios = &uartdm_gpio_map[QTI_UART_NUM - 1];
+
+	CASSERT(QTI_UART_NUM > 0 && QTI_UART_NUM <= ARRAY_SIZE(uartdm_gpio_map),
+		assert_qti_blsp_uart_valid);
+
+	/* Route GPIOs to BLSP UART */
+	mmio_write_32(TLMM_GPIO_CFG(gpios->tx), GPIO_CFG_FUNC(gpios->func) |
+		      GPIO_CFG_DRV_STRENGTH_MA(8));
+	mmio_write_32(TLMM_GPIO_CFG(gpios->rx), GPIO_CFG_FUNC(gpios->func) |
+		      GPIO_CFG_DRV_STRENGTH_MA(8));
 
 	/* Enable AHB clock */
 	mmio_setbits_32(GCC_APCS_CLOCK_BRANCH_ENA_VOTE, BLSP1_AHB_CLK_ENA);
 	while (mmio_read_32(GCC_BLSP1_AHB_CBCR) & CLK_OFF)
 		;
 
-	/* Enable BLSP UART2 clock */
-	mmio_setbits_32(GCC_BLSP1_UART2_APPS_CBCR, CLK_ENABLE);
-	while (mmio_read_32(GCC_BLSP1_UART2_APPS_CBCR) & CLK_OFF)
+	/* Enable BLSP UART clock */
+	mmio_setbits_32(GCC_BLSP1_UART_APPS_CBCR(QTI_UART_NUM), CLK_ENABLE);
+	while (mmio_read_32(GCC_BLSP1_UART_APPS_CBCR(QTI_UART_NUM)) & CLK_OFF)
 		;
 }
 
 void msm8916_early_platform_setup(void)
 {
 	/* Initialize the debug console as early as possible */
-	msm8916_enable_blsp_uart2();
-	console_uartdm_register(&console, BLSP_UART2_BASE);
+	msm8916_enable_blsp_uart();
+	console_uartdm_register(&console, BLSP_UART_BASE);
+
+	if (QTI_RUNTIME_UART) {
+		/* Mark UART as runtime usable */
+		console_set_scope(&console, CONSOLE_FLAG_BOOT |
+				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+	}
 }
 
 void msm8916_plat_arch_setup(uintptr_t base, size_t size)
diff --git a/plat/qti/msm8916/platform.mk b/plat/qti/msm8916/platform.mk
index 4dce773..7e698fb 100644
--- a/plat/qti/msm8916/platform.mk
+++ b/plat/qti/msm8916/platform.mk
@@ -76,3 +76,14 @@
 BL32_BASE			?= $(BL31_BASE)
 endif
 $(eval $(call add_define,BL32_BASE))
+
+# UART number to use for TF-A output during early boot
+QTI_UART_NUM			?= 2
+$(eval $(call assert_numeric,QTI_UART_NUM))
+$(eval $(call add_define,QTI_UART_NUM))
+
+# Set to 1 on the command line to keep using UART after early boot.
+# Requires reserving the UART and related clocks inside the normal world.
+QTI_RUNTIME_UART		?= 0
+$(eval $(call assert_boolean,QTI_RUNTIME_UART))
+$(eval $(call add_define,QTI_RUNTIME_UART))