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