[U-Boot] [PATCH v2 09/14] arm: zynq: Support the debug UART

Simon Glass sjg at chromium.org
Sun Oct 18 03:41:22 CEST 2015


Add support for the debug UART to assist with early debugging. Enable it
for Zybo as an example.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v2: None

 arch/arm/mach-zynq/spl.c     |  6 ++++
 configs/zynq_zybo_defconfig  |  4 +++
 drivers/serial/Kconfig       |  7 ++++
 drivers/serial/serial_zynq.c | 77 +++++++++++++++++++++++++++++++++++---------
 4 files changed, 78 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-zynq/spl.c b/arch/arm/mach-zynq/spl.c
index 1805455..723019d 100644
--- a/arch/arm/mach-zynq/spl.c
+++ b/arch/arm/mach-zynq/spl.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <debug_uart.h>
 #include <spl.h>
 
 #include <asm/io.h>
@@ -18,6 +19,11 @@ void board_init_f(ulong dummy)
 	ps7_init();
 
 	arch_cpu_init();
+	/*
+	 * The debug UART can be used from this point:
+	 * debug_uart_init();
+	 * printch('x');
+	 */
 }
 
 #ifdef CONFIG_SPL_BOARD_INIT
diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig
index fc251dc..b7531d6 100644
--- a/configs/zynq_zybo_defconfig
+++ b/configs/zynq_zybo_defconfig
@@ -11,3 +11,7 @@ CONFIG_FIT_SIGNATURE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_SEPARATE=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xe0001000
+CONFIG_DEBUG_UART_CLOCK=50000000
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ddb725d..6f2a1b1 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -77,6 +77,13 @@ config DEBUG_UART_S5P
 	  will need to provide parameters to make this work. The driver will
 	  be available until the real driver-model serial is running.
 
+config DEBUG_UART_ZYNQ
+	bool "Xilinx Zynq"
+	help
+	  Select this to enable a debug UART using the serial_s5p driver. You
+	  will need to provide parameters to make this work. The driver will
+	  be available until the real driver-model serial is running.
+
 endchoice
 
 config DEBUG_UART_BASE
diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
index 9d84290..c4304dd 100644
--- a/drivers/serial/serial_zynq.c
+++ b/drivers/serial/serial_zynq.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <errno.h>
 #include <fdtdec.h>
 #include <watchdog.h>
 #include <asm/io.h>
@@ -43,20 +44,16 @@ static struct uart_zynq *uart_zynq_ports[2] = {
 };
 
 /* Set up the baud rate in gd struct */
-static void uart_zynq_serial_setbrg(const int port)
+static void _uart_zynq_serial_setbrg(struct uart_zynq *regs,
+				     unsigned long clock, unsigned long baud)
 {
 	/* Calculation results. */
 	unsigned int calc_bauderror, bdiv, bgen;
 	unsigned long calc_baud = 0;
-	unsigned long baud;
-	unsigned long clock = get_uart_clk(port);
-	struct uart_zynq *regs = uart_zynq_ports[port];
 
 	/* Covering case where input clock is so slow */
-	if (clock < 1000000 && gd->baudrate > 4800)
-		gd->baudrate = 4800;
-
-	baud = gd->baudrate;
+	if (clock < 1000000 && baud > 4800)
+		baud = 4800;
 
 	/*                master clock
 	 * Baud rate = ------------------
@@ -87,36 +84,59 @@ static void uart_zynq_serial_setbrg(const int port)
 	writel(bgen, &regs->baud_rate_gen);
 }
 
-/* Initialize the UART, with...some settings. */
-static int uart_zynq_serial_init(const int port)
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
 {
+	unsigned long clock = get_uart_clk(port);
 	struct uart_zynq *regs = uart_zynq_ports[port];
 
-	if (!regs)
-		return -1;
+	return _uart_zynq_serial_setbrg(regs, clock, gd->baudrate);
+}
 
+/* Initialize the UART, with...some settings. */
+static void _uart_zynq_serial_init(struct uart_zynq *regs)
+{
 	/* RX/TX enabled & reset */
 	writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \
 					ZYNQ_UART_CR_RXRST, &regs->control);
 	writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
+}
+
+/* Initialize the UART, with...some settings. */
+static int uart_zynq_serial_init(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	if (!regs)
+		return -1;
+
+	_uart_zynq_serial_init(regs);
 	uart_zynq_serial_setbrg(port);
 
 	return 0;
 }
 
+static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c)
+{
+	if (readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL)
+		return -EAGAIN;
+
+	writel(c, &regs->tx_rx_fifo);
+
+	return 0;
+}
+
 static void uart_zynq_serial_putc(const char c, const int port)
 {
 	struct uart_zynq *regs = uart_zynq_ports[port];
 
-	while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)
+	while (_uart_zynq_serial_putc(regs, c) == -EAGAIN)
 		WATCHDOG_RESET();
 
 	if (c == '\n') {
-		writel('\r', &regs->tx_rx_fifo);
-		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)
+		while (_uart_zynq_serial_putc(regs, '\r') == -EAGAIN)
 			WATCHDOG_RESET();
 	}
-	writel(c, &regs->tx_rx_fifo);
 }
 
 static void uart_zynq_serial_puts(const char *s, const int port)
@@ -218,3 +238,28 @@ void zynq_serial_initialize(void)
 	serial_register(&uart_zynq_serial0_device);
 	serial_register(&uart_zynq_serial1_device);
 }
+
+#ifdef CONFIG_DEBUG_UART_ZYNQ
+
+#include <debug_uart.h>
+
+void debug_uart_init(void)
+{
+	struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE;
+
+	_uart_zynq_serial_init(regs);
+	_uart_zynq_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
+				 CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+	struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE;
+
+	while (_uart_zynq_serial_putc(regs, ch) == -EAGAIN)
+		WATCHDOG_RESET();
+}
+
+DEBUG_UART_FUNCS
+
+#endif
-- 
2.6.0.rc2.230.g3dd15c0



More information about the U-Boot mailing list