[U-Boot] [PATCH v6] nios2: convert altera_jtag_uart to driver model

Thomas Chou thomas at wytron.com.tw
Sun Sep 20 10:36:02 CEST 2015


Convert altera_jtag_uart to driver model.

Signed-off-by: Thomas Chou <thomas at wytron.com.tw>
Acked-by: Marek Vasut <marex at denx.de>
Reviewed-by: Simon Glass <sjg at chromium.org>
---
v2
  add ioremap.
  make the change to dts compatible with linux.

v3
  use fdt address translation patch from Stefan Roese.
  fix watchdog and loop as Marek suggested.

v4
  add clear AC flag to probe().
  remove polling loops and watchdog reset because they are
    done in the serial-uclass.c.

v5
  fix coding style as Marek suggested to altera_uart.

v6
  add early debug uart.
  use chosen stdout-path to assign console.
  fix coding style as Simon suggested.

 arch/nios2/dts/3c120_devboard.dts |   2 +
 configs/nios2-generic_defconfig   |   3 +
 drivers/serial/Kconfig            |  26 ++++++
 drivers/serial/altera_jtag_uart.c | 171 +++++++++++++++++++++++++-------------
 include/configs/nios2-generic.h   |   3 -
 5 files changed, 142 insertions(+), 63 deletions(-)

diff --git a/arch/nios2/dts/3c120_devboard.dts b/arch/nios2/dts/3c120_devboard.dts
index 02524ab..07bec69 100644
--- a/arch/nios2/dts/3c120_devboard.dts
+++ b/arch/nios2/dts/3c120_devboard.dts
@@ -93,6 +93,7 @@
 				reg = <0x00004d50 0x00000008>;
 				interrupt-parent = <&cpu>;
 				interrupts = <1>;
+				u-boot,dm-pre-reloc;
 			};
 
 			tse_mac: ethernet at 0x4000 {
@@ -149,5 +150,6 @@
 
 	chosen {
 		bootargs = "debug console=ttyJ0,115200";
+		stdout-path = &jtag_uart;
 	};
 };
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 9c1bec5..9dc6a72 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -1,4 +1,5 @@
 CONFIG_NIOS2=y
+CONFIG_DM_SERIAL=y
 CONFIG_TARGET_NIOS2_GENERIC=y
 CONFIG_DEFAULT_DEVICE_TREE="3c120_devboard"
 CONFIG_HUSH_PARSER=y
@@ -14,3 +15,5 @@ CONFIG_CMD_PING=y
 CONFIG_OF_CONTROL=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM=y
+CONFIG_ALTERA_JTAG_UART=y
+CONFIG_ALTERA_JTAG_UART_BYPASS=y
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ccb80d2..10505dc 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -54,6 +54,13 @@ choice
 	prompt "Select which UART will provide the debug UART"
 	depends on DEBUG_UART
 
+config DEBUG_UART_ALTERA_JTAGUART
+	bool "Altera JTAG UART"
+	help
+	  Select this to enable a debug UART using the altera_jtag_uart driver.
+	  You 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_NS16550
 	bool "ns16550"
 	help
@@ -109,6 +116,25 @@ config DEBUG_UART_SHIFT
 	  value. Use this value to specify the shift to use, where 0=byte
 	  registers, 2=32-bit word registers, etc.
 
+config ALTERA_JTAG_UART
+	bool "Altera JTAG UART support"
+	depends on DM_SERIAL
+	help
+	  Select this to enable an JTAG UART for Altera devices.The JTAG UART
+	  core implements a method to communicate serial character streams
+	  between a host PC and a Qsys system on an Altera FPGA. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
+config ALTERA_JTAG_UART_BYPASS
+	bool "Bypass output when no connection"
+	depends on ALTERA_JTAG_UART
+	help
+	  Bypass console output and keep going even if there is no JTAG
+	  terminal connection with the host. The console output will resume
+	  once the JTAG terminal is connected. Without the bypass, the console
+	  output will wait forever until a JTAG terminal is connected. If you
+	  not are sure, say Y.
+
 config ROCKCHIP_SERIAL
 	bool "Rockchip on-chip UART support"
 	depends on ARCH_UNIPHIER && DM_SERIAL
diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c
index 9a81402..39d4a4e 100644
--- a/drivers/serial/altera_jtag_uart.c
+++ b/drivers/serial/altera_jtag_uart.c
@@ -6,98 +6,149 @@
  */
 
 #include <common.h>
-#include <watchdog.h>
+#include <dm.h>
+#include <errno.h>
 #include <asm/io.h>
 #include <linux/compiler.h>
 #include <serial.h>
 
-typedef volatile struct {
-	unsigned	data;			/* Data register */
-	unsigned	control;		/* Control register */
-} nios_jtag_t;
+struct altera_jtaguart_regs {
+	u32	data;			/* Data register */
+	u32	control;		/* Control register */
+};
+
+struct altera_jtaguart_platdata {
+	struct altera_jtaguart_regs *regs;
+};
 
 /* data register */
-#define NIOS_JTAG_RVALID	(1<<15)		/* Read valid */
-#define NIOS_JTAG_DATA(d)	((d)&0x0ff)	/* Read data */
-#define NIOS_JTAG_RAVAIL(d)	((d)>>16)	/* Read space avail */
+#define ALTERA_JTAG_RVALID	(1<<15)		/* Read valid */
 
 /* control register */
-#define NIOS_JTAG_RE		(1 << 0)	/* read intr enable */
-#define NIOS_JTAG_WE		(1 << 1)	/* write intr enable */
-#define NIOS_JTAG_RI		(1 << 8)	/* read intr pending */
-#define NIOS_JTAG_WI		(1 << 9)	/* write intr pending*/
-#define NIOS_JTAG_AC		(1 << 10)	/* activity indicator */
-#define NIOS_JTAG_RRDY		(1 << 12)	/* read available */
-#define NIOS_JTAG_WSPACE(d)	((d)>>16)	/* Write space avail */
+#define ALTERA_JTAG_AC		(1 << 10)	/* activity indicator */
+#define ALTERA_JTAG_RRDY	(1 << 12)	/* read available */
+#define ALTERA_JTAG_WSPACE(d)	((d)>>16)	/* Write space avail */
+/* Write fifo size. FIXME: this should be extracted with sopc2dts */
+#define ALTERA_JTAG_WRITE_DEPTH	64
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/*------------------------------------------------------------------
- * JTAG acts as the serial port
- *-----------------------------------------------------------------*/
-static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE;
-
-static void altera_jtag_serial_setbrg(void)
+static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate)
 {
+	return 0;
 }
 
-static int altera_jtag_serial_init(void)
+static int altera_jtaguart_putc(struct udevice *dev, const char ch)
 {
+	struct altera_jtaguart_platdata *plat = dev->platdata;
+	struct altera_jtaguart_regs *const regs = plat->regs;
+	u32 st = readl(&regs->control);
+
+#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS
+	if (!(st & ALTERA_JTAG_AC)) /* no connection yet */
+		return -ENETUNREACH;
+#endif
+
+	if (ALTERA_JTAG_WSPACE(st) == 0)
+		return -EAGAIN;
+
+	writel(ch, &regs->data);
+
 	return 0;
 }
 
-static void altera_jtag_serial_putc(char c)
+static int altera_jtaguart_pending(struct udevice *dev, bool input)
 {
-	while (1) {
-		unsigned st = readl(&jtag->control);
-		if (NIOS_JTAG_WSPACE(st))
-			break;
-#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS
-		if (!(st & NIOS_JTAG_AC)) /* no connection */
-			return;
-#endif
-		WATCHDOG_RESET();
-	}
-	writel ((unsigned char)c, &jtag->data);
+	struct altera_jtaguart_platdata *plat = dev->platdata;
+	struct altera_jtaguart_regs *const regs = plat->regs;
+	u32 st = readl(&regs->control);
+
+	if (input)
+		return st & ALTERA_JTAG_RRDY ? 1 : 0;
+	else
+		return !(ALTERA_JTAG_WSPACE(st) == ALTERA_JTAG_WRITE_DEPTH);
 }
 
-static int altera_jtag_serial_tstc(void)
+static int altera_jtaguart_getc(struct udevice *dev)
 {
-	return ( readl (&jtag->control) & NIOS_JTAG_RRDY);
+	struct altera_jtaguart_platdata *plat = dev->platdata;
+	struct altera_jtaguart_regs *const regs = plat->regs;
+	u32 val;
+
+	val = readl(&regs->data);
+
+	if (!(val & ALTERA_JTAG_RVALID))
+		return -EAGAIN;
+
+	return val & 0xff;
 }
 
-static int altera_jtag_serial_getc(void)
+static int altera_jtaguart_probe(struct udevice *dev)
 {
-	int c;
-	unsigned val;
+#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS
+	struct altera_jtaguart_platdata *plat = dev->platdata;
+	struct altera_jtaguart_regs *const regs = plat->regs;
 
-	while (1) {
-		WATCHDOG_RESET ();
-		val = readl (&jtag->data);
-		if (val & NIOS_JTAG_RVALID)
-			break;
-	}
-	c = val & 0x0ff;
-	return (c);
+	writel(ALTERA_JTAG_AC, &regs->control); /* clear AC flag */
+#endif
+	return 0;
+}
+
+static int altera_jtaguart_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_jtaguart_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_jtaguart_regs));
+
+	return 0;
 }
 
-static struct serial_device altera_jtag_serial_drv = {
-	.name	= "altera_jtag_uart",
-	.start	= altera_jtag_serial_init,
-	.stop	= NULL,
-	.setbrg	= altera_jtag_serial_setbrg,
-	.putc	= altera_jtag_serial_putc,
-	.puts	= default_serial_puts,
-	.getc	= altera_jtag_serial_getc,
-	.tstc	= altera_jtag_serial_tstc,
+static const struct dm_serial_ops altera_jtaguart_ops = {
+	.putc = altera_jtaguart_putc,
+	.pending = altera_jtaguart_pending,
+	.getc = altera_jtaguart_getc,
+	.setbrg = altera_jtaguart_setbrg,
+};
+
+static const struct udevice_id altera_jtaguart_ids[] = {
+	{ .compatible = "altr,juart-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_jtaguart) = {
+	.name	= "altera_jtaguart",
+	.id	= UCLASS_SERIAL,
+	.of_match = altera_jtaguart_ids,
+	.ofdata_to_platdata = altera_jtaguart_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata),
+	.probe = altera_jtaguart_probe,
+	.ops	= &altera_jtaguart_ops,
+	.flags = DM_FLAG_PRE_RELOC,
 };
 
-void altera_jtag_serial_initialize(void)
+#ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART
+
+#include <debug_uart.h>
+
+void debug_uart_init(void)
 {
-	serial_register(&altera_jtag_serial_drv);
 }
 
-__weak struct serial_device *default_serial_console(void)
+static inline void _debug_uart_putc(int ch)
 {
-	return &altera_jtag_serial_drv;
+	struct altera_jtaguart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE;
+
+	while (1) {
+		u32 st = readl(&regs->control);
+
+		if (ALTERA_JTAG_WSPACE(st))
+			break;
+	}
+
+	writel(ch, &regs->data);
 }
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 66ad2f0..bd6d45c 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -23,14 +23,11 @@
 /*
  * SERIAL
  */
-#define CONFIG_ALTERA_JTAG_UART
 #if defined(CONFIG_ALTERA_JTAG_UART)
-# define CONFIG_SYS_NIOS_CONSOLE	CONFIG_SYS_JTAG_UART_BASE
 #else
 # define CONFIG_SYS_NIOS_CONSOLE	CONFIG_SYS_UART_BASE
 #endif
 
-#define CONFIG_ALTERA_JTAG_UART_BYPASS
 #define CONFIG_SYS_NIOS_FIXEDBAUD
 #define CONFIG_BAUDRATE		CONFIG_SYS_UART_BAUD
 #define CONFIG_SYS_BAUDRATE_TABLE	{CONFIG_BAUDRATE}
-- 
2.1.4



More information about the U-Boot mailing list