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

Reply via email to