
Hi Ben,
sorry for head quoting but this is V2. In my net branch is V3 which has some fixes which you reported.
Anyway. You want to create two separate patches. I am ok with it. I'll do it and let you know.
Thanks, Michal
Ben Warren wrote:
monstr@monstr.eu wrote:
From: Michal Simek monstr@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.
Please break this up into two independent patches. I can sort through the common files when it comes time to integrate.
There are some changes for proper initialization too.
Signed-off-by: Michal Simek monstr@monstr.eu
V2: Applied Ben comments
.../xilinx/microblaze-generic/microblaze-generic.c | 16 + drivers/net/Makefile | 1 + drivers/net/xilinx_emaclite.c | 86 ++-- drivers/net/xilinx_ll_temac.c | 558 ++++++++++++++++++++ include/configs/microblaze-generic.h | 2 + include/netdev.h | 2 + lib_microblaze/board.c | 21 +- 7 files changed, 639 insertions(+), 47 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.
*/
I asked before to remove this incorrect information.
+#ifdef CONFIG_XILINX_EMACLITE
- return xilinx_emaclite_initialize(bis);
+#endif +#ifdef CONFIG_XILINX_LL_TEMAC
- return xilinx_ll_temac_initialize(bis);
+#endif +}
Here's an opportunity to pass in device addresses.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 67018bb..4fd53f9 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -73,6 +73,7 @@ COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.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..99b5ae1 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -14,7 +14,7 @@
- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE.
- (C) Copyright 2007-2008 Michal Simek
- (C) Copyright 2007-2009 Michal Simek
- Michal SIMEK monstr@monstr.eu
- (c) Copyright 2003 Xilinx Inc.
@@ -25,6 +25,7 @@ #include <common.h> #include <net.h> #include <config.h> +#include <malloc.h> #include <asm/io.h>
#undef DEBUG @@ -62,26 +63,19 @@ #define XEL_RSR_RECV_IE_MASK 0x00000008UL
typedef struct {
- unsigned int baseaddress; /* Base address for device (IPIF) */
- unsigned int nexttxbuffertouse; /* Next TX buffer to write to */
- unsigned int nextrxbuffertouse; /* Next RX buffer to read from */
- unsigned char deviceid; /* Unique ID of device - for future */
- u32 baseaddress; /* Base address for device (IPIF) */
- u32 nexttxbuffertouse; /* Next TX buffer to write to */
- u32 nextrxbuffertouse; /* Next RX buffer to read from */
- uchar deviceid; /* Unique ID of device - for future */
} xemaclite;
static xemaclite emaclite;
static u32 etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */
-/* hardcoded MAC address for the Xilinx EMAC Core when env is nowhere*/ -#ifdef CONFIG_ENV_IS_NOWHERE -static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 }; -#else -static u8 emacaddr[ENET_ADDR_LENGTH]; -#endif
-void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount) +static void xemaclite_alignedread (u32 * srcptr, void *destptr, u32 bytecount) {
- unsigned int i;
- u32 i; u32 alignbuffer; u32 *to32ptr; u32 *from32ptr;
@@ -106,9 +100,9 @@ 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, u32 bytecount) {
- unsigned i;
- u32 i; u32 alignbuffer; u32 *to32ptr = (u32 *) destptr; u32 *from32ptr;
@@ -133,23 +127,16 @@ 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];
- debug ("EmacLite Initialization Started\n"); memset (&emaclite, 0, sizeof (xemaclite));
- emaclite.baseaddress = XILINX_EMACLITE_BASEADDR;
- if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
memcpy(enetaddr, emacaddr, ENET_ADDR_LENGTH);
eth_setenv_enetaddr("ethaddr", enetaddr);
- }
- emaclite.baseaddress = dev->iobase;
/*
- TX - TX_PING & TX_PONG initialization
@@ -157,7 +144,7 @@ int eth_init (bd_t * bis) /* Restart PING TX */ out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0); /* Copy MAC address */
- xemaclite_alignedwrite (enetaddr,
- xemaclite_alignedwrite (dev->enetaddr, emaclite.baseaddress, ENET_ADDR_LENGTH); /* Set the length */ out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
@@ -170,7 +157,7 @@ int eth_init (bd_t * bis) #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG /* The same operation with PONG TX */ out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0);
- xemaclite_alignedwrite (enetaddr, emaclite.baseaddress +
- xemaclite_alignedwrite (dev->enetaddr, emaclite.baseaddress + XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH); out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH); out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET,
@@ -193,7 +180,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,12 +202,12 @@ int xemaclite_txbufferavailable (xemaclite * instanceptr) return (!(txpingbusy && txpongbusy)); }
-int eth_send (volatile void *ptr, int len) {
- unsigned int reg;
- unsigned int baseaddress;
+static int emaclite_send (struct eth_device *dev, volatile void *ptr, int len) +{
- u32 reg;
- u32 baseaddress;
- unsigned maxtry = 1000;
u32 maxtry = 1000;
if (len > ENET_MAX_MTU) len = ENET_MAX_MTU;
@@ -292,11 +279,11 @@ 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;
- unsigned int baseaddress;
u32 length;
u32 reg;
u32 baseaddress;
baseaddress = emaclite.baseaddress + emaclite.nextrxbuffertouse; reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
@@ -352,3 +339,26 @@ 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 = XILINX_EMACLITE_BASEADDR;
Pass this in as a parameter, then you can have multiple instances.
- 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..d73e22e --- /dev/null +++ b/drivers/net/xilinx_ll_temac.c @@ -0,0 +1,558 @@ +/*
- Xilinx xps_ll_temac ethernet driver for u-boot
- Author: Yoshio Kashiwagi kashiwagi@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
Why not set the mode via a parameter to x_initialize()? You can have a mode element in the priv structure that moves a lot of choices to runtime. More importantly, it would get rid of a lot if #ifdefs
+#else +# error Xilinx LL Temac: Unsupported mode - Please setup SDMA or FIFO mode +#endif
+#undef ETH_HALTING
+#ifdef SDMA_MODE +/* XPS_LL_TEMAC SDMA registers definition */ +# define TX_NXTDESC_PTR (((struct ll_priv *)(dev->priv))->sdma + 0x00) +# define TX_CURBUF_ADDR (((struct ll_priv *)(dev->priv))->sdma + 0x04) +# define TX_CURBUF_LENGTH (((struct ll_priv *)(dev->priv))->sdma + 0x08) +# define TX_CURDESC_PTR (((struct ll_priv *)(dev->priv))->sdma + 0x0c) +# define TX_TAILDESC_PTR (((struct ll_priv *)(dev->priv))->sdma + 0x10) +# define TX_CHNL_CTRL (((struct ll_priv *)(dev->priv))->sdma + 0x14) +# define TX_IRQ_REG (((struct ll_priv *)(dev->priv))->sdma + 0x18) +# define TX_CHNL_STS (((struct ll_priv *)(dev->priv))->sdma + 0x1c)
+# define RX_NXTDESC_PTR (((struct ll_priv *)(dev->priv))->sdma + 0x20) +# define RX_CURBUF_ADDR (((struct ll_priv *)(dev->priv))->sdma + 0x24) +# define RX_CURBUF_LENGTH (((struct ll_priv *)(dev->priv))->sdma + 0x28) +# define RX_CURDESC_PTR (((struct ll_priv *)(dev->priv))->sdma + 0x2c) +# define RX_TAILDESC_PTR (((struct ll_priv *)(dev->priv))->sdma + 0x30) +# define RX_CHNL_CTRL (((struct ll_priv *)(dev->priv))->sdma + 0x34) +# define RX_IRQ_REG (((struct ll_priv *)(dev->priv))->sdma + 0x38) +# define RX_CHNL_STS (((struct ll_priv *)(dev->priv))->sdma + 0x3c)
+# define DMA_CONTROL_REG (((struct ll_priv *)(dev->priv))->sdma + 0x40) +#endif
+/* XPS_LL_TEMAC direct registers definition */ +#define TEMAC_RAF0 (dev->iobase + 0x00) +#define TEMAC_TPF0 (dev->iobase + 0x04) +#define TEMAC_IFGP0 (dev->iobase + 0x08) +#define TEMAC_IS0 (dev->iobase + 0x0c) +#define TEMAC_IP0 (dev->iobase + 0x10) +#define TEMAC_IE0 (dev->iobase + 0x14)
+#define TEMAC_MSW0 (dev->iobase + 0x20) +#define TEMAC_LSW0 (dev->iobase + 0x24) +#define TEMAC_CTL0 (dev->iobase + 0x28) +#define TEMAC_RDY0 (dev->iobase + 0x2c)
Please represent the registers as a struct. It makes the code much easier to read and removes a lot of casts.
+#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
+#ifdef SDMA_MODE +static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32))); +#endif +static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32)));
+struct ll_priv {
- unsigned int sdma;
+};
+#ifdef DEBUG +/* undirect hostif write to ll_temac */ +static void xps_ll_temac_hostif_set(struct eth_device *dev, int emac,
int phy_addr, int reg_addr, int phy_data)
+{
- out_be32((u32 *)TEMAC_LSW0, phy_data);
Like here, wouldn't it be nicer to have: out_be32(dev->priv->regs->lsw0, phy_data)
(of course, get a pointer to regs first...)
- 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(struct eth_device *dev,
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(struct eth_device *dev,
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));
+}
+#if DEBUG +/* undirect read from ll_temac */ +static int xps_ll_temac_indirect_get(struct eth_device *dev,
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);
+} +#endif
+#ifdef DEBUG +/* read from phy */ +static void read_phy_reg (struct eth_device *dev, int phy_addr) +{
- int j, result;
- debug ("phy%d ",phy_addr);
- for ( j = 0; j < 32; j++) {
result = xps_ll_temac_hostif_get(dev, 0, phy_addr, j);
debug ("%d: 0x%x ", j, result);
- }
- debug ("\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(struct eth_device *dev) +{
- 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(dev, 0, phy_addr, 1) & 0x24) == 0x24))
;
- if(phy_addr == -1) {
for(i = 31; i >= 0; i--) {
result = xps_ll_temac_hostif_get(dev, 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(dev, 0, phy_addr, 2) << 16) | \
xps_ll_temac_hostif_get(dev, 0, phy_addr, 3);
- debug ("LL_TEMAC: Phy ID 0x%x\n", i);
+#ifdef DEBUG
- xps_ll_temac_hostif_set(dev, 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(dev, 0, EMMC, 0x40000000);
link = 1;
return 1;
- }
- /* Marwell 88e1111 id - ml50x */
- if (i == 0x1410cc2) {
result = xps_ll_temac_hostif_get(dev, 0, phy_addr, 5);
if((result & 0x8000) == 0x8000) {
xps_ll_temac_indirect_set(dev, 0, EMMC, 0x80000000);
printf("1000BASE-T/FD\n");
link = 1;
} else if((result & 0x4000) == 0x4000) {
xps_ll_temac_indirect_set(dev, 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(struct eth_device *dev) +{
- 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(struct eth_device *dev,
unsigned char *buffer, int length)
+{
- if( xps_ll_temac_phy_ctrl(dev) == 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(struct eth_device *dev) +{
- 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 +#ifdef DEBUG +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);
+} +#endif
+static int xps_ll_temac_send_fifo(unsigned char *buffer, int length)
The FIFO functions should definitely take eth_device * as a parameter.
+{
- u32 *buf = (u32 *)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(void) +{
- u32 len, len2, i, val;
- u32 *buf = (u32 *)&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 ((uchar *)&rx_buffer, len);
- }
- return 0;
+} +#endif
+/* setup mac addr */ +static int xps_ll_temac_addr_setup(struct eth_device *dev) +{
- int val;
- /* set up unicast MAC address filter */
- val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) |
(dev->enetaddr[1] << 8) | (dev->enetaddr[0] ));
- xps_ll_temac_indirect_set(dev, 0, UAW0, val);
- val = (dev->enetaddr[5] << 8) | dev->enetaddr[4] ;
- xps_ll_temac_indirect_set(dev, 0, UAW1, val);
- return 0;
+}
+static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis) +{ +#ifdef SDMA_MODE
- xps_ll_temac_bd_init(dev);
+#endif +#ifdef FIFO_MODE
- ll_fifo->tdfr = 0x000000a5; /* set fifo length */
- ll_fifo->rdfr = 0x000000a5;
- /* ll_fifo->isr = 0x0; */
- /* ll_fifo->ier = 0x0; */
+#endif
- xps_ll_temac_indirect_set(dev, 0, MC,
MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_100MHz);
- xps_ll_temac_addr_setup(dev);
- /* Promiscuous mode disable */
- xps_ll_temac_indirect_set(dev, 0, AFM, 0x00000000);
- /* Enable Receiver */
- xps_ll_temac_indirect_set(dev, 0, RCW1, 0x10000000);
- /* Enable Transmitter */
- xps_ll_temac_indirect_set(dev, 0, TC, 0x10000000);
- return 0;
+}
+static void xps_ll_temac_halt(struct eth_device *dev) +{ +#ifdef ETH_HALTING
- /* Disable Receiver */
- xps_ll_temac_indirect_set(dev, 0, RCW1, 0x00000000);
- /* Disable Transmitter */
- xps_ll_temac_indirect_set(dev, 0, TC, 0x00000000);
+#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(dev);
+}
+static int ll_temac_init(struct eth_device *dev, bd_t *bis) +{
- static int first = 1;
+#if DEBUG
- int i;
+#endif
- if(!first)
return 0;
- first = 0;
- xps_ll_temac_init(dev, bis);
- printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
dev->name, 0, dev->iobase);
+#if DEBUG
- for(i = 0; i < 32; i++) {
read_phy_reg(dev, i);
- }
+#endif
- xps_ll_temac_phy_ctrl(dev);
- 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(dev, (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(dev);
+#endif +#ifdef FIFO_MODE
- return xps_ll_temac_recv_fifo();
+#endif +}
+int xilinx_ll_temac_initialize (bd_t *bis) +{
- struct eth_device *dev;
- dev = calloc(1, sizeof(*dev));
- if (dev == NULL)
hang();
- dev->priv = (struct ll_priv *)
calloc(1, sizeof(struct ll_priv));
- if (dev->priv == NULL)
hang();
- sprintf(dev->name, "Xilinx LL TEMAC");
- dev->iobase = XILINX_LLTEMAC_BASEADDR;
+#ifdef SDMA_MODE
- ((struct ll_priv *)(dev->priv))->sdma =
XILINX_LLTEMAC_SDMA_CTRL_BASEADDR;
+#endif
If you pass this stuff in as parameters, you can have multiple instances.
- 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 9a08987..3fd2211 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -229,8 +229,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 (;;) {
Thanks a lot. This is promising.
regards, Ben _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot