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: > [email protected] wrote: >> From: Michal Simek <[email protected]> >> >> 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 <[email protected]> >> >> --- >> >> 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 <[email protected]> >> * >> * (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 [email protected] >> + * >> + * Copyright (C) 2008 Nissin Systems Co.,Ltd. >> + * March 2008 created >> + * >> + * Copyright (C) 2008 - 2009 Michal Simek <[email protected]> >> + * 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 > [email protected] > http://lists.denx.de/mailman/listinfo/u-boot > -- Michal Simek, Ing. (M.Eng) w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/ Microblaze U-BOOT custodian _______________________________________________ U-Boot mailing list [email protected] http://lists.denx.de/mailman/listinfo/u-boot

