public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] Xilinx Zynq platform
@ 2012-08-14 11:42 Michal Simek
  2012-08-14 11:42 ` [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver Michal Simek
                   ` (3 more replies)
  0 siblings, 4 replies; 22+ messages in thread
From: Michal Simek @ 2012-08-14 11:42 UTC (permalink / raw)
  To: u-boot

Hi,

I am sending basic support for new Xilinx Zynq platform.
It is new ARM cortex a9 cpu with programmable logic.
For more information look at www.xilinx.com/zynq.

In future we are going to extend this platform for i2c, spi,
mmc, fpga, nand, nor support, and maybe more. 
These drivers will be send in the next round when this series
is applied to mainline.

Also this platform can also use all drivers targetted to 
Microblaze (axi) for example emaclite, axi ethernet, uartlite,
ns16550a, etc. 

As all others Xilinx platforms this is candidate for OF driven 
configuration.

It is tested on ZC702 platform.

Thanks for your review.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver
  2012-08-14 11:42 [U-Boot] Xilinx Zynq platform Michal Simek
@ 2012-08-14 11:42 ` Michal Simek
  2012-08-14 14:09   ` Joe Hershberger
  2012-08-14 11:42 ` [U-Boot] [PATCH 2/4] net: Add driver for Zynq Gem IP Michal Simek
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 11:42 UTC (permalink / raw)
  To: u-boot

The driver is used on Xilinx Zynq platform.

Signed-off-by: Michal Simek <monstr@monstr.eu>
---
 drivers/serial/Makefile          |    1 +
 drivers/serial/serial_xpssuart.c |  218 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 219 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/serial_xpssuart.c

diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 65d0f23..81350d0 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -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_XPSS_SERIAL) += serial_xpssuart.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_xpssuart.c b/drivers/serial/serial_xpssuart.c
new file mode 100644
index 0000000..3c6d838
--- /dev/null
+++ b/drivers/serial/serial_xpssuart.c
@@ -0,0 +1,218 @@
+/*
+ * U-Boot driver for Xilinx Dragonfire UART.
+ *
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * 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 <serial.h>
+
+#define XDFUART_SR_TXFULL	0x00000010 /* TX FIFO full */
+#define XDFUART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
+
+#define XDFUART_CR_TX_EN	0x00000010 /* TX enabled */
+#define XDFUART_CR_RX_EN	0x00000004 /* RX enabled */
+#define XDFUART_CR_TXRST	0x00000002 /* TX logic reset */
+#define XDFUART_CR_RXRST	0x00000001 /* RX logic reset */
+
+#define XDFUART_MR_PARITY_NONE	0x00000020  /* No parity mode */
+
+/* Some clock/baud constants */
+#define XDFUART_BDIV	15 /* Default/reset BDIV value */
+#define XDFUART_BASECLK	3125000L /* master / (bdiv + 1) */
+
+struct xdfuart {
+	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 xdfuart *xdf_ports[4] = {
+#ifdef CONFIG_XPSS_SERIAL_BASEADDR0
+	[0] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_XPSS_SERIAL_BASEADDR1
+	[1] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR1,
+#endif
+#ifdef CONFIG_XPSS_SERIAL_BASEADDR2
+	[2] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR2,
+#endif
+#ifdef CONFIG_XPSS_SERIAL_BASEADDR3
+	[3] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR3,
+#endif
+};
+
+struct xdfuart_params {
+	u32 baudrate;
+	u32 clock;
+};
+
+static struct xdfuart_params xdf_ports_param[4] = {
+#if defined(CONFIG_XPSS_SERIAL_BAUDRATE0) && defined(CONFIG_XPSS_SERIAL_CLOCK0)
+	[0].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE0,
+	[0].clock = CONFIG_XPSS_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_XPSS_SERIAL_BAUDRATE1) && defined(CONFIG_XPSS_SERIAL_CLOCK1)
+	[1].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE1,
+	[1].clock = CONFIG_XPSS_SERIAL_CLOCK1,
+#endif
+#if defined(CONFIG_XPSS_SERIAL_BAUDRATE2) && defined(CONFIG_XPSS_SERIAL_CLOCK2)
+	[2].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE2,
+	[2].clock = CONFIG_XPSS_SERIAL_CLOCK2,
+#endif
+#if defined(CONFIG_XPSS_SERIAL_BAUDRATE3) && defined(CONFIG_XPSS_SERIAL_CLOCK3)
+	[3].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE3,
+	[3].clock = CONFIG_XPSS_SERIAL_CLOCK3,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void xdfuart_serial_setbrg(const int port)
+{
+	/* Calculation results. */
+	unsigned int calc_bauderror, bdiv, bgen;
+	unsigned long calc_baud = 0;
+	unsigned long baud = xdf_ports_param[port].baudrate;
+	unsigned long clock = xdf_ports_param[port].clock;
+	struct xdfuart *regs = xdf_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 xdfuart_serial_init(const int port)
+{
+	struct xdfuart *regs = xdf_ports[port];
+
+	if (!regs)
+		return -1;
+
+	/* RX/TX enabled & reset */
+	writel(XDFUART_CR_TX_EN | XDFUART_CR_RX_EN | XDFUART_CR_TXRST | \
+					XDFUART_CR_RXRST, &regs->control);
+	writel(XDFUART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
+	xdfuart_serial_setbrg(port);
+
+	return 0;
+}
+
+static void xdfuart_serial_putc(const char c, const int port)
+{
+	struct xdfuart *regs = xdf_ports[port];
+
+	while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) != 0)
+		WATCHDOG_RESET();
+
+	if (c == '\n') {
+		writel('\r', &regs->tx_rx_fifo);
+		while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) != 0)
+			WATCHDOG_RESET();
+	}
+	writel(c, &regs->tx_rx_fifo);
+}
+
+static void xdfuart_serial_puts(const char *s, const int port)
+{
+	while (*s)
+		xdfuart_serial_putc(*s++, port);
+}
+
+static int xdfuart_serial_tstc(const int port)
+{
+	struct xdfuart *regs = xdf_ports[port];
+
+	return (readl(&regs->channel_sts) & XDFUART_SR_RXEMPTY) == 0;
+}
+
+static int xdfuart_serial_getc(const int port)
+{
+	struct xdfuart *regs = xdf_ports[port];
+
+	while (!xdfuart_serial_tstc(port))
+		WATCHDOG_RESET();
+	return readl(&regs->tx_rx_fifo);
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init(void)
+{
+	return xdfuart_serial_init(0);
+}
+
+void serial_setbrg(void)
+{
+	xdfuart_serial_setbrg(0);
+}
+
+void serial_putc(const char c)
+{
+	xdfuart_serial_putc(c, 0);
+}
+
+void serial_puts(const char *s)
+{
+	xdfuart_serial_puts(s, 0);
+}
+
+int serial_getc(void)
+{
+	return xdfuart_serial_getc(0);
+}
+
+int serial_tstc(void)
+{
+	return xdfuart_serial_tstc(0);
+}
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 2/4] net: Add driver for Zynq Gem IP
  2012-08-14 11:42 [U-Boot] Xilinx Zynq platform Michal Simek
  2012-08-14 11:42 ` [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver Michal Simek
@ 2012-08-14 11:42 ` Michal Simek
  2012-08-14 14:59   ` Joe Hershberger
  2012-08-14 11:42 ` [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform Michal Simek
  2012-08-14 11:42 ` [U-Boot] [PATCH 4/4] xilinx: Add new Zynq board Michal Simek
  3 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 11:42 UTC (permalink / raw)
  To: u-boot

Device driver for Zynq Gem IP.

Signed-off-by: Michal Simek <monstr@monstr.eu>
CC: Joe Hershberger <joe.hershberger@gmail.com>
---
 drivers/net/Makefile     |    1 +
 drivers/net/xilinx_gem.c |  514 ++++++++++++++++++++++++++++++++++++++++++++++
 include/netdev.h         |    1 +
 3 files changed, 516 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/xilinx_gem.c

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 430f90c..e510ffa 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -77,6 +77,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
 COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_GEM) += xilinx_gem.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
 
diff --git a/drivers/net/xilinx_gem.c b/drivers/net/xilinx_gem.c
new file mode 100644
index 0000000..7c8c14d
--- /dev/null
+++ b/drivers/net/xilinx_gem.c
@@ -0,0 +1,514 @@
+/*
+ * (C) Copyright 2011 Michal Simek
+ *
+ * Michal SIMEK <monstr@monstr.eu>
+ *
+ * Based on Xilinx gmac driver:
+ * (C) Copyright 2011 Xilinx
+ *
+ * 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 <net.h>
+#include <config.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <phy.h>
+#include <miiphy.h>
+
+#if !defined(CONFIG_PHYLIB)
+# error XILINX_GEM_ETHERNET requires PHYLIB
+#endif
+
+/* Bit/mask specification */
+#define XEMACPSS_PHYMNTNC_OP_MASK	0x40020000 /* operation mask bits */
+#define XEMACPSS_PHYMNTNC_OP_R_MASK	0x20000000 /* read operation */
+#define XEMACPSS_PHYMNTNC_OP_W_MASK	0x10000000 /* write operation */
+#define XEMACPSS_PHYMNTNC_PHYAD_SHIFT_MASK	23 /* Shift bits for PHYAD */
+#define XEMACPSS_PHYMNTNC_PHREG_SHIFT_MASK	18 /* Shift bits for PHREG */
+
+#define XEMACPSS_RXBUF_EOF_MASK		0x00008000 /* End of frame. */
+#define XEMACPSS_RXBUF_SOF_MASK		0x00004000 /* Start of frame. */
+#define XEMACPSS_RXBUF_LEN_MASK		0x00003FFF /* Mask for length field */
+
+#define XEMACPSS_RXBUF_WRAP_MASK	0x00000002 /* Wrap bit, last BD */
+#define XEMACPSS_RXBUF_NEW_MASK		0x00000001 /* Used bit.. */
+#define XEMACPSS_RXBUF_ADD_MASK		0xFFFFFFFC /* Mask for address */
+
+/* Wrap bit, last descriptor */
+#define XEMACPSS_TXBUF_WRAP_MASK	0x40000000
+#define XEMACPSS_TXBUF_LAST_MASK	0x00008000 /* Last buffer */
+
+#define XEMACPSS_TXSR_HRESPNOK_MASK	0x00000100 /* Transmit hresp not OK */
+#define XEMACPSS_TXSR_URUN_MASK		0x00000040 /* Transmit underrun */
+/* Transmit buffs exhausted mid frame */
+#define XEMACPSS_TXSR_BUFEXH_MASK	0x00000010
+
+#define XEMACPSS_NWCTRL_TXEN_MASK	0x00000008 /* Enable transmit */
+#define XEMACPSS_NWCTRL_RXEN_MASK	0x00000004 /* Enable receive */
+#define XEMACPSS_NWCTRL_MDEN_MASK	0x00000010 /* Enable MDIO port */
+#define XEMACPSS_NWCTRL_STARTTX_MASK	0x00000200 /* Start tx (tx_go) */
+
+#define XEMACPSS_NWSR_MDIOIDLE_MASK	0x00000004 /* PHY management idle */
+
+/* Use MII register 1 (MII status register) to detect PHY */
+#define PHY_DETECT_REG		1
+
+/* Mask used to verify certain PHY features (or register contents)
+ * in the register above:
+ *  0x1000: 10Mbps full duplex support
+ *  0x0800: 10Mbps half duplex support
+ *  0x0008: Auto-negotiation support
+ */
+#define PHY_DETECT_MASK		0x1808
+
+/* Device registers */
+struct gem_regs {
+	u32 nwctrl; /* Network Control reg */
+	u32 nwcfg; /* Network Config reg */
+	u32 nwsr; /* Network Status reg */
+	u32 reserved1;
+	u32 dmacr; /* DMA Control reg */
+	u32 txsr; /* TX Status reg */
+	u32 rxqbase; /* RX Q Base address reg */
+	u32 txqbase; /* TX Q Base address reg */
+	u32 rxsr; /* RX Status reg */
+	u32 reserved2[2];
+	u32 idr; /* Interrupt Disable reg */
+	u32 reserved3;
+	u32 phymntnc; /* Phy Maintaince reg */
+	u32 reserved4[18];
+	u32 hashl; /* Hash Low address reg */
+	u32 hashh; /* Hash High address reg */
+#define LADDR_LOW	0
+#define LADDR_HIGH	1
+	u32 laddr[4][LADDR_HIGH + 1]; /* Specific1 addr low/high reg */
+	u32 match[4]; /* Type ID1 Match reg */
+	u32 reserved6[18];
+	u32 stat[44]; /* Octects transmitted Low reg - stat start */
+};
+
+/* BD descriptors */
+struct emac_bd {
+	u32 addr; /* Next descriptor pointer */
+	u32 status;
+};
+
+#define RX_BUF 3
+
+/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
+struct gemac_priv {
+	struct emac_bd tx_bd;
+	struct emac_bd rx_bd[RX_BUF];
+	u32 initialized;
+	char rxbuffers[RX_BUF * PKTSIZE_ALIGN];
+	u32 rxbd_current;
+	u32 rx_first_buf;
+	int phyaddr;
+	struct phy_device *phydev;
+	struct mii_dev *bus;
+};
+
+static inline int mdio_wait(struct eth_device *dev)
+{
+	struct gem_regs *regs = (struct gem_regs *)dev->iobase;
+	u32 timeout = 200;
+
+	/* Wait till MDIO interface is ready to accept a new transaction. */
+	while (timeout && !(readl(&regs->nwsr) & XEMACPSS_NWSR_MDIOIDLE_MASK)) {
+		timeout--;
+		udelay(1);
+	}
+
+	if (!timeout) {
+		printf("%s: Timeout\n", __func__);
+		return 1;
+	}
+
+	return 0;
+}
+
+static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum,
+							u32 op, u16 *data)
+{
+	u32 mgtcr;
+	struct gem_regs *regs = (struct gem_regs *)dev->iobase;
+
+	if (mdio_wait(dev))
+		return 1;
+
+	/* Construct mgtcr mask for the operation */
+	mgtcr = XEMACPSS_PHYMNTNC_OP_MASK | op |
+		(phy_addr << XEMACPSS_PHYMNTNC_PHYAD_SHIFT_MASK) |
+		(regnum << XEMACPSS_PHYMNTNC_PHREG_SHIFT_MASK) | *data;
+
+	/* Write mgtcr and wait for completion */
+	writel(mgtcr, &regs->phymntnc);
+
+	if (mdio_wait(dev))
+		return 1;
+
+	if (op == XEMACPSS_PHYMNTNC_OP_R_MASK)
+		*data = readl(&regs->phymntnc);
+
+	return 0;
+}
+
+static u32 phyread(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 *val)
+{
+	return phy_setup_op(dev, phy_addr, regnum,
+				XEMACPSS_PHYMNTNC_OP_R_MASK, val);
+}
+
+static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data)
+{
+	return phy_setup_op(dev, phy_addr, regnum,
+				XEMACPSS_PHYMNTNC_OP_W_MASK, &data);
+}
+
+static void phy_detection(struct eth_device *dev)
+{
+	int i, ret;
+	u16 phyreg;
+	struct gemac_priv *priv = dev->priv;
+
+	if (priv->phyaddr != -1) {
+		ret = phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg);
+		if (!ret && (phyreg != 0xFFFF) &&
+		((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+			/* Found a valid PHY address */
+			debug("Default phy address %d is valid\n",
+								priv->phyaddr);
+			return;
+		} else {
+			debug("PHY address is not setup correctly %d\n",
+								priv->phyaddr);
+			priv->phyaddr = -1;
+		}
+	}
+
+	debug("detecting phy address\n");
+	if (priv->phyaddr == -1) {
+		/* detect the PHY address */
+		for (i = 31; i >= 0; i--) {
+			ret = phyread(dev, i, PHY_DETECT_REG, &phyreg);
+			if (!ret && (phyreg != 0xFFFF) &&
+			((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+				/* Found a valid PHY address */
+				priv->phyaddr = i;
+				debug("Found valid phy address, %d\n", i);
+				return;
+			}
+		}
+	}
+	printf("PHY is not detected\n");
+}
+
+/* Address bits[47:32] bit[31:0] are in BOTTOM */
+#define XEMACPSS_LADDR_MACH_MASK	0x0000FFFF
+
+static void setmacaddress(struct eth_device *dev, void *addressptr, u8 index)
+{
+	u32 macaddr;
+	struct gem_regs *regs = (struct gem_regs *)dev->iobase;
+	u8 *aptr = (u8 *) addressptr;
+
+	/* Set the MAC bits [31:0] in BOT */
+	macaddr = aptr[0];
+	macaddr |= aptr[1] << 8;
+	macaddr |= aptr[2] << 16;
+	macaddr |= aptr[3] << 24;
+	writel(macaddr, &regs->laddr[index][LADDR_LOW]);
+
+	/* There are reserved bits in TOP so don't affect them */
+	macaddr = readl(&regs->laddr[index][LADDR_HIGH]);
+
+	macaddr &= ~XEMACPSS_LADDR_MACH_MASK;
+
+	/* Set MAC bits [47:32] in TOP */
+	macaddr |= aptr[4];
+	macaddr |= aptr[5] << 8;
+
+	writel(macaddr, &regs->laddr[index][LADDR_HIGH]);
+
+	/* Set the ID bits in MATCHx register - settypeidcheck */
+	writel(0, &regs->match[index]);
+}
+
+static int gem_init(struct eth_device *dev, bd_t * bis)
+{
+	int tmp;
+	int i;
+	struct gem_regs *regs = (struct gem_regs *)dev->iobase;
+	char emacpss_zero_mac[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+	struct gemac_priv *priv = dev->priv;
+	struct phy_device *phydev;
+	u32 supported = SUPPORTED_10baseT_Half |
+			SUPPORTED_10baseT_Full |
+			SUPPORTED_100baseT_Half |
+			SUPPORTED_100baseT_Full |
+			SUPPORTED_1000baseT_Half |
+			SUPPORTED_1000baseT_Full;
+
+	if (priv->initialized)
+		return 0;
+
+	/* Disable all interrupts */
+	writel(0xFFFFFFFF, &regs->idr);
+
+	/* Disable the receiver & transmitter */
+	writel(0, &regs->nwctrl);
+	writel(0, &regs->txsr);
+	writel(0, &regs->rxsr);
+	writel(0, &regs->phymntnc);
+
+	/* Clear the Hash registers for the mac address pointed by AddressPtr */
+	writel(0x0, &regs->hashl);
+	/* Write bits [63:32] in TOP */
+	writel(0x0, &regs->hashh);
+
+	for (i = 0; i < 4; i++)
+		setmacaddress(dev, emacpss_zero_mac, i);
+
+	/* Clear all counters */
+	for (i = 0; i <= (sizeof(struct gem_regs) -
+			offsetof(struct gem_regs, stat)) / 4; i++)
+		readl(&regs->stat[i]);
+
+	/* Setup RxBD space */
+	memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd));
+	/* Create the RxBD ring */
+	memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers));
+
+	for (i = 0; i < RX_BUF; i++) {
+		priv->rx_bd[i].status = 0xF0000000;
+		priv->rx_bd[i].addr = (u32)((char *) &(priv->rxbuffers) +
+							(i * PKTSIZE_ALIGN));
+	}
+	/* WRAP bit to last BD */
+	priv->rx_bd[--i].addr |= XEMACPSS_RXBUF_WRAP_MASK;
+	/* Write RxBDs to IP */
+	writel((u32) &(priv->rx_bd), &regs->rxqbase);
+
+
+	/* MAC Setup */
+	/*
+	 *  Following is the setup for Network Configuration register.
+	 *  Bit 0:  Set for 100 Mbps operation.
+	 *  Bit 1:  Set for Full Duplex mode.
+	 *  Bit 4:  Set to allow Copy all frames.
+	 *  Bit 17: Set for FCS removal.
+	 *  Bits 20-18: Set with value binary 010 to divide pclk by 32
+	 *              (pclk up to 80 MHz)
+	 */
+	writel(0x000A0013, &regs->nwcfg);
+
+	/*
+	 * Following is the setup for DMA Configuration register.
+	 * Bits 4-0: To set AHB fixed burst length for DMA data operations ->
+	 *  Set with binary 00100 to use INCR4 AHB bursts.
+	 * Bits 9-8: Receiver packet buffer memory size ->
+	 *  Set with binary 11 to Use full configured addressable space (8 Kb)
+	 * Bit 10  : Transmitter packet buffer memory size ->
+	 *  Set with binary 1 to Use full configured addressable space (4 Kb)
+	 * Bits 23-16 : DMA receive buffer size in AHB system memory ->
+	 *  Set with binary 00011000 to use 1536 byte(1*max length frame/buffer)
+	 */
+	writel(0x00180704, &regs->dmacr);
+
+	/*
+	 * Following is the setup for Network Control register.
+	 * Bit 2:  Set to enable Receive operation.
+	 * Bit 3:  Set to enable Transmitt operation.
+	 * Bit 4:  Set to enable MDIO operation.
+	 */
+	tmp = readl(&regs->nwctrl);
+	/* MDIO, Rx and Tx enable */
+	tmp |= XEMACPSS_NWCTRL_MDEN_MASK | XEMACPSS_NWCTRL_RXEN_MASK |
+	    XEMACPSS_NWCTRL_TXEN_MASK;
+	writel(tmp, &regs->nwctrl);
+
+	phy_detection(dev);
+
+	/* interface - look at tsec */
+	phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0);
+
+	phydev->supported &= supported;
+	phydev->advertising = phydev->supported;
+	priv->phydev = phydev;
+	phy_config(phydev);
+	phy_startup(phydev);
+
+	priv->initialized = 1;
+	return 0;
+}
+
+static int gem_send(struct eth_device *dev, void *ptr, int len)
+{
+	int status;
+	u32 val;
+	struct gemac_priv *priv = dev->priv;
+	struct gem_regs *regs = (struct gem_regs *)dev->iobase;
+
+	if (!priv->initialized) {
+		puts("Error GMAC not initialized");
+		return -1;
+	}
+
+	/* setup BD */
+	writel((u32)&(priv->tx_bd), &regs->txqbase);
+
+	/* Setup Tx BD */
+	memset((void *) &(priv->tx_bd), 0, sizeof(struct emac_bd));
+
+	priv->tx_bd.addr = (u32)ptr;
+	priv->tx_bd.status = len | XEMACPSS_TXBUF_LAST_MASK |
+						XEMACPSS_TXBUF_WRAP_MASK;
+
+	/* Start transmit */
+	val = readl(&regs->nwctrl) | XEMACPSS_NWCTRL_STARTTX_MASK;
+	writel(val, &regs->nwctrl);
+
+	/* Read the stat register to know if the packet has been transmitted */
+	status = readl(&regs->txsr);
+	if (status & (XEMACPSS_TXSR_HRESPNOK_MASK | XEMACPSS_TXSR_URUN_MASK |
+						XEMACPSS_TXSR_BUFEXH_MASK)) {
+		printf("Something has gone wrong here!? Status is 0x%x.\n",
+		       status);
+	}
+
+	/* Clear Tx status register before leaving . */
+	writel(status, &regs->txsr);
+	return 0;
+}
+
+/* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
+static int gem_recv(struct eth_device *dev)
+{
+	int frame_len;
+	struct gemac_priv *priv = dev->priv;
+
+	if (!(priv->rx_bd[priv->rxbd_current].addr & XEMACPSS_RXBUF_NEW_MASK))
+		return 0;
+
+	if (!(priv->rx_bd[priv->rxbd_current].status &
+			(XEMACPSS_RXBUF_SOF_MASK | XEMACPSS_RXBUF_EOF_MASK))) {
+		printf("GEM: SOF or EOF not set for last buffer received!\n");
+		return 0;
+	}
+
+	frame_len = priv->rx_bd[priv->rxbd_current].status &
+							XEMACPSS_RXBUF_LEN_MASK;
+	if (frame_len) {
+		NetReceive((u8 *) (priv->rx_bd[priv->rxbd_current].addr &
+					XEMACPSS_RXBUF_ADD_MASK), frame_len);
+
+		if (priv->rx_bd[priv->rxbd_current].status &
+							XEMACPSS_RXBUF_SOF_MASK)
+			priv->rx_first_buf = priv->rxbd_current;
+		else {
+			priv->rx_bd[priv->rxbd_current].addr &=
+						~XEMACPSS_RXBUF_NEW_MASK;
+			priv->rx_bd[priv->rxbd_current].status = 0xF0000000;
+		}
+
+		if (priv->rx_bd[priv->rxbd_current].status &
+						XEMACPSS_RXBUF_EOF_MASK) {
+			priv->rx_bd[priv->rx_first_buf].addr &=
+						~XEMACPSS_RXBUF_NEW_MASK;
+			priv->rx_bd[priv->rx_first_buf].status = 0xF0000000;
+		}
+
+		if ((++priv->rxbd_current) >= RX_BUF)
+			priv->rxbd_current = 0;
+
+		return frame_len;
+	}
+
+	return 0;
+}
+
+static void gem_halt(struct eth_device *dev)
+{
+	return;
+}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
+static int gem_miiphyread(const char *devname, uchar addr,
+							uchar reg, ushort *val)
+{
+	struct eth_device *dev = eth_get_dev();
+	int ret;
+
+	ret = phyread(dev, addr, reg, val);
+	debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *val);
+	return ret;
+}
+
+static int gem_miiphy_write(const char *devname, uchar addr,
+							uchar reg, ushort val)
+{
+	struct eth_device *dev = eth_get_dev();
+
+	debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val);
+	return phywrite(dev, addr, reg, val);
+}
+#endif
+
+int xilinx_gem_initialize(bd_t *bis, int base_addr)
+{
+	struct eth_device *dev;
+	struct gemac_priv *priv;
+
+	dev = calloc(1, sizeof(*dev));
+	if (dev == NULL)
+		return -1;
+
+	dev->priv = calloc(1, sizeof(struct gemac_priv));
+	if (dev->priv == NULL) {
+		free(dev);
+		return -1;
+	}
+	priv = dev->priv;
+
+#ifdef CONFIG_PHY_ADDR
+	priv->phyaddr = CONFIG_PHY_ADDR;
+#else
+	priv->phyaddr = -1;
+#endif
+
+	sprintf(dev->name, "XGem.%x", base_addr);
+
+	dev->iobase = base_addr;
+
+	dev->init = gem_init;
+	dev->halt = gem_halt;
+	dev->send = gem_send;
+	dev->recv = gem_recv;
+
+	eth_register(dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
+	miiphy_register(dev->name, gem_miiphyread, gem_miiphy_write);
+	priv->bus = miiphy_get_dev_by_name(dev->name);
+#endif
+
+	return 1;
+}
diff --git a/include/netdev.h b/include/netdev.h
index d1aaf0c..cd60ebb 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -102,6 +102,7 @@ int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
 							unsigned long dma_addr);
 int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
 							int txpp, int rxpp);
+int xilinx_gem_initialize(bd_t *bis, int base_addr);
 int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
 						unsigned long ctrl_addr);
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 11:42 [U-Boot] Xilinx Zynq platform Michal Simek
  2012-08-14 11:42 ` [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver Michal Simek
  2012-08-14 11:42 ` [U-Boot] [PATCH 2/4] net: Add driver for Zynq Gem IP Michal Simek
@ 2012-08-14 11:42 ` Michal Simek
  2012-08-14 15:36   ` Joe Hershberger
  2012-08-14 11:42 ` [U-Boot] [PATCH 4/4] xilinx: Add new Zynq board Michal Simek
  3 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 11:42 UTC (permalink / raw)
  To: u-boot

Add timer driver.

Signed-off-by: Michal Simek <monstr@monstr.eu>
---
 arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
 arch/arm/cpu/armv7/zynq/timer.c  |  151 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 199 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
 create mode 100644 arch/arm/cpu/armv7/zynq/timer.c

diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/cpu/armv7/zynq/Makefile
new file mode 100644
index 0000000..814c1d4
--- /dev/null
+++ b/arch/arm/cpu/armv7/zynq/Makefile
@@ -0,0 +1,48 @@
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# (C) Copyright 2008
+# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= timer.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c
new file mode 100644
index 0000000..d79da97
--- /dev/null
+++ b/arch/arm/cpu/armv7/zynq/timer.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * (C) Copyright 2008
+ * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
+ *
+ * (C) Copyright 2004
+ * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
+ *
+ * (C) Copyright 2002-2004
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2003
+ * Texas Instruments <www.ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.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 <common.h>
+#include <div64.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct scu_timer {
+	u32 load; /* Timer Load Register */
+	u32 counter; /* Timer Counter Register */
+	u32 control; /* Timer Control Register */
+};
+
+static struct scu_timer *timer_base = CONFIG_XPSS_SCUTIMER_BASEADDR;
+
+#define XSCUTIMER_CONTROL_PRESCALER_MASK	0x0000FF00 /* Prescaler */
+#define XSCUTIMER_CONTROL_PRESCALER_SHIFT	8
+#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK	0x00000002 /* Auto-reload */
+#define XSCUTIMER_CONTROL_ENABLE_MASK		0x00000001 /* Timer enable */
+
+#define TIMER_LOAD_VAL 0xFFFFFFFF
+#define TIMER_PRESCALE 255
+#define TIMER_TICK_HZ  (CONFIG_CPU_FREQ_HZ / 2 / TIMER_PRESCALE)
+
+int timer_init(void)
+{
+	u32 val;
+
+	/* Load the timer counter register */
+	writel(0xFFFFFFFF, &timer_base->counter);
+
+	/* Start the A9Timer device */
+	val = readl(&timer_base->control);
+	/* Enable Auto reload mode */
+	val |= XSCUTIMER_CONTROL_AUTO_RELOAD_MASK;
+	/* Clear prescaler control bits */
+	val &= ~XSCUTIMER_CONTROL_PRESCALER_MASK;
+	/* Set prescaler value */
+	val |= (TIMER_PRESCALE << XSCUTIMER_CONTROL_PRESCALER_SHIFT);
+	/* Enable the decrementer */
+	val |= XSCUTIMER_CONTROL_ENABLE_MASK;
+	writel(val, &timer_base->control);
+
+	/* Reset time */
+	gd->lastinc = readl(&timer_base->counter) /
+					(TIMER_TICK_HZ / CONFIG_SYS_HZ);
+	gd->tbl = 0;
+
+	return 0;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+ulong get_timer_masked(void)
+{
+	ulong now;
+
+	now = readl(&timer_base->counter) / (TIMER_TICK_HZ / CONFIG_SYS_HZ);
+
+	if (gd->lastinc >= now) {
+		/* Normal mode */
+		gd->tbl += gd->lastinc - now;
+	} else {
+		/* We have an overflow ... */
+		gd->tbl += gd->lastinc + TIMER_LOAD_VAL - now;
+	}
+	gd->lastinc = now;
+
+	return gd->tbl;
+}
+
+void __udelay(unsigned long usec)
+{
+	unsigned long long tmp;
+	ulong tmo;
+
+	tmo = usec / (1000000 / CONFIG_SYS_HZ);
+	tmp = get_ticks() + tmo; /* Get current timestamp */
+
+	while (get_ticks() < tmp) { /* Loop till event */
+		 /* NOP */;
+	}
+}
+
+/* Timer without interrupts */
+ulong get_timer(ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 4/4] xilinx: Add new Zynq board
  2012-08-14 11:42 [U-Boot] Xilinx Zynq platform Michal Simek
                   ` (2 preceding siblings ...)
  2012-08-14 11:42 ` [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform Michal Simek
@ 2012-08-14 11:42 ` Michal Simek
  2012-08-14 12:16   ` Michal Simek
  3 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 11:42 UTC (permalink / raw)
  To: u-boot

Add support for Xilinx Zynq board.

Signed-off-by: Michal Simek <monstr@monstr.eu>
---
 board/xilinx/zynq/Makefile        |   57 +++++++++++++++++++++++++++++++++
 board/xilinx/zynq/board.c         |   64 +++++++++++++++++++++++++++++++++++++
 board/xilinx/zynq/lowlevel_init.S |   27 +++++++++++++++
 boards.cfg                        |    1 +
 4 files changed, 149 insertions(+), 0 deletions(-)
 create mode 100644 board/xilinx/zynq/Makefile
 create mode 100644 board/xilinx/zynq/board.c
 create mode 100644 board/xilinx/zynq/lowlevel_init.S

diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile
new file mode 100644
index 0000000..373a8a7
--- /dev/null
+++ b/board/xilinx/zynq/Makefile
@@ -0,0 +1,57 @@
+#
+# (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))
+
+SOBJS	:= lowlevel_init.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c
new file mode 100644
index 0000000..716fcfe
--- /dev/null
+++ b/board/xilinx/zynq/board.c
@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2012 Michal Simek <monstr@monstr.eu>
+ *
+ * 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 <netdev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	icache_enable();
+
+	return 0;
+}
+
+int board_late_init(void)
+{
+	return 0;
+}
+
+#ifdef CONFIG_CMD_NET
+int board_eth_init(bd_t *bis)
+{
+	int ret = 0;
+
+#if defined(CONFIG_XILINX_GEM) && defined(CONFIG_XPSS_GEM_BASEADDR0)
+	ret |= xilinx_gem_initialize(bis, CONFIG_XPSS_GEM_BASEADDR0);
+#endif
+
+	return ret;
+}
+#endif
+
+int dram_init(void)
+{
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+	while (1)
+		;
+}
diff --git a/board/xilinx/zynq/lowlevel_init.S b/board/xilinx/zynq/lowlevel_init.S
new file mode 100644
index 0000000..642eb18
--- /dev/null
+++ b/board/xilinx/zynq/lowlevel_init.S
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright 2012 Michal Simek <monstr@monstr.eu>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+ENTRY(lowlevel_init)
+        mov     pc, lr
+ENDPROC(lowlevel_init)
diff --git a/boards.cfg b/boards.cfg
index fdb84ad..aeca912 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -261,6 +261,7 @@ seaboard                     arm         armv7       seaboard            nvidia
 ventana                      arm         armv7       ventana             nvidia         tegra2
 whistler                     arm         armv7       whistler            nvidia         tegra2
 u8500_href                   arm         armv7       u8500               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
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 4/4] xilinx: Add new Zynq board
  2012-08-14 11:42 ` [U-Boot] [PATCH 4/4] xilinx: Add new Zynq board Michal Simek
@ 2012-08-14 12:16   ` Michal Simek
  0 siblings, 0 replies; 22+ messages in thread
From: Michal Simek @ 2012-08-14 12:16 UTC (permalink / raw)
  To: u-boot

On 08/14/2012 01:42 PM, Michal Simek wrote:
> Add support for Xilinx Zynq board.
>
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> ---
>   board/xilinx/zynq/Makefile        |   57 +++++++++++++++++++++++++++++++++
>   board/xilinx/zynq/board.c         |   64 +++++++++++++++++++++++++++++++++++++
>   board/xilinx/zynq/lowlevel_init.S |   27 +++++++++++++++
>   boards.cfg                        |    1 +
>   4 files changed, 149 insertions(+), 0 deletions(-)
>   create mode 100644 board/xilinx/zynq/Makefile
>   create mode 100644 board/xilinx/zynq/board.c
>   create mode 100644 board/xilinx/zynq/lowlevel_init.S


oops. I forget to add also config file.
Will send v2 patch.

Thanks,
Michal

-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver
  2012-08-14 11:42 ` [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver Michal Simek
@ 2012-08-14 14:09   ` Joe Hershberger
  2012-08-14 16:38     ` Michal Simek
  0 siblings, 1 reply; 22+ messages in thread
From: Joe Hershberger @ 2012-08-14 14:09 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
> The driver is used on Xilinx Zynq platform.
>
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> ---
>  drivers/serial/Makefile          |    1 +
>  drivers/serial/serial_xpssuart.c |  218 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 219 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/serial/serial_xpssuart.c

I think this would be clearer if it was named serial_zynq.c

> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index 65d0f23..81350d0 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -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_XPSS_SERIAL) += serial_xpssuart.o

Replace every reference to "XPSS" with "ZYNQ".

>  ifndef CONFIG_SPL_BUILD
>  COBJS-$(CONFIG_USB_TTY) += usbtty.o
> diff --git a/drivers/serial/serial_xpssuart.c b/drivers/serial/serial_xpssuart.c
> new file mode 100644
> index 0000000..3c6d838
> --- /dev/null
> +++ b/drivers/serial/serial_xpssuart.c
> @@ -0,0 +1,218 @@
> +/*
> + * U-Boot driver for Xilinx Dragonfire UART.

Use the released name "Zynq" not the old codename "Dragonfire".

> + *
> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
> + * 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 <serial.h>
> +
> +#define XDFUART_SR_TXFULL      0x00000010 /* TX FIFO full */
> +#define XDFUART_SR_RXEMPTY     0x00000002 /* RX FIFO empty */

Replace all references to "XDFUART" with "ZYNQ_UART".

> +
> +#define XDFUART_CR_TX_EN       0x00000010 /* TX enabled */
> +#define XDFUART_CR_RX_EN       0x00000004 /* RX enabled */
> +#define XDFUART_CR_TXRST       0x00000002 /* TX logic reset */
> +#define XDFUART_CR_RXRST       0x00000001 /* RX logic reset */
> +
> +#define XDFUART_MR_PARITY_NONE 0x00000020  /* No parity mode */
> +
> +/* Some clock/baud constants */
> +#define XDFUART_BDIV   15 /* Default/reset BDIV value */
> +#define XDFUART_BASECLK        3125000L /* master / (bdiv + 1) */
> +
> +struct xdfuart {
> +       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 xdfuart *xdf_ports[4] = {
> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR0
> +       [0] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR0,
> +#endif
> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR1
> +       [1] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR1,
> +#endif

There are 2 UARTS in hard silicon.  They should be supported with
their known base addresses (0xE0000000 and 0xE0001000) here without
pushing that into the config header.

> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR2
> +       [2] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR2,
> +#endif
> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR3
> +       [3] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR3,
> +#endif
> +};
> +
> +struct xdfuart_params {
> +       u32 baudrate;
> +       u32 clock;
> +};
> +
> +static struct xdfuart_params xdf_ports_param[4] = {
> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE0) && defined(CONFIG_XPSS_SERIAL_CLOCK0)
> +       [0].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE0,
> +       [0].clock = CONFIG_XPSS_SERIAL_CLOCK0,
> +#endif
> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE1) && defined(CONFIG_XPSS_SERIAL_CLOCK1)
> +       [1].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE1,
> +       [1].clock = CONFIG_XPSS_SERIAL_CLOCK1,
> +#endif
> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE2) && defined(CONFIG_XPSS_SERIAL_CLOCK2)
> +       [2].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE2,
> +       [2].clock = CONFIG_XPSS_SERIAL_CLOCK2,
> +#endif
> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE3) && defined(CONFIG_XPSS_SERIAL_CLOCK3)
> +       [3].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE3,
> +       [3].clock = CONFIG_XPSS_SERIAL_CLOCK3,
> +#endif
> +};
> +
> +/* Set up the baud rate in gd struct */
> +static void xdfuart_serial_setbrg(const int port)
> +{
> +       /* Calculation results. */
> +       unsigned int calc_bauderror, bdiv, bgen;
> +       unsigned long calc_baud = 0;
> +       unsigned long baud = xdf_ports_param[port].baudrate;
> +       unsigned long clock = xdf_ports_param[port].clock;
> +       struct xdfuart *regs = xdf_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 xdfuart_serial_init(const int port)
> +{
> +       struct xdfuart *regs = xdf_ports[port];
> +
> +       if (!regs)
> +               return -1;
> +
> +       /* RX/TX enabled & reset */
> +       writel(XDFUART_CR_TX_EN | XDFUART_CR_RX_EN | XDFUART_CR_TXRST | \
> +                                       XDFUART_CR_RXRST, &regs->control);
> +       writel(XDFUART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
> +       xdfuart_serial_setbrg(port);
> +
> +       return 0;
> +}
> +
> +static void xdfuart_serial_putc(const char c, const int port)
> +{
> +       struct xdfuart *regs = xdf_ports[port];
> +
> +       while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) != 0)
> +               WATCHDOG_RESET();
> +
> +       if (c == '\n') {
> +               writel('\r', &regs->tx_rx_fifo);
> +               while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) != 0)
> +                       WATCHDOG_RESET();
> +       }
> +       writel(c, &regs->tx_rx_fifo);
> +}
> +
> +static void xdfuart_serial_puts(const char *s, const int port)
> +{
> +       while (*s)
> +               xdfuart_serial_putc(*s++, port);
> +}
> +
> +static int xdfuart_serial_tstc(const int port)
> +{
> +       struct xdfuart *regs = xdf_ports[port];
> +
> +       return (readl(&regs->channel_sts) & XDFUART_SR_RXEMPTY) == 0;
> +}
> +
> +static int xdfuart_serial_getc(const int port)
> +{
> +       struct xdfuart *regs = xdf_ports[port];
> +
> +       while (!xdfuart_serial_tstc(port))
> +               WATCHDOG_RESET();
> +       return readl(&regs->tx_rx_fifo);
> +}
> +
> +#if !defined(CONFIG_SERIAL_MULTI)
> +int serial_init(void)
> +{
> +       return xdfuart_serial_init(0);

If there is no SERIAL_MULTI support, there should be a config to
select which one to use.

> +}
> +
> +void serial_setbrg(void)
> +{
> +       xdfuart_serial_setbrg(0);
> +}
> +
> +void serial_putc(const char c)
> +{
> +       xdfuart_serial_putc(c, 0);
> +}
> +
> +void serial_puts(const char *s)
> +{
> +       xdfuart_serial_puts(s, 0);
> +}
> +
> +int serial_getc(void)
> +{
> +       return xdfuart_serial_getc(0);
> +}
> +
> +int serial_tstc(void)
> +{
> +       return xdfuart_serial_tstc(0);
> +}
> +#endif
> --
> 1.7.0.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 2/4] net: Add driver for Zynq Gem IP
  2012-08-14 11:42 ` [U-Boot] [PATCH 2/4] net: Add driver for Zynq Gem IP Michal Simek
@ 2012-08-14 14:59   ` Joe Hershberger
  2012-08-14 17:04     ` Michal Simek
  0 siblings, 1 reply; 22+ messages in thread
From: Joe Hershberger @ 2012-08-14 14:59 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
> Device driver for Zynq Gem IP.
>
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> CC: Joe Hershberger <joe.hershberger@gmail.com>
> ---
>  drivers/net/Makefile     |    1 +
>  drivers/net/xilinx_gem.c |  514 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/netdev.h         |    1 +
>  3 files changed, 516 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/xilinx_gem.c

Call this zynq_gem.c  My understanding is this is only available in
the hard silicon for Zynq.

>
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 430f90c..e510ffa 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -77,6 +77,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
>  COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
>  COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
>  COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
> +COBJS-$(CONFIG_XILINX_GEM) += xilinx_gem.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
>
> diff --git a/drivers/net/xilinx_gem.c b/drivers/net/xilinx_gem.c
> new file mode 100644
> index 0000000..7c8c14d
> --- /dev/null
> +++ b/drivers/net/xilinx_gem.c
> @@ -0,0 +1,514 @@
> +/*
> + * (C) Copyright 2011 Michal Simek
> + *
> + * Michal SIMEK <monstr@monstr.eu>
> + *
> + * Based on Xilinx gmac driver:
> + * (C) Copyright 2011 Xilinx
> + *
> + * 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 <net.h>
> +#include <config.h>
> +#include <malloc.h>
> +#include <asm/io.h>
> +#include <phy.h>
> +#include <miiphy.h>
> +
> +#if !defined(CONFIG_PHYLIB)
> +# error XILINX_GEM_ETHERNET requires PHYLIB
> +#endif
> +
> +/* Bit/mask specification */
> +#define XEMACPSS_PHYMNTNC_OP_MASK      0x40020000 /* operation mask bits */
> +#define XEMACPSS_PHYMNTNC_OP_R_MASK    0x20000000 /* read operation */
> +#define XEMACPSS_PHYMNTNC_OP_W_MASK    0x10000000 /* write operation */
> +#define XEMACPSS_PHYMNTNC_PHYAD_SHIFT_MASK     23 /* Shift bits for PHYAD */
> +#define XEMACPSS_PHYMNTNC_PHREG_SHIFT_MASK     18 /* Shift bits for PHREG */

Replace all "XEMACPSS" with "ZYNQ_GEM"

> +
> +#define XEMACPSS_RXBUF_EOF_MASK                0x00008000 /* End of frame. */
> +#define XEMACPSS_RXBUF_SOF_MASK                0x00004000 /* Start of frame. */
> +#define XEMACPSS_RXBUF_LEN_MASK                0x00003FFF /* Mask for length field */
> +
> +#define XEMACPSS_RXBUF_WRAP_MASK       0x00000002 /* Wrap bit, last BD */
> +#define XEMACPSS_RXBUF_NEW_MASK                0x00000001 /* Used bit.. */
> +#define XEMACPSS_RXBUF_ADD_MASK                0xFFFFFFFC /* Mask for address */
> +
> +/* Wrap bit, last descriptor */
> +#define XEMACPSS_TXBUF_WRAP_MASK       0x40000000
> +#define XEMACPSS_TXBUF_LAST_MASK       0x00008000 /* Last buffer */
> +
> +#define XEMACPSS_TXSR_HRESPNOK_MASK    0x00000100 /* Transmit hresp not OK */
> +#define XEMACPSS_TXSR_URUN_MASK                0x00000040 /* Transmit underrun */
> +/* Transmit buffs exhausted mid frame */
> +#define XEMACPSS_TXSR_BUFEXH_MASK      0x00000010
> +
> +#define XEMACPSS_NWCTRL_TXEN_MASK      0x00000008 /* Enable transmit */
> +#define XEMACPSS_NWCTRL_RXEN_MASK      0x00000004 /* Enable receive */
> +#define XEMACPSS_NWCTRL_MDEN_MASK      0x00000010 /* Enable MDIO port */
> +#define XEMACPSS_NWCTRL_STARTTX_MASK   0x00000200 /* Start tx (tx_go) */
> +
> +#define XEMACPSS_NWSR_MDIOIDLE_MASK    0x00000004 /* PHY management idle */
> +
> +/* Use MII register 1 (MII status register) to detect PHY */
> +#define PHY_DETECT_REG         1
> +
> +/* Mask used to verify certain PHY features (or register contents)
> + * in the register above:
> + *  0x1000: 10Mbps full duplex support
> + *  0x0800: 10Mbps half duplex support
> + *  0x0008: Auto-negotiation support
> + */
> +#define PHY_DETECT_MASK                0x1808
> +
> +/* Device registers */
> +struct gem_regs {
> +       u32 nwctrl; /* Network Control reg */
> +       u32 nwcfg; /* Network Config reg */
> +       u32 nwsr; /* Network Status reg */
> +       u32 reserved1;
> +       u32 dmacr; /* DMA Control reg */
> +       u32 txsr; /* TX Status reg */
> +       u32 rxqbase; /* RX Q Base address reg */
> +       u32 txqbase; /* TX Q Base address reg */
> +       u32 rxsr; /* RX Status reg */
> +       u32 reserved2[2];
> +       u32 idr; /* Interrupt Disable reg */
> +       u32 reserved3;
> +       u32 phymntnc; /* Phy Maintaince reg */
> +       u32 reserved4[18];
> +       u32 hashl; /* Hash Low address reg */
> +       u32 hashh; /* Hash High address reg */
> +#define LADDR_LOW      0
> +#define LADDR_HIGH     1
> +       u32 laddr[4][LADDR_HIGH + 1]; /* Specific1 addr low/high reg */
> +       u32 match[4]; /* Type ID1 Match reg */
> +       u32 reserved6[18];
> +       u32 stat[44]; /* Octects transmitted Low reg - stat start */
> +};
> +
> +/* BD descriptors */
> +struct emac_bd {
> +       u32 addr; /* Next descriptor pointer */
> +       u32 status;
> +};
> +
> +#define RX_BUF 3
> +
> +/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
> +struct gemac_priv {
> +       struct emac_bd tx_bd;
> +       struct emac_bd rx_bd[RX_BUF];
> +       u32 initialized;
> +       char rxbuffers[RX_BUF * PKTSIZE_ALIGN];
> +       u32 rxbd_current;
> +       u32 rx_first_buf;
> +       int phyaddr;
> +       struct phy_device *phydev;
> +       struct mii_dev *bus;
> +};
> +
> +static inline int mdio_wait(struct eth_device *dev)
> +{
> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
> +       u32 timeout = 200;
> +
> +       /* Wait till MDIO interface is ready to accept a new transaction. */
> +       while (timeout && !(readl(&regs->nwsr) & XEMACPSS_NWSR_MDIOIDLE_MASK)) {
> +               timeout--;
> +               udelay(1);
> +       }
> +
> +       if (!timeout) {
> +               printf("%s: Timeout\n", __func__);
> +               return 1;
> +       }
> +
> +       return 0;
> +}
> +
> +static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum,
> +                                                       u32 op, u16 *data)
> +{
> +       u32 mgtcr;
> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
> +
> +       if (mdio_wait(dev))
> +               return 1;
> +
> +       /* Construct mgtcr mask for the operation */
> +       mgtcr = XEMACPSS_PHYMNTNC_OP_MASK | op |
> +               (phy_addr << XEMACPSS_PHYMNTNC_PHYAD_SHIFT_MASK) |
> +               (regnum << XEMACPSS_PHYMNTNC_PHREG_SHIFT_MASK) | *data;
> +
> +       /* Write mgtcr and wait for completion */
> +       writel(mgtcr, &regs->phymntnc);
> +
> +       if (mdio_wait(dev))
> +               return 1;
> +
> +       if (op == XEMACPSS_PHYMNTNC_OP_R_MASK)
> +               *data = readl(&regs->phymntnc);
> +
> +       return 0;
> +}
> +
> +static u32 phyread(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 *val)
> +{
> +       return phy_setup_op(dev, phy_addr, regnum,
> +                               XEMACPSS_PHYMNTNC_OP_R_MASK, val);
> +}
> +
> +static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data)
> +{
> +       return phy_setup_op(dev, phy_addr, regnum,
> +                               XEMACPSS_PHYMNTNC_OP_W_MASK, &data);
> +}
> +
> +static void phy_detection(struct eth_device *dev)
> +{
> +       int i, ret;
> +       u16 phyreg;
> +       struct gemac_priv *priv = dev->priv;
> +
> +       if (priv->phyaddr != -1) {
> +               ret = phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg);
> +               if (!ret && (phyreg != 0xFFFF) &&
> +               ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
> +                       /* Found a valid PHY address */
> +                       debug("Default phy address %d is valid\n",
> +                                                               priv->phyaddr);
> +                       return;
> +               } else {
> +                       debug("PHY address is not setup correctly %d\n",
> +                                                               priv->phyaddr);
> +                       priv->phyaddr = -1;
> +               }
> +       }
> +
> +       debug("detecting phy address\n");
> +       if (priv->phyaddr == -1) {
> +               /* detect the PHY address */
> +               for (i = 31; i >= 0; i--) {
> +                       ret = phyread(dev, i, PHY_DETECT_REG, &phyreg);
> +                       if (!ret && (phyreg != 0xFFFF) &&
> +                       ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
> +                               /* Found a valid PHY address */
> +                               priv->phyaddr = i;
> +                               debug("Found valid phy address, %d\n", i);
> +                               return;
> +                       }
> +               }
> +       }
> +       printf("PHY is not detected\n");
> +}

Phy detection should be optional (behind a config token).  It also
sounds like something that has nothing to do with this driver.  If you
want to add it, it should probably be in phylib and work with any
driver.

> +
> +/* Address bits[47:32] bit[31:0] are in BOTTOM */
> +#define XEMACPSS_LADDR_MACH_MASK       0x0000FFFF
> +
> +static void setmacaddress(struct eth_device *dev, void *addressptr, u8 index)
> +{
> +       u32 macaddr;
> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
> +       u8 *aptr = (u8 *) addressptr;
> +
> +       /* Set the MAC bits [31:0] in BOT */
> +       macaddr = aptr[0];
> +       macaddr |= aptr[1] << 8;
> +       macaddr |= aptr[2] << 16;
> +       macaddr |= aptr[3] << 24;
> +       writel(macaddr, &regs->laddr[index][LADDR_LOW]);
> +
> +       /* There are reserved bits in TOP so don't affect them */
> +       macaddr = readl(&regs->laddr[index][LADDR_HIGH]);
> +
> +       macaddr &= ~XEMACPSS_LADDR_MACH_MASK;
> +
> +       /* Set MAC bits [47:32] in TOP */
> +       macaddr |= aptr[4];
> +       macaddr |= aptr[5] << 8;
> +
> +       writel(macaddr, &regs->laddr[index][LADDR_HIGH]);
> +
> +       /* Set the ID bits in MATCHx register - settypeidcheck */
> +       writel(0, &regs->match[index]);
> +}
> +
> +static int gem_init(struct eth_device *dev, bd_t * bis)
> +{
> +       int tmp;
> +       int i;
> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
> +       char emacpss_zero_mac[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
> +       struct gemac_priv *priv = dev->priv;
> +       struct phy_device *phydev;
> +       u32 supported = SUPPORTED_10baseT_Half |
> +                       SUPPORTED_10baseT_Full |
> +                       SUPPORTED_100baseT_Half |
> +                       SUPPORTED_100baseT_Full |
> +                       SUPPORTED_1000baseT_Half |
> +                       SUPPORTED_1000baseT_Full;
> +
> +       if (priv->initialized)
> +               return 0;
> +
> +       /* Disable all interrupts */
> +       writel(0xFFFFFFFF, &regs->idr);
> +
> +       /* Disable the receiver & transmitter */
> +       writel(0, &regs->nwctrl);
> +       writel(0, &regs->txsr);
> +       writel(0, &regs->rxsr);
> +       writel(0, &regs->phymntnc);
> +
> +       /* Clear the Hash registers for the mac address pointed by AddressPtr */
> +       writel(0x0, &regs->hashl);
> +       /* Write bits [63:32] in TOP */
> +       writel(0x0, &regs->hashh);
> +
> +       for (i = 0; i < 4; i++)
> +               setmacaddress(dev, emacpss_zero_mac, i);
> +
> +       /* Clear all counters */
> +       for (i = 0; i <= (sizeof(struct gem_regs) -
> +                       offsetof(struct gem_regs, stat)) / 4; i++)
> +               readl(&regs->stat[i]);
> +
> +       /* Setup RxBD space */
> +       memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd));
> +       /* Create the RxBD ring */
> +       memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers));
> +
> +       for (i = 0; i < RX_BUF; i++) {
> +               priv->rx_bd[i].status = 0xF0000000;
> +               priv->rx_bd[i].addr = (u32)((char *) &(priv->rxbuffers) +
> +                                                       (i * PKTSIZE_ALIGN));
> +       }
> +       /* WRAP bit to last BD */
> +       priv->rx_bd[--i].addr |= XEMACPSS_RXBUF_WRAP_MASK;
> +       /* Write RxBDs to IP */
> +       writel((u32) &(priv->rx_bd), &regs->rxqbase);
> +
> +
> +       /* MAC Setup */
> +       /*
> +        *  Following is the setup for Network Configuration register.
> +        *  Bit 0:  Set for 100 Mbps operation.
> +        *  Bit 1:  Set for Full Duplex mode.
> +        *  Bit 4:  Set to allow Copy all frames.
> +        *  Bit 17: Set for FCS removal.
> +        *  Bits 20-18: Set with value binary 010 to divide pclk by 32
> +        *              (pclk up to 80 MHz)
> +        */
> +       writel(0x000A0013, &regs->nwcfg);
> +
> +       /*
> +        * Following is the setup for DMA Configuration register.
> +        * Bits 4-0: To set AHB fixed burst length for DMA data operations ->
> +        *  Set with binary 00100 to use INCR4 AHB bursts.
> +        * Bits 9-8: Receiver packet buffer memory size ->
> +        *  Set with binary 11 to Use full configured addressable space (8 Kb)
> +        * Bit 10  : Transmitter packet buffer memory size ->
> +        *  Set with binary 1 to Use full configured addressable space (4 Kb)
> +        * Bits 23-16 : DMA receive buffer size in AHB system memory ->
> +        *  Set with binary 00011000 to use 1536 byte(1*max length frame/buffer)
> +        */
> +       writel(0x00180704, &regs->dmacr);
> +
> +       /*
> +        * Following is the setup for Network Control register.
> +        * Bit 2:  Set to enable Receive operation.
> +        * Bit 3:  Set to enable Transmitt operation.
> +        * Bit 4:  Set to enable MDIO operation.
> +        */
> +       tmp = readl(&regs->nwctrl);
> +       /* MDIO, Rx and Tx enable */
> +       tmp |= XEMACPSS_NWCTRL_MDEN_MASK | XEMACPSS_NWCTRL_RXEN_MASK |
> +           XEMACPSS_NWCTRL_TXEN_MASK;
> +       writel(tmp, &regs->nwctrl);
> +
> +       phy_detection(dev);
> +
> +       /* interface - look at tsec */
> +       phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0);
> +
> +       phydev->supported &= supported;
> +       phydev->advertising = phydev->supported;
> +       priv->phydev = phydev;
> +       phy_config(phydev);
> +       phy_startup(phydev);
> +
> +       priv->initialized = 1;
> +       return 0;

How do you set the clock rate for the GEM based on the phy's link
speed?  You specify that you support 10 Mb/s, 100 Mb/s, and 1000Mb/s.
They need the GEM running at 2.5 MHz, 25 MHz, and 125 MHz
respectively.

> +}
> +
> +static int gem_send(struct eth_device *dev, void *ptr, int len)
> +{
> +       int status;
> +       u32 val;
> +       struct gemac_priv *priv = dev->priv;
> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
> +
> +       if (!priv->initialized) {
> +               puts("Error GMAC not initialized");
> +               return -1;
> +       }
> +
> +       /* setup BD */
> +       writel((u32)&(priv->tx_bd), &regs->txqbase);
> +
> +       /* Setup Tx BD */
> +       memset((void *) &(priv->tx_bd), 0, sizeof(struct emac_bd));
> +
> +       priv->tx_bd.addr = (u32)ptr;
> +       priv->tx_bd.status = len | XEMACPSS_TXBUF_LAST_MASK |
> +                                               XEMACPSS_TXBUF_WRAP_MASK;
> +
> +       /* Start transmit */
> +       val = readl(&regs->nwctrl) | XEMACPSS_NWCTRL_STARTTX_MASK;
> +       writel(val, &regs->nwctrl);
> +
> +       /* Read the stat register to know if the packet has been transmitted */
> +       status = readl(&regs->txsr);
> +       if (status & (XEMACPSS_TXSR_HRESPNOK_MASK | XEMACPSS_TXSR_URUN_MASK |
> +                                               XEMACPSS_TXSR_BUFEXH_MASK)) {
> +               printf("Something has gone wrong here!? Status is 0x%x.\n",
> +                      status);
> +       }
> +
> +       /* Clear Tx status register before leaving . */
> +       writel(status, &regs->txsr);
> +       return 0;
> +}
> +
> +/* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
> +static int gem_recv(struct eth_device *dev)
> +{
> +       int frame_len;
> +       struct gemac_priv *priv = dev->priv;
> +
> +       if (!(priv->rx_bd[priv->rxbd_current].addr & XEMACPSS_RXBUF_NEW_MASK))
> +               return 0;
> +
> +       if (!(priv->rx_bd[priv->rxbd_current].status &
> +                       (XEMACPSS_RXBUF_SOF_MASK | XEMACPSS_RXBUF_EOF_MASK))) {
> +               printf("GEM: SOF or EOF not set for last buffer received!\n");
> +               return 0;
> +       }
> +
> +       frame_len = priv->rx_bd[priv->rxbd_current].status &
> +                                                       XEMACPSS_RXBUF_LEN_MASK;
> +       if (frame_len) {
> +               NetReceive((u8 *) (priv->rx_bd[priv->rxbd_current].addr &
> +                                       XEMACPSS_RXBUF_ADD_MASK), frame_len);
> +
> +               if (priv->rx_bd[priv->rxbd_current].status &
> +                                                       XEMACPSS_RXBUF_SOF_MASK)
> +                       priv->rx_first_buf = priv->rxbd_current;
> +               else {
> +                       priv->rx_bd[priv->rxbd_current].addr &=
> +                                               ~XEMACPSS_RXBUF_NEW_MASK;
> +                       priv->rx_bd[priv->rxbd_current].status = 0xF0000000;
> +               }
> +
> +               if (priv->rx_bd[priv->rxbd_current].status &
> +                                               XEMACPSS_RXBUF_EOF_MASK) {
> +                       priv->rx_bd[priv->rx_first_buf].addr &=
> +                                               ~XEMACPSS_RXBUF_NEW_MASK;
> +                       priv->rx_bd[priv->rx_first_buf].status = 0xF0000000;
> +               }
> +
> +               if ((++priv->rxbd_current) >= RX_BUF)
> +                       priv->rxbd_current = 0;
> +
> +               return frame_len;
> +       }
> +
> +       return 0;
> +}
> +
> +static void gem_halt(struct eth_device *dev)
> +{
> +       return;
> +}
> +
> +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)

At the top of this file you error if CONFIG_PHYLIB is not defined.
That means that in no useful case will this not be defined, so you can
remove this #if entirely.

> +static int gem_miiphyread(const char *devname, uchar addr,
> +                                                       uchar reg, ushort *val)
> +{
> +       struct eth_device *dev = eth_get_dev();
> +       int ret;
> +
> +       ret = phyread(dev, addr, reg, val);
> +       debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *val);
> +       return ret;
> +}
> +
> +static int gem_miiphy_write(const char *devname, uchar addr,
> +                                                       uchar reg, ushort val)
> +{
> +       struct eth_device *dev = eth_get_dev();
> +
> +       debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val);
> +       return phywrite(dev, addr, reg, val);
> +}
> +#endif
> +
> +int xilinx_gem_initialize(bd_t *bis, int base_addr)
> +{
> +       struct eth_device *dev;
> +       struct gemac_priv *priv;
> +
> +       dev = calloc(1, sizeof(*dev));
> +       if (dev == NULL)
> +               return -1;
> +
> +       dev->priv = calloc(1, sizeof(struct gemac_priv));
> +       if (dev->priv == NULL) {
> +               free(dev);
> +               return -1;
> +       }
> +       priv = dev->priv;
> +
> +#ifdef CONFIG_PHY_ADDR
> +       priv->phyaddr = CONFIG_PHY_ADDR;
> +#else
> +       priv->phyaddr = -1;
> +#endif
> +
> +       sprintf(dev->name, "XGem.%x", base_addr);

Replace "XGem" with "Zynq GEM".  Also, the base address is not nice to
look at here.  You should know about the 2 base addresses in hardware
(0xE000B000 and 0xE000C000) and should pass in the instance instead of
the base address.  Then you can use the instance here and not force
each board to specify the base address.

> +
> +       dev->iobase = base_addr;
> +
> +       dev->init = gem_init;
> +       dev->halt = gem_halt;
> +       dev->send = gem_send;
> +       dev->recv = gem_recv;

You should have dev->write_hwaddr = setmacaddress; here.  Naturally
you should make the signature match and rename the function.

> +
> +       eth_register(dev);
> +
> +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)

At the top of this file you error if CONFIG_PHYLIB is not defined.
That means that in no useful case will this not be defined, so you can
remove this #if entirely.

> +       miiphy_register(dev->name, gem_miiphyread, gem_miiphy_write);
> +       priv->bus = miiphy_get_dev_by_name(dev->name);
> +#endif
> +
> +       return 1;
> +}
> diff --git a/include/netdev.h b/include/netdev.h
> index d1aaf0c..cd60ebb 100644
> --- a/include/netdev.h
> +++ b/include/netdev.h
> @@ -102,6 +102,7 @@ int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
>                                                         unsigned long dma_addr);
>  int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
>                                                         int txpp, int rxpp);
> +int xilinx_gem_initialize(bd_t *bis, int base_addr);
>  int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
>                                                 unsigned long ctrl_addr);
>
> --
> 1.7.0.4
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 11:42 ` [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform Michal Simek
@ 2012-08-14 15:36   ` Joe Hershberger
  2012-08-14 16:28     ` Michal Simek
  0 siblings, 1 reply; 22+ messages in thread
From: Joe Hershberger @ 2012-08-14 15:36 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
> Add timer driver.
>
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> ---
>  arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>  arch/arm/cpu/armv7/zynq/timer.c  |  151 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 199 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>  create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>
> diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/cpu/armv7/zynq/Makefile
> new file mode 100644
> index 0000000..814c1d4
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/zynq/Makefile
> @@ -0,0 +1,48 @@
> +#
> +# (C) Copyright 2000-2003
> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> +#
> +# (C) Copyright 2008
> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
> +
> +LIB    = $(obj)lib$(SOC).o
> +

You should include the lowlevel_init.o here instead of in the board.

> +COBJS  = timer.o
> +

Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
that I mean use COBJS-y instead of COBJS directly.  This is more
forward looking to allow for features to be disabled in the future.

> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
> +
> +all:   $(obj).depend $(LIB)
> +
> +$(LIB): $(OBJS)
> +       $(call cmd_link_o_target, $(OBJS))
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c
> new file mode 100644
> index 0000000..d79da97
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/zynq/timer.c
> @@ -0,0 +1,151 @@
> +/*
> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
> + *
> + * (C) Copyright 2008
> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
> + *
> + * (C) Copyright 2004
> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
> + *
> + * (C) Copyright 2002-2004
> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
> + *
> + * (C) Copyright 2003
> + * Texas Instruments <www.ti.com>
> + *
> + * (C) Copyright 2002
> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
> + * Marius Groeger <mgroeger@sysgo.de>
> + *
> + * (C) Copyright 2002
> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
> + * Alex Zuepke <azu@sysgo.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 <common.h>
> +#include <div64.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct scu_timer {
> +       u32 load; /* Timer Load Register */
> +       u32 counter; /* Timer Counter Register */
> +       u32 control; /* Timer Control Register */
> +};

You are using the timer in the ARM Cortex A9 core.  This is not
Zynq-specific in any way.  It should be made available in a different
place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
references.  Use ARM names instead.

> +
> +static struct scu_timer *timer_base = CONFIG_XPSS_SCUTIMER_BASEADDR;
> +
> +#define XSCUTIMER_CONTROL_PRESCALER_MASK       0x0000FF00 /* Prescaler */
> +#define XSCUTIMER_CONTROL_PRESCALER_SHIFT      8
> +#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK     0x00000002 /* Auto-reload */
> +#define XSCUTIMER_CONTROL_ENABLE_MASK          0x00000001 /* Timer enable */
> +
> +#define TIMER_LOAD_VAL 0xFFFFFFFF
> +#define TIMER_PRESCALE 255
> +#define TIMER_TICK_HZ  (CONFIG_CPU_FREQ_HZ / 2 / TIMER_PRESCALE)
> +
> +int timer_init(void)
> +{
> +       u32 val;
> +
> +       /* Load the timer counter register */
> +       writel(0xFFFFFFFF, &timer_base->counter);
> +
> +       /* Start the A9Timer device */
> +       val = readl(&timer_base->control);
> +       /* Enable Auto reload mode */
> +       val |= XSCUTIMER_CONTROL_AUTO_RELOAD_MASK;
> +       /* Clear prescaler control bits */
> +       val &= ~XSCUTIMER_CONTROL_PRESCALER_MASK;
> +       /* Set prescaler value */
> +       val |= (TIMER_PRESCALE << XSCUTIMER_CONTROL_PRESCALER_SHIFT);
> +       /* Enable the decrementer */
> +       val |= XSCUTIMER_CONTROL_ENABLE_MASK;
> +       writel(val, &timer_base->control);
> +
> +       /* Reset time */
> +       gd->lastinc = readl(&timer_base->counter) /
> +                                       (TIMER_TICK_HZ / CONFIG_SYS_HZ);
> +       gd->tbl = 0;
> +
> +       return 0;
> +}
> +
> +/*
> + * This function is derived from PowerPC code (read timebase as long long).
> + * On ARM it just returns the timer value.
> + */
> +ulong get_timer_masked(void)
> +{
> +       ulong now;
> +
> +       now = readl(&timer_base->counter) / (TIMER_TICK_HZ / CONFIG_SYS_HZ);
> +
> +       if (gd->lastinc >= now) {
> +               /* Normal mode */
> +               gd->tbl += gd->lastinc - now;
> +       } else {
> +               /* We have an overflow ... */
> +               gd->tbl += gd->lastinc + TIMER_LOAD_VAL - now;
> +       }
> +       gd->lastinc = now;
> +
> +       return gd->tbl;
> +}
> +
> +void __udelay(unsigned long usec)
> +{
> +       unsigned long long tmp;
> +       ulong tmo;
> +
> +       tmo = usec / (1000000 / CONFIG_SYS_HZ);
> +       tmp = get_ticks() + tmo; /* Get current timestamp */
> +
> +       while (get_ticks() < tmp) { /* Loop till event */
> +                /* NOP */;
> +       }
> +}
> +
> +/* Timer without interrupts */
> +ulong get_timer(ulong base)
> +{
> +       return get_timer_masked() - base;
> +}
> +
> +/*
> + * This function is derived from PowerPC code (read timebase as long long).
> + * On ARM it just returns the timer value.
> + */
> +unsigned long long get_ticks(void)
> +{
> +       return get_timer(0);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (timebase clock frequency).
> + * On ARM it returns the number of timer ticks per second.
> + */
> +ulong get_tbclk(void)
> +{
> +       return CONFIG_SYS_HZ;
> +}
> --
> 1.7.0.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 15:36   ` Joe Hershberger
@ 2012-08-14 16:28     ` Michal Simek
  2012-08-14 16:41       ` Joe Hershberger
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 16:28 UTC (permalink / raw)
  To: u-boot

On 08/14/2012 05:36 PM, Joe Hershberger wrote:
> Hi Michal,
>
> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>> Add timer driver.
>>
>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>> ---
>>   arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>>   arch/arm/cpu/armv7/zynq/timer.c  |  151 ++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 199 insertions(+), 0 deletions(-)
>>   create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>>   create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>>
>> diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/cpu/armv7/zynq/Makefile
>> new file mode 100644
>> index 0000000..814c1d4
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/zynq/Makefile
>> @@ -0,0 +1,48 @@
>> +#
>> +# (C) Copyright 2000-2003
>> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>> +#
>> +# (C) Copyright 2008
>> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
>> +
>> +LIB    = $(obj)lib$(SOC).o
>> +
>
> You should include the lowlevel_init.o here instead of in the board.

Probably make sense.


>
>> +COBJS  = timer.o
>> +
>
> Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
> that I mean use COBJS-y instead of COBJS directly.  This is more
> forward looking to allow for features to be disabled in the future.

no problem with that.

>
>> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
>> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
>> +
>> +all:   $(obj).depend $(LIB)
>> +
>> +$(LIB): $(OBJS)
>> +       $(call cmd_link_o_target, $(OBJS))
>> +
>> +#########################################################################
>> +
>> +# defines $(obj).depend target
>> +include $(SRCTREE)/rules.mk
>> +
>> +sinclude $(obj).depend
>> +
>> +#########################################################################
>> diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c
>> new file mode 100644
>> index 0000000..d79da97
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/zynq/timer.c
>> @@ -0,0 +1,151 @@
>> +/*
>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>> + *
>> + * (C) Copyright 2008
>> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
>> + *
>> + * (C) Copyright 2004
>> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
>> + *
>> + * (C) Copyright 2002-2004
>> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
>> + *
>> + * (C) Copyright 2003
>> + * Texas Instruments <www.ti.com>
>> + *
>> + * (C) Copyright 2002
>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>> + * Marius Groeger <mgroeger@sysgo.de>
>> + *
>> + * (C) Copyright 2002
>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>> + * Alex Zuepke <azu@sysgo.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 <common.h>
>> +#include <div64.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +struct scu_timer {
>> +       u32 load; /* Timer Load Register */
>> +       u32 counter; /* Timer Counter Register */
>> +       u32 control; /* Timer Control Register */
>> +};
>
> You are using the timer in the ARM Cortex A9 core.  This is not
> Zynq-specific in any way.  It should be made available in a different
> place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
> references.  Use ARM names instead.


Based on this I can't see the reason why XSCU should be stripped.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/BABDEAGJ.html

It is SCU private timer. Agree that we can remove X prefix.


I don't think that arch/arm/lib is the proper location for that.
I am not arm specialist to say that this timer is available in all arm families
to be in lib folder.

Thanks,
Michal

-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver
  2012-08-14 14:09   ` Joe Hershberger
@ 2012-08-14 16:38     ` Michal Simek
  2012-08-14 16:45       ` Joe Hershberger
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 16:38 UTC (permalink / raw)
  To: u-boot

On 08/14/2012 04:09 PM, Joe Hershberger wrote:
> Hi Michal,
>
> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>> The driver is used on Xilinx Zynq platform.
>>
>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>> ---
>>   drivers/serial/Makefile          |    1 +
>>   drivers/serial/serial_xpssuart.c |  218 ++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 219 insertions(+), 0 deletions(-)
>>   create mode 100644 drivers/serial/serial_xpssuart.c
>
> I think this would be clearer if it was named serial_zynq.c
>
>> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
>> index 65d0f23..81350d0 100644
>> --- a/drivers/serial/Makefile
>> +++ b/drivers/serial/Makefile
>> @@ -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_XPSS_SERIAL) += serial_xpssuart.o
>
> Replace every reference to "XPSS" with "ZYNQ".
>
>>   ifndef CONFIG_SPL_BUILD
>>   COBJS-$(CONFIG_USB_TTY) += usbtty.o
>> diff --git a/drivers/serial/serial_xpssuart.c b/drivers/serial/serial_xpssuart.c
>> new file mode 100644
>> index 0000000..3c6d838
>> --- /dev/null
>> +++ b/drivers/serial/serial_xpssuart.c
>> @@ -0,0 +1,218 @@
>> +/*
>> + * U-Boot driver for Xilinx Dragonfire UART.
>
> Use the released name "Zynq" not the old codename "Dragonfire".

ok.

>
>> + *
>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>> + * 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 <serial.h>
>> +
>> +#define XDFUART_SR_TXFULL      0x00000010 /* TX FIFO full */
>> +#define XDFUART_SR_RXEMPTY     0x00000002 /* RX FIFO empty */
>
> Replace all references to "XDFUART" with "ZYNQ_UART".

agree.

>
>> +
>> +#define XDFUART_CR_TX_EN       0x00000010 /* TX enabled */
>> +#define XDFUART_CR_RX_EN       0x00000004 /* RX enabled */
>> +#define XDFUART_CR_TXRST       0x00000002 /* TX logic reset */
>> +#define XDFUART_CR_RXRST       0x00000001 /* RX logic reset */
>> +
>> +#define XDFUART_MR_PARITY_NONE 0x00000020  /* No parity mode */
>> +
>> +/* Some clock/baud constants */
>> +#define XDFUART_BDIV   15 /* Default/reset BDIV value */
>> +#define XDFUART_BASECLK        3125000L /* master / (bdiv + 1) */
>> +
>> +struct xdfuart {
>> +       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 xdfuart *xdf_ports[4] = {
>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR0
>> +       [0] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR0,
>> +#endif
>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR1
>> +       [1] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR1,
>> +#endif
>
> There are 2 UARTS in hard silicon.

My fault.

   They should be supported with
> their known base addresses (0xE0000000 and 0xE0001000) here without
> pushing that into the config header.

I am not sure that hardcoding addresses here is the right thing to do.
The main reason is that none has tested option that hard IPs can be
also used from programmable logic. It means that this driver
could be possible to use from Microblaze with address translation.

No problem to setup these addresses in config file.


>
>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR2
>> +       [2] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR2,
>> +#endif
>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR3
>> +       [3] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR3,
>> +#endif
>> +};
>> +
>> +struct xdfuart_params {
>> +       u32 baudrate;
>> +       u32 clock;
>> +};
>> +
>> +static struct xdfuart_params xdf_ports_param[4] = {
>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE0) && defined(CONFIG_XPSS_SERIAL_CLOCK0)
>> +       [0].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE0,
>> +       [0].clock = CONFIG_XPSS_SERIAL_CLOCK0,
>> +#endif
>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE1) && defined(CONFIG_XPSS_SERIAL_CLOCK1)
>> +       [1].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE1,
>> +       [1].clock = CONFIG_XPSS_SERIAL_CLOCK1,
>> +#endif
>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE2) && defined(CONFIG_XPSS_SERIAL_CLOCK2)
>> +       [2].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE2,
>> +       [2].clock = CONFIG_XPSS_SERIAL_CLOCK2,
>> +#endif
>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE3) && defined(CONFIG_XPSS_SERIAL_CLOCK3)
>> +       [3].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE3,
>> +       [3].clock = CONFIG_XPSS_SERIAL_CLOCK3,
>> +#endif
>> +};
>> +
>> +/* Set up the baud rate in gd struct */
>> +static void xdfuart_serial_setbrg(const int port)
>> +{
>> +       /* Calculation results. */
>> +       unsigned int calc_bauderror, bdiv, bgen;
>> +       unsigned long calc_baud = 0;
>> +       unsigned long baud = xdf_ports_param[port].baudrate;
>> +       unsigned long clock = xdf_ports_param[port].clock;
>> +       struct xdfuart *regs = xdf_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 xdfuart_serial_init(const int port)
>> +{
>> +       struct xdfuart *regs = xdf_ports[port];
>> +
>> +       if (!regs)
>> +               return -1;
>> +
>> +       /* RX/TX enabled & reset */
>> +       writel(XDFUART_CR_TX_EN | XDFUART_CR_RX_EN | XDFUART_CR_TXRST | \
>> +                                       XDFUART_CR_RXRST, &regs->control);
>> +       writel(XDFUART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
>> +       xdfuart_serial_setbrg(port);
>> +
>> +       return 0;
>> +}
>> +
>> +static void xdfuart_serial_putc(const char c, const int port)
>> +{
>> +       struct xdfuart *regs = xdf_ports[port];
>> +
>> +       while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) != 0)
>> +               WATCHDOG_RESET();
>> +
>> +       if (c == '\n') {
>> +               writel('\r', &regs->tx_rx_fifo);
>> +               while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) != 0)
>> +                       WATCHDOG_RESET();
>> +       }
>> +       writel(c, &regs->tx_rx_fifo);
>> +}
>> +
>> +static void xdfuart_serial_puts(const char *s, const int port)
>> +{
>> +       while (*s)
>> +               xdfuart_serial_putc(*s++, port);
>> +}
>> +
>> +static int xdfuart_serial_tstc(const int port)
>> +{
>> +       struct xdfuart *regs = xdf_ports[port];
>> +
>> +       return (readl(&regs->channel_sts) & XDFUART_SR_RXEMPTY) == 0;
>> +}
>> +
>> +static int xdfuart_serial_getc(const int port)
>> +{
>> +       struct xdfuart *regs = xdf_ports[port];
>> +
>> +       while (!xdfuart_serial_tstc(port))
>> +               WATCHDOG_RESET();
>> +       return readl(&regs->tx_rx_fifo);
>> +}
>> +
>> +#if !defined(CONFIG_SERIAL_MULTI)
>> +int serial_init(void)
>> +{
>> +       return xdfuart_serial_init(0);
>
> If there is no SERIAL_MULTI support, there should be a config to
> select which one to use.

Not right now but I will add it in the next patch.
But yes, this ifdef shouldn't be here.

Thanks,
Michal


-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 16:28     ` Michal Simek
@ 2012-08-14 16:41       ` Joe Hershberger
  2012-08-14 17:11         ` Michal Simek
  0 siblings, 1 reply; 22+ messages in thread
From: Joe Hershberger @ 2012-08-14 16:41 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Aug 14, 2012 at 11:28 AM, Michal Simek <monstr@monstr.eu> wrote:
> On 08/14/2012 05:36 PM, Joe Hershberger wrote:
>>
>> Hi Michal,
>>
>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>
>>> Add timer driver.
>>>
>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>> ---
>>>   arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>>>   arch/arm/cpu/armv7/zynq/timer.c  |  151
>>> ++++++++++++++++++++++++++++++++++++++
>>>   2 files changed, 199 insertions(+), 0 deletions(-)
>>>   create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>>>   create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>>>
>>> diff --git a/arch/arm/cpu/armv7/zynq/Makefile
>>> b/arch/arm/cpu/armv7/zynq/Makefile
>>> new file mode 100644
>>> index 0000000..814c1d4
>>> --- /dev/null
>>> +++ b/arch/arm/cpu/armv7/zynq/Makefile
>>> @@ -0,0 +1,48 @@
>>> +#
>>> +# (C) Copyright 2000-2003
>>> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>>> +#
>>> +# (C) Copyright 2008
>>> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
>>> +
>>> +LIB    = $(obj)lib$(SOC).o
>>> +
>>
>>
>> You should include the lowlevel_init.o here instead of in the board.
>
>
> Probably make sense.
>
>
>
>>
>>> +COBJS  = timer.o
>>> +
>>
>>
>> Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
>> that I mean use COBJS-y instead of COBJS directly.  This is more
>> forward looking to allow for features to be disabled in the future.
>
>
> no problem with that.
>
>
>>
>>> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
>>> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
>>> +
>>> +all:   $(obj).depend $(LIB)
>>> +
>>> +$(LIB): $(OBJS)
>>> +       $(call cmd_link_o_target, $(OBJS))
>>> +
>>>
>>> +#########################################################################
>>> +
>>> +# defines $(obj).depend target
>>> +include $(SRCTREE)/rules.mk
>>> +
>>> +sinclude $(obj).depend
>>> +
>>>
>>> +#########################################################################
>>> diff --git a/arch/arm/cpu/armv7/zynq/timer.c
>>> b/arch/arm/cpu/armv7/zynq/timer.c
>>> new file mode 100644
>>> index 0000000..d79da97
>>> --- /dev/null
>>> +++ b/arch/arm/cpu/armv7/zynq/timer.c
>>> @@ -0,0 +1,151 @@
>>> +/*
>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>>> + *
>>> + * (C) Copyright 2008
>>> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
>>> + *
>>> + * (C) Copyright 2004
>>> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
>>> + *
>>> + * (C) Copyright 2002-2004
>>> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
>>> + *
>>> + * (C) Copyright 2003
>>> + * Texas Instruments <www.ti.com>
>>> + *
>>> + * (C) Copyright 2002
>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>> + * Marius Groeger <mgroeger@sysgo.de>
>>> + *
>>> + * (C) Copyright 2002
>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>> + * Alex Zuepke <azu@sysgo.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 <common.h>
>>> +#include <div64.h>
>>> +#include <asm/io.h>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +struct scu_timer {
>>> +       u32 load; /* Timer Load Register */
>>> +       u32 counter; /* Timer Counter Register */
>>> +       u32 control; /* Timer Control Register */
>>> +};
>>
>>
>> You are using the timer in the ARM Cortex A9 core.  This is not
>> Zynq-specific in any way.  It should be made available in a different
>> place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
>> references.  Use ARM names instead.
>
>
>
> Based on this I can't see the reason why XSCU should be stripped.
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/BABDEAGJ.html
>
> It is SCU private timer. Agree that we can remove X prefix.
>
>
> I don't think that arch/arm/lib is the proper location for that.
> I am not arm specialist to say that this timer is available in all arm
> families
> to be in lib folder.

I'm not sure that it is available on more than armv7 (like
arch/arm/lib/cache-pl310.c).  If it is only available in armv7, then
it can go in arch/arm/cpu/armv7/.

-Joe

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver
  2012-08-14 16:38     ` Michal Simek
@ 2012-08-14 16:45       ` Joe Hershberger
  2012-08-14 17:17         ` Michal Simek
  0 siblings, 1 reply; 22+ messages in thread
From: Joe Hershberger @ 2012-08-14 16:45 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Aug 14, 2012 at 11:38 AM, Michal Simek <monstr@monstr.eu> wrote:
> On 08/14/2012 04:09 PM, Joe Hershberger wrote:
>>
>> Hi Michal,
>>
>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>
>>> The driver is used on Xilinx Zynq platform.
>>>
>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>> ---
>>>   drivers/serial/Makefile          |    1 +
>>>   drivers/serial/serial_xpssuart.c |  218
>>> ++++++++++++++++++++++++++++++++++++++
>>>   2 files changed, 219 insertions(+), 0 deletions(-)
>>>   create mode 100644 drivers/serial/serial_xpssuart.c
>>
>>
>> I think this would be clearer if it was named serial_zynq.c
>>
>>> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
>>> index 65d0f23..81350d0 100644
>>> --- a/drivers/serial/Makefile
>>> +++ b/drivers/serial/Makefile
>>> @@ -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_XPSS_SERIAL) += serial_xpssuart.o
>>
>>
>> Replace every reference to "XPSS" with "ZYNQ".
>>
>>>   ifndef CONFIG_SPL_BUILD
>>>   COBJS-$(CONFIG_USB_TTY) += usbtty.o
>>> diff --git a/drivers/serial/serial_xpssuart.c
>>> b/drivers/serial/serial_xpssuart.c
>>> new file mode 100644
>>> index 0000000..3c6d838
>>> --- /dev/null
>>> +++ b/drivers/serial/serial_xpssuart.c
>>> @@ -0,0 +1,218 @@
>>> +/*
>>> + * U-Boot driver for Xilinx Dragonfire UART.
>>
>>
>> Use the released name "Zynq" not the old codename "Dragonfire".
>
>
> ok.
>
>
>>
>>> + *
>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>> + * 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 <serial.h>
>>> +
>>> +#define XDFUART_SR_TXFULL      0x00000010 /* TX FIFO full */
>>> +#define XDFUART_SR_RXEMPTY     0x00000002 /* RX FIFO empty */
>>
>>
>> Replace all references to "XDFUART" with "ZYNQ_UART".
>
>
> agree.
>
>
>>
>>> +
>>> +#define XDFUART_CR_TX_EN       0x00000010 /* TX enabled */
>>> +#define XDFUART_CR_RX_EN       0x00000004 /* RX enabled */
>>> +#define XDFUART_CR_TXRST       0x00000002 /* TX logic reset */
>>> +#define XDFUART_CR_RXRST       0x00000001 /* RX logic reset */
>>> +
>>> +#define XDFUART_MR_PARITY_NONE 0x00000020  /* No parity mode */
>>> +
>>> +/* Some clock/baud constants */
>>> +#define XDFUART_BDIV   15 /* Default/reset BDIV value */
>>> +#define XDFUART_BASECLK        3125000L /* master / (bdiv + 1) */
>>> +
>>> +struct xdfuart {
>>> +       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 xdfuart *xdf_ports[4] = {
>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR0
>>> +       [0] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR0,
>>> +#endif
>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR1
>>> +       [1] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR1,
>>> +#endif
>>
>>
>> There are 2 UARTS in hard silicon.
>
>
> My fault.
>
>
>   They should be supported with
>>
>> their known base addresses (0xE0000000 and 0xE0001000) here without
>> pushing that into the config header.
>
>
> I am not sure that hardcoding addresses here is the right thing to do.
> The main reason is that none has tested option that hard IPs can be
> also used from programmable logic. It means that this driver
> could be possible to use from Microblaze with address translation.
>
> No problem to setup these addresses in config file.

I accept that you can access these from microblaze, but I think that
will be the 1% use-case.  You can make the base address overridable,
but use the ARM core address space by default and have them here
instead of copied to every config.

>>
>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR2
>>> +       [2] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR2,
>>> +#endif
>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR3
>>> +       [3] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR3,
>>> +#endif
>>> +};
>>> +
>>> +struct xdfuart_params {
>>> +       u32 baudrate;
>>> +       u32 clock;
>>> +};
>>> +
>>> +static struct xdfuart_params xdf_ports_param[4] = {
>>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE0) &&
>>> defined(CONFIG_XPSS_SERIAL_CLOCK0)
>>> +       [0].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE0,
>>> +       [0].clock = CONFIG_XPSS_SERIAL_CLOCK0,
>>> +#endif
>>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE1) &&
>>> defined(CONFIG_XPSS_SERIAL_CLOCK1)
>>> +       [1].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE1,
>>> +       [1].clock = CONFIG_XPSS_SERIAL_CLOCK1,
>>> +#endif
>>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE2) &&
>>> defined(CONFIG_XPSS_SERIAL_CLOCK2)
>>> +       [2].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE2,
>>> +       [2].clock = CONFIG_XPSS_SERIAL_CLOCK2,
>>> +#endif
>>> +#if defined(CONFIG_XPSS_SERIAL_BAUDRATE3) &&
>>> defined(CONFIG_XPSS_SERIAL_CLOCK3)
>>> +       [3].baudrate = CONFIG_XPSS_SERIAL_BAUDRATE3,
>>> +       [3].clock = CONFIG_XPSS_SERIAL_CLOCK3,
>>> +#endif
>>> +};
>>> +
>>> +/* Set up the baud rate in gd struct */
>>> +static void xdfuart_serial_setbrg(const int port)
>>> +{
>>> +       /* Calculation results. */
>>> +       unsigned int calc_bauderror, bdiv, bgen;
>>> +       unsigned long calc_baud = 0;
>>> +       unsigned long baud = xdf_ports_param[port].baudrate;
>>> +       unsigned long clock = xdf_ports_param[port].clock;
>>> +       struct xdfuart *regs = xdf_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 xdfuart_serial_init(const int port)
>>> +{
>>> +       struct xdfuart *regs = xdf_ports[port];
>>> +
>>> +       if (!regs)
>>> +               return -1;
>>> +
>>> +       /* RX/TX enabled & reset */
>>> +       writel(XDFUART_CR_TX_EN | XDFUART_CR_RX_EN | XDFUART_CR_TXRST | \
>>> +                                       XDFUART_CR_RXRST,
>>> &regs->control);
>>> +       writel(XDFUART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity
>>> */
>>> +       xdfuart_serial_setbrg(port);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static void xdfuart_serial_putc(const char c, const int port)
>>> +{
>>> +       struct xdfuart *regs = xdf_ports[port];
>>> +
>>> +       while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) != 0)
>>> +               WATCHDOG_RESET();
>>> +
>>> +       if (c == '\n') {
>>> +               writel('\r', &regs->tx_rx_fifo);
>>> +               while ((readl(&regs->channel_sts) & XDFUART_SR_TXFULL) !=
>>> 0)
>>> +                       WATCHDOG_RESET();
>>> +       }
>>> +       writel(c, &regs->tx_rx_fifo);
>>> +}
>>> +
>>> +static void xdfuart_serial_puts(const char *s, const int port)
>>> +{
>>> +       while (*s)
>>> +               xdfuart_serial_putc(*s++, port);
>>> +}
>>> +
>>> +static int xdfuart_serial_tstc(const int port)
>>> +{
>>> +       struct xdfuart *regs = xdf_ports[port];
>>> +
>>> +       return (readl(&regs->channel_sts) & XDFUART_SR_RXEMPTY) == 0;
>>> +}
>>> +
>>> +static int xdfuart_serial_getc(const int port)
>>> +{
>>> +       struct xdfuart *regs = xdf_ports[port];
>>> +
>>> +       while (!xdfuart_serial_tstc(port))
>>> +               WATCHDOG_RESET();
>>> +       return readl(&regs->tx_rx_fifo);
>>> +}
>>> +
>>> +#if !defined(CONFIG_SERIAL_MULTI)
>>> +int serial_init(void)
>>> +{
>>> +       return xdfuart_serial_init(0);
>>
>>
>> If there is no SERIAL_MULTI support, there should be a config to
>> select which one to use.
>
>
> Not right now but I will add it in the next patch.
> But yes, this ifdef shouldn't be here.
>
> Thanks,
> Michal
>
>
> --
> 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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 2/4] net: Add driver for Zynq Gem IP
  2012-08-14 14:59   ` Joe Hershberger
@ 2012-08-14 17:04     ` Michal Simek
  0 siblings, 0 replies; 22+ messages in thread
From: Michal Simek @ 2012-08-14 17:04 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 08/14/2012 04:59 PM, Joe Hershberger wrote:
> Hi Michal,
>
> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>> Device driver for Zynq Gem IP.
>>
>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>> CC: Joe Hershberger <joe.hershberger@gmail.com>
>> ---
>>   drivers/net/Makefile     |    1 +
>>   drivers/net/xilinx_gem.c |  514 ++++++++++++++++++++++++++++++++++++++++++++++
>>   include/netdev.h         |    1 +
>>   3 files changed, 516 insertions(+), 0 deletions(-)
>>   create mode 100644 drivers/net/xilinx_gem.c
>
> Call this zynq_gem.c  My understanding is this is only available in
> the hard silicon for Zynq.

That's correct understanding.

>
>>
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index 430f90c..e510ffa 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -77,6 +77,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
>>   COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
>>   COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
>>   COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
>> +COBJS-$(CONFIG_XILINX_GEM) += xilinx_gem.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
>>
>> diff --git a/drivers/net/xilinx_gem.c b/drivers/net/xilinx_gem.c
>> new file mode 100644
>> index 0000000..7c8c14d
>> --- /dev/null
>> +++ b/drivers/net/xilinx_gem.c
>> @@ -0,0 +1,514 @@
>> +/*
>> + * (C) Copyright 2011 Michal Simek
>> + *
>> + * Michal SIMEK <monstr@monstr.eu>
>> + *
>> + * Based on Xilinx gmac driver:
>> + * (C) Copyright 2011 Xilinx
>> + *
>> + * 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 <net.h>
>> +#include <config.h>
>> +#include <malloc.h>
>> +#include <asm/io.h>
>> +#include <phy.h>
>> +#include <miiphy.h>
>> +
>> +#if !defined(CONFIG_PHYLIB)
>> +# error XILINX_GEM_ETHERNET requires PHYLIB
>> +#endif
>> +
>> +/* Bit/mask specification */
>> +#define XEMACPSS_PHYMNTNC_OP_MASK      0x40020000 /* operation mask bits */
>> +#define XEMACPSS_PHYMNTNC_OP_R_MASK    0x20000000 /* read operation */
>> +#define XEMACPSS_PHYMNTNC_OP_W_MASK    0x10000000 /* write operation */
>> +#define XEMACPSS_PHYMNTNC_PHYAD_SHIFT_MASK     23 /* Shift bits for PHYAD */
>> +#define XEMACPSS_PHYMNTNC_PHREG_SHIFT_MASK     18 /* Shift bits for PHREG */
>
> Replace all "XEMACPSS" with "ZYNQ_GEM"

ok

>
>> +
>> +#define XEMACPSS_RXBUF_EOF_MASK                0x00008000 /* End of frame. */
>> +#define XEMACPSS_RXBUF_SOF_MASK                0x00004000 /* Start of frame. */
>> +#define XEMACPSS_RXBUF_LEN_MASK                0x00003FFF /* Mask for length field */
>> +
>> +#define XEMACPSS_RXBUF_WRAP_MASK       0x00000002 /* Wrap bit, last BD */
>> +#define XEMACPSS_RXBUF_NEW_MASK                0x00000001 /* Used bit.. */
>> +#define XEMACPSS_RXBUF_ADD_MASK                0xFFFFFFFC /* Mask for address */
>> +
>> +/* Wrap bit, last descriptor */
>> +#define XEMACPSS_TXBUF_WRAP_MASK       0x40000000
>> +#define XEMACPSS_TXBUF_LAST_MASK       0x00008000 /* Last buffer */
>> +
>> +#define XEMACPSS_TXSR_HRESPNOK_MASK    0x00000100 /* Transmit hresp not OK */
>> +#define XEMACPSS_TXSR_URUN_MASK                0x00000040 /* Transmit underrun */
>> +/* Transmit buffs exhausted mid frame */
>> +#define XEMACPSS_TXSR_BUFEXH_MASK      0x00000010
>> +
>> +#define XEMACPSS_NWCTRL_TXEN_MASK      0x00000008 /* Enable transmit */
>> +#define XEMACPSS_NWCTRL_RXEN_MASK      0x00000004 /* Enable receive */
>> +#define XEMACPSS_NWCTRL_MDEN_MASK      0x00000010 /* Enable MDIO port */
>> +#define XEMACPSS_NWCTRL_STARTTX_MASK   0x00000200 /* Start tx (tx_go) */
>> +
>> +#define XEMACPSS_NWSR_MDIOIDLE_MASK    0x00000004 /* PHY management idle */
>> +
>> +/* Use MII register 1 (MII status register) to detect PHY */
>> +#define PHY_DETECT_REG         1
>> +
>> +/* Mask used to verify certain PHY features (or register contents)
>> + * in the register above:
>> + *  0x1000: 10Mbps full duplex support
>> + *  0x0800: 10Mbps half duplex support
>> + *  0x0008: Auto-negotiation support
>> + */
>> +#define PHY_DETECT_MASK                0x1808
>> +
>> +/* Device registers */
>> +struct gem_regs {
>> +       u32 nwctrl; /* Network Control reg */
>> +       u32 nwcfg; /* Network Config reg */
>> +       u32 nwsr; /* Network Status reg */
>> +       u32 reserved1;
>> +       u32 dmacr; /* DMA Control reg */
>> +       u32 txsr; /* TX Status reg */
>> +       u32 rxqbase; /* RX Q Base address reg */
>> +       u32 txqbase; /* TX Q Base address reg */
>> +       u32 rxsr; /* RX Status reg */
>> +       u32 reserved2[2];
>> +       u32 idr; /* Interrupt Disable reg */
>> +       u32 reserved3;
>> +       u32 phymntnc; /* Phy Maintaince reg */
>> +       u32 reserved4[18];
>> +       u32 hashl; /* Hash Low address reg */
>> +       u32 hashh; /* Hash High address reg */
>> +#define LADDR_LOW      0
>> +#define LADDR_HIGH     1
>> +       u32 laddr[4][LADDR_HIGH + 1]; /* Specific1 addr low/high reg */
>> +       u32 match[4]; /* Type ID1 Match reg */
>> +       u32 reserved6[18];
>> +       u32 stat[44]; /* Octects transmitted Low reg - stat start */
>> +};
>> +
>> +/* BD descriptors */
>> +struct emac_bd {
>> +       u32 addr; /* Next descriptor pointer */
>> +       u32 status;
>> +};
>> +
>> +#define RX_BUF 3
>> +
>> +/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
>> +struct gemac_priv {
>> +       struct emac_bd tx_bd;
>> +       struct emac_bd rx_bd[RX_BUF];
>> +       u32 initialized;
>> +       char rxbuffers[RX_BUF * PKTSIZE_ALIGN];
>> +       u32 rxbd_current;
>> +       u32 rx_first_buf;
>> +       int phyaddr;
>> +       struct phy_device *phydev;
>> +       struct mii_dev *bus;
>> +};
>> +
>> +static inline int mdio_wait(struct eth_device *dev)
>> +{
>> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
>> +       u32 timeout = 200;
>> +
>> +       /* Wait till MDIO interface is ready to accept a new transaction. */
>> +       while (timeout && !(readl(&regs->nwsr) & XEMACPSS_NWSR_MDIOIDLE_MASK)) {
>> +               timeout--;
>> +               udelay(1);
>> +       }
>> +
>> +       if (!timeout) {
>> +               printf("%s: Timeout\n", __func__);
>> +               return 1;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum,
>> +                                                       u32 op, u16 *data)
>> +{
>> +       u32 mgtcr;
>> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
>> +
>> +       if (mdio_wait(dev))
>> +               return 1;
>> +
>> +       /* Construct mgtcr mask for the operation */
>> +       mgtcr = XEMACPSS_PHYMNTNC_OP_MASK | op |
>> +               (phy_addr << XEMACPSS_PHYMNTNC_PHYAD_SHIFT_MASK) |
>> +               (regnum << XEMACPSS_PHYMNTNC_PHREG_SHIFT_MASK) | *data;
>> +
>> +       /* Write mgtcr and wait for completion */
>> +       writel(mgtcr, &regs->phymntnc);
>> +
>> +       if (mdio_wait(dev))
>> +               return 1;
>> +
>> +       if (op == XEMACPSS_PHYMNTNC_OP_R_MASK)
>> +               *data = readl(&regs->phymntnc);
>> +
>> +       return 0;
>> +}
>> +
>> +static u32 phyread(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 *val)
>> +{
>> +       return phy_setup_op(dev, phy_addr, regnum,
>> +                               XEMACPSS_PHYMNTNC_OP_R_MASK, val);
>> +}
>> +
>> +static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data)
>> +{
>> +       return phy_setup_op(dev, phy_addr, regnum,
>> +                               XEMACPSS_PHYMNTNC_OP_W_MASK, &data);
>> +}
>> +
>> +static void phy_detection(struct eth_device *dev)
>> +{
>> +       int i, ret;
>> +       u16 phyreg;
>> +       struct gemac_priv *priv = dev->priv;
>> +
>> +       if (priv->phyaddr != -1) {
>> +               ret = phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg);
>> +               if (!ret && (phyreg != 0xFFFF) &&
>> +               ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
>> +                       /* Found a valid PHY address */
>> +                       debug("Default phy address %d is valid\n",
>> +                                                               priv->phyaddr);
>> +                       return;
>> +               } else {
>> +                       debug("PHY address is not setup correctly %d\n",
>> +                                                               priv->phyaddr);
>> +                       priv->phyaddr = -1;
>> +               }
>> +       }
>> +
>> +       debug("detecting phy address\n");
>> +       if (priv->phyaddr == -1) {
>> +               /* detect the PHY address */
>> +               for (i = 31; i >= 0; i--) {
>> +                       ret = phyread(dev, i, PHY_DETECT_REG, &phyreg);
>> +                       if (!ret && (phyreg != 0xFFFF) &&
>> +                       ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
>> +                               /* Found a valid PHY address */
>> +                               priv->phyaddr = i;
>> +                               debug("Found valid phy address, %d\n", i);
>> +                               return;
>> +                       }
>> +               }
>> +       }
>> +       printf("PHY is not detected\n");
>> +}
>
> Phy detection should be optional (behind a config token).  It also
> sounds like something that has nothing to do with this driver.  If you
> want to add it, it should probably be in phylib and work with any
> driver.

No problem to remove it. Will look at phylib if provides feature like this.
It means detect phy or check that the actual phy address is correct.



>
>> +
>> +/* Address bits[47:32] bit[31:0] are in BOTTOM */
>> +#define XEMACPSS_LADDR_MACH_MASK       0x0000FFFF
>> +
>> +static void setmacaddress(struct eth_device *dev, void *addressptr, u8 index)
>> +{
>> +       u32 macaddr;
>> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
>> +       u8 *aptr = (u8 *) addressptr;
>> +
>> +       /* Set the MAC bits [31:0] in BOT */
>> +       macaddr = aptr[0];
>> +       macaddr |= aptr[1] << 8;
>> +       macaddr |= aptr[2] << 16;
>> +       macaddr |= aptr[3] << 24;
>> +       writel(macaddr, &regs->laddr[index][LADDR_LOW]);
>> +
>> +       /* There are reserved bits in TOP so don't affect them */
>> +       macaddr = readl(&regs->laddr[index][LADDR_HIGH]);
>> +
>> +       macaddr &= ~XEMACPSS_LADDR_MACH_MASK;
>> +
>> +       /* Set MAC bits [47:32] in TOP */
>> +       macaddr |= aptr[4];
>> +       macaddr |= aptr[5] << 8;
>> +
>> +       writel(macaddr, &regs->laddr[index][LADDR_HIGH]);
>> +
>> +       /* Set the ID bits in MATCHx register - settypeidcheck */
>> +       writel(0, &regs->match[index]);
>> +}
>> +
>> +static int gem_init(struct eth_device *dev, bd_t * bis)
>> +{
>> +       int tmp;
>> +       int i;
>> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
>> +       char emacpss_zero_mac[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
>> +       struct gemac_priv *priv = dev->priv;
>> +       struct phy_device *phydev;
>> +       u32 supported = SUPPORTED_10baseT_Half |
>> +                       SUPPORTED_10baseT_Full |
>> +                       SUPPORTED_100baseT_Half |
>> +                       SUPPORTED_100baseT_Full |
>> +                       SUPPORTED_1000baseT_Half |
>> +                       SUPPORTED_1000baseT_Full;
>> +
>> +       if (priv->initialized)
>> +               return 0;
>> +
>> +       /* Disable all interrupts */
>> +       writel(0xFFFFFFFF, &regs->idr);
>> +
>> +       /* Disable the receiver & transmitter */
>> +       writel(0, &regs->nwctrl);
>> +       writel(0, &regs->txsr);
>> +       writel(0, &regs->rxsr);
>> +       writel(0, &regs->phymntnc);
>> +
>> +       /* Clear the Hash registers for the mac address pointed by AddressPtr */
>> +       writel(0x0, &regs->hashl);
>> +       /* Write bits [63:32] in TOP */
>> +       writel(0x0, &regs->hashh);
>> +
>> +       for (i = 0; i < 4; i++)
>> +               setmacaddress(dev, emacpss_zero_mac, i);
>> +
>> +       /* Clear all counters */
>> +       for (i = 0; i <= (sizeof(struct gem_regs) -
>> +                       offsetof(struct gem_regs, stat)) / 4; i++)
>> +               readl(&regs->stat[i]);
>> +
>> +       /* Setup RxBD space */
>> +       memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd));
>> +       /* Create the RxBD ring */
>> +       memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers));
>> +
>> +       for (i = 0; i < RX_BUF; i++) {
>> +               priv->rx_bd[i].status = 0xF0000000;
>> +               priv->rx_bd[i].addr = (u32)((char *) &(priv->rxbuffers) +
>> +                                                       (i * PKTSIZE_ALIGN));
>> +       }
>> +       /* WRAP bit to last BD */
>> +       priv->rx_bd[--i].addr |= XEMACPSS_RXBUF_WRAP_MASK;
>> +       /* Write RxBDs to IP */
>> +       writel((u32) &(priv->rx_bd), &regs->rxqbase);
>> +
>> +
>> +       /* MAC Setup */
>> +       /*
>> +        *  Following is the setup for Network Configuration register.
>> +        *  Bit 0:  Set for 100 Mbps operation.
>> +        *  Bit 1:  Set for Full Duplex mode.
>> +        *  Bit 4:  Set to allow Copy all frames.
>> +        *  Bit 17: Set for FCS removal.
>> +        *  Bits 20-18: Set with value binary 010 to divide pclk by 32
>> +        *              (pclk up to 80 MHz)
>> +        */
>> +       writel(0x000A0013, &regs->nwcfg);
>> +
>> +       /*
>> +        * Following is the setup for DMA Configuration register.
>> +        * Bits 4-0: To set AHB fixed burst length for DMA data operations ->
>> +        *  Set with binary 00100 to use INCR4 AHB bursts.
>> +        * Bits 9-8: Receiver packet buffer memory size ->
>> +        *  Set with binary 11 to Use full configured addressable space (8 Kb)
>> +        * Bit 10  : Transmitter packet buffer memory size ->
>> +        *  Set with binary 1 to Use full configured addressable space (4 Kb)
>> +        * Bits 23-16 : DMA receive buffer size in AHB system memory ->
>> +        *  Set with binary 00011000 to use 1536 byte(1*max length frame/buffer)
>> +        */
>> +       writel(0x00180704, &regs->dmacr);
>> +
>> +       /*
>> +        * Following is the setup for Network Control register.
>> +        * Bit 2:  Set to enable Receive operation.
>> +        * Bit 3:  Set to enable Transmitt operation.
>> +        * Bit 4:  Set to enable MDIO operation.
>> +        */
>> +       tmp = readl(&regs->nwctrl);
>> +       /* MDIO, Rx and Tx enable */
>> +       tmp |= XEMACPSS_NWCTRL_MDEN_MASK | XEMACPSS_NWCTRL_RXEN_MASK |
>> +           XEMACPSS_NWCTRL_TXEN_MASK;
>> +       writel(tmp, &regs->nwctrl);
>> +
>> +       phy_detection(dev);
>> +
>> +       /* interface - look at tsec */
>> +       phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0);
>> +
>> +       phydev->supported &= supported;
>> +       phydev->advertising = phydev->supported;
>> +       priv->phydev = phydev;
>> +       phy_config(phydev);
>> +       phy_startup(phydev);
>> +
>> +       priv->initialized = 1;
>> +       return 0;
>
> How do you set the clock rate for the GEM based on the phy's link
> speed?  You specify that you support 10 Mb/s, 100 Mb/s, and 1000Mb/s.
> They need the GEM running at 2.5 MHz, 25 MHz, and 125 MHz
> respectively.

I think you are talking about MDCCLKDIV value. Current setting is 010 which is
pclk up to 80MHz. My zc702 works only at 100MHz that's why I can't test 1000Mb/s.

If doesn't work at 1000Mb/s, we can setup different value.

On two boards which we have tested there were no problem with this driver.


>
>> +}
>> +
>> +static int gem_send(struct eth_device *dev, void *ptr, int len)
>> +{
>> +       int status;
>> +       u32 val;
>> +       struct gemac_priv *priv = dev->priv;
>> +       struct gem_regs *regs = (struct gem_regs *)dev->iobase;
>> +
>> +       if (!priv->initialized) {
>> +               puts("Error GMAC not initialized");
>> +               return -1;
>> +       }
>> +
>> +       /* setup BD */
>> +       writel((u32)&(priv->tx_bd), &regs->txqbase);
>> +
>> +       /* Setup Tx BD */
>> +       memset((void *) &(priv->tx_bd), 0, sizeof(struct emac_bd));
>> +
>> +       priv->tx_bd.addr = (u32)ptr;
>> +       priv->tx_bd.status = len | XEMACPSS_TXBUF_LAST_MASK |
>> +                                               XEMACPSS_TXBUF_WRAP_MASK;
>> +
>> +       /* Start transmit */
>> +       val = readl(&regs->nwctrl) | XEMACPSS_NWCTRL_STARTTX_MASK;
>> +       writel(val, &regs->nwctrl);
>> +
>> +       /* Read the stat register to know if the packet has been transmitted */
>> +       status = readl(&regs->txsr);
>> +       if (status & (XEMACPSS_TXSR_HRESPNOK_MASK | XEMACPSS_TXSR_URUN_MASK |
>> +                                               XEMACPSS_TXSR_BUFEXH_MASK)) {
>> +               printf("Something has gone wrong here!? Status is 0x%x.\n",
>> +                      status);
>> +       }
>> +
>> +       /* Clear Tx status register before leaving . */
>> +       writel(status, &regs->txsr);
>> +       return 0;
>> +}
>> +
>> +/* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
>> +static int gem_recv(struct eth_device *dev)
>> +{
>> +       int frame_len;
>> +       struct gemac_priv *priv = dev->priv;
>> +
>> +       if (!(priv->rx_bd[priv->rxbd_current].addr & XEMACPSS_RXBUF_NEW_MASK))
>> +               return 0;
>> +
>> +       if (!(priv->rx_bd[priv->rxbd_current].status &
>> +                       (XEMACPSS_RXBUF_SOF_MASK | XEMACPSS_RXBUF_EOF_MASK))) {
>> +               printf("GEM: SOF or EOF not set for last buffer received!\n");
>> +               return 0;
>> +       }
>> +
>> +       frame_len = priv->rx_bd[priv->rxbd_current].status &
>> +                                                       XEMACPSS_RXBUF_LEN_MASK;
>> +       if (frame_len) {
>> +               NetReceive((u8 *) (priv->rx_bd[priv->rxbd_current].addr &
>> +                                       XEMACPSS_RXBUF_ADD_MASK), frame_len);
>> +
>> +               if (priv->rx_bd[priv->rxbd_current].status &
>> +                                                       XEMACPSS_RXBUF_SOF_MASK)
>> +                       priv->rx_first_buf = priv->rxbd_current;
>> +               else {
>> +                       priv->rx_bd[priv->rxbd_current].addr &=
>> +                                               ~XEMACPSS_RXBUF_NEW_MASK;
>> +                       priv->rx_bd[priv->rxbd_current].status = 0xF0000000;
>> +               }
>> +
>> +               if (priv->rx_bd[priv->rxbd_current].status &
>> +                                               XEMACPSS_RXBUF_EOF_MASK) {
>> +                       priv->rx_bd[priv->rx_first_buf].addr &=
>> +                                               ~XEMACPSS_RXBUF_NEW_MASK;
>> +                       priv->rx_bd[priv->rx_first_buf].status = 0xF0000000;
>> +               }
>> +
>> +               if ((++priv->rxbd_current) >= RX_BUF)
>> +                       priv->rxbd_current = 0;
>> +
>> +               return frame_len;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void gem_halt(struct eth_device *dev)
>> +{
>> +       return;
>> +}
>> +
>> +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
>
> At the top of this file you error if CONFIG_PHYLIB is not defined.
> That means that in no useful case will this not be defined, so you can
> remove this #if entirely.

ok. I have one more patch which covers cases where PHYLIB is not enabled
but yes it can be removed from this driver.

>
>> +static int gem_miiphyread(const char *devname, uchar addr,
>> +                                                       uchar reg, ushort *val)
>> +{
>> +       struct eth_device *dev = eth_get_dev();
>> +       int ret;
>> +
>> +       ret = phyread(dev, addr, reg, val);
>> +       debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *val);
>> +       return ret;
>> +}
>> +
>> +static int gem_miiphy_write(const char *devname, uchar addr,
>> +                                                       uchar reg, ushort val)
>> +{
>> +       struct eth_device *dev = eth_get_dev();
>> +
>> +       debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val);
>> +       return phywrite(dev, addr, reg, val);
>> +}
>> +#endif
>> +
>> +int xilinx_gem_initialize(bd_t *bis, int base_addr)
>> +{
>> +       struct eth_device *dev;
>> +       struct gemac_priv *priv;
>> +
>> +       dev = calloc(1, sizeof(*dev));
>> +       if (dev == NULL)
>> +               return -1;
>> +
>> +       dev->priv = calloc(1, sizeof(struct gemac_priv));
>> +       if (dev->priv == NULL) {
>> +               free(dev);
>> +               return -1;
>> +       }
>> +       priv = dev->priv;
>> +
>> +#ifdef CONFIG_PHY_ADDR
>> +       priv->phyaddr = CONFIG_PHY_ADDR;
>> +#else
>> +       priv->phyaddr = -1;
>> +#endif
>> +
>> +       sprintf(dev->name, "XGem.%x", base_addr);
>
> Replace "XGem" with "Zynq GEM".  Also, the base address is not nice to
> look at here.  You should know about the 2 base addresses in hardware
> (0xE000B000 and 0xE000C000) and should pass in the instance instead of
> the base address.  Then you can use the instance here and not force
> each board to specify the base address.

This is the same case as was for serial driver. If we connect Microblaze to it
then Microblaze could use it and addresses can changed. That's why
using name.<addr> is 100% description which IP u-boot uses.

About the name - there is 16 chars for it where 9 chars is used for baseaddr + dot
and the rest can be used for driver identification.

I don't care if is XGem or Zynq, etc.

>
>> +
>> +       dev->iobase = base_addr;
>> +
>> +       dev->init = gem_init;
>> +       dev->halt = gem_halt;
>> +       dev->send = gem_send;
>> +       dev->recv = gem_recv;
>
> You should have dev->write_hwaddr = setmacaddress; here.  Naturally
> you should make the signature match and rename the function.

will look.

>
>> +
>> +       eth_register(dev);
>> +
>> +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
>
> At the top of this file you error if CONFIG_PHYLIB is not defined.
> That means that in no useful case will this not be defined, so you can
> remove this #if entirely.

The same reason as above.

Thanks,
Michal



-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 16:41       ` Joe Hershberger
@ 2012-08-14 17:11         ` Michal Simek
  2012-08-14 17:15           ` Joe Hershberger
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 17:11 UTC (permalink / raw)
  To: u-boot

On 08/14/2012 06:41 PM, Joe Hershberger wrote:
> Hi Michal,
>
> On Tue, Aug 14, 2012 at 11:28 AM, Michal Simek <monstr@monstr.eu> wrote:
>> On 08/14/2012 05:36 PM, Joe Hershberger wrote:
>>>
>>> Hi Michal,
>>>
>>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>
>>>> Add timer driver.
>>>>
>>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>>> ---
>>>>    arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>>>>    arch/arm/cpu/armv7/zynq/timer.c  |  151
>>>> ++++++++++++++++++++++++++++++++++++++
>>>>    2 files changed, 199 insertions(+), 0 deletions(-)
>>>>    create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>>>>    create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>>>>
>>>> diff --git a/arch/arm/cpu/armv7/zynq/Makefile
>>>> b/arch/arm/cpu/armv7/zynq/Makefile
>>>> new file mode 100644
>>>> index 0000000..814c1d4
>>>> --- /dev/null
>>>> +++ b/arch/arm/cpu/armv7/zynq/Makefile
>>>> @@ -0,0 +1,48 @@
>>>> +#
>>>> +# (C) Copyright 2000-2003
>>>> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>>>> +#
>>>> +# (C) Copyright 2008
>>>> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
>>>> +
>>>> +LIB    = $(obj)lib$(SOC).o
>>>> +
>>>
>>>
>>> You should include the lowlevel_init.o here instead of in the board.
>>
>>
>> Probably make sense.
>>
>>
>>
>>>
>>>> +COBJS  = timer.o
>>>> +
>>>
>>>
>>> Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
>>> that I mean use COBJS-y instead of COBJS directly.  This is more
>>> forward looking to allow for features to be disabled in the future.
>>
>>
>> no problem with that.
>>
>>
>>>
>>>> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
>>>> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
>>>> +
>>>> +all:   $(obj).depend $(LIB)
>>>> +
>>>> +$(LIB): $(OBJS)
>>>> +       $(call cmd_link_o_target, $(OBJS))
>>>> +
>>>>
>>>> +#########################################################################
>>>> +
>>>> +# defines $(obj).depend target
>>>> +include $(SRCTREE)/rules.mk
>>>> +
>>>> +sinclude $(obj).depend
>>>> +
>>>>
>>>> +#########################################################################
>>>> diff --git a/arch/arm/cpu/armv7/zynq/timer.c
>>>> b/arch/arm/cpu/armv7/zynq/timer.c
>>>> new file mode 100644
>>>> index 0000000..d79da97
>>>> --- /dev/null
>>>> +++ b/arch/arm/cpu/armv7/zynq/timer.c
>>>> @@ -0,0 +1,151 @@
>>>> +/*
>>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>>>> + *
>>>> + * (C) Copyright 2008
>>>> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
>>>> + *
>>>> + * (C) Copyright 2004
>>>> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
>>>> + *
>>>> + * (C) Copyright 2002-2004
>>>> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
>>>> + *
>>>> + * (C) Copyright 2003
>>>> + * Texas Instruments <www.ti.com>
>>>> + *
>>>> + * (C) Copyright 2002
>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>> + * Marius Groeger <mgroeger@sysgo.de>
>>>> + *
>>>> + * (C) Copyright 2002
>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>> + * Alex Zuepke <azu@sysgo.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 <common.h>
>>>> +#include <div64.h>
>>>> +#include <asm/io.h>
>>>> +
>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>> +
>>>> +struct scu_timer {
>>>> +       u32 load; /* Timer Load Register */
>>>> +       u32 counter; /* Timer Counter Register */
>>>> +       u32 control; /* Timer Control Register */
>>>> +};
>>>
>>>
>>> You are using the timer in the ARM Cortex A9 core.  This is not
>>> Zynq-specific in any way.  It should be made available in a different
>>> place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
>>> references.  Use ARM names instead.
>>
>>
>>
>> Based on this I can't see the reason why XSCU should be stripped.
>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/BABDEAGJ.html
>>
>> It is SCU private timer. Agree that we can remove X prefix.
>>
>>
>> I don't think that arch/arm/lib is the proper location for that.
>> I am not arm specialist to say that this timer is available in all arm
>> families
>> to be in lib folder.
>
> I'm not sure that it is available on more than armv7 (like
> arch/arm/lib/cache-pl310.c).  If it is only available in armv7, then
> it can go in arch/arm/cpu/armv7/.

For me was just safer to use it in zynq folder because I am not familiar with others ARMs.
+ I see that other armv7 cpus uses own timer drivers.

Any input from arm custodian will be helpful.

Thanks,
Michal
-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 17:11         ` Michal Simek
@ 2012-08-14 17:15           ` Joe Hershberger
  2012-08-14 17:39             ` Michal Simek
  0 siblings, 1 reply; 22+ messages in thread
From: Joe Hershberger @ 2012-08-14 17:15 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Aug 14, 2012 at 12:11 PM, Michal Simek <monstr@monstr.eu> wrote:
> On 08/14/2012 06:41 PM, Joe Hershberger wrote:
>>
>> Hi Michal,
>>
>> On Tue, Aug 14, 2012 at 11:28 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>
>>> On 08/14/2012 05:36 PM, Joe Hershberger wrote:
>>>>
>>>>
>>>> Hi Michal,
>>>>
>>>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>>
>>>>>
>>>>> Add timer driver.
>>>>>
>>>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>>>> ---
>>>>>    arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>>>>>    arch/arm/cpu/armv7/zynq/timer.c  |  151
>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>    2 files changed, 199 insertions(+), 0 deletions(-)
>>>>>    create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>>>>>    create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>>>>>
>>>>> diff --git a/arch/arm/cpu/armv7/zynq/Makefile
>>>>> b/arch/arm/cpu/armv7/zynq/Makefile
>>>>> new file mode 100644
>>>>> index 0000000..814c1d4
>>>>> --- /dev/null
>>>>> +++ b/arch/arm/cpu/armv7/zynq/Makefile
>>>>> @@ -0,0 +1,48 @@
>>>>> +#
>>>>> +# (C) Copyright 2000-2003
>>>>> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>>>>> +#
>>>>> +# (C) Copyright 2008
>>>>> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
>>>>> +
>>>>> +LIB    = $(obj)lib$(SOC).o
>>>>> +
>>>>
>>>>
>>>>
>>>> You should include the lowlevel_init.o here instead of in the board.
>>>
>>>
>>>
>>> Probably make sense.
>>>
>>>
>>>
>>>>
>>>>> +COBJS  = timer.o
>>>>> +
>>>>
>>>>
>>>>
>>>> Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
>>>> that I mean use COBJS-y instead of COBJS directly.  This is more
>>>> forward looking to allow for features to be disabled in the future.
>>>
>>>
>>>
>>> no problem with that.
>>>
>>>
>>>>
>>>>> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
>>>>> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
>>>>> +
>>>>> +all:   $(obj).depend $(LIB)
>>>>> +
>>>>> +$(LIB): $(OBJS)
>>>>> +       $(call cmd_link_o_target, $(OBJS))
>>>>> +
>>>>>
>>>>>
>>>>> +#########################################################################
>>>>> +
>>>>> +# defines $(obj).depend target
>>>>> +include $(SRCTREE)/rules.mk
>>>>> +
>>>>> +sinclude $(obj).depend
>>>>> +
>>>>>
>>>>>
>>>>> +#########################################################################
>>>>> diff --git a/arch/arm/cpu/armv7/zynq/timer.c
>>>>> b/arch/arm/cpu/armv7/zynq/timer.c
>>>>> new file mode 100644
>>>>> index 0000000..d79da97
>>>>> --- /dev/null
>>>>> +++ b/arch/arm/cpu/armv7/zynq/timer.c
>>>>> @@ -0,0 +1,151 @@
>>>>> +/*
>>>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>>> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>>>>> + *
>>>>> + * (C) Copyright 2008
>>>>> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
>>>>> + *
>>>>> + * (C) Copyright 2004
>>>>> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
>>>>> + *
>>>>> + * (C) Copyright 2002-2004
>>>>> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
>>>>> + *
>>>>> + * (C) Copyright 2003
>>>>> + * Texas Instruments <www.ti.com>
>>>>> + *
>>>>> + * (C) Copyright 2002
>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>> + * Marius Groeger <mgroeger@sysgo.de>
>>>>> + *
>>>>> + * (C) Copyright 2002
>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>> + * Alex Zuepke <azu@sysgo.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 <common.h>
>>>>> +#include <div64.h>
>>>>> +#include <asm/io.h>
>>>>> +
>>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>>> +
>>>>> +struct scu_timer {
>>>>> +       u32 load; /* Timer Load Register */
>>>>> +       u32 counter; /* Timer Counter Register */
>>>>> +       u32 control; /* Timer Control Register */
>>>>> +};
>>>>
>>>>
>>>>
>>>> You are using the timer in the ARM Cortex A9 core.  This is not
>>>> Zynq-specific in any way.  It should be made available in a different
>>>> place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
>>>> references.  Use ARM names instead.
>>>
>>>
>>>
>>>
>>> Based on this I can't see the reason why XSCU should be stripped.
>>>
>>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/BABDEAGJ.html
>>>
>>> It is SCU private timer. Agree that we can remove X prefix.
>>>
>>>
>>> I don't think that arch/arm/lib is the proper location for that.
>>> I am not arm specialist to say that this timer is available in all arm
>>> families
>>> to be in lib folder.
>>
>>
>> I'm not sure that it is available on more than armv7 (like
>> arch/arm/lib/cache-pl310.c).  If it is only available in armv7, then
>> it can go in arch/arm/cpu/armv7/.
>
>
> For me was just safer to use it in zynq folder because I am not familiar
> with others ARMs.
> + I see that other armv7 cpus uses own timer drivers.

That is true, but they seem to be using other timer hardware instead
of the ARM core timers.  For instance, if you were using the Zynq's
Triple Timer Counter module instead, then it would make sense to have
this in the zynq directory.

>
> Any input from arm custodian will be helpful.

Albert?

>
>
> Thanks,
> Michal
> --
> 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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver
  2012-08-14 16:45       ` Joe Hershberger
@ 2012-08-14 17:17         ` Michal Simek
  2012-08-14 22:40           ` John Williams
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 17:17 UTC (permalink / raw)
  To: u-boot

On 08/14/2012 06:45 PM, Joe Hershberger wrote:
> Hi Michal,
>
> On Tue, Aug 14, 2012 at 11:38 AM, Michal Simek <monstr@monstr.eu> wrote:
>> On 08/14/2012 04:09 PM, Joe Hershberger wrote:
>>>
>>> Hi Michal,
>>>
>>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>
>>>> The driver is used on Xilinx Zynq platform.
>>>>
>>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>>> ---
>>>>    drivers/serial/Makefile          |    1 +
>>>>    drivers/serial/serial_xpssuart.c |  218
>>>> ++++++++++++++++++++++++++++++++++++++
>>>>    2 files changed, 219 insertions(+), 0 deletions(-)
>>>>    create mode 100644 drivers/serial/serial_xpssuart.c
>>>
>>>
>>> I think this would be clearer if it was named serial_zynq.c
>>>
>>>> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
>>>> index 65d0f23..81350d0 100644
>>>> --- a/drivers/serial/Makefile
>>>> +++ b/drivers/serial/Makefile
>>>> @@ -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_XPSS_SERIAL) += serial_xpssuart.o
>>>
>>>
>>> Replace every reference to "XPSS" with "ZYNQ".
>>>
>>>>    ifndef CONFIG_SPL_BUILD
>>>>    COBJS-$(CONFIG_USB_TTY) += usbtty.o
>>>> diff --git a/drivers/serial/serial_xpssuart.c
>>>> b/drivers/serial/serial_xpssuart.c
>>>> new file mode 100644
>>>> index 0000000..3c6d838
>>>> --- /dev/null
>>>> +++ b/drivers/serial/serial_xpssuart.c
>>>> @@ -0,0 +1,218 @@
>>>> +/*
>>>> + * U-Boot driver for Xilinx Dragonfire UART.
>>>
>>>
>>> Use the released name "Zynq" not the old codename "Dragonfire".
>>
>>
>> ok.
>>
>>
>>>
>>>> + *
>>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>> + * 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 <serial.h>
>>>> +
>>>> +#define XDFUART_SR_TXFULL      0x00000010 /* TX FIFO full */
>>>> +#define XDFUART_SR_RXEMPTY     0x00000002 /* RX FIFO empty */
>>>
>>>
>>> Replace all references to "XDFUART" with "ZYNQ_UART".
>>
>>
>> agree.
>>
>>
>>>
>>>> +
>>>> +#define XDFUART_CR_TX_EN       0x00000010 /* TX enabled */
>>>> +#define XDFUART_CR_RX_EN       0x00000004 /* RX enabled */
>>>> +#define XDFUART_CR_TXRST       0x00000002 /* TX logic reset */
>>>> +#define XDFUART_CR_RXRST       0x00000001 /* RX logic reset */
>>>> +
>>>> +#define XDFUART_MR_PARITY_NONE 0x00000020  /* No parity mode */
>>>> +
>>>> +/* Some clock/baud constants */
>>>> +#define XDFUART_BDIV   15 /* Default/reset BDIV value */
>>>> +#define XDFUART_BASECLK        3125000L /* master / (bdiv + 1) */
>>>> +
>>>> +struct xdfuart {
>>>> +       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 xdfuart *xdf_ports[4] = {
>>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR0
>>>> +       [0] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR0,
>>>> +#endif
>>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR1
>>>> +       [1] = (struct xdfuart *)CONFIG_XPSS_SERIAL_BASEADDR1,
>>>> +#endif
>>>
>>>
>>> There are 2 UARTS in hard silicon.
>>
>>
>> My fault.
>>
>>
>>    They should be supported with
>>>
>>> their known base addresses (0xE0000000 and 0xE0001000) here without
>>> pushing that into the config header.
>>
>>
>> I am not sure that hardcoding addresses here is the right thing to do.
>> The main reason is that none has tested option that hard IPs can be
>> also used from programmable logic. It means that this driver
>> could be possible to use from Microblaze with address translation.
>>
>> No problem to setup these addresses in config file.
>
> I accept that you can access these from microblaze, but I think that
> will be the 1% use-case.  You can make the base address overridable,
> but use the ARM core address space by default and have them here
> instead of copied to every config.

None has shown any table with use cases that why you can't say it will be 1% use-cases.

+ I don't think that hardcode IP address in generic driver is right way to go.
For example we are using SERIAL0 as console and in EDK you can setup which
IP it is. It means that sometimes SERIAL0 is at 0xe0001000 and sometimes at 0xe0000000.
This setting is also done for Linux that on serial0 is also Linux console which
simplify configuration.

Thanks,
Michal


-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 17:15           ` Joe Hershberger
@ 2012-08-14 17:39             ` Michal Simek
  2012-08-14 18:19               ` Joe Hershberger
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 17:39 UTC (permalink / raw)
  To: u-boot

On 08/14/2012 07:15 PM, Joe Hershberger wrote:
> Hi Michal,
>
> On Tue, Aug 14, 2012 at 12:11 PM, Michal Simek <monstr@monstr.eu> wrote:
>> On 08/14/2012 06:41 PM, Joe Hershberger wrote:
>>>
>>> Hi Michal,
>>>
>>> On Tue, Aug 14, 2012 at 11:28 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>
>>>> On 08/14/2012 05:36 PM, Joe Hershberger wrote:
>>>>>
>>>>>
>>>>> Hi Michal,
>>>>>
>>>>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>>>
>>>>>>
>>>>>> Add timer driver.
>>>>>>
>>>>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>>>>> ---
>>>>>>     arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>>>>>>     arch/arm/cpu/armv7/zynq/timer.c  |  151
>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>>     2 files changed, 199 insertions(+), 0 deletions(-)
>>>>>>     create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>>>>>>     create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>>>>>>
>>>>>> diff --git a/arch/arm/cpu/armv7/zynq/Makefile
>>>>>> b/arch/arm/cpu/armv7/zynq/Makefile
>>>>>> new file mode 100644
>>>>>> index 0000000..814c1d4
>>>>>> --- /dev/null
>>>>>> +++ b/arch/arm/cpu/armv7/zynq/Makefile
>>>>>> @@ -0,0 +1,48 @@
>>>>>> +#
>>>>>> +# (C) Copyright 2000-2003
>>>>>> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>>>>>> +#
>>>>>> +# (C) Copyright 2008
>>>>>> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
>>>>>> +
>>>>>> +LIB    = $(obj)lib$(SOC).o
>>>>>> +
>>>>>
>>>>>
>>>>>
>>>>> You should include the lowlevel_init.o here instead of in the board.
>>>>
>>>>
>>>>
>>>> Probably make sense.
>>>>
>>>>
>>>>
>>>>>
>>>>>> +COBJS  = timer.o
>>>>>> +
>>>>>
>>>>>
>>>>>
>>>>> Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
>>>>> that I mean use COBJS-y instead of COBJS directly.  This is more
>>>>> forward looking to allow for features to be disabled in the future.
>>>>
>>>>
>>>>
>>>> no problem with that.
>>>>
>>>>
>>>>>
>>>>>> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
>>>>>> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
>>>>>> +
>>>>>> +all:   $(obj).depend $(LIB)
>>>>>> +
>>>>>> +$(LIB): $(OBJS)
>>>>>> +       $(call cmd_link_o_target, $(OBJS))
>>>>>> +
>>>>>>
>>>>>>
>>>>>> +#########################################################################
>>>>>> +
>>>>>> +# defines $(obj).depend target
>>>>>> +include $(SRCTREE)/rules.mk
>>>>>> +
>>>>>> +sinclude $(obj).depend
>>>>>> +
>>>>>>
>>>>>>
>>>>>> +#########################################################################
>>>>>> diff --git a/arch/arm/cpu/armv7/zynq/timer.c
>>>>>> b/arch/arm/cpu/armv7/zynq/timer.c
>>>>>> new file mode 100644
>>>>>> index 0000000..d79da97
>>>>>> --- /dev/null
>>>>>> +++ b/arch/arm/cpu/armv7/zynq/timer.c
>>>>>> @@ -0,0 +1,151 @@
>>>>>> +/*
>>>>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>>>> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>>>>>> + *
>>>>>> + * (C) Copyright 2008
>>>>>> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
>>>>>> + *
>>>>>> + * (C) Copyright 2004
>>>>>> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
>>>>>> + *
>>>>>> + * (C) Copyright 2002-2004
>>>>>> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
>>>>>> + *
>>>>>> + * (C) Copyright 2003
>>>>>> + * Texas Instruments <www.ti.com>
>>>>>> + *
>>>>>> + * (C) Copyright 2002
>>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>>> + * Marius Groeger <mgroeger@sysgo.de>
>>>>>> + *
>>>>>> + * (C) Copyright 2002
>>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>>> + * Alex Zuepke <azu@sysgo.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 <common.h>
>>>>>> +#include <div64.h>
>>>>>> +#include <asm/io.h>
>>>>>> +
>>>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>>>> +
>>>>>> +struct scu_timer {
>>>>>> +       u32 load; /* Timer Load Register */
>>>>>> +       u32 counter; /* Timer Counter Register */
>>>>>> +       u32 control; /* Timer Control Register */
>>>>>> +};
>>>>>
>>>>>
>>>>>
>>>>> You are using the timer in the ARM Cortex A9 core.  This is not
>>>>> Zynq-specific in any way.  It should be made available in a different
>>>>> place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
>>>>> references.  Use ARM names instead.
>>>>
>>>>
>>>>
>>>>
>>>> Based on this I can't see the reason why XSCU should be stripped.
>>>>
>>>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/BABDEAGJ.html
>>>>
>>>> It is SCU private timer. Agree that we can remove X prefix.
>>>>
>>>>
>>>> I don't think that arch/arm/lib is the proper location for that.
>>>> I am not arm specialist to say that this timer is available in all arm
>>>> families
>>>> to be in lib folder.
>>>
>>>
>>> I'm not sure that it is available on more than armv7 (like
>>> arch/arm/lib/cache-pl310.c).  If it is only available in armv7, then
>>> it can go in arch/arm/cpu/armv7/.
>>
>>
>> For me was just safer to use it in zynq folder because I am not familiar
>> with others ARMs.
>> + I see that other armv7 cpus uses own timer drivers.
>
> That is true, but they seem to be using other timer hardware instead
> of the ARM core timers.  For instance, if you were using the Zynq's
> Triple Timer Counter module instead, then it would make sense to have
> this in the zynq directory.

Yes, that's partially clear case if Microblaze doesn't want to use it.

Zynq can also use axi_timer. We have this driver in Microblaze folder.
This is driver sharing across architectures. IRC there was any discussion about
moving drivers to generic location in past but this has never happen. (BTW: this
driver can be used by xilinx ppc405 and ppc440)


If Albert tends to move this driver to any general location I have no problem to do
in spite of there is probably not any other armv7 close which will use it.

 From my point of view if there is not other armv7 clone which will use it,
make sense to keep this in zynq folder. And move it to generic location
when any other armv7 wants to use.

Thanks,
Michal






-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 17:39             ` Michal Simek
@ 2012-08-14 18:19               ` Joe Hershberger
  2012-08-14 18:39                 ` Michal Simek
  0 siblings, 1 reply; 22+ messages in thread
From: Joe Hershberger @ 2012-08-14 18:19 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Aug 14, 2012 at 12:39 PM, Michal Simek <monstr@monstr.eu> wrote:
> On 08/14/2012 07:15 PM, Joe Hershberger wrote:
>>
>> Hi Michal,
>>
>> On Tue, Aug 14, 2012 at 12:11 PM, Michal Simek <monstr@monstr.eu> wrote:
>>>
>>> On 08/14/2012 06:41 PM, Joe Hershberger wrote:
>>>>
>>>>
>>>> Hi Michal,
>>>>
>>>> On Tue, Aug 14, 2012 at 11:28 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>>
>>>>>
>>>>> On 08/14/2012 05:36 PM, Joe Hershberger wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> Hi Michal,
>>>>>>
>>>>>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu>
>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Add timer driver.
>>>>>>>
>>>>>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>>>>>> ---
>>>>>>>     arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>>>>>>>     arch/arm/cpu/armv7/zynq/timer.c  |  151
>>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>>>     2 files changed, 199 insertions(+), 0 deletions(-)
>>>>>>>     create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>>>>>>>     create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>>>>>>>
>>>>>>> diff --git a/arch/arm/cpu/armv7/zynq/Makefile
>>>>>>> b/arch/arm/cpu/armv7/zynq/Makefile
>>>>>>> new file mode 100644
>>>>>>> index 0000000..814c1d4
>>>>>>> --- /dev/null
>>>>>>> +++ b/arch/arm/cpu/armv7/zynq/Makefile
>>>>>>> @@ -0,0 +1,48 @@
>>>>>>> +#
>>>>>>> +# (C) Copyright 2000-2003
>>>>>>> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>>>>>>> +#
>>>>>>> +# (C) Copyright 2008
>>>>>>> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
>>>>>>> +
>>>>>>> +LIB    = $(obj)lib$(SOC).o
>>>>>>> +
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> You should include the lowlevel_init.o here instead of in the board.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Probably make sense.
>>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>> +COBJS  = timer.o
>>>>>>> +
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
>>>>>> that I mean use COBJS-y instead of COBJS directly.  This is more
>>>>>> forward looking to allow for features to be disabled in the future.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> no problem with that.
>>>>>
>>>>>
>>>>>>
>>>>>>> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
>>>>>>> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
>>>>>>> +
>>>>>>> +all:   $(obj).depend $(LIB)
>>>>>>> +
>>>>>>> +$(LIB): $(OBJS)
>>>>>>> +       $(call cmd_link_o_target, $(OBJS))
>>>>>>> +
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> +#########################################################################
>>>>>>> +
>>>>>>> +# defines $(obj).depend target
>>>>>>> +include $(SRCTREE)/rules.mk
>>>>>>> +
>>>>>>> +sinclude $(obj).depend
>>>>>>> +
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> +#########################################################################
>>>>>>> diff --git a/arch/arm/cpu/armv7/zynq/timer.c
>>>>>>> b/arch/arm/cpu/armv7/zynq/timer.c
>>>>>>> new file mode 100644
>>>>>>> index 0000000..d79da97
>>>>>>> --- /dev/null
>>>>>>> +++ b/arch/arm/cpu/armv7/zynq/timer.c
>>>>>>> @@ -0,0 +1,151 @@
>>>>>>> +/*
>>>>>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>>>>> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>>>>>>> + *
>>>>>>> + * (C) Copyright 2008
>>>>>>> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
>>>>>>> + *
>>>>>>> + * (C) Copyright 2004
>>>>>>> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
>>>>>>> + *
>>>>>>> + * (C) Copyright 2002-2004
>>>>>>> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
>>>>>>> + *
>>>>>>> + * (C) Copyright 2003
>>>>>>> + * Texas Instruments <www.ti.com>
>>>>>>> + *
>>>>>>> + * (C) Copyright 2002
>>>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>>>> + * Marius Groeger <mgroeger@sysgo.de>
>>>>>>> + *
>>>>>>> + * (C) Copyright 2002
>>>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>>>> + * Alex Zuepke <azu@sysgo.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 <common.h>
>>>>>>> +#include <div64.h>
>>>>>>> +#include <asm/io.h>
>>>>>>> +
>>>>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>>>>> +
>>>>>>> +struct scu_timer {
>>>>>>> +       u32 load; /* Timer Load Register */
>>>>>>> +       u32 counter; /* Timer Counter Register */
>>>>>>> +       u32 control; /* Timer Control Register */
>>>>>>> +};
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> You are using the timer in the ARM Cortex A9 core.  This is not
>>>>>> Zynq-specific in any way.  It should be made available in a different
>>>>>> place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
>>>>>> references.  Use ARM names instead.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Based on this I can't see the reason why XSCU should be stripped.
>>>>>
>>>>>
>>>>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/BABDEAGJ.html
>>>>>
>>>>> It is SCU private timer. Agree that we can remove X prefix.
>>>>>
>>>>>
>>>>> I don't think that arch/arm/lib is the proper location for that.
>>>>> I am not arm specialist to say that this timer is available in all arm
>>>>> families
>>>>> to be in lib folder.
>>>>
>>>>
>>>>
>>>> I'm not sure that it is available on more than armv7 (like
>>>> arch/arm/lib/cache-pl310.c).  If it is only available in armv7, then
>>>> it can go in arch/arm/cpu/armv7/.
>>>
>>>
>>>
>>> For me was just safer to use it in zynq folder because I am not familiar
>>> with others ARMs.
>>> + I see that other armv7 cpus uses own timer drivers.
>>
>>
>> That is true, but they seem to be using other timer hardware instead
>> of the ARM core timers.  For instance, if you were using the Zynq's
>> Triple Timer Counter module instead, then it would make sense to have
>> this in the zynq directory.
>
>
> Yes, that's partially clear case if Microblaze doesn't want to use it.
>
> Zynq can also use axi_timer. We have this driver in Microblaze folder.

This would be bad because it would assume some timer in the fabric.

> This is driver sharing across architectures. IRC there was any discussion
> about
> moving drivers to generic location in past but this has never happen. (BTW:
> this
> driver can be used by xilinx ppc405 and ppc440)

I guess by "this driver" you mean axi_timer and not scu_timer.

>
>
> If Albert tends to move this driver to any general location I have no
> problem to do
> in spite of there is probably not any other armv7 close which will use it.
>
> From my point of view if there is not other armv7 clone which will use it,
> make sense to keep this in zynq folder. And move it to generic location
> when any other armv7 wants to use.

This is exactly the opposite of what we should be doing.  It is true
that this refactoring has not been very wide-spread yet, but certainly
for new things, the idea is to only put things into a less generic
place if there is no reasonable chance that it will be reused outside
of the more specific scope.  If it is available in other places in
hardware, make it generic.  It's not as good to expect that every new
board should have to search every other board dir in the hope that he
finds a driver that he can reuse.  He should be able to look in the
arch (or even drivers/ if applicable) and complete the search sooner.
Why force extra work to move it later.  To the best of your ability,
put it in the best place.  If this driver is available for all cortex
a9 based SoCs, then chances are every new one added from now on will
use this instead of writing a new one, even if there are other timers
available.

Thanks,
-Joe

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 18:19               ` Joe Hershberger
@ 2012-08-14 18:39                 ` Michal Simek
  2012-08-14 20:18                   ` Marek Vasut
  0 siblings, 1 reply; 22+ messages in thread
From: Michal Simek @ 2012-08-14 18:39 UTC (permalink / raw)
  To: u-boot

On 08/14/2012 08:19 PM, Joe Hershberger wrote:
> Hi Michal,
>
> On Tue, Aug 14, 2012 at 12:39 PM, Michal Simek <monstr@monstr.eu> wrote:
>> On 08/14/2012 07:15 PM, Joe Hershberger wrote:
>>>
>>> Hi Michal,
>>>
>>> On Tue, Aug 14, 2012 at 12:11 PM, Michal Simek <monstr@monstr.eu> wrote:
>>>>
>>>> On 08/14/2012 06:41 PM, Joe Hershberger wrote:
>>>>>
>>>>>
>>>>> Hi Michal,
>>>>>
>>>>> On Tue, Aug 14, 2012 at 11:28 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>>>
>>>>>>
>>>>>> On 08/14/2012 05:36 PM, Joe Hershberger wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Hi Michal,
>>>>>>>
>>>>>>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Add timer driver.
>>>>>>>>
>>>>>>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>>>>>>> ---
>>>>>>>>      arch/arm/cpu/armv7/zynq/Makefile |   48 ++++++++++++
>>>>>>>>      arch/arm/cpu/armv7/zynq/timer.c  |  151
>>>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>>>>      2 files changed, 199 insertions(+), 0 deletions(-)
>>>>>>>>      create mode 100644 arch/arm/cpu/armv7/zynq/Makefile
>>>>>>>>      create mode 100644 arch/arm/cpu/armv7/zynq/timer.c
>>>>>>>>
>>>>>>>> diff --git a/arch/arm/cpu/armv7/zynq/Makefile
>>>>>>>> b/arch/arm/cpu/armv7/zynq/Makefile
>>>>>>>> new file mode 100644
>>>>>>>> index 0000000..814c1d4
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/arch/arm/cpu/armv7/zynq/Makefile
>>>>>>>> @@ -0,0 +1,48 @@
>>>>>>>> +#
>>>>>>>> +# (C) Copyright 2000-2003
>>>>>>>> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>>>>>>>> +#
>>>>>>>> +# (C) Copyright 2008
>>>>>>>> +# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
>>>>>>>> +
>>>>>>>> +LIB    = $(obj)lib$(SOC).o
>>>>>>>> +
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> You should include the lowlevel_init.o here instead of in the board.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Probably make sense.
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>> +COBJS  = timer.o
>>>>>>>> +
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Preferably emulate the Makefile in arch/arm/cpu/armv7/tegra2/.  By
>>>>>>> that I mean use COBJS-y instead of COBJS directly.  This is more
>>>>>>> forward looking to allow for features to be disabled in the future.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> no problem with that.
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>> +SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
>>>>>>>> +OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
>>>>>>>> +
>>>>>>>> +all:   $(obj).depend $(LIB)
>>>>>>>> +
>>>>>>>> +$(LIB): $(OBJS)
>>>>>>>> +       $(call cmd_link_o_target, $(OBJS))
>>>>>>>> +
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> +#########################################################################
>>>>>>>> +
>>>>>>>> +# defines $(obj).depend target
>>>>>>>> +include $(SRCTREE)/rules.mk
>>>>>>>> +
>>>>>>>> +sinclude $(obj).depend
>>>>>>>> +
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> +#########################################################################
>>>>>>>> diff --git a/arch/arm/cpu/armv7/zynq/timer.c
>>>>>>>> b/arch/arm/cpu/armv7/zynq/timer.c
>>>>>>>> new file mode 100644
>>>>>>>> index 0000000..d79da97
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/arch/arm/cpu/armv7/zynq/timer.c
>>>>>>>> @@ -0,0 +1,151 @@
>>>>>>>> +/*
>>>>>>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>>>>>> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>>>>>>>> + *
>>>>>>>> + * (C) Copyright 2008
>>>>>>>> + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
>>>>>>>> + *
>>>>>>>> + * (C) Copyright 2004
>>>>>>>> + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
>>>>>>>> + *
>>>>>>>> + * (C) Copyright 2002-2004
>>>>>>>> + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
>>>>>>>> + *
>>>>>>>> + * (C) Copyright 2003
>>>>>>>> + * Texas Instruments <www.ti.com>
>>>>>>>> + *
>>>>>>>> + * (C) Copyright 2002
>>>>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>>>>> + * Marius Groeger <mgroeger@sysgo.de>
>>>>>>>> + *
>>>>>>>> + * (C) Copyright 2002
>>>>>>>> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>>>>>>>> + * Alex Zuepke <azu@sysgo.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 <common.h>
>>>>>>>> +#include <div64.h>
>>>>>>>> +#include <asm/io.h>
>>>>>>>> +
>>>>>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>>>>>> +
>>>>>>>> +struct scu_timer {
>>>>>>>> +       u32 load; /* Timer Load Register */
>>>>>>>> +       u32 counter; /* Timer Counter Register */
>>>>>>>> +       u32 control; /* Timer Control Register */
>>>>>>>> +};
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> You are using the timer in the ARM Cortex A9 core.  This is not
>>>>>>> Zynq-specific in any way.  It should be made available in a different
>>>>>>> place.  Probably in arch/arm/lib.  It should be stripped on any "XSCU"
>>>>>>> references.  Use ARM names instead.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Based on this I can't see the reason why XSCU should be stripped.
>>>>>>
>>>>>>
>>>>>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/BABDEAGJ.html
>>>>>>
>>>>>> It is SCU private timer. Agree that we can remove X prefix.
>>>>>>
>>>>>>
>>>>>> I don't think that arch/arm/lib is the proper location for that.
>>>>>> I am not arm specialist to say that this timer is available in all arm
>>>>>> families
>>>>>> to be in lib folder.
>>>>>
>>>>>
>>>>>
>>>>> I'm not sure that it is available on more than armv7 (like
>>>>> arch/arm/lib/cache-pl310.c).  If it is only available in armv7, then
>>>>> it can go in arch/arm/cpu/armv7/.
>>>>
>>>>
>>>>
>>>> For me was just safer to use it in zynq folder because I am not familiar
>>>> with others ARMs.
>>>> + I see that other armv7 cpus uses own timer drivers.
>>>
>>>
>>> That is true, but they seem to be using other timer hardware instead
>>> of the ARM core timers.  For instance, if you were using the Zynq's
>>> Triple Timer Counter module instead, then it would make sense to have
>>> this in the zynq directory.
>>
>>
>> Yes, that's partially clear case if Microblaze doesn't want to use it.
>>
>> Zynq can also use axi_timer. We have this driver in Microblaze folder.
>
> This would be bad because it would assume some timer in the fabric.
>
>> This is driver sharing across architectures. IRC there was any discussion
>> about
>> moving drivers to generic location in past but this has never happen. (BTW:
>> this
>> driver can be used by xilinx ppc405 and ppc440)
>
> I guess by "this driver" you mean axi_timer and not scu_timer.

yep

>
>>
>>
>> If Albert tends to move this driver to any general location I have no
>> problem to do
>> in spite of there is probably not any other armv7 close which will use it.
>>
>>  From my point of view if there is not other armv7 clone which will use it,
>> make sense to keep this in zynq folder. And move it to generic location
>> when any other armv7 wants to use.
>
> This is exactly the opposite of what we should be doing.  It is true
> that this refactoring has not been very wide-spread yet, but certainly
> for new things, the idea is to only put things into a less generic
> place if there is no reasonable chance that it will be reused outside
> of the more specific scope.  If it is available in other places in
> hardware, make it generic.  It's not as good to expect that every new
> board should have to search every other board dir in the hope that he
> finds a driver that he can reuse.  He should be able to look in the
> arch (or even drivers/ if applicable) and complete the search sooner.
> Why force extra work to move it later.  To the best of your ability,
> put it in the best place.  If this driver is available for all cortex
> a9 based SoCs, then chances are every new one added from now on will
> use this instead of writing a new one, even if there are other timers
> available.

I agree with that. Have no problem to move this driver to arch/arm/cpu/armv7/
folder or even to drivers/timer if is what we should do.
I am just not sure if this should be done before new DM model.

Marek: I believe you are going to change all timer drivers. Are you going to
move all of them to generic location?

Thanks,
Michal



-- 
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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform
  2012-08-14 18:39                 ` Michal Simek
@ 2012-08-14 20:18                   ` Marek Vasut
  0 siblings, 0 replies; 22+ messages in thread
From: Marek Vasut @ 2012-08-14 20:18 UTC (permalink / raw)
  To: u-boot

Dear Michal Simek,

> On 08/14/2012 08:19 PM, Joe Hershberger wrote:
> > Hi Michal,
[...]
CUT!

> Marek: I believe you are going to change all timer drivers. Are you going
> to move all of them to generic location?

I'm not moving timer drivers in the first wave, so hacking on them should be 
safe sail so far.

> Thanks,
> Michal

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver
  2012-08-14 17:17         ` Michal Simek
@ 2012-08-14 22:40           ` John Williams
  0 siblings, 0 replies; 22+ messages in thread
From: John Williams @ 2012-08-14 22:40 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 15, 2012 at 3:17 AM, Michal Simek <monstr@monstr.eu> wrote:

> On 08/14/2012 06:45 PM, Joe Hershberger wrote:
>
>> Hi Michal,
>>
>> On Tue, Aug 14, 2012 at 11:38 AM, Michal Simek <monstr@monstr.eu> wrote:
>>
>>> On 08/14/2012 04:09 PM, Joe Hershberger wrote:
>>>
>>>>
>>>> Hi Michal,
>>>>
>>>> On Tue, Aug 14, 2012 at 6:42 AM, Michal Simek <monstr@monstr.eu> wrote:
>>>>
>>>>>
>>>>> The driver is used on Xilinx Zynq platform.
>>>>>
>>>>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>>>>> ---
>>>>>    drivers/serial/Makefile          |    1 +
>>>>>    drivers/serial/serial_**xpssuart.c |  218
>>>>> ++++++++++++++++++++++++++++++**++++++++
>>>>>    2 files changed, 219 insertions(+), 0 deletions(-)
>>>>>    create mode 100644 drivers/serial/serial_**xpssuart.c
>>>>>
>>>>
>>>>
>>>> I think this would be clearer if it was named serial_zynq.c
>>>>
>>>>  diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
>>>>> index 65d0f23..81350d0 100644
>>>>> --- a/drivers/serial/Makefile
>>>>> +++ b/drivers/serial/Makefile
>>>>> @@ -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_XPSS_SERIAL) += serial_xpssuart.o
>>>>>
>>>>
>>>>
>>>> Replace every reference to "XPSS" with "ZYNQ".
>>>>
>>>>     ifndef CONFIG_SPL_BUILD
>>>>>    COBJS-$(CONFIG_USB_TTY) += usbtty.o
>>>>> diff --git a/drivers/serial/serial_**xpssuart.c
>>>>> b/drivers/serial/serial_**xpssuart.c
>>>>> new file mode 100644
>>>>> index 0000000..3c6d838
>>>>> --- /dev/null
>>>>> +++ b/drivers/serial/serial_**xpssuart.c
>>>>> @@ -0,0 +1,218 @@
>>>>> +/*
>>>>> + * U-Boot driver for Xilinx Dragonfire UART.
>>>>>
>>>>
>>>>
>>>> Use the released name "Zynq" not the old codename "Dragonfire".
>>>>
>>>
>>>
>>> ok.
>>>
>>>
>>>
>>>>  + *
>>>>> + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>>> + * 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 <serial.h>
>>>>> +
>>>>> +#define XDFUART_SR_TXFULL      0x00000010 /* TX FIFO full */
>>>>> +#define XDFUART_SR_RXEMPTY     0x00000002 /* RX FIFO empty */
>>>>>
>>>>
>>>>
>>>> Replace all references to "XDFUART" with "ZYNQ_UART".
>>>>
>>>
>>>
>>> agree.
>>>
>>>
>>>
>>>>  +
>>>>> +#define XDFUART_CR_TX_EN       0x00000010 /* TX enabled */
>>>>> +#define XDFUART_CR_RX_EN       0x00000004 /* RX enabled */
>>>>> +#define XDFUART_CR_TXRST       0x00000002 /* TX logic reset */
>>>>> +#define XDFUART_CR_RXRST       0x00000001 /* RX logic reset */
>>>>> +
>>>>> +#define XDFUART_MR_PARITY_NONE 0x00000020  /* No parity mode */
>>>>> +
>>>>> +/* Some clock/baud constants */
>>>>> +#define XDFUART_BDIV   15 /* Default/reset BDIV value */
>>>>> +#define XDFUART_BASECLK        3125000L /* master / (bdiv + 1) */
>>>>> +
>>>>> +struct xdfuart {
>>>>> +       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 xdfuart *xdf_ports[4] = {
>>>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR0
>>>>> +       [0] = (struct xdfuart *)CONFIG_XPSS_SERIAL_**BASEADDR0,
>>>>> +#endif
>>>>> +#ifdef CONFIG_XPSS_SERIAL_BASEADDR1
>>>>> +       [1] = (struct xdfuart *)CONFIG_XPSS_SERIAL_**BASEADDR1,
>>>>> +#endif
>>>>>
>>>>
>>>>
>>>> There are 2 UARTS in hard silicon.
>>>>
>>>
>>>
>>> My fault.
>>>
>>>
>>>    They should be supported with
>>>
>>>>
>>>> their known base addresses (0xE0000000 and 0xE0001000) here without
>>>> pushing that into the config header.
>>>>
>>>
>>>
>>> I am not sure that hardcoding addresses here is the right thing to do.
>>> The main reason is that none has tested option that hard IPs can be
>>> also used from programmable logic. It means that this driver
>>> could be possible to use from Microblaze with address translation.
>>>
>>> No problem to setup these addresses in config file.
>>>
>>
>> I accept that you can access these from microblaze, but I think that
>> will be the 1% use-case.  You can make the base address overridable,
>> but use the ARM core address space by default and have them here
>> instead of copied to every config.
>>
>
> None has shown any table with use cases that why you can't say it will be
> 1% use-cases.
>
> + I don't think that hardcode IP address in generic driver is right way to
> go.
> For example we are using SERIAL0 as console and in EDK you can setup which
> IP it is. It means that sometimes SERIAL0 is at 0xe0001000 and sometimes
> at 0xe0000000.
> This setting is also done for Linux that on serial0 is also Linux console
> which
> simplify configuration.


I agree - coding base addresses in drivers, rather than machines/platforms,
sounds like a bad idea.

There is a somewhat open question in both Linux and u-boot about what to do
if the MIOs enable PS7_UART1 but not PS7_UART0.  Should UART1 enumerate as
u-boot's first serial device?  In Linux as /dev/ttyS0?

Let's keep addresses and decisions like this in platform files, not device
drivers.

John
-- 
John Williams, PhD, B. Eng, B. IT
PetaLogix - Linux Solutions for a Reconfigurable World
w: www.petalogix.com  p: +61-7-30090663  f: +61-7-30090663

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2012-08-14 22:40 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-14 11:42 [U-Boot] Xilinx Zynq platform Michal Simek
2012-08-14 11:42 ` [U-Boot] [PATCH 1/4] serial: Add Dragonfire serial driver Michal Simek
2012-08-14 14:09   ` Joe Hershberger
2012-08-14 16:38     ` Michal Simek
2012-08-14 16:45       ` Joe Hershberger
2012-08-14 17:17         ` Michal Simek
2012-08-14 22:40           ` John Williams
2012-08-14 11:42 ` [U-Boot] [PATCH 2/4] net: Add driver for Zynq Gem IP Michal Simek
2012-08-14 14:59   ` Joe Hershberger
2012-08-14 17:04     ` Michal Simek
2012-08-14 11:42 ` [U-Boot] [PATCH 3/4] arm: Support new Xilinx Zynq platform Michal Simek
2012-08-14 15:36   ` Joe Hershberger
2012-08-14 16:28     ` Michal Simek
2012-08-14 16:41       ` Joe Hershberger
2012-08-14 17:11         ` Michal Simek
2012-08-14 17:15           ` Joe Hershberger
2012-08-14 17:39             ` Michal Simek
2012-08-14 18:19               ` Joe Hershberger
2012-08-14 18:39                 ` Michal Simek
2012-08-14 20:18                   ` Marek Vasut
2012-08-14 11:42 ` [U-Boot] [PATCH 4/4] xilinx: Add new Zynq board Michal Simek
2012-08-14 12:16   ` Michal Simek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox