public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
@ 2009-02-01 11:16 monstr at monstr.eu
  2009-02-17  9:35 ` Michal Simek
  2009-02-23  6:45 ` Ben Warren
  0 siblings, 2 replies; 9+ messages in thread
From: monstr at monstr.eu @ 2009-02-01 11:16 UTC (permalink / raw)
  To: u-boot

From: Michal Simek <monstr@monstr.eu>

---
v2: Coding style cleanup, use debug() instead of printf
in debug messages

v1: Initial version

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

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 631336a..1e80698 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -68,6 +68,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
 COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
 COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c
new file mode 100644
index 0000000..e17c97e
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac.c
@@ -0,0 +1,540 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * Author: Yoshio Kashiwagi kashiwagi at co-nss.co.jp
+ *
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * Copyright (C) 2008 - 2009 Michal Simek <monstr@monstr.eu>
+ * June 2008 Microblaze optimalization, FIFO mode support
+ *
+ * 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.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+#include <malloc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#ifdef XILINX_LLTEMAC_FIFO_BASEADDR
+# define FIFO_MODE	1
+#elif XILINX_LLTEMAC_SDMA_CTRL_BASEADDR
+# define SDMA_MODE	1
+#else
+# error Unsupported mode
+#endif
+
+#undef ETH_HALTING
+
+#ifdef SDMA_MODE
+/* XPS_LL_TEMAC SDMA registers definition */
+# define TX_NXTDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x00)
+# define TX_CURBUF_ADDR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x04)
+# define TX_CURBUF_LENGTH	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x08)
+# define TX_CURDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x0c)
+# define TX_TAILDESC_PTR	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x10)
+# define TX_CHNL_CTRL		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x14)
+# define TX_IRQ_REG		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x18)
+# define TX_CHNL_STS		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x1c)
+
+# define RX_NXTDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x20)
+# define RX_CURBUF_ADDR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x24)
+# define RX_CURBUF_LENGTH	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x28)
+# define RX_CURDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x2c)
+# define RX_TAILDESC_PTR	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x30)
+# define RX_CHNL_CTRL		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x34)
+# define RX_IRQ_REG		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x38)
+# define RX_CHNL_STS		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x3c)
+
+# define DMA_CONTROL_REG	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x40)
+#endif
+
+/* XPS_LL_TEMAC direct registers definition */
+#define TEMAC_RAF0		(XILINX_LLTEMAC_BASEADDR + 0x00)
+#define TEMAC_TPF0		(XILINX_LLTEMAC_BASEADDR + 0x04)
+#define TEMAC_IFGP0		(XILINX_LLTEMAC_BASEADDR + 0x08)
+#define TEMAC_IS0		(XILINX_LLTEMAC_BASEADDR + 0x0c)
+#define TEMAC_IP0		(XILINX_LLTEMAC_BASEADDR + 0x10)
+#define TEMAC_IE0		(XILINX_LLTEMAC_BASEADDR + 0x14)
+
+#define TEMAC_MSW0		(XILINX_LLTEMAC_BASEADDR + 0x20)
+#define TEMAC_LSW0		(XILINX_LLTEMAC_BASEADDR + 0x24)
+#define TEMAC_CTL0		(XILINX_LLTEMAC_BASEADDR + 0x28)
+#define TEMAC_RDY0		(XILINX_LLTEMAC_BASEADDR + 0x2c)
+
+#define XTE_RSE_MIIM_RR_MASK	0x0002
+#define XTE_RSE_MIIM_WR_MASK	0x0004
+#define XTE_RSE_CFG_RR_MASK	0x0020
+#define XTE_RSE_CFG_WR_MASK	0x0040
+
+/* XPS_LL_TEMAC indirect registers offset definition */
+
+#define RCW0	0x200
+#define RCW1	0x240
+#define TC	0x280
+#define FCC	0x2c0
+#define EMMC	0x300
+#define PHYC	0x320
+#define MC	0x340
+#define UAW0	0x380
+#define UAW1	0x384
+#define MAW0	0x388
+#define MAW1	0x38c
+#define AFM	0x390
+#define TIS	0x3a0
+#define TIE	0x3a4
+#define MIIMWD	0x3b0
+#define MIIMAI	0x3b4
+
+#define CNTLREG_WRITE_ENABLE_MASK	0x8000
+#define CNTLREG_EMAC1SEL_MASK		0x0400
+#define CNTLREG_ADDRESSCODE_MASK	0x03ff
+
+#define MDIO_ENABLE_MASK	0x40
+#define MDIO_CLOCK_DIV_MASK	0x3F
+#define MDIO_CLOCK_DIV_100MHz	0x28
+
+#define ETHER_MTU		1520
+
+#ifdef SDMA_MODE
+/* CDMAC descriptor status bit definitions */
+# define BDSTAT_ERROR_MASK		0x80
+# define BDSTAT_INT_ON_END_MASK		0x40
+# define BDSTAT_STOP_ON_END_MASK	0x20
+# define BDSTAT_COMPLETED_MASK		0x10
+# define BDSTAT_SOP_MASK		0x08
+# define BDSTAT_EOP_MASK		0x04
+# define BDSTAT_CHANBUSY_MASK		0x02
+# define BDSTAT_CHANRESET_MASK		0x01
+
+/* SDMA Buffer Descriptor */
+
+typedef struct cdmac_bd_t {
+	struct cdmac_bd_t *next_p;
+	unsigned char *phys_buf_p;
+	unsigned long buf_len;
+	unsigned char stat;
+	unsigned char app1_1;
+	unsigned short app1_2;
+	unsigned long app2;
+	unsigned long app3;
+	unsigned long app4;
+	unsigned long app5;
+} cdmac_bd __attribute((aligned(32))) ;
+
+static cdmac_bd	tx_bd;
+static cdmac_bd	rx_bd;
+#endif
+
+#ifdef FIFO_MODE
+typedef struct ll_fifo_s {
+	int isr; /* Interrupt Status Register 0x0 */
+	int ier; /* Interrupt Enable Register 0x4 */
+	int tdfr; /* Transmit data FIFO reset 0x8 */
+	int tdfv; /* Transmit data FIFO Vacancy 0xC */
+	int tdfd; /* Transmit data FIFO 32bit wide data write port 0x10 */
+	int tlf; /* Write Transmit Length FIFO 0x14 */
+	int rdfr; /* Read Receive data FIFO reset 0x18 */
+	int rdfo; /* Receive data FIFO Occupancy 0x1C */
+	int rdfd; /* Read Receive data FIFO 32bit wide data read port 0x20 */
+	int rlf; /* Read Receive Length FIFO 0x24 */
+	int llr; /* Read LocalLink reset 0x28 */
+} ll_fifo_s;
+
+ll_fifo_s *ll_fifo = (ll_fifo_s *) (XILINX_LLTEMAC_FIFO_BASEADDR);
+#endif
+
+static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32)));
+static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32)));
+
+struct xps_ll_temac_private {
+	int idx;
+	unsigned char dev_addr[6];
+};
+
+#ifdef DEBUG
+/* undirect hostif write to ll_temac */
+static void xps_ll_temac_hostif_set(int emac, int phy_addr,
+					int reg_addr, int phy_data)
+{
+	out_be32((u32 *)TEMAC_LSW0, phy_data);
+	out_be32((u32 *)TEMAC_CTL0, CNTLREG_WRITE_ENABLE_MASK | MIIMWD);
+	out_be32((u32 *)TEMAC_LSW0, (phy_addr << 5) | (reg_addr));
+	out_be32((u32 *)TEMAC_CTL0, \
+			CNTLREG_WRITE_ENABLE_MASK | MIIMAI | (emac << 10));
+	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_MIIM_WR_MASK));
+}
+#endif
+
+/* undirect hostif read from ll_temac */
+static unsigned int xps_ll_temac_hostif_get(int emac, int phy_addr,
+						int reg_addr)
+{
+	out_be32((u32 *)TEMAC_LSW0, (phy_addr << 5) | (reg_addr));
+	out_be32((u32 *)TEMAC_CTL0, MIIMAI | (emac << 10));
+	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_MIIM_RR_MASK));
+	return in_be32((u32 *)TEMAC_LSW0);
+}
+
+/* undirect write to ll_temac */
+static void xps_ll_temac_indirect_set(int emac, int reg_offset, int reg_data)
+{
+	out_be32((u32 *)TEMAC_LSW0, reg_data);
+	out_be32((u32 *)TEMAC_CTL0, \
+			CNTLREG_WRITE_ENABLE_MASK | (emac << 10) | reg_offset);
+	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_CFG_WR_MASK));
+}
+
+/* undirect read from ll_temac */
+int xps_ll_temac_indirect_get(int emac, int reg_offset)
+{
+	out_be32((u32 *)TEMAC_CTL0, (emac << 10) | reg_offset);
+	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_CFG_RR_MASK));
+	return in_be32((u32 *)TEMAC_LSW0);
+}
+
+#ifdef DEBUG
+/* read from phy */
+static void read_phy_reg (int phy_addr)
+{
+	int j, result;
+	printf("phy%d ",phy_addr);
+	for ( j = 0; j < 32; j++) {
+		result = xps_ll_temac_hostif_get(0, phy_addr, j);
+		printf("%d: 0x%x ", j, result);
+	}
+	puts("\n");
+}
+#endif
+
+static int phy_addr = -1;
+static int link = 0;
+
+/* setting ll_temac and phy to proper setting */
+static int xps_ll_temac_phy_ctrl(void)
+{
+	int i;
+	unsigned int result;
+	unsigned retries = 10;
+
+	if(link == 1)
+		return 1; /* link is setup */
+
+	/* wait for link up */
+	while (retries-- &&
+		((xps_ll_temac_hostif_get(0, phy_addr, 1) & 0x24) == 0x24))
+		;
+
+	if(phy_addr == -1) {
+		for(i = 31; i >= 0; i--) {
+			result = xps_ll_temac_hostif_get(0, i, 1);
+			if((result & 0x0ffff) != 0x0ffff) {
+				debug ("phy %x result %x\n", i, result);
+				phy_addr = i;
+				break;
+			}
+		}
+	}
+
+	/* get PHY id */
+	i = (xps_ll_temac_hostif_get(0, phy_addr, 2) << 16) | \
+		xps_ll_temac_hostif_get(0, phy_addr, 3);
+	debug("LL_TEMAC: Phy ID 0x%x\n", i);
+
+
+#ifdef DEBUG
+	xps_ll_temac_hostif_set(0, 0, 0, 0x8000); /* phy reset */
+#endif
+	/* FIXME this part will be replaced by PHY lib */
+	/* s3e boards */
+	if (i == 0x7c0a3) {
+		/* 100BASE-T/FD */
+		xps_ll_temac_indirect_set(0, EMMC, 0x40000000);
+		link = 1;
+		return 1;
+	}
+
+	/* Marwell 88e1111 id - ml50x */
+	if (i == 0x1410cc2) {
+		result = xps_ll_temac_hostif_get(0, phy_addr, 5);
+		if((result & 0x8000) == 0x8000) {
+			xps_ll_temac_indirect_set(0, EMMC, 0x80000000);
+			printf("1000BASE-T/FD\n");
+			link = 1;
+		} else if((result & 0x4000) == 0x4000) {
+			xps_ll_temac_indirect_set(0, EMMC, 0x40000000);
+			printf("100BASE-T/FD\n");
+			link = 1;
+		} else {
+			printf("Unsupported mode\n");
+			link = 0;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+#ifdef SDMA_MODE
+/* bd init */
+static void xps_ll_temac_bd_init(void)
+{
+	memset((void *)&tx_bd, 0, sizeof(cdmac_bd));
+	memset((void *)&rx_bd, 0, sizeof(cdmac_bd));
+
+	rx_bd.phys_buf_p = &rx_buffer[0];
+
+	rx_bd.next_p = &rx_bd;
+	rx_bd.buf_len = ETHER_MTU;
+	flush_cache((u32)&rx_bd, sizeof(cdmac_bd));
+
+	out_be32((u32 *)RX_CURDESC_PTR, (u32)&rx_bd);
+	out_be32((u32 *)RX_TAILDESC_PTR, (u32)&rx_bd);
+	out_be32((u32 *)RX_NXTDESC_PTR, (u32)&rx_bd); /* setup first fd */
+
+	tx_bd.phys_buf_p = &tx_buffer[0];
+	tx_bd.next_p = &tx_bd;
+
+	flush_cache((u32)&tx_bd, sizeof(cdmac_bd));
+	out_be32((u32 *)TX_CURDESC_PTR, (u32)&tx_bd);
+}
+
+static int xps_ll_temac_send_sdma(unsigned char *buffer, int length)
+{
+	if( xps_ll_temac_phy_ctrl() == 0)
+		return 0;
+
+	memcpy (tx_buffer, buffer, length);
+	flush_cache ((u32)tx_buffer, length);
+
+	tx_bd.stat = BDSTAT_SOP_MASK | BDSTAT_EOP_MASK \
+			| BDSTAT_STOP_ON_END_MASK;
+	tx_bd.buf_len = length;
+	flush_cache ((u32)&tx_bd, sizeof(cdmac_bd));
+
+	out_be32((u32 *)TX_CURDESC_PTR, (u32)&tx_bd);
+	out_be32((u32 *)TX_TAILDESC_PTR, (u32)&tx_bd); /* DMA start */
+
+	do {
+		flush_cache ((u32)&tx_bd, sizeof(cdmac_bd));
+	} while(!(((volatile int)tx_bd.stat) & BDSTAT_COMPLETED_MASK));
+
+	return length;
+}
+
+static int xps_ll_temac_recv_sdma(void)
+{
+	int length;
+
+	flush_cache ((u32)&rx_bd, sizeof(cdmac_bd));
+
+	if(!(rx_bd.stat & BDSTAT_COMPLETED_MASK)) {
+		return 0;
+	}
+
+	length = rx_bd.app5;
+	flush_cache ((u32)rx_bd.phys_buf_p, length);
+
+	rx_bd.buf_len = ETHER_MTU;
+	rx_bd.stat = 0;
+	rx_bd.app5 = 0;
+
+	flush_cache ((u32)&rx_bd, sizeof(cdmac_bd));
+	out_be32((u32 *)RX_TAILDESC_PTR, (u32)&rx_bd);
+
+	if(length > 0) {
+		NetReceive(rx_bd.phys_buf_p, length);
+	}
+
+	return length;
+}
+#endif
+
+#ifdef FIFO_MODE
+void debugll(int count)
+{
+	printf ("%d fifo isr 0x%08x, fifo_ier 0x%08x,"
+		"fifo_rdfr 0x%08x, fifo_rdfo 0x%08x fifo_rlr 0x%08x\n",
+		count, ll_fifo->isr, ll_fifo->ier,
+		ll_fifo->rdfr, ll_fifo->rdfo, ll_fifo->rlf);
+}
+
+static int xps_ll_temac_send_fifo(unsigned char *buffer, int length)
+{
+	u32 *buf = buffer;
+	u32 len, i, val;
+
+	len = (length / 4) + 1;
+
+	for (i = 0; i < len; i++) {
+		val = *buf++;
+		ll_fifo->tdfd = val;
+	}
+
+	ll_fifo->tlf = length;
+
+	return length;
+}
+
+static int xps_ll_temac_recv_fifo()
+{
+	int len, len2, i, val;
+	int *buf;
+	buf = &rx_buffer;
+
+	if (ll_fifo->isr & 0x04000000 ) {
+		ll_fifo->isr = 0xffffffff; /* reset isr */
+	
+		/* while (ll_fifo->isr); */
+		len = ll_fifo->rlf & 0x7FF;
+		len2 = (len / 4) + 1;
+	
+		for (i = 0; i < len2; i++) {
+			val = ll_fifo->rdfd;
+			*buf++ = val ;
+		}
+	
+		/* debugll(1); */
+		NetReceive (&rx_buffer, len);
+	}
+	return 0;
+}
+#endif
+
+/* setup mac addr */
+static int xps_ll_temac_addr_setup(struct xps_ll_temac_private * lp)
+{
+	char * env_p;
+	char * end;
+	int i, val;
+
+	env_p = getenv("ethaddr");
+	if (env_p == NULL) {
+		printf("cannot get enviroment for \"ethaddr\".\n");
+		return -1;
+	}
+
+	for (i = 0; i < 6; i++) {
+		lp->dev_addr[i] = env_p ? simple_strtoul(env_p, &end, 16) : 0;
+		if (env_p) env_p = (*end) ? end + 1 : end;
+	}
+
+	/* set up unicast MAC address filter */
+	val = ((lp->dev_addr[3] << 24) | (lp->dev_addr[2] << 16) |
+		(lp->dev_addr[1] << 8) | (lp->dev_addr[0] ));
+	xps_ll_temac_indirect_set(0, UAW0, val);
+	val = (lp->dev_addr[5] << 8) | lp->dev_addr[4] ;
+	xps_ll_temac_indirect_set(0, UAW1, val);
+
+	return 0;
+}
+
+static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis)
+{
+	struct xps_ll_temac_private *lp =
+				(struct xps_ll_temac_private *)dev->priv;
+
+#ifdef SDMA_MODE
+	xps_ll_temac_bd_init();
+#endif
+#ifdef FIFO_MODE
+	ll_fifo->tdfr = 0x000000a5; /* set fifo lenght */
+	ll_fifo->rdfr = 0x000000a5;
+
+	/* ll_fifo->isr = 0x0; */
+	/* ll_fifo->ier = 0x0; */
+#endif
+	xps_ll_temac_indirect_set(0, MC,
+				MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_100MHz);
+
+	xps_ll_temac_addr_setup(lp);
+	/* Promiscuos mode disable */
+	xps_ll_temac_indirect_set(0, AFM, 0x00000000);
+	xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver */
+	xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable Transmitter */
+
+}
+
+#ifdef ETH_HALTING
+static int xps_ll_temac_halt(void)
+{
+	xps_ll_temac_indirect_set(0, RCW1, 0x00000000); /* Disable Receiver */
+	xps_ll_temac_indirect_set(0, TC, 0x00000000); /* Disable Transmitter */
+
+#ifdef SDMA_MODE
+	out_be32((u32 *)DMA_CONTROL_REG, 0x00000001);
+	while(in_be32((u32 *)DMA_CONTROL_REG) & 1);
+#endif
+#ifdef FIFO_MODE
+	/* reset fifos */
+#endif
+}
+#endif
+
+/* halt device */
+void eth_halt(void){
+	link = 0;
+#ifdef ETH_HALTING
+	xps_ll_temac_halt();
+#endif
+}
+
+int eth_init(bd_t *bis)
+{
+	static int first = 1;
+	struct eth_device *dev;
+	struct xps_ll_temac_private *lp;
+
+	if(!first)
+		return 0;
+	first = 0;
+	dev = (struct eth_device *) calloc(1, sizeof(struct eth_device));
+	if (NULL == dev)
+		return 0;
+
+	lp = (struct xps_ll_temac_private *)
+				calloc(1, sizeof(struct xps_ll_temac_private));
+	if (lp == NULL)
+		return 0;
+	dev->priv = lp;
+	sprintf(dev->name, "eth0");
+
+	xps_ll_temac_init(dev, bis);
+
+	printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
+		dev->name, 0, XILINX_LLTEMAC_BASEADDR);
+
+#ifdef DEBUG
+	int i;
+	for(i = 0;i < 32;i++) {
+		read_phy_reg(i);
+	}
+#endif
+	xps_ll_temac_phy_ctrl();
+	return 1;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+#ifdef SDMA_MODE
+	return xps_ll_temac_send_sdma((unsigned char *)packet, length);
+#endif
+#ifdef FIFO_MODE
+	return xps_ll_temac_send_fifo((unsigned char *)packet, length);
+#endif
+}
+
+int eth_rx(void)
+{
+#ifdef SDMA_MODE
+	return xps_ll_temac_recv_sdma();
+#endif
+#ifdef FIFO_MODE
+	return xps_ll_temac_recv_fifo();
+#endif
+}
-- 
1.5.5.1

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-01 11:16 [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2 monstr at monstr.eu
@ 2009-02-17  9:35 ` Michal Simek
  2009-02-23  6:45 ` Ben Warren
  1 sibling, 0 replies; 9+ messages in thread
From: Michal Simek @ 2009-02-17  9:35 UTC (permalink / raw)
  To: u-boot

Hi Ben,

do you have any comment? If not please add it to your net repo!

Thanks,
Michal


> From: Michal Simek <monstr@monstr.eu>
> 
> ---
> v2: Coding style cleanup, use debug() instead of printf
> in debug messages
> 
> v1: Initial version
> 
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> ---
>  drivers/net/Makefile          |    1 +
>  drivers/net/xilinx_ll_temac.c |  540 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 541 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/xilinx_ll_temac.c
> 
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 631336a..1e80698 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -68,6 +68,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
>  COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
>  COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
>  COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
> +COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
>  COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
>  
>  COBJS	:= $(COBJS-y)
> diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c
> new file mode 100644
> index 0000000..e17c97e
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac.c
> @@ -0,0 +1,540 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * Author: Yoshio Kashiwagi kashiwagi at co-nss.co.jp
> + *
> + * Copyright (C) 2008 Nissin Systems Co.,Ltd.
> + * March 2008 created
> + *
> + * Copyright (C) 2008 - 2009 Michal Simek <monstr@monstr.eu>
> + * June 2008 Microblaze optimalization, FIFO mode support
> + *
> + * 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.
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <net.h>
> +#include <malloc.h>
> +#include <asm/processor.h>
> +#include <asm/io.h>
> +
> +#ifdef XILINX_LLTEMAC_FIFO_BASEADDR
> +# define FIFO_MODE	1
> +#elif XILINX_LLTEMAC_SDMA_CTRL_BASEADDR
> +# define SDMA_MODE	1
> +#else
> +# error Unsupported mode
> +#endif
> +
> +#undef ETH_HALTING
> +
> +#ifdef SDMA_MODE
> +/* XPS_LL_TEMAC SDMA registers definition */
> +# define TX_NXTDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x00)
> +# define TX_CURBUF_ADDR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x04)
> +# define TX_CURBUF_LENGTH	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x08)
> +# define TX_CURDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x0c)
> +# define TX_TAILDESC_PTR	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x10)
> +# define TX_CHNL_CTRL		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x14)
> +# define TX_IRQ_REG		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x18)
> +# define TX_CHNL_STS		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x1c)
> +
> +# define RX_NXTDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x20)
> +# define RX_CURBUF_ADDR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x24)
> +# define RX_CURBUF_LENGTH	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x28)
> +# define RX_CURDESC_PTR		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x2c)
> +# define RX_TAILDESC_PTR	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x30)
> +# define RX_CHNL_CTRL		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x34)
> +# define RX_IRQ_REG		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x38)
> +# define RX_CHNL_STS		(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x3c)
> +
> +# define DMA_CONTROL_REG	(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x40)
> +#endif
> +
> +/* XPS_LL_TEMAC direct registers definition */
> +#define TEMAC_RAF0		(XILINX_LLTEMAC_BASEADDR + 0x00)
> +#define TEMAC_TPF0		(XILINX_LLTEMAC_BASEADDR + 0x04)
> +#define TEMAC_IFGP0		(XILINX_LLTEMAC_BASEADDR + 0x08)
> +#define TEMAC_IS0		(XILINX_LLTEMAC_BASEADDR + 0x0c)
> +#define TEMAC_IP0		(XILINX_LLTEMAC_BASEADDR + 0x10)
> +#define TEMAC_IE0		(XILINX_LLTEMAC_BASEADDR + 0x14)
> +
> +#define TEMAC_MSW0		(XILINX_LLTEMAC_BASEADDR + 0x20)
> +#define TEMAC_LSW0		(XILINX_LLTEMAC_BASEADDR + 0x24)
> +#define TEMAC_CTL0		(XILINX_LLTEMAC_BASEADDR + 0x28)
> +#define TEMAC_RDY0		(XILINX_LLTEMAC_BASEADDR + 0x2c)
> +
> +#define XTE_RSE_MIIM_RR_MASK	0x0002
> +#define XTE_RSE_MIIM_WR_MASK	0x0004
> +#define XTE_RSE_CFG_RR_MASK	0x0020
> +#define XTE_RSE_CFG_WR_MASK	0x0040
> +
> +/* XPS_LL_TEMAC indirect registers offset definition */
> +
> +#define RCW0	0x200
> +#define RCW1	0x240
> +#define TC	0x280
> +#define FCC	0x2c0
> +#define EMMC	0x300
> +#define PHYC	0x320
> +#define MC	0x340
> +#define UAW0	0x380
> +#define UAW1	0x384
> +#define MAW0	0x388
> +#define MAW1	0x38c
> +#define AFM	0x390
> +#define TIS	0x3a0
> +#define TIE	0x3a4
> +#define MIIMWD	0x3b0
> +#define MIIMAI	0x3b4
> +
> +#define CNTLREG_WRITE_ENABLE_MASK	0x8000
> +#define CNTLREG_EMAC1SEL_MASK		0x0400
> +#define CNTLREG_ADDRESSCODE_MASK	0x03ff
> +
> +#define MDIO_ENABLE_MASK	0x40
> +#define MDIO_CLOCK_DIV_MASK	0x3F
> +#define MDIO_CLOCK_DIV_100MHz	0x28
> +
> +#define ETHER_MTU		1520
> +
> +#ifdef SDMA_MODE
> +/* CDMAC descriptor status bit definitions */
> +# define BDSTAT_ERROR_MASK		0x80
> +# define BDSTAT_INT_ON_END_MASK		0x40
> +# define BDSTAT_STOP_ON_END_MASK	0x20
> +# define BDSTAT_COMPLETED_MASK		0x10
> +# define BDSTAT_SOP_MASK		0x08
> +# define BDSTAT_EOP_MASK		0x04
> +# define BDSTAT_CHANBUSY_MASK		0x02
> +# define BDSTAT_CHANRESET_MASK		0x01
> +
> +/* SDMA Buffer Descriptor */
> +
> +typedef struct cdmac_bd_t {
> +	struct cdmac_bd_t *next_p;
> +	unsigned char *phys_buf_p;
> +	unsigned long buf_len;
> +	unsigned char stat;
> +	unsigned char app1_1;
> +	unsigned short app1_2;
> +	unsigned long app2;
> +	unsigned long app3;
> +	unsigned long app4;
> +	unsigned long app5;
> +} cdmac_bd __attribute((aligned(32))) ;
> +
> +static cdmac_bd	tx_bd;
> +static cdmac_bd	rx_bd;
> +#endif
> +
> +#ifdef FIFO_MODE
> +typedef struct ll_fifo_s {
> +	int isr; /* Interrupt Status Register 0x0 */
> +	int ier; /* Interrupt Enable Register 0x4 */
> +	int tdfr; /* Transmit data FIFO reset 0x8 */
> +	int tdfv; /* Transmit data FIFO Vacancy 0xC */
> +	int tdfd; /* Transmit data FIFO 32bit wide data write port 0x10 */
> +	int tlf; /* Write Transmit Length FIFO 0x14 */
> +	int rdfr; /* Read Receive data FIFO reset 0x18 */
> +	int rdfo; /* Receive data FIFO Occupancy 0x1C */
> +	int rdfd; /* Read Receive data FIFO 32bit wide data read port 0x20 */
> +	int rlf; /* Read Receive Length FIFO 0x24 */
> +	int llr; /* Read LocalLink reset 0x28 */
> +} ll_fifo_s;
> +
> +ll_fifo_s *ll_fifo = (ll_fifo_s *) (XILINX_LLTEMAC_FIFO_BASEADDR);
> +#endif
> +
> +static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32)));
> +static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32)));
> +
> +struct xps_ll_temac_private {
> +	int idx;
> +	unsigned char dev_addr[6];
> +};
> +
> +#ifdef DEBUG
> +/* undirect hostif write to ll_temac */
> +static void xps_ll_temac_hostif_set(int emac, int phy_addr,
> +					int reg_addr, int phy_data)
> +{
> +	out_be32((u32 *)TEMAC_LSW0, phy_data);
> +	out_be32((u32 *)TEMAC_CTL0, CNTLREG_WRITE_ENABLE_MASK | MIIMWD);
> +	out_be32((u32 *)TEMAC_LSW0, (phy_addr << 5) | (reg_addr));
> +	out_be32((u32 *)TEMAC_CTL0, \
> +			CNTLREG_WRITE_ENABLE_MASK | MIIMAI | (emac << 10));
> +	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_MIIM_WR_MASK));
> +}
> +#endif
> +
> +/* undirect hostif read from ll_temac */
> +static unsigned int xps_ll_temac_hostif_get(int emac, int phy_addr,
> +						int reg_addr)
> +{
> +	out_be32((u32 *)TEMAC_LSW0, (phy_addr << 5) | (reg_addr));
> +	out_be32((u32 *)TEMAC_CTL0, MIIMAI | (emac << 10));
> +	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_MIIM_RR_MASK));
> +	return in_be32((u32 *)TEMAC_LSW0);
> +}
> +
> +/* undirect write to ll_temac */
> +static void xps_ll_temac_indirect_set(int emac, int reg_offset, int reg_data)
> +{
> +	out_be32((u32 *)TEMAC_LSW0, reg_data);
> +	out_be32((u32 *)TEMAC_CTL0, \
> +			CNTLREG_WRITE_ENABLE_MASK | (emac << 10) | reg_offset);
> +	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_CFG_WR_MASK));
> +}
> +
> +/* undirect read from ll_temac */
> +int xps_ll_temac_indirect_get(int emac, int reg_offset)
> +{
> +	out_be32((u32 *)TEMAC_CTL0, (emac << 10) | reg_offset);
> +	while(! (in_be32((u32 *)TEMAC_RDY0) & XTE_RSE_CFG_RR_MASK));
> +	return in_be32((u32 *)TEMAC_LSW0);
> +}
> +
> +#ifdef DEBUG
> +/* read from phy */
> +static void read_phy_reg (int phy_addr)
> +{
> +	int j, result;
> +	printf("phy%d ",phy_addr);
> +	for ( j = 0; j < 32; j++) {
> +		result = xps_ll_temac_hostif_get(0, phy_addr, j);
> +		printf("%d: 0x%x ", j, result);
> +	}
> +	puts("\n");
> +}
> +#endif
> +
> +static int phy_addr = -1;
> +static int link = 0;
> +
> +/* setting ll_temac and phy to proper setting */
> +static int xps_ll_temac_phy_ctrl(void)
> +{
> +	int i;
> +	unsigned int result;
> +	unsigned retries = 10;
> +
> +	if(link == 1)
> +		return 1; /* link is setup */
> +
> +	/* wait for link up */
> +	while (retries-- &&
> +		((xps_ll_temac_hostif_get(0, phy_addr, 1) & 0x24) == 0x24))
> +		;
> +
> +	if(phy_addr == -1) {
> +		for(i = 31; i >= 0; i--) {
> +			result = xps_ll_temac_hostif_get(0, i, 1);
> +			if((result & 0x0ffff) != 0x0ffff) {
> +				debug ("phy %x result %x\n", i, result);
> +				phy_addr = i;
> +				break;
> +			}
> +		}
> +	}
> +
> +	/* get PHY id */
> +	i = (xps_ll_temac_hostif_get(0, phy_addr, 2) << 16) | \
> +		xps_ll_temac_hostif_get(0, phy_addr, 3);
> +	debug("LL_TEMAC: Phy ID 0x%x\n", i);
> +
> +
> +#ifdef DEBUG
> +	xps_ll_temac_hostif_set(0, 0, 0, 0x8000); /* phy reset */
> +#endif
> +	/* FIXME this part will be replaced by PHY lib */
> +	/* s3e boards */
> +	if (i == 0x7c0a3) {
> +		/* 100BASE-T/FD */
> +		xps_ll_temac_indirect_set(0, EMMC, 0x40000000);
> +		link = 1;
> +		return 1;
> +	}
> +
> +	/* Marwell 88e1111 id - ml50x */
> +	if (i == 0x1410cc2) {
> +		result = xps_ll_temac_hostif_get(0, phy_addr, 5);
> +		if((result & 0x8000) == 0x8000) {
> +			xps_ll_temac_indirect_set(0, EMMC, 0x80000000);
> +			printf("1000BASE-T/FD\n");
> +			link = 1;
> +		} else if((result & 0x4000) == 0x4000) {
> +			xps_ll_temac_indirect_set(0, EMMC, 0x40000000);
> +			printf("100BASE-T/FD\n");
> +			link = 1;
> +		} else {
> +			printf("Unsupported mode\n");
> +			link = 0;
> +		}
> +		return 1;
> +	}
> +	return 0;
> +}
> +
> +#ifdef SDMA_MODE
> +/* bd init */
> +static void xps_ll_temac_bd_init(void)
> +{
> +	memset((void *)&tx_bd, 0, sizeof(cdmac_bd));
> +	memset((void *)&rx_bd, 0, sizeof(cdmac_bd));
> +
> +	rx_bd.phys_buf_p = &rx_buffer[0];
> +
> +	rx_bd.next_p = &rx_bd;
> +	rx_bd.buf_len = ETHER_MTU;
> +	flush_cache((u32)&rx_bd, sizeof(cdmac_bd));
> +
> +	out_be32((u32 *)RX_CURDESC_PTR, (u32)&rx_bd);
> +	out_be32((u32 *)RX_TAILDESC_PTR, (u32)&rx_bd);
> +	out_be32((u32 *)RX_NXTDESC_PTR, (u32)&rx_bd); /* setup first fd */
> +
> +	tx_bd.phys_buf_p = &tx_buffer[0];
> +	tx_bd.next_p = &tx_bd;
> +
> +	flush_cache((u32)&tx_bd, sizeof(cdmac_bd));
> +	out_be32((u32 *)TX_CURDESC_PTR, (u32)&tx_bd);
> +}
> +
> +static int xps_ll_temac_send_sdma(unsigned char *buffer, int length)
> +{
> +	if( xps_ll_temac_phy_ctrl() == 0)
> +		return 0;
> +
> +	memcpy (tx_buffer, buffer, length);
> +	flush_cache ((u32)tx_buffer, length);
> +
> +	tx_bd.stat = BDSTAT_SOP_MASK | BDSTAT_EOP_MASK \
> +			| BDSTAT_STOP_ON_END_MASK;
> +	tx_bd.buf_len = length;
> +	flush_cache ((u32)&tx_bd, sizeof(cdmac_bd));
> +
> +	out_be32((u32 *)TX_CURDESC_PTR, (u32)&tx_bd);
> +	out_be32((u32 *)TX_TAILDESC_PTR, (u32)&tx_bd); /* DMA start */
> +
> +	do {
> +		flush_cache ((u32)&tx_bd, sizeof(cdmac_bd));
> +	} while(!(((volatile int)tx_bd.stat) & BDSTAT_COMPLETED_MASK));
> +
> +	return length;
> +}
> +
> +static int xps_ll_temac_recv_sdma(void)
> +{
> +	int length;
> +
> +	flush_cache ((u32)&rx_bd, sizeof(cdmac_bd));
> +
> +	if(!(rx_bd.stat & BDSTAT_COMPLETED_MASK)) {
> +		return 0;
> +	}
> +
> +	length = rx_bd.app5;
> +	flush_cache ((u32)rx_bd.phys_buf_p, length);
> +
> +	rx_bd.buf_len = ETHER_MTU;
> +	rx_bd.stat = 0;
> +	rx_bd.app5 = 0;
> +
> +	flush_cache ((u32)&rx_bd, sizeof(cdmac_bd));
> +	out_be32((u32 *)RX_TAILDESC_PTR, (u32)&rx_bd);
> +
> +	if(length > 0) {
> +		NetReceive(rx_bd.phys_buf_p, length);
> +	}
> +
> +	return length;
> +}
> +#endif
> +
> +#ifdef FIFO_MODE
> +void debugll(int count)
> +{
> +	printf ("%d fifo isr 0x%08x, fifo_ier 0x%08x,"
> +		"fifo_rdfr 0x%08x, fifo_rdfo 0x%08x fifo_rlr 0x%08x\n",
> +		count, ll_fifo->isr, ll_fifo->ier,
> +		ll_fifo->rdfr, ll_fifo->rdfo, ll_fifo->rlf);
> +}
> +
> +static int xps_ll_temac_send_fifo(unsigned char *buffer, int length)
> +{
> +	u32 *buf = buffer;
> +	u32 len, i, val;
> +
> +	len = (length / 4) + 1;
> +
> +	for (i = 0; i < len; i++) {
> +		val = *buf++;
> +		ll_fifo->tdfd = val;
> +	}
> +
> +	ll_fifo->tlf = length;
> +
> +	return length;
> +}
> +
> +static int xps_ll_temac_recv_fifo()
> +{
> +	int len, len2, i, val;
> +	int *buf;
> +	buf = &rx_buffer;
> +
> +	if (ll_fifo->isr & 0x04000000 ) {
> +		ll_fifo->isr = 0xffffffff; /* reset isr */
> +	
> +		/* while (ll_fifo->isr); */
> +		len = ll_fifo->rlf & 0x7FF;
> +		len2 = (len / 4) + 1;
> +	
> +		for (i = 0; i < len2; i++) {
> +			val = ll_fifo->rdfd;
> +			*buf++ = val ;
> +		}
> +	
> +		/* debugll(1); */
> +		NetReceive (&rx_buffer, len);
> +	}
> +	return 0;
> +}
> +#endif
> +
> +/* setup mac addr */
> +static int xps_ll_temac_addr_setup(struct xps_ll_temac_private * lp)
> +{
> +	char * env_p;
> +	char * end;
> +	int i, val;
> +
> +	env_p = getenv("ethaddr");
> +	if (env_p == NULL) {
> +		printf("cannot get enviroment for \"ethaddr\".\n");
> +		return -1;
> +	}
> +
> +	for (i = 0; i < 6; i++) {
> +		lp->dev_addr[i] = env_p ? simple_strtoul(env_p, &end, 16) : 0;
> +		if (env_p) env_p = (*end) ? end + 1 : end;
> +	}
> +
> +	/* set up unicast MAC address filter */
> +	val = ((lp->dev_addr[3] << 24) | (lp->dev_addr[2] << 16) |
> +		(lp->dev_addr[1] << 8) | (lp->dev_addr[0] ));
> +	xps_ll_temac_indirect_set(0, UAW0, val);
> +	val = (lp->dev_addr[5] << 8) | lp->dev_addr[4] ;
> +	xps_ll_temac_indirect_set(0, UAW1, val);
> +
> +	return 0;
> +}
> +
> +static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis)
> +{
> +	struct xps_ll_temac_private *lp =
> +				(struct xps_ll_temac_private *)dev->priv;
> +
> +#ifdef SDMA_MODE
> +	xps_ll_temac_bd_init();
> +#endif
> +#ifdef FIFO_MODE
> +	ll_fifo->tdfr = 0x000000a5; /* set fifo lenght */
> +	ll_fifo->rdfr = 0x000000a5;
> +
> +	/* ll_fifo->isr = 0x0; */
> +	/* ll_fifo->ier = 0x0; */
> +#endif
> +	xps_ll_temac_indirect_set(0, MC,
> +				MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_100MHz);
> +
> +	xps_ll_temac_addr_setup(lp);
> +	/* Promiscuos mode disable */
> +	xps_ll_temac_indirect_set(0, AFM, 0x00000000);
> +	xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver */
> +	xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable Transmitter */
> +
> +}
> +
> +#ifdef ETH_HALTING
> +static int xps_ll_temac_halt(void)
> +{
> +	xps_ll_temac_indirect_set(0, RCW1, 0x00000000); /* Disable Receiver */
> +	xps_ll_temac_indirect_set(0, TC, 0x00000000); /* Disable Transmitter */
> +
> +#ifdef SDMA_MODE
> +	out_be32((u32 *)DMA_CONTROL_REG, 0x00000001);
> +	while(in_be32((u32 *)DMA_CONTROL_REG) & 1);
> +#endif
> +#ifdef FIFO_MODE
> +	/* reset fifos */
> +#endif
> +}
> +#endif
> +
> +/* halt device */
> +void eth_halt(void){
> +	link = 0;
> +#ifdef ETH_HALTING
> +	xps_ll_temac_halt();
> +#endif
> +}
> +
> +int eth_init(bd_t *bis)
> +{
> +	static int first = 1;
> +	struct eth_device *dev;
> +	struct xps_ll_temac_private *lp;
> +
> +	if(!first)
> +		return 0;
> +	first = 0;
> +	dev = (struct eth_device *) calloc(1, sizeof(struct eth_device));
> +	if (NULL == dev)
> +		return 0;
> +
> +	lp = (struct xps_ll_temac_private *)
> +				calloc(1, sizeof(struct xps_ll_temac_private));
> +	if (lp == NULL)
> +		return 0;
> +	dev->priv = lp;
> +	sprintf(dev->name, "eth0");
> +
> +	xps_ll_temac_init(dev, bis);
> +
> +	printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
> +		dev->name, 0, XILINX_LLTEMAC_BASEADDR);
> +
> +#ifdef DEBUG
> +	int i;
> +	for(i = 0;i < 32;i++) {
> +		read_phy_reg(i);
> +	}
> +#endif
> +	xps_ll_temac_phy_ctrl();
> +	return 1;
> +}
> +
> +int eth_send(volatile void *packet, int length)
> +{
> +#ifdef SDMA_MODE
> +	return xps_ll_temac_send_sdma((unsigned char *)packet, length);
> +#endif
> +#ifdef FIFO_MODE
> +	return xps_ll_temac_send_fifo((unsigned char *)packet, length);
> +#endif
> +}
> +
> +int eth_rx(void)
> +{
> +#ifdef SDMA_MODE
> +	return xps_ll_temac_recv_sdma();
> +#endif
> +#ifdef FIFO_MODE
> +	return xps_ll_temac_recv_fifo();
> +#endif
> +}

-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-01 11:16 [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2 monstr at monstr.eu
  2009-02-17  9:35 ` Michal Simek
@ 2009-02-23  6:45 ` Ben Warren
  2009-02-23  8:03   ` Michal Simek
  2009-02-23 13:51   ` Michal Simek
  1 sibling, 2 replies; 9+ messages in thread
From: Ben Warren @ 2009-02-23  6:45 UTC (permalink / raw)
  To: u-boot

Hi Michal,

You submitted this so long ago that this driver should be in the tree 
right now.  Unfortunately, I didn't give a thorough enough review the 
first time and I think it would be wrong to pull it in right now without 
addressing some more things.  If you take care of this, I promise to put 
it in the front of the queue for the next release:

monstr at monstr.eu wrote:
> From: Michal Simek <monstr@monstr.eu>
>
> ---
>   
This '---' line ensures that nothing below it (including your SOB) goes 
in the commit.  Please remove it, add a meaningful commit message and 
move the next few lines below the next '---' line.  Also, the "version 
2" in the title should be in square brackets so it get stripped from the 
commit title.
> v2: Coding style cleanup, use debug() instead of printf
> in debug messages
>
> v1: Initial version
>
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> ---
>  drivers/net/Makefile          |    1 +
>  drivers/net/xilinx_ll_temac.c |  540 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 541 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/xilinx_ll_temac.c
>
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 631336a..1e80698 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -68,6 +68,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
>  COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
>  COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
>  COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
> +COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
>  COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
>  
>   
This doesn't apply any more.  Not your fault :)


I get the following whitespace errors:

Applying net: Add Xilinx LL Temac driver
.dotest/patch:415: trailing whitespace.
   
.dotest/patch:419: trailing whitespace.
   
.dotest/patch:424: trailing whitespace.


All of the above mentioned issues are ones that I could easily deal 
with, but one thing that really does need to change is that you need to 
use the CONFIG_NET_MULTI API.  In other words, your driver should have a 
single initialize() function (prototyped in include/netdev.h), and an 
eth_device struct that gets registered.  All your access functions 
(eth_init, eth_send, eth_recv etc.) will be static and pointed to by the 
eth_device struct.  Most drivers are already this way.

Other than that, it's fine.  Sorry again for taking so very long.

regards,
Ben

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-23  6:45 ` Ben Warren
@ 2009-02-23  8:03   ` Michal Simek
  2009-02-23 13:51   ` Michal Simek
  1 sibling, 0 replies; 9+ messages in thread
From: Michal Simek @ 2009-02-23  8:03 UTC (permalink / raw)
  To: u-boot

OK. I'll look at it this week.

Thanks,
Michal

> Hi Michal,
> 
> You submitted this so long ago that this driver should be in the tree 
> right now.  Unfortunately, I didn't give a thorough enough review the 
> first time and I think it would be wrong to pull it in right now without 
> addressing some more things.  If you take care of this, I promise to put 
> it in the front of the queue for the next release:
> 
> monstr at monstr.eu wrote:
>> From: Michal Simek <monstr@monstr.eu>
>>
>> ---
>>   
> This '---' line ensures that nothing below it (including your SOB) goes 
> in the commit.  Please remove it, add a meaningful commit message and 
> move the next few lines below the next '---' line.  Also, the "version 
> 2" in the title should be in square brackets so it get stripped from the 
> commit title.
>> v2: Coding style cleanup, use debug() instead of printf
>> in debug messages
>>
>> v1: Initial version
>>
>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>> ---
>>  drivers/net/Makefile          |    1 +
>>  drivers/net/xilinx_ll_temac.c |  540 +++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 541 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/net/xilinx_ll_temac.c
>>
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index 631336a..1e80698 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -68,6 +68,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
>>  COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
>>  COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
>>  COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
>> +COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
>>  COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
>>  
>>   
> This doesn't apply any more.  Not your fault :)
> 
> 
> I get the following whitespace errors:
> 
> Applying net: Add Xilinx LL Temac driver
> .dotest/patch:415: trailing whitespace.
>    
> .dotest/patch:419: trailing whitespace.
>    
> .dotest/patch:424: trailing whitespace.
> 
> 
> All of the above mentioned issues are ones that I could easily deal 
> with, but one thing that really does need to change is that you need to 
> use the CONFIG_NET_MULTI API.  In other words, your driver should have a 
> single initialize() function (prototyped in include/netdev.h), and an 
> eth_device struct that gets registered.  All your access functions 
> (eth_init, eth_send, eth_recv etc.) will be static and pointed to by the 
> eth_device struct.  Most drivers are already this way.
> 
> Other than that, it's fine.  Sorry again for taking so very long.
> 
> regards,
> Ben
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
> 

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-23  6:45 ` Ben Warren
  2009-02-23  8:03   ` Michal Simek
@ 2009-02-23 13:51   ` Michal Simek
  2009-02-23 18:29     ` Ben Warren
  1 sibling, 1 reply; 9+ messages in thread
From: Michal Simek @ 2009-02-23 13:51 UTC (permalink / raw)
  To: u-boot

Hi Ben,

> Hi Michal,
> 
> You submitted this so long ago that this driver should be in the tree
> right now.  Unfortunately, I didn't give a thorough enough review the
> first time and I think it would be wrong to pull it in right now without
> addressing some more things.  If you take care of this, I promise to put
> it in the front of the queue for the next release:
> 
> monstr at monstr.eu wrote:
>> From: Michal Simek <monstr@monstr.eu>
>>
>> ---
>>   
> This '---' line ensures that nothing below it (including your SOB) goes
> in the commit.  Please remove it, add a meaningful commit message and
> move the next few lines below the next '---' line.  Also, the "version
> 2" in the title should be in square brackets so it get stripped from the
> commit title.
>> v2: Coding style cleanup, use debug() instead of printf
>> in debug messages
>>
>> v1: Initial version
>>
>> Signed-off-by: Michal Simek <monstr@monstr.eu>
>> ---
>>  drivers/net/Makefile          |    1 +
>>  drivers/net/xilinx_ll_temac.c |  540
>> +++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 541 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/net/xilinx_ll_temac.c
>>
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index 631336a..1e80698 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -68,6 +68,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
>>  COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
>>  COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
>>  COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
>> +COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
>>  COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
>>  
>>   
> This doesn't apply any more.  Not your fault :)
> 
> 
> I get the following whitespace errors:
> 
> Applying net: Add Xilinx LL Temac driver
> .dotest/patch:415: trailing whitespace.
>   .dotest/patch:419: trailing whitespace.
>   .dotest/patch:424: trailing whitespace.

yes, There were three tabs.

> 
> All of the above mentioned issues are ones that I could easily deal
> with, but one thing that really does need to change is that you need to
> use the CONFIG_NET_MULTI API.  In other words, your driver should have a
> single initialize() function (prototyped in include/netdev.h), and an
> eth_device struct that gets registered.  All your access functions
> (eth_init, eth_send, eth_recv etc.) will be static and pointed to by the
> eth_device struct.  Most drivers are already this way.

I look at it and I did some change and the main problem is in Microblaze GCC.
We use GCC 3.4.1 and CONFIG_NET_MULTI use weak function and board_eth_init is
never called. We are working on GCC 4.1.2 but I don't know when I get it.

I have two more Xilinx eth drivers in U-BOOT and I think that will be the best
to do all changes together. What do you think?

Thanks,
Michal

> 
> Other than that, it's fine.  Sorry again for taking so very long.
> 
> regards,
> Ben


-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-23 13:51   ` Michal Simek
@ 2009-02-23 18:29     ` Ben Warren
  2009-02-24 15:11       ` Michal Simek
  0 siblings, 1 reply; 9+ messages in thread
From: Ben Warren @ 2009-02-23 18:29 UTC (permalink / raw)
  To: u-boot

Hi Michal,

Michal Simek wrote:

<snip>
>> All of the above mentioned issues are ones that I could easily deal
>> with, but one thing that really does need to change is that you need to
>> use the CONFIG_NET_MULTI API.  In other words, your driver should have a
>> single initialize() function (prototyped in include/netdev.h), and an
>> eth_device struct that gets registered.  All your access functions
>> (eth_init, eth_send, eth_recv etc.) will be static and pointed to by the
>> eth_device struct.  Most drivers are already this way.
>>     
>
> I look at it and I did some change and the main problem is in Microblaze GCC.
> We use GCC 3.4.1 and CONFIG_NET_MULTI use weak function and board_eth_init is
> never called. We are working on GCC 4.1.2 but I don't know when I get it.
>
>   
According to the documentation I could find, weak symbols were present 
in gcc 3.4.1.  Are you sure you're using them properly?  Due to the way 
linking is performed in U-boot, any weak symbol overrides need to be in 
source files that have strongly linked symbols.  You'll see that all 
implementations of cpu_eth_init() and board_eth_init() are in files that 
already contain stuff that is sure to be linked.
> I have two more Xilinx eth drivers in U-BOOT and I think that will be the best
> to do all changes together. What do you think?
>
> Thanks,
> Michal
>
>   
If you're really unable to make this change due to your tools, I'm not 
opposed to pulling this driver in.  I just want to know that you intend 
to port all the Xilinx drivers over some time in the near future.

regards,
Ben

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-23 18:29     ` Ben Warren
@ 2009-02-24 15:11       ` Michal Simek
  2009-02-24 17:51         ` Ben Warren
  0 siblings, 1 reply; 9+ messages in thread
From: Michal Simek @ 2009-02-24 15:11 UTC (permalink / raw)
  To: u-boot

Hi Ben,
> Hi Michal,
> 
> Michal Simek wrote:
> 
> <snip>
>>> All of the above mentioned issues are ones that I could easily deal
>>> with, but one thing that really does need to change is that you need to
>>> use the CONFIG_NET_MULTI API.  In other words, your driver should have a
>>> single initialize() function (prototyped in include/netdev.h), and an
>>> eth_device struct that gets registered.  All your access functions
>>> (eth_init, eth_send, eth_recv etc.) will be static and pointed to by the
>>> eth_device struct.  Most drivers are already this way.
>>>     
>>
>> I look at it and I did some change and the main problem is in
>> Microblaze GCC.
>> We use GCC 3.4.1 and CONFIG_NET_MULTI use weak function and
>> board_eth_init is
>> never called. We are working on GCC 4.1.2 but I don't know when I get it.
>>
>>   
> According to the documentation I could find, weak symbols were present
> in gcc 3.4.1.  Are you sure you're using them properly?  Due to the way
> linking is performed in U-boot, any weak symbol overrides need to be in
> source files that have strongly linked symbols.  You'll see that all
> implementations of cpu_eth_init() and board_eth_init() are in files that
> already contain stuff that is sure to be linked.


hmm. I did some tests and I found that the my problem is with this line 40. (I
use board_eth_init initialization)
int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
I am not gcc specialist but I smell problem with GCC.

First log is when this line is there. -> here is board_eth_init called

SDRAM :
                Icache:OK
                Dcache:OK
        U-Boot Start:0x91800000
FLASH: 32 MB
MAC:00:E0:0C:00:00:FD
before
after
No ethernet found.
*** Warning - bad CRC, using default environment

U-BOOT for hw

U-Boot-mONStR>


Commented that line.


SDRAM :
                Icache:OK
                Dcache:OK
        U-Boot Start:0x91800000
FLASH: 32 MB
MAC:00:E0:0C:00:00:FD
before
board_eth_initafter
Xilinx LL Temac
*** Warning - bad CRC, using default environment

U-BOOT for hw

U-Boot-mONStR> ping 192.168.0.1
Xilinx LL Temac: Xilinx XPS LocalLink Tri-Mode Ether MAC #0 at 0x81C00000.
100BASE-T/FD
Using Xilinx LL Temac device
host 192.168.0.1 is alive
U-Boot-mONStR>


Not working -> dump

918038c8:	b000ffff 	imm	-1
918038cc:	b9f4fdf8 	brlid	r15, -520	// 918036c4 <cpu_eth_init>
918038d0:	10b30000 	addk	r5, r19, r0
918038d4:	bca30010 	bgei	r3, 16		// 918038e4
918038d8:	b000ffff 	imm	-1
918038dc:	b9f4fde8 	brlid	r15, -536	// 918036c4 <cpu_eth_init>

Working dump

918038c8:	b0000001 	imm	1
918038cc:	b9f49268 	brlid	r15, -28056	// 9181cb34 <board_eth_init>
918038d0:	10b30000 	addk	r5, r19, r0
918038d4:	bca30010 	bgei	r3, 16		// 918038e4
918038d8:	b000ffff 	imm	-1
918038dc:	b9f4fde8 	brlid	r15, -536	// 918036c4 <cpu_eth_init>

Using cpu_eth_init nothing solve -> gcc has problem with attributes - weak or
alias?

>> I have two more Xilinx eth drivers in U-BOOT and I think that will be
>> the best
>> to do all changes together. What do you think?
>>
>> Thanks,
>> Michal
>>
>>   
> If you're really unable to make this change due to your tools, I'm not
> opposed to pulling this driver in.  I just want to know that you intend
> to port all the Xilinx drivers over some time in the near future.

Yes. I will do it. Below are my changes for ll_temac driver. Do you see any
problem in it?

Thanks,
Michal

> regards,
> Ben


diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c
b/board/xilinx/microblaze-generic/microblaze-generic.c
index f388b77..878a2a3 100644
--- a/board/xilinx/microblaze-generic/microblaze-generic.c
+++ b/board/xilinx/microblaze-generic/microblaze-generic.c
@@ -27,6 +27,7 @@

 #include <common.h>
 #include <config.h>
+#include <netdev.h>
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>

@@ -67,3 +68,11 @@ void fsl_init2 (void) {
  NULL);
 }
 #endif
+
+int board_eth_init(bd_t *bis)
+{
+	puts (__func__);
+#ifdef CONFIG_XILINX_LL_TEMAC
+	return lltemac_eth_initialize(bis);
+#endif
+}
diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c
index 4f897d2..d6d767a 100644
--- a/drivers/net/xilinx_ll_temac.c
+++ b/drivers/net/xilinx_ll_temac.c
@@ -21,6 +21,7 @@
 #include <common.h>
 #include <net.h>
 #include <malloc.h>
+#include <netdev.h>
 #include <asm/processor.h>
 #include <asm/io.h>

@@ -394,16 +395,16 @@ static int xps_ll_temac_recv_fifo()

 	if (ll_fifo->isr & 0x04000000 ) {
 		ll_fifo->isr = 0xffffffff; /* reset isr */
-	
+
 		/* while (ll_fifo->isr); */
 		len = ll_fifo->rlf & 0x7FF;
 		len2 = (len / 4) + 1;
-	
+
 		for (i = 0; i < len2; i++) {
 			val = ll_fifo->rdfd;
 			*buf++ = val ;
 		}
-	
+
 		/* debugll(1); */
 		NetReceive (&rx_buffer, len);
 	}
@@ -479,35 +480,19 @@ static int xps_ll_temac_halt(void)
 #endif

 /* halt device */
-void eth_halt(void){
+static void lltemac_eth_halt(struct eth_device *dev)
+{
 	link = 0;
 #ifdef ETH_HALTING
 	xps_ll_temac_halt();
 #endif
 }

-int eth_init(bd_t *bis)
+static int lltemac_eth_init(struct eth_device *dev, bd_t * bis)
 {
-	static int first = 1;
-	struct eth_device *dev;
-	struct xps_ll_temac_private *lp;
 #ifdef DEBUG
 	int i;
 #endif
-
-	if(!first)
-		return 0;
-	first = 0;
-	dev = (struct eth_device *) calloc(1, sizeof(struct eth_device));
-	if (NULL == dev)
-		return 0;
-
-	lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct
xps_ll_temac_private));
-	if (lp == NULL)
-		return 0;
-	dev->priv = lp;
-	sprintf(dev->name, "eth0");
-
 	xps_ll_temac_init(dev, bis);

 	printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
@@ -522,7 +507,9 @@ int eth_init(bd_t *bis)
 	return 1;
 }

-int eth_send(volatile void *packet, int length)
+
+static int lltemac_eth_send(struct eth_device *dev, volatile void *packet,
+						int length)
 {
 #ifdef SDMA_MODE
 	return xps_ll_temac_send_sdma((unsigned char *)packet, length);
@@ -532,7 +519,7 @@ int eth_send(volatile void *packet, int length)
 #endif
 }

-int eth_rx(void)
+static int lltemac_eth_recv(struct eth_device *dev)
 {
 #ifdef SDMA_MODE
 	return xps_ll_temac_recv_sdma();
@@ -541,3 +528,31 @@ int eth_rx(void)
 	return xps_ll_temac_recv_fifo();
 #endif
 }
+
+int lltemac_eth_initialize(bd_t * bis)
+{
+	struct eth_device *dev;
+	struct xps_ll_temac_private *lp;
+
+	dev = (struct eth_device *) calloc(1, sizeof(struct eth_device));
+	if (NULL == dev)
+	{
+		puts("Failed to allocate memory\n");
+		return -1;
+	}
+	memset(dev, 0, sizeof(*dev));
+
+	sprintf(dev->name, "Xilinx LL Temac");
+	dev->init = lltemac_eth_init;
+	dev->halt = lltemac_eth_halt;
+	dev->send = lltemac_eth_send;
+	dev->recv = lltemac_eth_recv;
+
+	lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct
xps_ll_temac_private));
+	if (lp == NULL)
+		return 0;
+	dev->priv = lp;
+
+	eth_register(dev);
+	return 0;
+}
diff --git a/include/configs/microblaze-generic.h
b/include/configs/microblaze-generic.h
index 7110f91..2035923 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -67,6 +67,7 @@
 #elif XILINX_LLTEMAC_BASEADDR
 	#define CONFIG_XILINX_LL_TEMAC	1
 	#define CONFIG_SYS_ENET
+	#define CONFIG_NET_MULTI
 #endif

 #undef ET_DEBUG

diff --git a/include/netdev.h b/include/netdev.h
index 751f0da..398c589 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -51,6 +51,7 @@ int fec_initialize (bd_t *bis);
 int greth_initialize(bd_t *bis);
 void gt6426x_eth_initialize(bd_t *bis);
 int inca_switch_initialize(bd_t *bis);
+int lltemac_eth_initialize(bd_t * bis);
 int macb_eth_initialize(int id, void *regs, unsigned int phy_addr);
 int mcdmafec_initialize(bd_t *bis);
 int mcffec_initialize(bd_t *bis);
diff --git a/lib_microblaze/board.c b/lib_microblaze/board.c
index 30d7641..1274934 100644
--- a/lib_microblaze/board.c
+++ b/lib_microblaze/board.c
@@ -29,6 +29,7 @@
 #include <malloc.h>
 #include <timestamp.h>
 #include <version.h>
+#include <net.h>
 #include <watchdog.h>

 DECLARE_GLOBAL_DATA_PTR;
@@ -43,7 +44,7 @@ extern int interrupts_init (void);
 #endif
 #if defined(CONFIG_CMD_NET)
 extern int eth_init (bd_t * bis);
-extern int getenv_IPaddr (char *);
+//extern int getenv_IPaddr (char *);
 #endif

 /*
@@ -183,7 +184,9 @@ void board_init (void)
 	}
 	/* IP Address */
 	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
-	eth_init (bd);
+//	eth_init (bd);
+	eth_initialize (bd);
+
 #endif

 	/* relocate environment function pointers etc. */
diff --git a/net/eth.c b/net/eth.c
index b7ef09f..f5e6bc4 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -37,7 +37,7 @@ static int __def_eth_init(bd_t *bis)
 	return -1;
 }
 int cpu_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
-int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
+//int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));

 extern int mv6436x_eth_initialize(bd_t *);
 extern int mv6446x_eth_initialize(bd_t *);
@@ -143,9 +143,13 @@ int eth_initialize(bd_t *bis)
 #endif
 	/* Try board-specific initialization first.  If it fails or isn't
 	 * present, try the cpu-specific initialization */
+	puts ("before\n");
+
 	if (board_eth_init(bis) < 0)
 		cpu_eth_init(bis);

+	puts("after\n");
+
 #if defined(CONFIG_DB64360) || defined(CONFIG_CPCI750)
 	mv6436x_eth_initialize(bis);
 #endif


-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-24 15:11       ` Michal Simek
@ 2009-02-24 17:51         ` Ben Warren
  2009-02-24 18:27           ` Michal Simek
  0 siblings, 1 reply; 9+ messages in thread
From: Ben Warren @ 2009-02-24 17:51 UTC (permalink / raw)
  To: u-boot

Hi Michal,

Michal Simek wrote:
> Hi Ben,
>   
>> Hi Michal,
>>
>> Michal Simek wrote:
>>
>> <snip>
>>     
>>>> All of the above mentioned issues are ones that I could easily deal
>>>> with, but one thing that really does need to change is that you need to
>>>> use the CONFIG_NET_MULTI API.  In other words, your driver should have a
>>>> single initialize() function (prototyped in include/netdev.h), and an
>>>> eth_device struct that gets registered.  All your access functions
>>>> (eth_init, eth_send, eth_recv etc.) will be static and pointed to by the
>>>> eth_device struct.  Most drivers are already this way.
>>>>     
>>>>         
>>> I look at it and I did some change and the main problem is in
>>> Microblaze GCC.
>>> We use GCC 3.4.1 and CONFIG_NET_MULTI use weak function and
>>> board_eth_init is
>>> never called. We are working on GCC 4.1.2 but I don't know when I get it.
>>>
>>>   
>>>       
>> According to the documentation I could find, weak symbols were present
>> in gcc 3.4.1.  Are you sure you're using them properly?  Due to the way
>> linking is performed in U-boot, any weak symbol overrides need to be in
>> source files that have strongly linked symbols.  You'll see that all
>> implementations of cpu_eth_init() and board_eth_init() are in files that
>> already contain stuff that is sure to be linked.
>>     
>
>
> hmm. I did some tests and I found that the my problem is with this line 40. (I
> use board_eth_init initialization)
> int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
> I am not gcc specialist but I smell problem with GCC.
>
>   
This essentially says "board_eth_init() = __def_eth_init() unless 
overridden by a strongly linked function".  Here's how I debug this 
stuff, and you don't need to instrument your code or even run it to know 
if the linking worked properly:

Look in the System.map file that the build system generates (it's 
human-readable).   If there are no overriding functions, you'd expect 
that the addresses of __def_eth_int(), cpu_eth_init() and 
board_eth_init() to be identical.  If YOUR board_eth_init() is linked 
in, it will have a different address.  That's it!

regards,
Ben

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

* [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2
  2009-02-24 17:51         ` Ben Warren
@ 2009-02-24 18:27           ` Michal Simek
  0 siblings, 0 replies; 9+ messages in thread
From: Michal Simek @ 2009-02-24 18:27 UTC (permalink / raw)
  To: u-boot

Ben Warren wrote:
> Hi Michal,
> 
> Michal Simek wrote:
>> Hi Ben,
>>  
>>> Hi Michal,
>>>
>>> Michal Simek wrote:
>>>
>>> <snip>
>>>    
>>>>> All of the above mentioned issues are ones that I could easily deal
>>>>> with, but one thing that really does need to change is that you
>>>>> need to
>>>>> use the CONFIG_NET_MULTI API.  In other words, your driver should
>>>>> have a
>>>>> single initialize() function (prototyped in include/netdev.h), and an
>>>>> eth_device struct that gets registered.  All your access functions
>>>>> (eth_init, eth_send, eth_recv etc.) will be static and pointed to
>>>>> by the
>>>>> eth_device struct.  Most drivers are already this way.
>>>>>             
>>>> I look at it and I did some change and the main problem is in
>>>> Microblaze GCC.
>>>> We use GCC 3.4.1 and CONFIG_NET_MULTI use weak function and
>>>> board_eth_init is
>>>> never called. We are working on GCC 4.1.2 but I don't know when I
>>>> get it.
>>>>
>>>>         
>>> According to the documentation I could find, weak symbols were present
>>> in gcc 3.4.1.  Are you sure you're using them properly?  Due to the way
>>> linking is performed in U-boot, any weak symbol overrides need to be in
>>> source files that have strongly linked symbols.  You'll see that all
>>> implementations of cpu_eth_init() and board_eth_init() are in files that
>>> already contain stuff that is sure to be linked.
>>>     
>>
>>
>> hmm. I did some tests and I found that the my problem is with this
>> line 40. (I
>> use board_eth_init initialization)
>> int board_eth_init(bd_t *bis) __attribute((weak,
>> alias("__def_eth_init")));
>> I am not gcc specialist but I smell problem with GCC.
>>
>>   
> This essentially says "board_eth_init() = __def_eth_init() unless
> overridden by a strongly linked function".  Here's how I debug this
> stuff, and you don't need to instrument your code or even run it to know
> if the linking worked properly:
> 
> Look in the System.map file that the build system generates (it's
> human-readable).   If there are no overriding functions, you'd expect
> that the addresses of __def_eth_int(), cpu_eth_init() and
> board_eth_init() to be identical.  If YOUR board_eth_init() is linked
> in, it will have a different address.  That's it!

Address are different for both cases
[monstr at monstr u-boot-eth]$ cat System.map | grep board_eth_init
9181cb34 T board_eth_init
[monstr at monstr u-boot-eth]$ cat System.map | grep def_eth_init
918036c4 t __def_eth_init
[monstr at monstr u-boot-eth]$ cat System.map | grep cpu_eth_init
918036c4 W cpu_eth_init


918038c8:       b000ffff        imm     -1
918038cc:       b9f4fdf8        brlid   r15, -520       // 918036c4 <cpu_eth_init>
918038d0:       10b30000        addk    r5, r19, r0
918038d4:       bca30010        bgei    r3, 16          // 918038e4
918038d8:       b000ffff        imm     -1
918038dc:       b9f4fde8        brlid   r15, -536       // 918036c4 <cpu_eth_init>


from net/eth.c 148:149
        if (board_eth_init(bis) < 0)
                cpu_eth_init(bis);

As you can see from objdump above -> my toolchain add the same address for
board_eth_init and cpu_eth_init but that's wrong.

Thanks,
Michal


> 
> regards,
> Ben


-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854

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

end of thread, other threads:[~2009-02-24 18:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-01 11:16 [U-Boot] [PATCH 1/1] net: Add Xilinx LL Temac driver version2 monstr at monstr.eu
2009-02-17  9:35 ` Michal Simek
2009-02-23  6:45 ` Ben Warren
2009-02-23  8:03   ` Michal Simek
2009-02-23 13:51   ` Michal Simek
2009-02-23 18:29     ` Ben Warren
2009-02-24 15:11       ` Michal Simek
2009-02-24 17:51         ` Ben Warren
2009-02-24 18:27           ` Michal Simek

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