mon...@monstr.eu wrote: > From: Michal Simek <mon...@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 <mon...@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 <mon...@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 kashiw...@co-nss.co.jp > + * > + * Copyright (C) 2008 Nissin Systems Co.,Ltd. > + * March 2008 created > + * > + * Copyright (C) 2008 - 2009 Michal Simek <mon...@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