Skip to contentSkip to conversation

serial: Add Zynq serial driver

PATCH Superseded Michal Simek 5 participants 28 messages Sep 14, 2012 – Sep 28, 2012

Subsystems (3)

v3 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART
Rename driver name
Remove driver description

v3: SERIAL_MULTI support
Rename xdfuart to uart_zynq

---
 common/serial.c              |    8 ++
 drivers/serial/Makefile      |    1 +
 drivers/serial/serial_zynq.c |  246 ++++++++++++++++++++++++++++++++++++++++++
 include/serial.h             |    5 +
 4 files changed, 260 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/serial_zynq.c
common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
 	serial_register(&uartlite_serial3_device);
 # endif /* XILINX_UARTLITE_BASEADDR3 */
 #endif /* CONFIG_XILINX_UARTLITE */
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
 	serial_assign(default_serial_console()->name);
 }
 
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
 COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
 COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
 COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/serial_zynq.c new file +246 -0

246 lines not on this page · raw message

include/serial.h +5 -0
index cbdf8a9..dc8e9b4 100644
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
 extern struct serial_device bfin_serial3_device;
 #endif
 
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+
 extern void serial_register(struct serial_device *);
 extern void serial_initialize(void);
 extern void serial_stdio_init(void);
Signature · 1 line
1.7.0.4
#1 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Hi John,

sorry I forget you to cc you with this new series in spite of I promised to John W to do so.
My big apology it wasn't intention. Just forget to do it. I will forward you them.

Sorry,
Michal

Quoted 321 lines · Michal Simek

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART
Rename driver name
Remove driver description

v3: SERIAL_MULTI support
Rename xdfuart to uart_zynq

---
  common/serial.c              |    8 ++
  drivers/serial/Makefile      |    1 +
  drivers/serial/serial_zynq.c |  246 ++++++++++++++++++++++++++++++++++++++++++
  include/serial.h             |    5 +
  4 files changed, 260 insertions(+), 0 deletions(-)

create mode 100644 drivers/serial/serial_zynq.c

common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
  	serial_register(&uartlite_serial3_device);
  # endif /* XILINX_UARTLITE_BASEADDR3 */
  #endif /* CONFIG_XILINX_UARTLITE */
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
  	serial_assign(default_serial_console()->name);
  }
 
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
  COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
  COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
  COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
  ifndef CONFIG_SPL_BUILD
  COBJS-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/serial_zynq.c new file +246 -0
new file mode 100644
index 0000000..30f2445
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+	u32 control; /* Control Register [8:0] */
+	u32 mode; /* Mode Register [10:0] */
+	u32 reserved1[4];
+	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+	u32 reserved2[4];
+	u32 channel_sts; /* Channel Status [11:0] */
+	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) && defined(CONFIG_ZYNQ_SERIAL_CLOCK0)
+	[0].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE0,
+	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) && defined(CONFIG_ZYNQ_SERIAL_CLOCK1)
+	[1].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE1,
+	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = uart_zynq_ports_param[port].baudrate;
+	unsigned long clock = uart_zynq_ports_param[port].clock;
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	/*                master clock
+	 * Baud rate = ------------------
+	 *              bgen * (bdiv + 1)
+	 *
+	 * Find acceptable values for baud generation.
+	 */
+	for (bdiv = 4; bdiv < 255; bdiv++) {
+		bgen = clock / (baud * (bdiv + 1));
+		if (bgen < 2 || bgen > 65535)
+			continue;
+
+		calc_baud = clock / (bgen * (bdiv + 1));
+
+		/*
+		 * Use first calculated baudrate with
+		 * an acceptable (<3%) error
+		 */
+		if (baud > calc_baud)
+			calc_bauderror = baud - calc_baud;
+		else
+			calc_bauderror = calc_baud - baud;
+		if (((calc_bauderror * 100) / baud) < 3)
+			break;
+	}
+
+	writel(bdiv, &regs->baud_rate_divider);
+	writel(bgen, &regs->baud_rate_gen);
+}
+
+/* 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;
+
+	/* 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 */
+	uart_zynq_serial_setbrg(port);
+
+	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)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		uart_zynq_serial_putc(*s++, port);
+}
+
+static int uart_zynq_serial_tstc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while (!uart_zynq_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return uart_zynq_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	uart_zynq_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	uart_zynq_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	uart_zynq_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return uart_zynq_serial_getc(0);
+}
+
+int serial_tstc(void)
+{
+	return uart_zynq_serial_tstc(0);
+}
+#else
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+	int uart_zynq##port##_init(void) \
+				{ return uart_zynq_serial_init(port); } \
+	void uart_zynq##port##_setbrg(void) \
+				{ return uart_zynq_serial_setbrg(port); } \
+	int uart_zynq##port##_getc(void) \
+				{ return uart_zynq_serial_getc(port); } \
+	int uart_zynq##port##_tstc(void) \
+				{ return uart_zynq_serial_tstc(port); } \
+	void uart_zynq##port##_putc(const char c) \
+				{ uart_zynq_serial_putc(c, port); } \
+	void uart_zynq##port##_puts(const char *s) \
+				{ uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, name) {\
+	  name,\
+	  uart_zynq##port##_init,\
+	  NULL,\
+	  uart_zynq##port##_setbrg,\
+	  uart_zynq##port##_getc,\
+	  uart_zynq##port##_tstc,\
+	  uart_zynq##port##_putc,\
+	  uart_zynq##port##_puts, }
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+	if (uart_zynq_ports[0])
+		return &uart_zynq_serial0_device;
+	if (uart_zynq_ports[1])
+		return &uart_zynq_serial1_device;
+
+	return NULL;
+}
+#endif
include/serial.h +5 -0
index cbdf8a9..dc8e9b4 100644
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
  extern struct serial_device bfin_serial3_device;
  #endif
 
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+
  extern void serial_register(struct serial_device *);
  extern void serial_initialize(void);
  extern void serial_stdio_init(void);
Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#2 lore raw

PATCH v3 2/4 net: Add driver for Zynq Gem IP

In reply to Michal Simek

Device driver for Zynq Gem IP.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Remove phylib protection
Rename driver file name xilinx_gem to zynq_gem Rename XEMACPSS to ZYNQ_GEM
Rename gemac_priv to zynq_gem_priv
Rename gem_regs to zynq_gem_regs
Add zynq_ prefix to several functions Remove phy detection
Rename driver name XGem to Gem
Change setup_mac function to reflect u-boot style

v3: Remove magic variables
Remove initialized flag
Optimize waiting loop by WATCHDOG_RESET
Fix uninitialized variable
Use setbits_le32
Use const u32 mask variables
Implement zynq_gem_halt

---
 drivers/net/Makefile   |    1 +
 drivers/net/zynq_gem.c |  440 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/netdev.h       |    2 +-
 3 files changed, 442 insertions(+), 1 deletions(-)
 create mode 100644 drivers/net/zynq_gem.c
drivers/net/Makefile +1 -0
index 011cd51..e4abac7 100644
@@ -80,6 +80,7 @@ COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
 COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
 		xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
+COBJS-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
 
 COBJS	:= $(sort $(COBJS-y))
 SRCS	:= $(COBJS:.o=.c)
drivers/net/zynq_gem.c new file +440 -0

440 lines not on this page · raw message

include/netdev.h +1 -1
index d1aaf0c..b8d303d 100644
@@ -104,7 +104,7 @@ int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
 							int txpp, int rxpp);
 int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
 						unsigned long ctrl_addr);
-
+int zynq_gem_initialize(bd_t *bis, int base_addr);
 /*
  * As long as the Xilinx xps_ll_temac ethernet driver has not its own interface
  * exported by a public hader file, we need a global definition at this point.
Signature · 1 line
1.7.0.4
#3 lore raw

PATCH v3 2/4 net: Add driver for Zynq Gem IP

Dear Michal Simek,

Quoted 17 lines

Device driver for Zynq Gem IP.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Remove phylib protection
Rename driver file name xilinx_gem to zynq_gem Rename XEMACPSS to ZYNQ_GEM
Rename gemac_priv to zynq_gem_priv
Rename gem_regs to zynq_gem_regs
Add zynq_ prefix to several functions Remove phy detection
Rename driver name XGem to Gem
Change setup_mac function to reflect u-boot style

Quoted 7 lines

v3: Remove magic variables
Remove initialized flag
Optimize waiting loop by WATCHDOG_RESET
Fix uninitialized variable
Use setbits_le32
Use const u32 mask variables
Implement zynq_gem_halt

Best regards,
Marek Vasut

#5 lore raw

PATCH v4 4/4 xilinx: Add new Zynq board

In reply to Michal Simek

Add support for Xilinx Zynq board.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Forget to also add config file

v3: Change name for serial driver
Remove lowlevel_init from board folder
Remove XPSS part from timer baseaddr
Change name for Zynq gem driver
Clean coding style
Remove mac + ip addresses from config file
Remove additional PHYs

v4: Move reset_cpu to cpu folder
Remove empty board_late_init
Enable SERIAL_MULTI
Setup SYS_TEXT_BASE
Changed eth initialization

---
 board/xilinx/zynq/Makefile |   54 +++++++++++++++++++++
 board/xilinx/zynq/board.c  |   54 +++++++++++++++++++++
 boards.cfg                 |    1 +
 include/configs/zynq.h     |  112 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 221 insertions(+), 0 deletions(-)
 create mode 100644 board/xilinx/zynq/Makefile
 create mode 100644 board/xilinx/zynq/board.c
 create mode 100644 include/configs/zynq.h
board/xilinx/zynq/Makefile new file +54 -0
new file mode 100644
index 0000000..ef4faa1
@@ -0,0 +1,54 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+ifneq ($(OBJTREE),$(SRCTREE))
+$(shell mkdir -p $(obj)../common)
+endif
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS-y	:= board.o
+
+COBJS	:= $(sort $(COBJS-y))
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+clean:
+	rm -f $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
board/xilinx/zynq/board.c new file +54 -0

54 lines not on this page · raw message

boards.cfg +1 -0
index 72e7803..323dcc0 100644
@@ -272,6 +272,7 @@ ventana                      arm         armv7:arm720t ventana           nvidia
 whistler                     arm         armv7:arm720t whistler          nvidia         tegra20
 u8500_href                   arm         armv7       u8500               st-ericsson    u8500
 snowball                     arm         armv7       snowball               st-ericsson    u8500
+zynq                         arm         armv7       zynq                xilinx         zynq
 actux1_4_16                  arm         ixp         actux1              -              -           actux1:FLASH2X2
 actux1_4_32                  arm         ixp         actux1              -              -           actux1:FLASH2X2,RAM_32MB
 actux1_8_16                  arm         ixp         actux1              -              -           actux1:FLASH1X8
include/configs/zynq.h new file +112 -0

112 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#6 lore raw

PATCH v4 4/4 xilinx: Add new Zynq board

Dear Michal Simek,

Quoted 22 lines

Add support for Xilinx Zynq board.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Forget to also add config file

v3: Change name for serial driver
Remove lowlevel_init from board folder
Remove XPSS part from timer baseaddr
Change name for Zynq gem driver
Clean coding style
Remove mac + ip addresses from config file
Remove additional PHYs

v4: Move reset_cpu to cpu folder
Remove empty board_late_init
Enable SERIAL_MULTI
Setup SYS_TEXT_BASE
Changed eth initialization

[...]

Best regards,
Marek Vasut

#7 lore raw

PATCH v4 4/4 xilinx: Add new Zynq board

In reply to Michal Simek

Hi Michal,

Quoted 22 lines · Michal Simek

Add support for Xilinx Zynq board.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Forget to also add config file

v3: Change name for serial driver
Remove lowlevel_init from board folder
Remove XPSS part from timer baseaddr
Change name for Zynq gem driver
Clean coding style
Remove mac + ip addresses from config file
Remove additional PHYs

v4: Move reset_cpu to cpu folder
Remove empty board_late_init
Enable SERIAL_MULTI
Setup SYS_TEXT_BASE
Changed eth initialization

Quoted 9 lines
---
 board/xilinx/zynq/Makefile |   54 +++++++++++++++++++++
 board/xilinx/zynq/board.c  |   54 +++++++++++++++++++++
 boards.cfg                 |    1 +
 include/configs/zynq.h     |  112 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 221 insertions(+), 0 deletions(-)
 create mode 100644 board/xilinx/zynq/Makefile
 create mode 100644 board/xilinx/zynq/board.c
 create mode 100644 include/configs/zynq.h

Sorry for barging in late... Can you make a V5 with the MAINTAINERS file updated?

Amicalement,

Signature · 1 line
Albert.
#8 lore raw

PATCH v4 4/4 xilinx: Add new Zynq board

Hi Albert,

Quoted 37 lines · Albert ARIBAUD

Hi Michal,

Quoted 28 lines · Michal Simek

Add support for Xilinx Zynq board.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Forget to also add config file

v3: Change name for serial driver
Remove lowlevel_init from board folder
Remove XPSS part from timer baseaddr
Change name for Zynq gem driver
Clean coding style
Remove mac + ip addresses from config file
Remove additional PHYs

v4: Move reset_cpu to cpu folder
Remove empty board_late_init
Enable SERIAL_MULTI
Setup SYS_TEXT_BASE
Changed eth initialization

---
  board/xilinx/zynq/Makefile |   54 +++++++++++++++++++++
  board/xilinx/zynq/board.c  |   54 +++++++++++++++++++++
  boards.cfg                 |    1 +
  include/configs/zynq.h     |  112 ++++++++++++++++++++++++++++++++++++++++++++
  4 files changed, 221 insertions(+), 0 deletions(-)
Quoted 3 lines

create mode 100644 board/xilinx/zynq/Makefile
create mode 100644 board/xilinx/zynq/board.c
create mode 100644 include/configs/zynq.h

Quoted 2 lines

Sorry for barging in late... Can you make a V5 with the MAINTAINERS file updated?

I have sent v5 patch to the mailing list.
I have also updated master-zynq branch in my microblaze custodian repo
(git://git.denx.de/u-boot-microblaze.git).

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#9 lore raw

PATCH v3 3/4 arm: Support new Xilinx Zynq platform

In reply to Michal Simek

Add timer driver.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Move lowlevel_init.S from board to cpu folder
Remove XPSS prefix
Rename XSCUTIMER -> SCUTIMER

v3: Using clrsetbits_le32
Fix compilation warning
Move reset_cpu from board to cpu.c
Move lowlevel_init to cpu.c

---
 arch/arm/cpu/armv7/zynq/Makefile |   51 +++++++++++++
 arch/arm/cpu/armv7/zynq/cpu.c    |   31 ++++++++
 arch/arm/cpu/armv7/zynq/timer.c  |  150 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 232 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
 create mode 100644 arch/arm/cpu/armv7/zynq/cpu.c
 create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
arch/arm/cpu/armv7/zynq/Makefile new file +51 -0
new file mode 100644
index 0000000..499ace4
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# (C) Copyright 2008
+# Guennadi Liakhovetki, DENX Software Engineering, <[email protected]>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS-y	:= timer.o
+COBJS-y	+= cpu.o
+
+COBJS	:= $(COBJS-y)
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
arch/arm/cpu/armv7/zynq/cpu.c new file +31 -0
new file mode 100644
index 0000000..ab615cc
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}
arch/arm/cpu/armv7/zynq/timer.c new file +150 -0

150 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#10 lore raw

PATCH v3 3/4 arm: Support new Xilinx Zynq platform

Dear Michal Simek,

Quoted 15 lines

Add timer driver.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Move lowlevel_init.S from board to cpu folder
Remove XPSS prefix
Rename XSCUTIMER -> SCUTIMER

v3: Using clrsetbits_le32
Fix compilation warning
Move reset_cpu from board to cpu.c
Move lowlevel_init to cpu.c

[...]

arch/arm/cpu/armv7/zynq/cpu.c line 31

Quoted 9 lines
arch/arm/cpu/armv7/zynq/cpu.c new file +9 -0
+#include <common.h>
+
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}

I wonder how useful such CPU is if simple endless loop restarts it ;-)

[...]

#11 lore raw

PATCH v3 3/4 arm: Support new Xilinx Zynq platform

Quoted 20 lines · Marek Vasut

Dear Michal Simek,

Quoted 15 lines

Add timer driver.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Move lowlevel_init.S from board to cpu folder
Remove XPSS prefix
Rename XSCUTIMER -> SCUTIMER

v3: Using clrsetbits_le32
Fix compilation warning
Move reset_cpu from board to cpu.c
Move lowlevel_init to cpu.c

[...]

Quoted 11 lines

arch/arm/cpu/armv7/zynq/cpu.c line 31

Quoted 9 lines
arch/arm/cpu/armv7/zynq/cpu.c new file +9 -0
+#include <common.h>
+
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}

I wonder how useful such CPU is if simple endless loop restarts it ;-)

Don't be scared it will be fixed when slcr is ready.

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#12 lore raw

PATCH v3 3/4 arm: Support new Xilinx Zynq platform

Dear Michal Simek,

Quoted 35 lines · Marek Vasut
Quoted 22 lines

Dear Michal Simek,

Quoted 17 lines

Add timer driver.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Move lowlevel_init.S from board to cpu folder

Remove XPSS prefix
Rename XSCUTIMER -> SCUTIMER

v3: Using clrsetbits_le32

Fix compilation warning
Move reset_cpu from board to cpu.c
Move lowlevel_init to cpu.c

[...]

Quoted 11 lines

arch/arm/cpu/armv7/zynq/cpu.c line 31

Quoted 9 lines
arch/arm/cpu/armv7/zynq/cpu.c new file +9 -0
+#include <common.h>
+
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}

I wonder how useful such CPU is if simple endless loop restarts it ;-)

Quoted 1 line

Don't be scared it will be fixed when slcr is ready.

Nay, I was just rambling and giving you a bit of torture :-)

What's SLCR ?

Quoted 2 lines

Thanks,
Michal

Best regards,
Marek Vasut

#13 lore raw

PATCH v3 3/4 arm: Support new Xilinx Zynq platform

Quoted 37 lines · Marek Vasut

Dear Michal Simek,

Quoted 35 lines · Marek Vasut
Quoted 33 lines

Dear Michal Simek,

Quoted 17 lines

Add timer driver.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Move lowlevel_init.S from board to cpu folder

Remove XPSS prefix
Rename XSCUTIMER -> SCUTIMER

v3: Using clrsetbits_le32

Fix compilation warning
Move reset_cpu from board to cpu.c
Move lowlevel_init to cpu.c

[...]

arch/arm/cpu/armv7/zynq/cpu.c line 31

Quoted 9 lines
arch/arm/cpu/armv7/zynq/cpu.c new file +9 -0
+#include <common.h>
+
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}

I wonder how useful such CPU is if simple endless loop restarts it ;-)

Quoted 3 lines
Quoted 1 line

Don't be scared it will be fixed when slcr is ready.

Nay, I was just rambling and giving you a bit of torture :-)

:-)

Quoted 2 lines

What's SLCR ?

System level control registers. For example for clock setup, unit reset, ddr setup configuration pin setup, etc.

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#14 lore raw

PATCH v3 3/4 arm: Support new Xilinx Zynq platform

Dear Michal Simek,

Quoted 40 lines · Marek Vasut
Quoted 39 lines

Dear Michal Simek,

Quoted 36 lines · Marek Vasut
Quoted 22 lines

Dear Michal Simek,

Quoted 17 lines

Add timer driver.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Move lowlevel_init.S from board to cpu folder

Remove XPSS prefix
Rename XSCUTIMER -> SCUTIMER

v3: Using clrsetbits_le32

Fix compilation warning
Move reset_cpu from board to cpu.c
Move lowlevel_init to cpu.c

[...]

Quoted 11 lines

arch/arm/cpu/armv7/zynq/cpu.c line 31

Quoted 9 lines
arch/arm/cpu/armv7/zynq/cpu.c new file +9 -0
+#include <common.h>
+
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}

I wonder how useful such CPU is if simple endless loop restarts it ;-)

Don't be scared it will be fixed when slcr is ready.

Quoted 8 lines
Quoted 1 line

Nay, I was just rambling and giving you a bit of torture :-)

:
:-)
:

Quoted 1 line

What's SLCR ?

System level control registers. For example for clock setup, unit reset, ddr setup configuration pin setup, etc.

Shouldn't that be part of this patchset then?

Quoted 3 lines

Thanks,
Michal

Best regards,
Marek Vasut

#15 lore raw

PATCH v3 3/4 arm: Support new Xilinx Zynq platform

Quoted 46 lines · Marek Vasut

Dear Michal Simek,

Quoted 44 lines · Marek Vasut
Quoted 37 lines

Dear Michal Simek,

Quoted 35 lines · Marek Vasut
Quoted 33 lines

Dear Michal Simek,

Quoted 17 lines

Add timer driver.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Move lowlevel_init.S from board to cpu folder

Remove XPSS prefix
Rename XSCUTIMER -> SCUTIMER

v3: Using clrsetbits_le32

Fix compilation warning
Move reset_cpu from board to cpu.c
Move lowlevel_init to cpu.c

[...]

arch/arm/cpu/armv7/zynq/cpu.c line 31

Quoted 9 lines
arch/arm/cpu/armv7/zynq/cpu.c new file +9 -0
+#include <common.h>
+
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}

I wonder how useful such CPU is if simple endless loop restarts it ;-)

Quoted 3 lines
Quoted 1 line

Don't be scared it will be fixed when slcr is ready.

Nay, I was just rambling and giving you a bit of torture :-)

:
:-)
:

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

What's SLCR ?

System level control registers. For example for clock setup, unit reset, ddr setup configuration pin setup, etc.

Shouldn't that be part of this patchset then?

No. Basic setup is done in first stage bootloader. I will talk with Xilinx how to handle this. I think that special driver(in zynq cpu folder) for slcr make sense to have all SLCR operation at one place and not to call it directly.

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#16 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

In reply to Michal Simek

Dear Michal Simek,

Quoted 206 lines

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART
Rename driver name
Remove driver description

v3: SERIAL_MULTI support
Rename xdfuart to uart_zynq

---
 common/serial.c              |    8 ++
 drivers/serial/Makefile      |    1 +
 drivers/serial/serial_zynq.c |  246
++++++++++++++++++++++++++++++++++++++++++ include/serial.h             | 
  5 +
 4 files changed, 260 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/serial_zynq.c
common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
 	serial_register(&uartlite_serial3_device);
 # endif /* XILINX_UARTLITE_BASEADDR3 */
 #endif /* CONFIG_XILINX_UARTLITE */
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
 	serial_assign(default_serial_console()->name);
 }
 
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
 COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
 COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
 COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/serial_zynq.c new file +70 -0
new file mode 100644
index 0000000..30f2445
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+	u32 control; /* Control Register [8:0] */
+	u32 mode; /* Mode Register [10:0] */
+	u32 reserved1[4];
+	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+	u32 reserved2[4];
+	u32 channel_sts; /* Channel Status [11:0] */
+	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK0) + [0].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE0,

drivers/serial/serial_zynq.c new file +3 -0
+	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK1) + [1].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE1,

drivers/serial/serial_zynq.c new file +70 -0
+	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = uart_zynq_ports_param[port].baudrate;
+	unsigned long clock = uart_zynq_ports_param[port].clock;
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	/*                master clock
+	 * Baud rate = ------------------
+	 *              bgen * (bdiv + 1)
+	 *
+	 * Find acceptable values for baud generation.
+	 */
+	for (bdiv = 4; bdiv < 255; bdiv++) {
+		bgen = clock / (baud * (bdiv + 1));
+		if (bgen < 2 || bgen > 65535)
+			continue;
+
+		calc_baud = clock / (bgen * (bdiv + 1));
+
+		/*
+		 * Use first calculated baudrate with
+		 * an acceptable (<3%) error
+		 */
+		if (baud > calc_baud)
+			calc_bauderror = baud - calc_baud;
+		else
+			calc_bauderror = calc_baud - baud;
+		if (((calc_bauderror * 100) / baud) < 3)
+			break;
+	}
+
+	writel(bdiv, &regs->baud_rate_divider);
+	writel(bgen, &regs->baud_rate_gen);
+}
+
+/* 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;
+
+	/* 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 */
+	uart_zynq_serial_setbrg(port);
+
+	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)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)

drivers/serial/serial_zynq.c line 155

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		uart_zynq_serial_putc(*s++, port);
+}

Remark for myself ... squash all these while (*s) putc() constructs into serial core. I'll be adding a patch into my massive patchset I'm cooking for this, you don't worry as this is ok for now.

Quoted 54 lines
drivers/serial/serial_zynq.c new file +54 -0
+static int uart_zynq_serial_tstc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while (!uart_zynq_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return uart_zynq_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	uart_zynq_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	uart_zynq_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	uart_zynq_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return uart_zynq_serial_getc(0);
+}
+
+int serial_tstc(void)
+{
+	return uart_zynq_serial_tstc(0);
+}
+#else
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+	int uart_zynq##port##_init(void) \
+				{ return uart_zynq_serial_init(port); } \
+	void uart_zynq##port##_setbrg(void) \
+				{ return uart_zynq_serial_setbrg(port); } \
+	int uart_zynq##port##_getc(void) \

drivers/serial/serial_zynq.c line 220

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+				{ return uart_zynq_serial_getc(port); } \
+	int uart_zynq##port##_tstc(void) \
+				{ return uart_zynq_serial_tstc(port); } \
+	void uart_zynq##port##_putc(const char c) \
+				{ uart_zynq_serial_putc(c, port); } \
+	void uart_zynq##port##_puts(const char *s) \
+				{ uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, name) {\

Rename the "name" to __name (this is because once you rename it -- see below -- name will colide with .name)

drivers/serial/serial_zynq.c line 221

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	  name,\

explicitly spell out the name of structure members, so the structure instance is agile to reordering the the declaration members.

Quoted 30 lines
drivers/serial/serial_zynq.c new file +25 -0
+	  uart_zynq##port##_init,\
+	  NULL,\
+	  uart_zynq##port##_setbrg,\
+	  uart_zynq##port##_getc,\
+	  uart_zynq##port##_tstc,\
+	  uart_zynq##port##_putc,\
+	  uart_zynq##port##_puts, }
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+	if (uart_zynq_ports[0])
+		return &uart_zynq_serial0_device;
+	if (uart_zynq_ports[1])
+		return &uart_zynq_serial1_device;
+
+	return NULL;
+}
+#endif
include/serial.h +0 -0
index cbdf8a9..dc8e9b4 100644

include/serial.h extern struct serial_device bfin_serial2_device; · line 96

Quoted 8 lines
include/serial.h +5 -0
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
 extern struct serial_device bfin_serial3_device;
 #endif
 
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+

Let's not add this, noone uses it.

Quoted 3 lines
include/serial.h +0 -0
 extern void serial_register(struct serial_device *);
 extern void serial_initialize(void);
 extern void serial_stdio_init(void);
#17 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Quoted 291 lines · Marek Vasut

Dear Michal Simek,

Quoted 206 lines

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART
Rename driver name
Remove driver description

v3: SERIAL_MULTI support
Rename xdfuart to uart_zynq

---
  common/serial.c              |    8 ++
  drivers/serial/Makefile      |    1 +
  drivers/serial/serial_zynq.c |  246
++++++++++++++++++++++++++++++++++++++++++ include/serial.h             |
   5 +
  4 files changed, 260 insertions(+), 0 deletions(-)

create mode 100644 drivers/serial/serial_zynq.c

common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
  	serial_register(&uartlite_serial3_device);
  # endif /* XILINX_UARTLITE_BASEADDR3 */
  #endif /* CONFIG_XILINX_UARTLITE */
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
  	serial_assign(default_serial_console()->name);
  }
 
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
  COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
  COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
  COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
  ifndef CONFIG_SPL_BUILD
  COBJS-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/serial_zynq.c new file +70 -0
new file mode 100644
index 0000000..30f2445
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+	u32 control; /* Control Register [8:0] */
+	u32 mode; /* Mode Register [10:0] */
+	u32 reserved1[4];
+	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+	u32 reserved2[4];
+	u32 channel_sts; /* Channel Status [11:0] */
+	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK0) + [0].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE0,

drivers/serial/serial_zynq.c new file +3 -0
+	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK1) + [1].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE1,

drivers/serial/serial_zynq.c new file +70 -0
+	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = uart_zynq_ports_param[port].baudrate;
+	unsigned long clock = uart_zynq_ports_param[port].clock;
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	/*                master clock
+	 * Baud rate = ------------------
+	 *              bgen * (bdiv + 1)
+	 *
+	 * Find acceptable values for baud generation.
+	 */
+	for (bdiv = 4; bdiv < 255; bdiv++) {
+		bgen = clock / (baud * (bdiv + 1));
+		if (bgen < 2 || bgen > 65535)
+			continue;
+
+		calc_baud = clock / (bgen * (bdiv + 1));
+
+		/*
+		 * Use first calculated baudrate with
+		 * an acceptable (<3%) error
+		 */
+		if (baud > calc_baud)
+			calc_bauderror = baud - calc_baud;
+		else
+			calc_bauderror = calc_baud - baud;
+		if (((calc_bauderror * 100) / baud) < 3)
+			break;
+	}
+
+	writel(bdiv, &regs->baud_rate_divider);
+	writel(bgen, &regs->baud_rate_gen);
+}
+
+/* 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;
+
+	/* 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 */
+	uart_zynq_serial_setbrg(port);
+
+	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)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)

drivers/serial/serial_zynq.c line 155

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		uart_zynq_serial_putc(*s++, port);
+}

Remark for myself ... squash all these while (*s) putc() constructs into serial core. I'll be adding a patch into my massive patchset I'm cooking for this, you don't worry as this is ok for now.

Quoted 54 lines
drivers/serial/serial_zynq.c new file +54 -0
+static int uart_zynq_serial_tstc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while (!uart_zynq_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return uart_zynq_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	uart_zynq_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	uart_zynq_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	uart_zynq_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return uart_zynq_serial_getc(0);
+}
+
+int serial_tstc(void)
+{
+	return uart_zynq_serial_tstc(0);
+}
+#else
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+	int uart_zynq##port##_init(void) \
+				{ return uart_zynq_serial_init(port); } \
+	void uart_zynq##port##_setbrg(void) \
+				{ return uart_zynq_serial_setbrg(port); } \
+	int uart_zynq##port##_getc(void) \

drivers/serial/serial_zynq.c line 220

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+				{ return uart_zynq_serial_getc(port); } \
+	int uart_zynq##port##_tstc(void) \
+				{ return uart_zynq_serial_tstc(port); } \
+	void uart_zynq##port##_putc(const char c) \
+				{ uart_zynq_serial_putc(c, port); } \
+	void uart_zynq##port##_puts(const char *s) \
+				{ uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, name) {\

Rename the "name" to __name (this is because once you rename it -- see below -- name will colide with .name)

Quoted 4 lines

drivers/serial/serial_zynq.c line 221

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	  name,\

explicitly spell out the name of structure members, so the structure instance is agile to reordering the the declaration members.

No problem to change it. I have seen it in your stdio branch

Quoted 34 lines
Quoted 34 lines
drivers/serial/serial_zynq.c new file +25 -0
+	  uart_zynq##port##_init,\
+	  NULL,\
+	  uart_zynq##port##_setbrg,\
+	  uart_zynq##port##_getc,\
+	  uart_zynq##port##_tstc,\
+	  uart_zynq##port##_putc,\
+	  uart_zynq##port##_puts, }
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+	if (uart_zynq_ports[0])
+		return &uart_zynq_serial0_device;
+	if (uart_zynq_ports[1])
+		return &uart_zynq_serial1_device;
+
+	return NULL;
+}
+#endif
include/serial.h +0 -0
index cbdf8a9..dc8e9b4 100644
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
  extern struct serial_device bfin_serial3_device;
  #endif
 
Quoted 7 lines

include/serial.h extern struct serial_device bfin_serial2_device; · line 96

Quoted 5 lines
include/serial.h +5 -0
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+

Let's not add this, noone uses it.

It is used by serial core where you register serial device.

Quoted 1 line

include/serial.h extern struct serial_device bfin_serial2_device; · line 97

Quoted 1 line
include/serial.h +1 -0
+	serial_register(&uart_zynq_serial0_device);

You need declaration somewhere. If you don't have it then this error message is shown. serial.c: In function 'serial_initialize':
serial.c:127:19: error: 'uart_zynq_serial0_device' undeclared (first use in this function) serial.c:127:19: note: each undeclared identifier is reported only once for each function it appears in

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#18 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Dear Michal Simek,

Quoted 360 lines · Marek Vasut
Quoted 200 lines

Dear Michal Simek,

Quoted 198 lines

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART

Rename driver name
Remove driver description

v3: SERIAL_MULTI support

Rename xdfuart to uart_zynq

---

  common/serial.c              |    8 ++
  drivers/serial/Makefile      |    1 +
  drivers/serial/serial_zynq.c |  246

++++++++++++++++++++++++++++++++++++++++++ include/serial.h |

   5 +
  4 files changed, 260 insertions(+), 0 deletions(-)

create mode 100644 drivers/serial/serial_zynq.c

common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
 
  	serial_register(&uartlite_serial3_device);
 
  # endif /* XILINX_UARTLITE_BASEADDR3 */
  #endif /* CONFIG_XILINX_UARTLITE */
 
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
  	serial_assign(default_serial_console()->name);
  
  }
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
 
  COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
  COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
  COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
 
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
  ifndef CONFIG_SPL_BUILD
  COBJS-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/serial_zynq.c new file +70 -0
new file mode 100644
index 0000000..30f2445
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+	u32 control; /* Control Register [8:0] */
+	u32 mode; /* Mode Register [10:0] */
+	u32 reserved1[4];
+	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+	u32 reserved2[4];
+	u32 channel_sts; /* Channel Status [11:0] */
+	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK0) + [0].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE0,

drivers/serial/serial_zynq.c new file +3 -0
+	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK1) + [1].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE1,

drivers/serial/serial_zynq.c new file +46 -0
+	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = uart_zynq_ports_param[port].baudrate;
+	unsigned long clock = uart_zynq_ports_param[port].clock;
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	/*                master clock
+	 * Baud rate = ------------------
+	 *              bgen * (bdiv + 1)
+	 *
+	 * Find acceptable values for baud generation.
+	 */
+	for (bdiv = 4; bdiv < 255; bdiv++) {
+		bgen = clock / (baud * (bdiv + 1));
+		if (bgen < 2 || bgen > 65535)
+			continue;
+
+		calc_baud = clock / (bgen * (bdiv + 1));
+
+		/*
+		 * Use first calculated baudrate with
+		 * an acceptable (<3%) error
+		 */
+		if (baud > calc_baud)
+			calc_bauderror = baud - calc_baud;
+		else
+			calc_bauderror = calc_baud - baud;
+		if (((calc_bauderror * 100) / baud) < 3)
+			break;
+	}
+
+	writel(bdiv, &regs->baud_rate_divider);
+	writel(bgen, &regs->baud_rate_gen);
+}
+
+/* Initialize the UART, with...some settings. */
+static int uart_zynq_serial_init(const int port)
+{
Quoted 8 lines
Quoted 8 lines
drivers/serial/serial_zynq.c new file +7 -0
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	if (!regs)
+		return -1;
+
+	/* 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);

Quoted 99 lines
Quoted 16 lines
drivers/serial/serial_zynq.c new file +16 -0
+	writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
+	uart_zynq_serial_setbrg(port);
+
+	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)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)

drivers/serial/serial_zynq.c line 155

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		uart_zynq_serial_putc(*s++, port);
+}

Remark for myself ... squash all these while (*s) putc() constructs into serial core. I'll be adding a patch into my massive patchset I'm cooking for this, you don't worry as this is ok for now.

Quoted 54 lines
drivers/serial/serial_zynq.c new file +54 -0
+static int uart_zynq_serial_tstc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while (!uart_zynq_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return uart_zynq_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	uart_zynq_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	uart_zynq_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	uart_zynq_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return uart_zynq_serial_getc(0);
+}
+
+int serial_tstc(void)
+{
+	return uart_zynq_serial_tstc(0);
+}
+#else
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+	int uart_zynq##port##_init(void) \
+				{ return uart_zynq_serial_init(port); } \
+	void uart_zynq##port##_setbrg(void) \
+				{ return uart_zynq_serial_setbrg(port); } \
+	int uart_zynq##port##_getc(void) \

drivers/serial/serial_zynq.c line 220

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+				{ return uart_zynq_serial_getc(port); } \
+	int uart_zynq##port##_tstc(void) \
+				{ return uart_zynq_serial_tstc(port); } \
+	void uart_zynq##port##_putc(const char c) \
+				{ uart_zynq_serial_putc(c, port); } \
+	void uart_zynq##port##_puts(const char *s) \
+				{ uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, name) {\

Rename the "name" to __name (this is because once you rename it -- see below -- name will colide with .name)

Quoted 4 lines

drivers/serial/serial_zynq.c line 221

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	  name,\

explicitly spell out the name of structure members, so the structure instance is agile to reordering the the declaration members.

No problem to change it. I have seen it in your stdio branch

Quoted 34 lines
Quoted 34 lines
drivers/serial/serial_zynq.c new file +25 -0
+	  uart_zynq##port##_init,\
+	  NULL,\
+	  uart_zynq##port##_setbrg,\
+	  uart_zynq##port##_getc,\
+	  uart_zynq##port##_tstc,\
+	  uart_zynq##port##_putc,\
+	  uart_zynq##port##_puts, }
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+	if (uart_zynq_ports[0])
+		return &uart_zynq_serial0_device;
+	if (uart_zynq_ports[1])
+		return &uart_zynq_serial1_device;
+
+	return NULL;
+}
+#endif
include/serial.h +0 -0
index cbdf8a9..dc8e9b4 100644
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
 
  extern struct serial_device bfin_serial3_device;
  #endif
 
Quoted 7 lines

include/serial.h extern struct serial_device bfin_serial2_device; · line 96

Quoted 5 lines
include/serial.h +5 -0
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+

Let's not add this, noone uses it.

It is used by serial core where you register serial device.

Quoted 7 lines
Quoted 1 line

include/serial.h extern struct serial_device bfin_serial2_device; · line 98

Quoted 1 line
include/serial.h +1 -0
+	serial_register(&uart_zynq_serial0_device);

You need declaration somewhere. If you don't have it then this error message is shown. serial.c: In function 'serial_initialize':
serial.c:127:19: error: 'uart_zynq_serial0_device' undeclared (first use in this function) serial.c:127:19: note: each undeclared identifier is reported only once for each function it appears in

Oh damn, you're right ... I reworked the serial core so it's not needed -- by sticking an init func into each and every driver.

Maybe we should start pushing the serial drivers through that branch of mine once I post it?

I guess this platform won't make it into .10 release anyway.

Quoted 2 lines

Thanks,
Michal

#19 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Quoted 370 lines · Marek Vasut

Dear Michal Simek,

Quoted 360 lines · Marek Vasut
Quoted 200 lines

Dear Michal Simek,

Quoted 198 lines

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART

Rename driver name
Remove driver description

v3: SERIAL_MULTI support

Rename xdfuart to uart_zynq

---

   common/serial.c              |    8 ++
   drivers/serial/Makefile      |    1 +
   drivers/serial/serial_zynq.c |  246

++++++++++++++++++++++++++++++++++++++++++ include/serial.h |

    5 +
   4 files changed, 260 insertions(+), 0 deletions(-)

create mode 100644 drivers/serial/serial_zynq.c

common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
 
   	serial_register(&uartlite_serial3_device);
 
   # endif /* XILINX_UARTLITE_BASEADDR3 */
   #endif /* CONFIG_XILINX_UARTLITE */
 
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
   	serial_assign(default_serial_console()->name);

   }
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
 
   COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
   COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
   COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
 
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
   ifndef CONFIG_SPL_BUILD
   COBJS-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/serial_zynq.c new file +70 -0
new file mode 100644
index 0000000..30f2445
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+	u32 control; /* Control Register [8:0] */
+	u32 mode; /* Mode Register [10:0] */
+	u32 reserved1[4];
+	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+	u32 reserved2[4];
+	u32 channel_sts; /* Channel Status [11:0] */
+	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK0) + [0].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE0,

drivers/serial/serial_zynq.c new file +3 -0
+	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK1) + [1].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE1,

drivers/serial/serial_zynq.c new file +46 -0
+	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = uart_zynq_ports_param[port].baudrate;
+	unsigned long clock = uart_zynq_ports_param[port].clock;
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	/*                master clock
+	 * Baud rate = ------------------
+	 *              bgen * (bdiv + 1)
+	 *
+	 * Find acceptable values for baud generation.
+	 */
+	for (bdiv = 4; bdiv < 255; bdiv++) {
+		bgen = clock / (baud * (bdiv + 1));
+		if (bgen < 2 || bgen > 65535)
+			continue;
+
+		calc_baud = clock / (bgen * (bdiv + 1));
+
+		/*
+		 * Use first calculated baudrate with
+		 * an acceptable (<3%) error
+		 */
+		if (baud > calc_baud)
+			calc_bauderror = baud - calc_baud;
+		else
+			calc_bauderror = calc_baud - baud;
+		if (((calc_bauderror * 100) / baud) < 3)
+			break;
+	}
+
+	writel(bdiv, &regs->baud_rate_divider);
+	writel(bgen, &regs->baud_rate_gen);
+}
+
+/* Initialize the UART, with...some settings. */
+static int uart_zynq_serial_init(const int port)
+{
Quoted 8 lines
Quoted 8 lines
drivers/serial/serial_zynq.c new file +7 -0
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	if (!regs)
+		return -1;
+
+	/* 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);

Quoted 99 lines
Quoted 16 lines
drivers/serial/serial_zynq.c new file +16 -0
+	writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
+	uart_zynq_serial_setbrg(port);
+
+	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)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)

drivers/serial/serial_zynq.c line 155

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		uart_zynq_serial_putc(*s++, port);
+}

Remark for myself ... squash all these while (*s) putc() constructs into serial core. I'll be adding a patch into my massive patchset I'm cooking for this, you don't worry as this is ok for now.

Quoted 54 lines
drivers/serial/serial_zynq.c new file +54 -0
+static int uart_zynq_serial_tstc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while (!uart_zynq_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return uart_zynq_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	uart_zynq_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	uart_zynq_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	uart_zynq_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return uart_zynq_serial_getc(0);
+}
+
+int serial_tstc(void)
+{
+	return uart_zynq_serial_tstc(0);
+}
+#else
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+	int uart_zynq##port##_init(void) \
+				{ return uart_zynq_serial_init(port); } \
+	void uart_zynq##port##_setbrg(void) \
+				{ return uart_zynq_serial_setbrg(port); } \
+	int uart_zynq##port##_getc(void) \

drivers/serial/serial_zynq.c line 220

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+				{ return uart_zynq_serial_getc(port); } \
+	int uart_zynq##port##_tstc(void) \
+				{ return uart_zynq_serial_tstc(port); } \
+	void uart_zynq##port##_putc(const char c) \
+				{ uart_zynq_serial_putc(c, port); } \
+	void uart_zynq##port##_puts(const char *s) \
+				{ uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, name) {\

Rename the "name" to __name (this is because once you rename it -- see below -- name will colide with .name)

Quoted 4 lines

drivers/serial/serial_zynq.c line 221

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	  name,\

explicitly spell out the name of structure members, so the structure instance is agile to reordering the the declaration members.

No problem to change it. I have seen it in your stdio branch

Quoted 34 lines
Quoted 34 lines
drivers/serial/serial_zynq.c new file +25 -0
+	  uart_zynq##port##_init,\
+	  NULL,\
+	  uart_zynq##port##_setbrg,\
+	  uart_zynq##port##_getc,\
+	  uart_zynq##port##_tstc,\
+	  uart_zynq##port##_putc,\
+	  uart_zynq##port##_puts, }
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+	if (uart_zynq_ports[0])
+		return &uart_zynq_serial0_device;
+	if (uart_zynq_ports[1])
+		return &uart_zynq_serial1_device;
+
+	return NULL;
+}
+#endif
include/serial.h +0 -0
index cbdf8a9..dc8e9b4 100644
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
 
   extern struct serial_device bfin_serial3_device;
   #endif
 
Quoted 7 lines

include/serial.h extern struct serial_device bfin_serial2_device; · line 96

Quoted 5 lines
include/serial.h +5 -0
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+

Let's not add this, noone uses it.

It is used by serial core where you register serial device.

Quoted 7 lines
Quoted 1 line

include/serial.h extern struct serial_device bfin_serial2_device; · line 98

Quoted 1 line
include/serial.h +1 -0
+	serial_register(&uart_zynq_serial0_device);

You need declaration somewhere. If you don't have it then this error message is shown. serial.c: In function 'serial_initialize':
serial.c:127:19: error: 'uart_zynq_serial0_device' undeclared (first use in this function) serial.c:127:19: note: each undeclared identifier is reported only once for each function it appears in

Quoted 5 lines

Oh damn, you're right ... I reworked the serial core so it's not needed -- by sticking an init func into each and every driver.

Maybe we should start pushing the serial drivers through that branch of mine once I post it?

You have mentioned in one email that your tree is not ready.
http://lists.denx.de/pipermail/u-boot/2012-September/133836.html

I will send update v4.

Quoted 2 lines

I guess this platform won't make it into .10 release anyway.

Why not? Any reason why these 4 patches should wait till the next release? Even if merge open is still open?
They are also completely separated from others and they are not breaking anything.

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#20 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Dear Michal Simek,

Quoted 202 lines · Marek Vasut
Quoted 201 lines

Dear Michal Simek,

Quoted 199 lines · Marek Vasut
Quoted 198 lines

Dear Michal Simek,

Quoted 196 lines

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART

Rename driver name
Remove driver description

v3: SERIAL_MULTI support

Rename xdfuart to uart_zynq

---

   common/serial.c              |    8 ++
   drivers/serial/Makefile      |    1 +
   drivers/serial/serial_zynq.c |  246

++++++++++++++++++++++++++++++++++++++++++ include/serial.h

    5 +
   4 files changed, 260 insertions(+), 0 deletions(-)

create mode 100644 drivers/serial/serial_zynq.c

common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
 
   	serial_register(&uartlite_serial3_device);
 
   # endif /* XILINX_UARTLITE_BASEADDR3 */
   #endif /* CONFIG_XILINX_UARTLITE */
 
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
   	serial_assign(default_serial_console()->name);
   
   }
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
 
   COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
   COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
   COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
 
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
   ifndef CONFIG_SPL_BUILD
   COBJS-$(CONFIG_USB_TTY) += usbtty.o
(quoted diff) +0 -0

b/drivers/serial/serial_zynq.c new file mode 100644 index 0000000..30f2445

drivers/serial/serial_zynq.c new file +70 -0
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+	u32 control; /* Control Register [8:0] */
+	u32 mode; /* Mode Register [10:0] */
+	u32 reserved1[4];
+	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+	u32 reserved2[4];
+	u32 channel_sts; /* Channel Status [11:0] */
+	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK0) + [0].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE0,

drivers/serial/serial_zynq.c new file +3 -0
+	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK1) + [1].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE1,

drivers/serial/serial_zynq.c new file +45 -0
+	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = uart_zynq_ports_param[port].baudrate;
+	unsigned long clock = uart_zynq_ports_param[port].clock;
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	/*                master clock
+	 * Baud rate = ------------------
+	 *              bgen * (bdiv + 1)
+	 *
+	 * Find acceptable values for baud generation.
+	 */
+	for (bdiv = 4; bdiv < 255; bdiv++) {
+		bgen = clock / (baud * (bdiv + 1));
+		if (bgen < 2 || bgen > 65535)
+			continue;
+
+		calc_baud = clock / (bgen * (bdiv + 1));
+
+		/*
+		 * Use first calculated baudrate with
+		 * an acceptable (<3%) error
+		 */
+		if (baud > calc_baud)
+			calc_bauderror = baud - calc_baud;
+		else
+			calc_bauderror = calc_baud - baud;
+		if (((calc_bauderror * 100) / baud) < 3)
+			break;
+	}
+
+	writel(bdiv, &regs->baud_rate_divider);
+	writel(bgen, &regs->baud_rate_gen);
+}
+
+/* Initialize the UART, with...some settings. */
+static int uart_zynq_serial_init(const int port)
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/serial/serial_zynq.c

Quoted 8 lines
drivers/serial/serial_zynq.c new file +8 -0
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	if (!regs)
+		return -1;
+
+	/* RX/TX enabled & reset */
+	writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | 

ZYNQ_UART_CR_TXRST

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line

| \ + ZYNQ_UART_CR_RXRST, &regs-

control);

Quoted 1 line

drivers/serial/serial_zynq.c

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no 

parity

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

*/ + uart_zynq_serial_setbrg(port);

drivers/serial/serial_zynq.c new file +6 -0
+
+	return 0;
+}
+
+static void uart_zynq_serial_putc(const char c, const int port)
+{
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/serial/serial_zynq.c

Quoted 8 lines
drivers/serial/serial_zynq.c new file +8 -0
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) 

!= 0)

Quoted 58 lines
Quoted 58 lines
Quoted 58 lines
Quoted 58 lines

drivers/serial/serial_zynq.c line 155

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		uart_zynq_serial_putc(*s++, port);
+}

Remark for myself ... squash all these while (*s) putc() constructs into serial core. I'll be adding a patch into my massive patchset I'm cooking for this, you don't worry as this is ok for now.

Quoted 43 lines
drivers/serial/serial_zynq.c new file +43 -0
+static int uart_zynq_serial_tstc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while (!uart_zynq_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return uart_zynq_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	uart_zynq_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	uart_zynq_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	uart_zynq_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return uart_zynq_serial_getc(0);
+}
+
+int serial_tstc(void)
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/serial/serial_zynq.c

Quoted 8 lines
drivers/serial/serial_zynq.c new file +8 -0
+{
+	return uart_zynq_serial_tstc(0);
+}
+#else
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+	int uart_zynq##port##_init(void) \
+				{ return uart_zynq_serial_init(port); } 

\

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/serial/serial_zynq.c

Quoted 2 lines
drivers/serial/serial_zynq.c new file +2 -0
+	void uart_zynq##port##_setbrg(void) \
+				{ return uart_zynq_serial_setbrg(port); 

} \

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/serial/serial_zynq.c

Quoted 2 lines
drivers/serial/serial_zynq.c new file +2 -0
+	int uart_zynq##port##_getc(void) \
+				{ return uart_zynq_serial_getc(port); } 

\

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/serial/serial_zynq.c

Quoted 2 lines
drivers/serial/serial_zynq.c new file +2 -0
+	int uart_zynq##port##_tstc(void) \
+				{ return uart_zynq_serial_tstc(port); } 

\

Quoted 70 lines
Quoted 70 lines
Quoted 69 lines
Quoted 11 lines

drivers/serial/serial_zynq.c line 220

Quoted 7 lines
drivers/serial/serial_zynq.c new file +7 -0
+	void uart_zynq##port##_putc(const char c) \
+				{ uart_zynq_serial_putc(c, port); } \
+	void uart_zynq##port##_puts(const char *s) \
+				{ uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, name) {\

Rename the "name" to __name (this is because once you rename it -- see below -- name will colide with .name)

Quoted 4 lines

drivers/serial/serial_zynq.c line 221

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	  name,\

explicitly spell out the name of structure members, so the structure instance is agile to reordering the the declaration members.

No problem to change it. I have seen it in your stdio branch

Quoted 34 lines
Quoted 34 lines
drivers/serial/serial_zynq.c new file +25 -0
+	  uart_zynq##port##_init,\
+	  NULL,\
+	  uart_zynq##port##_setbrg,\
+	  uart_zynq##port##_getc,\
+	  uart_zynq##port##_tstc,\
+	  uart_zynq##port##_putc,\
+	  uart_zynq##port##_puts, }
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+	if (uart_zynq_ports[0])
+		return &uart_zynq_serial0_device;
+	if (uart_zynq_ports[1])
+		return &uart_zynq_serial1_device;
+
+	return NULL;
+}
+#endif
include/serial.h +0 -0
index cbdf8a9..dc8e9b4 100644
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
 
   extern struct serial_device bfin_serial3_device;
   #endif
 
Quoted 7 lines

include/serial.h extern struct serial_device bfin_serial2_device; · line 96

Quoted 5 lines
include/serial.h +5 -0
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+

Let's not add this, noone uses it.

It is used by serial core where you register serial device.

Quoted 1 line

include/serial.h extern struct serial_device bfin_serial2_device; · line 98

Quoted 1 line
include/serial.h +1 -0
+	serial_register(&uart_zynq_serial0_device);

You need declaration somewhere. If you don't have it then this error message is shown. serial.c: In function 'serial_initialize':
serial.c:127:19: error: 'uart_zynq_serial0_device' undeclared (first use in this function) serial.c:127:19: note: each undeclared identifier is reported only once for each function it appears in

Quoted 8 lines
Quoted 5 lines

Oh damn, you're right ... I reworked the serial core so it's not needed -- by sticking an init func into each and every driver.

Maybe we should start pushing the serial drivers through that branch of mine once I post it?

You have mentioned in one email that your tree is not ready.
http://lists.denx.de/pipermail/u-boot/2012-September/133836.html

That's the "once I post it" part of the previous sentence ;-)

Quoted 6 lines

I will send update v4.

Quoted 1 line

I guess this platform won't make it into .10 release anyway.

Why not? Any reason why these 4 patches should wait till the next release?

MW is closed (Aug. 18)

Quoted 6 lines

Even if merge open is still open?
They are also completely separated from others and they are not breaking anything.

Thanks,
Michal

#21 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Quoted 393 lines · Marek Vasut

Dear Michal Simek,

Quoted 202 lines · Marek Vasut
Quoted 201 lines

Dear Michal Simek,

Quoted 199 lines · Marek Vasut
Quoted 198 lines

Dear Michal Simek,

Quoted 196 lines

The driver is used on Xilinx Zynq platform.

CC Joe Hershberger <[email protected]>
CC Marek Vasut <[email protected]>

---
v2: Use Zynq name instead of Dragonfire and XPSS/XDFUART

Rename driver name
Remove driver description

v3: SERIAL_MULTI support

Rename xdfuart to uart_zynq

---

    common/serial.c              |    8 ++
    drivers/serial/Makefile      |    1 +
    drivers/serial/serial_zynq.c |  246

++++++++++++++++++++++++++++++++++++++++++ include/serial.h

     5 +

    4 files changed, 260 insertions(+), 0 deletions(-)
    create mode 100644 drivers/serial/serial_zynq.c
common/serial.c +8 -0
index 75cc1bb..4f2bc7f 100644
@@ -122,6 +122,14 @@ void serial_initialize(void)
 
    	serial_register(&uartlite_serial3_device);
 
    # endif /* XILINX_UARTLITE_BASEADDR3 */
    #endif /* CONFIG_XILINX_UARTLITE */
 
+#if defined(CONFIG_ZYNQ_SERIAL)
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	serial_register(&uart_zynq_serial0_device);
+# endif
+# ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	serial_register(&uart_zynq_serial1_device);
+# endif
+#endif
    	serial_assign(default_serial_console()->name);

    }
drivers/serial/Makefile +1 -0
index 65d0f23..dfc22a4 100644
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
 
    COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
    COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
    COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
 
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 
    ifndef CONFIG_SPL_BUILD
    COBJS-$(CONFIG_USB_TTY) += usbtty.o
(quoted diff) +0 -0

b/drivers/serial/serial_zynq.c new file mode 100644 index 0000000..30f2445

drivers/serial/serial_zynq.c new file +70 -0
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2012 Michal Simek <[email protected]>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV	15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+	u32 control; /* Control Register [8:0] */
+	u32 mode; /* Mode Register [10:0] */
+	u32 reserved1[4];
+	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+	u32 reserved2[4];
+	u32 channel_sts; /* Channel Status [11:0] */
+	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+	[0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+	[1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK0) + [0].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE0,

drivers/serial/serial_zynq.c new file +3 -0
+	[0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) &&

defined(CONFIG_ZYNQ_SERIAL_CLOCK1) + [1].baudrate =
CONFIG_ZYNQ_SERIAL_BAUDRATE1,

drivers/serial/serial_zynq.c new file +45 -0
+	[1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = uart_zynq_ports_param[port].baudrate;
+	unsigned long clock = uart_zynq_ports_param[port].clock;
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	/*                master clock
+	 * Baud rate = ------------------
+	 *              bgen * (bdiv + 1)
+	 *
+	 * Find acceptable values for baud generation.
+	 */
+	for (bdiv = 4; bdiv < 255; bdiv++) {
+		bgen = clock / (baud * (bdiv + 1));
+		if (bgen < 2 || bgen > 65535)
+			continue;
+
+		calc_baud = clock / (bgen * (bdiv + 1));
+
+		/*
+		 * Use first calculated baudrate with
+		 * an acceptable (<3%) error
+		 */
+		if (baud > calc_baud)
+			calc_bauderror = baud - calc_baud;
+		else
+			calc_bauderror = calc_baud - baud;
+		if (((calc_bauderror * 100) / baud) < 3)
+			break;
+	}
+
+	writel(bdiv, &regs->baud_rate_divider);
+	writel(bgen, &regs->baud_rate_gen);
+}
+
+/* Initialize the UART, with...some settings. */
+static int uart_zynq_serial_init(const int port)
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/serial/serial_zynq.c

Quoted 8 lines
drivers/serial/serial_zynq.c new file +8 -0
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	if (!regs)
+		return -1;
+
+	/* RX/TX enabled & reset */
+	writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN |

ZYNQ_UART_CR_TXRST

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line

| \ + ZYNQ_UART_CR_RXRST, &regs-

control);

Quoted 1 line

drivers/serial/serial_zynq.c

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no

parity

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

*/ + uart_zynq_serial_setbrg(port);

drivers/serial/serial_zynq.c new file +6 -0
+
+	return 0;
+}
+
+static void uart_zynq_serial_putc(const char c, const int port)
+{
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/serial/serial_zynq.c

Quoted 8 lines
drivers/serial/serial_zynq.c new file +8 -0
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL)

!= 0)

Quoted 58 lines
Quoted 58 lines
Quoted 58 lines
Quoted 58 lines

drivers/serial/serial_zynq.c line 155

Quoted 10 lines
drivers/serial/serial_zynq.c new file +10 -0
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		uart_zynq_serial_putc(*s++, port);
+}

Remark for myself ... squash all these while (*s) putc() constructs into serial core. I'll be adding a patch into my massive patchset I'm cooking for this, you don't worry as this is ok for now.

Quoted 43 lines
drivers/serial/serial_zynq.c new file +43 -0
+static int uart_zynq_serial_tstc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+	struct uart_zynq *regs = uart_zynq_ports[port];
+
+	while (!uart_zynq_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return uart_zynq_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	uart_zynq_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	uart_zynq_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	uart_zynq_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return uart_zynq_serial_getc(0);
+}
+
+int serial_tstc(void)
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/serial/serial_zynq.c

Quoted 8 lines
drivers/serial/serial_zynq.c new file +8 -0
+{
+	return uart_zynq_serial_tstc(0);
+}
+#else
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+	int uart_zynq##port##_init(void) \
+				{ return uart_zynq_serial_init(port); }

\

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/serial/serial_zynq.c

Quoted 2 lines
drivers/serial/serial_zynq.c new file +2 -0
+	void uart_zynq##port##_setbrg(void) \
+				{ return uart_zynq_serial_setbrg(port);

} \

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/serial/serial_zynq.c

Quoted 2 lines
drivers/serial/serial_zynq.c new file +2 -0
+	int uart_zynq##port##_getc(void) \
+				{ return uart_zynq_serial_getc(port); }

\

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/serial/serial_zynq.c

Quoted 2 lines
drivers/serial/serial_zynq.c new file +2 -0
+	int uart_zynq##port##_tstc(void) \
+				{ return uart_zynq_serial_tstc(port); }

\

Quoted 70 lines
Quoted 70 lines
Quoted 69 lines
Quoted 11 lines

drivers/serial/serial_zynq.c line 220

Quoted 7 lines
drivers/serial/serial_zynq.c new file +7 -0
+	void uart_zynq##port##_putc(const char c) \
+				{ uart_zynq_serial_putc(c, port); } \
+	void uart_zynq##port##_puts(const char *s) \
+				{ uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, name) {\

Rename the "name" to __name (this is because once you rename it -- see below -- name will colide with .name)

Quoted 4 lines

drivers/serial/serial_zynq.c line 221

Quoted 1 line
drivers/serial/serial_zynq.c new file +1 -0
+	  name,\

explicitly spell out the name of structure members, so the structure instance is agile to reordering the the declaration members.

No problem to change it. I have seen it in your stdio branch

Quoted 34 lines
Quoted 34 lines
drivers/serial/serial_zynq.c new file +25 -0
+	  uart_zynq##port##_init,\
+	  NULL,\
+	  uart_zynq##port##_setbrg,\
+	  uart_zynq##port##_getc,\
+	  uart_zynq##port##_tstc,\
+	  uart_zynq##port##_putc,\
+	  uart_zynq##port##_puts, }
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+	if (uart_zynq_ports[0])
+		return &uart_zynq_serial0_device;
+	if (uart_zynq_ports[1])
+		return &uart_zynq_serial1_device;
+
+	return NULL;
+}
+#endif
include/serial.h +0 -0
index cbdf8a9..dc8e9b4 100644
@@ -89,6 +89,11 @@ extern struct serial_device bfin_serial2_device;
 
    extern struct serial_device bfin_serial3_device;
    #endif
 
Quoted 7 lines

include/serial.h extern struct serial_device bfin_serial2_device; · line 96

Quoted 5 lines
include/serial.h +5 -0
+#if defined(CONFIG_ZYNQ_SERIAL)
+extern struct serial_device uart_zynq_serial0_device;
+extern struct serial_device uart_zynq_serial1_device;
+#endif
+

Let's not add this, noone uses it.

It is used by serial core where you register serial device.

Quoted 1 line

include/serial.h extern struct serial_device bfin_serial2_device; · line 98

Quoted 1 line
include/serial.h +1 -0
+	serial_register(&uart_zynq_serial0_device);

You need declaration somewhere. If you don't have it then this error message is shown. serial.c: In function 'serial_initialize':
serial.c:127:19: error: 'uart_zynq_serial0_device' undeclared (first use in this function) serial.c:127:19: note: each undeclared identifier is reported only once for each function it appears in

Quoted 8 lines
Quoted 5 lines

Oh damn, you're right ... I reworked the serial core so it's not needed -- by sticking an init func into each and every driver.

Maybe we should start pushing the serial drivers through that branch of mine once I post it?

You have mentioned in one email that your tree is not ready.
http://lists.denx.de/pipermail/u-boot/2012-September/133836.html

That's the "once I post it" part of the previous sentence ;-)

Quoted 1 line
Quoted 7 lines
Quoted 5 lines

I will send update v4.

Quoted 1 line

I guess this platform won't make it into .10 release anyway.

Why not? Any reason why these 4 patches should wait till the next release?

MW is closed (Aug. 18)

ok. Isn't there any "next" branch for this purpose? I believe it can go at least to custodian arm tree.

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#22 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Dear Michal Simek,

[...]

Quoted 4 lines
Quoted 1 line

MW is closed (Aug. 18)

ok. Isn't there any "next" branch for this purpose? I believe it can go at least to custodian arm tree.

That's a question for Albert I think.

Quoted 2 lines

Thanks,
Michal

Best regards,
Marek Vasut

#24 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Quoted 11 lines · Joe Hershberger

Hi Marek,

Quoted 5 lines · Marek Vasut
Quoted 3 lines
Quoted 1 line

I guess this platform won't make it into .10 release anyway.

Why not? Any reason why these 4 patches should wait till the next release?

MW is closed (Aug. 18)

The first version of this series was sent on Aug 14.
http://patchwork.ozlabs.org/patch/177232/

Marek any response?

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#25 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Dear Michal Simek,

Quoted 9 lines · Joe Hershberger
Quoted 8 lines

Hi Marek,

Quoted 5 lines · Marek Vasut
Quoted 4 lines
Quoted 1 line

I guess this platform won't make it into .10 release anyway.

Why not? Any reason why these 4 patches should wait till the next release?

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

MW is closed (Aug. 18)

The first version of this series was sent on Aug 14.
http://patchwork.ozlabs.org/patch/177232/

Marek any response?

Did I not review this? I CCed Tom to decide, I'm fine either way.

Best regards,
Marek Vasut

#26 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

Quoted 11 lines · Marek Vasut

Dear Michal Simek,

Quoted 9 lines · Joe Hershberger
Quoted 8 lines

Hi Marek,

Quoted 5 lines · Marek Vasut
Quoted 4 lines
Quoted 1 line

I guess this platform won't make it into .10 release anyway.

Why not? Any reason why these 4 patches should wait till the next release?

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 1 line

MW is closed (Aug. 18)

The first version of this series was sent on Aug 14.
http://patchwork.ozlabs.org/patch/177232/

Marek any response?

Did I not review this? I CCed Tom to decide, I'm fine either way.

I didn't see your answer.

Tom: are you OK to add these 4 patches to mainline tree?
All of them are ACKed by Marek. I haven't got any response from Albert.

I have added to my custodian tree and if you agree I can just send pull request directly to you.

Please let me know what you think.

Thanks,
Michal

Signature · 4 lines
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
#27 lore raw

PATCH v3 1/4 serial: Add Zynq serial driver

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 24 lines · Michal Simek
Quoted 15 lines · Marek Vasut

Dear Michal Simek,

Quoted 13 lines · Joe Hershberger
Quoted 12 lines

Hi Marek,

Quoted 7 lines · Marek Vasut
Quoted 5 lines
Quoted 2 lines

I guess this platform won't make it into .10 release anyway.

Why not? Any reason why these 4 patches should wait till the next release?

MW is closed (Aug. 18)

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

The first version of this series was sent on Aug 14.
http://patchwork.ozlabs.org/patch/177232/

Marek any response?

Did I not review this? I CCed Tom to decide, I'm fine either way.

Quoted 7 lines

I didn't see your answer.

Tom: are you OK to add these 4 patches to mainline tree? All of them are ACKed by Marek. I haven't got any response from Albert.

I have added to my custodian tree and if you agree I can just send pull request directly to you.

So, lets see if I can not contradict myself as I also need to put a pull request up for Albert. I had said what, -rc2? if Albert didn't respond and at the time you had gotten more feedback from Marek, which you have addressed. So I've updated patchwork for all of the patches, assigned 3 of them to Albert and the network one to Joe.

- --
Tom

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://www.enigmail.net/

iQIcBAEBAgAGBQJQWgMCAAoJENk4IS6UOR1WShYQAIiTW06y9CcBJVbBxhJFbtVI CPBOkq1FRQwGJ5lbwINdgfLxMbXsd/R9OWyo3JkTn8vnCKcx+Mu2on6GkvCbKnEL W2ycfo3N8X6EuTS2YxbSB3Dl2oDy97GHQRxsXQ3bOFrtH0fxaNFYc12ofhOsIObn m5qqIXjd8yxc5ylnNZjfNi3dPgdeZxXMt3CqA4E568PvDetgOs/OgeLnIdNR/L6S vCCnmOZhpIszJPFmbCNVK2iDHMDGfbff7A8TNkjT9dSyOftU+GQcW/E3vUoxiYVi vXt1G5m2556lYNsRa43O4Rr6cJRRg5GfzG1U/X0JnWGTTyKZytKfCdhvy7ifn1M8 lwFDlkCtw+x2cH1UNC743LqptaXQin+xGUkGD8n1L+GZhgrSKvzLtjTGTST5zre0 8X/xOQDhW8onn3ra03DCDOKPByzDZKilbO/9EDSHKWaTWFTA7KL9974dSLL7hLur yWzvHpVeqZQUSG/YC4vaWDF5JCUiDEZVZ6+mQx9n9AkrOsDSEDoyUgOefNgeZhkO 2h2Dq1l/HUyl65x8TZHFaYPw4x7m2Sj69t1R2JlGNnoFicFf1hLMV/BvLSoJCiK8 fuh9FcHy6HGw7pFiEam7DgE3Sj7ZU/L/sE4pwTe0eoUyrh2VN7ljScl9opwrbfkK RbHoZ2OJz2uYLX9/3OyN
=zgGt
-----END PGP SIGNATURE-----