[U-Boot] [PATCH 2/7] net: Add LL TEMAC driver to u-boot and move Emaclite to NET_MULTI
monstr at monstr.eu
monstr at monstr.eu
Thu Aug 20 22:52:26 CEST 2009
From: Michal Simek <monstr at monstr.eu>
Here are two major changes which should go together.
First is adding LL Temac driver to u-boot and the second
is changing Emaclite to NET_MULTI api.
There are some changes for proper initialization too.
Signed-off-by: Michal Simek <monstr at monstr.eu>
Signed-off-by: Michal Simek <michal.simek at petalogix.com>
---
.../xilinx/microblaze-generic/microblaze-generic.c | 16 +
drivers/net/Makefile | 1 +
drivers/net/xilinx_emaclite.c | 42 ++-
drivers/net/xilinx_ll_temac.c | 567 ++++++++++++++++++++
include/configs/microblaze-generic.h | 2 +
include/netdev.h | 2 +
lib_microblaze/board.c | 21 +-
7 files changed, 634 insertions(+), 17 deletions(-)
create mode 100644 drivers/net/xilinx_ll_temac.c
diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c
index f388b77..4ad9eb6 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,18 @@ void fsl_init2 (void) {
NULL);
}
#endif
+
+int board_eth_init(bd_t *bis)
+{
+ /*
+ * This board either has PCI NICs or uses the CPU's TSECs
+ * pci_eth_init() will return 0 if no NICs found, so in that case
+ * returning -1 will force cpu_eth_init() to be called.
+ */
+#ifdef CONFIG_XILINX_EMACLITE
+ return xilinx_emaclite_initialize(bis);
+#endif
+#ifdef CONFIG_XILINX_LL_TEMAC
+ return xilinx_ll_temac_initialize(bis);
+#endif
+}
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 1c6e402..98cb3a1 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -74,6 +74,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 := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index cf39573..e437d16 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -25,6 +25,7 @@
#include <common.h>
#include <net.h>
#include <config.h>
+#include <malloc.h>
#include <asm/io.h>
#undef DEBUG
@@ -79,7 +80,7 @@ static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 };
static u8 emacaddr[ENET_ADDR_LENGTH];
#endif
-void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount)
+static void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount)
{
unsigned int i;
u32 alignbuffer;
@@ -106,7 +107,7 @@ void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount)
}
}
-void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount)
+static void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount)
{
unsigned i;
u32 alignbuffer;
@@ -133,12 +134,12 @@ void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount)
*to32ptr++ = alignbuffer;
}
-void eth_halt (void)
+static void emaclite_halt(struct eth_device *dev)
{
debug ("eth_halt\n");
}
-int eth_init (bd_t * bis)
+static int emaclite_init(struct eth_device *dev, bd_t *bis)
{
uchar enetaddr[6];
@@ -193,7 +194,7 @@ int eth_init (bd_t * bis)
return 0;
}
-int xemaclite_txbufferavailable (xemaclite * instanceptr)
+static int xemaclite_txbufferavailable (xemaclite * instanceptr)
{
u32 reg;
u32 txpingbusy;
@@ -215,8 +216,8 @@ int xemaclite_txbufferavailable (xemaclite * instanceptr)
return (!(txpingbusy && txpongbusy));
}
-int eth_send (volatile void *ptr, int len) {
-
+static int emaclite_send (struct eth_device *dev, volatile void *ptr, int len)
+{
unsigned int reg;
unsigned int baseaddress;
@@ -292,7 +293,8 @@ int eth_send (volatile void *ptr, int len) {
return 0;
}
-int eth_rx (void)
+
+static int emaclite_recv(struct eth_device *dev)
{
unsigned int length;
unsigned int reg;
@@ -352,3 +354,27 @@ int eth_rx (void)
return 1;
}
+
+
+int xilinx_emaclite_initialize (bd_t *bis)
+{
+ struct eth_device *dev;
+
+ dev = malloc(sizeof(*dev));
+ if (dev == NULL)
+ hang();
+
+ memset(dev, 0, sizeof(*dev));
+ sprintf(dev->name, "Xilinx Emaclite");
+
+ dev->iobase = 0;
+ dev->priv = 0;
+ dev->init = emaclite_init;
+ dev->halt = emaclite_halt;
+ dev->send = emaclite_send;
+ dev->recv = emaclite_recv;
+
+ eth_register(dev);
+
+ return 0;
+}
diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c
new file mode 100644
index 0000000..4b42b06
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac.c
@@ -0,0 +1,567 @@
+/*
+ *
+ * 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 at 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 */
+static 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) {
+#ifdef DEBUG
+ printf ("phy %x result %x\n", i, result);
+#endif
+ 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);
+#ifdef DEBUG
+ printf("LL_TEMAC: Phy ID 0x%x\n", i);
+#endif
+
+#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) {
+ xps_ll_temac_indirect_set(0, EMMC, 0x40000000); /* 100BASE-T/FD */
+ 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);
+}
+#endif
+
+#ifdef SDMA_MODE
+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
+static 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);
+ xps_ll_temac_indirect_set(0, AFM, 0x00000000); /* Promiscuos mode disable */
+ xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver */
+ xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable Transmitter */
+ return 0;
+}
+
+
+static void xps_ll_temac_halt(void)
+{
+#ifdef ETH_HALTING
+ 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 */
+static void ll_temac_halt(struct eth_device *dev)
+{
+ link = 0;
+ xps_ll_temac_halt();
+}
+
+static int ll_temac_init(struct eth_device *dev, bd_t *bis)
+{
+ static int first = 1;
+ struct xps_ll_temac_private *lp;
+#if 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",
+ dev->name, 0, XILINX_LLTEMAC_BASEADDR);
+
+#if DEBUG
+ for(i = 0;i < 32;i++) {
+ read_phy_reg(i);
+ }
+#endif
+ xps_ll_temac_phy_ctrl();
+ return 1;
+}
+
+
+static int ll_temac_send(struct eth_device *dev, 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
+}
+
+static int ll_temac_recv(struct eth_device *dev)
+{
+#ifdef SDMA_MODE
+ return xps_ll_temac_recv_sdma();
+#endif
+#ifdef FIFO_MODE
+ return xps_ll_temac_recv_fifo();
+#endif
+}
+
+int xilinx_ll_temac_initialize (bd_t *bis)
+{
+ struct eth_device *dev;
+
+ dev = malloc(sizeof(*dev));
+ if (dev == NULL)
+ hang();
+
+ memset(dev, 0, sizeof(*dev));
+ sprintf(dev->name, "Xilinx LL TEMAC");
+
+ dev->iobase = 0;
+ dev->priv = 0;
+ dev->init = ll_temac_init;
+ dev->halt = ll_temac_halt;
+ dev->send = ll_temac_send;
+ dev->recv = ll_temac_recv;
+
+ eth_register(dev);
+
+ return 0;
+}
diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h
index 72715f6..89e4bcc 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -232,8 +232,10 @@
#ifndef CONFIG_SYS_ENET
#undef CONFIG_CMD_NET
+ #undef CONFIG_NET_MULTI
#else
#define CONFIG_CMD_PING
+ #define CONFIG_NET_MULTI
#endif
#if defined(CONFIG_SYSTEMACE)
diff --git a/include/netdev.h b/include/netdev.h
index 50329a3..8da0110 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -78,6 +78,8 @@ int tsi108_eth_initialize(bd_t *bis);
int uec_initialize(int index);
int uec_standard_init(bd_t *bis);
int uli526x_initialize(bd_t *bis);
+int xilinx_emaclite_initialize (bd_t *bis);
+int xilinx_ll_temac_initialize(bd_t *bis);
int sh_eth_initialize(bd_t *bis);
int dm9000_initialize(bd_t *bis);
diff --git a/lib_microblaze/board.c b/lib_microblaze/board.c
index cfed5fe..8d17b03 100644
--- a/lib_microblaze/board.c
+++ b/lib_microblaze/board.c
@@ -30,6 +30,7 @@
#include <timestamp.h>
#include <version.h>
#include <watchdog.h>
+#include <net.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -41,10 +42,6 @@ extern int gpio_init (void);
#ifdef CONFIG_SYS_INTC_0
extern int interrupts_init (void);
#endif
-#if defined(CONFIG_CMD_NET)
-extern int eth_init (bd_t * bis);
-extern int getenv_IPaddr (char *);
-#endif
/*
* Begin and End of memory area for malloc(), and current "brk"
@@ -168,14 +165,20 @@ void board_init (void)
}
#endif
+ /* relocate environment function pointers etc. */
+ env_relocate ();
+
#if defined(CONFIG_CMD_NET)
/* IP Address */
- bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
- eth_init (bd);
-#endif
+ bd->bi_ip_addr = getenv_IPaddr("ipaddr");
- /* relocate environment function pointers etc. */
- env_relocate ();
+ printf("Net: ");
+ eth_initialize(gd->bd);
+
+ uchar enetaddr[6];
+ eth_getenv_enetaddr("ethaddr", enetaddr);
+ printf("MAC: %pM\n", enetaddr);
+#endif
/* main_loop */
for (;;) {
--
1.5.4.7
More information about the U-Boot
mailing list