[Skiboot] [PATCH 1/5] uart: Fix Linux pass-through policy

Benjamin Herrenschmidt benh at kernel.crashing.org
Fri Feb 3 20:51:56 AEDT 2017


This was broken on Rhesus. Also add an nvram way of
overriding the policy

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
 hw/lpc-uart.c             | 37 ++++++++++++++++++++++++++++++++++---
 include/skiboot.h         |  7 +++++--
 platforms/astbmc/zaius.c  |  3 +++
 platforms/rhesus/rhesus.c |  2 +-
 4 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c
index 17abe08..d063710 100644
--- a/hw/lpc-uart.c
+++ b/hw/lpc-uart.c
@@ -27,6 +27,7 @@
 #include <cpu.h>
 #include <chip.h>
 #include <io.h>
+#include <nvram.h>
 
 DEFINE_LOG_ENTRY(OPAL_RC_UART_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_UART,
 		 OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
@@ -68,6 +69,12 @@ static bool has_irq = false, irq_ok, rx_full, tx_full;
 static uint8_t tx_room;
 static uint8_t cached_ier;
 static void *mmio_uart_base;
+static int uart_console_policy = UART_CONSOLE_OPAL;
+
+void uart_set_console_policy(int policy)
+{
+	uart_console_policy = policy;
+}
 
 static void uart_trace(u8 ctx, u8 cnt, u8 irq_state, u8 in_count)
 {
@@ -412,7 +419,7 @@ static void uart_irq(uint32_t chip_id __unused, uint32_t irq_mask __unused)
  * Common setup/inits
  */
 
-void uart_setup_linux_passthrough(void)
+static void uart_setup_os_passthrough(void)
 {
 	char *path;
 
@@ -423,7 +430,7 @@ void uart_setup_linux_passthrough(void)
 	prlog(PR_DEBUG, "UART: Enabled as OS pass-through\n");
 }
 
-void uart_setup_opal_console(void)
+static void uart_setup_opal_console(void)
 {
 	/* Add the opal console node */
 	add_opal_console_node(0, "raw", OUT_BUF_SIZE);
@@ -451,9 +458,33 @@ void uart_setup_opal_console(void)
 	opal_add_poller(uart_console_poll, NULL);
 }
 
+static void uart_init_opal_console(void)
+{
+	const char *nv_policy;
+
+	/* Update the policy if the corresponding nvram variable
+	 * is present
+	 */
+	nv_policy = nvram_query("uart-con-policy");
+	if (nv_policy) {
+		if (!strcmp(nv_policy, "opal"))
+			uart_console_policy = UART_CONSOLE_OPAL;
+		else if (!strcmp(nv_policy, "os"))
+			uart_console_policy = UART_CONSOLE_OS;
+		else
+			prlog(PR_WARNING,
+			      "UART: Unknown console policy in NVRAM: %s\n",
+			      nv_policy);
+	}
+	if (uart_console_policy == UART_CONSOLE_OPAL)
+		uart_setup_opal_console();
+	else
+		uart_setup_os_passthrough();
+}
+
 struct opal_con_ops uart_opal_con = {
 	.name = "OPAL UART console",
-	.init = uart_setup_opal_console,
+	.init = uart_init_opal_console,
 	.read = uart_opal_read,
 	.write = uart_opal_write,
 	.space = uart_opal_write_buffer_space,
diff --git a/include/skiboot.h b/include/skiboot.h
index bc716f9..7904eee 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -243,8 +243,11 @@ extern void nvram_init(void);
 extern void nvram_read_complete(bool success);
 
 /* UART stuff */
-extern void uart_setup_linux_passthrough(void);
-extern void uart_setup_opal_console(void);
+enum {
+	UART_CONSOLE_OPAL,
+	UART_CONSOLE_OS
+};
+extern void uart_set_console_policy(int policy);
 extern bool uart_enabled(void);
 
 /* OCC interrupt */
diff --git a/platforms/astbmc/zaius.c b/platforms/astbmc/zaius.c
index b95be21..2c063d4 100644
--- a/platforms/astbmc/zaius.c
+++ b/platforms/astbmc/zaius.c
@@ -33,6 +33,9 @@ static bool zaius_probe(void)
 	astbmc_early_init();
 	psi_set_external_irq_policy(EXTERNAL_IRQ_POLICY_LINUX);
 
+	/* Setup UART for direct use by Linux */
+	uart_set_console_policy(UART_CONSOLE_OS);
+
 	return true;
 }
 
diff --git a/platforms/rhesus/rhesus.c b/platforms/rhesus/rhesus.c
index c96f120..0571e22 100644
--- a/platforms/rhesus/rhesus.c
+++ b/platforms/rhesus/rhesus.c
@@ -154,7 +154,7 @@ static void rhesus_init(void)
 	rhesus_pnor_init();
 
 	/* Setup UART for direct use by Linux */
-	uart_setup_linux_passthrough();
+	uart_set_console_policy(UART_CONSOLE_OS);
 }
 
 static void rhesus_dt_fixup_uart(struct dt_node *lpc, bool has_irq)
-- 
2.9.3



More information about the Skiboot mailing list