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

Reply via email to