[U-Boot] Xilinx LL-TEMAC driver

Hi Ben and Wolfgang,
first patch just sort labels in drivers/net/Makefile I think this patch could be applied directly to Wolfgang tree.
The second patch is Xilinx LL Temac driver. This driver was sent to mailing list some month ago by Yoshio Kashiwagi. I clean the driver and add support for Fifo mode.
This driver is tested on some Microblaze boards.
There is one part which should be rework in future. (FIXME comment) It is about PHY lib which we discussed in past. I believe that this part won't be a problem.
Thanks for your comments, Michal

From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu --- drivers/net/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..128dc11 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o @@ -54,11 +55,11 @@ COBJS-$(CONFIG_NS8382X) += ns8382x.o COBJS-$(CONFIG_DRIVER_NS9750_ETHERNET) += ns9750_eth.o COBJS-$(CONFIG_PCNET) += pcnet.o COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o -COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o COBJS-$(CONFIG_RTL8139) += rtl8139.o COBJS-$(CONFIG_RTL8169) += rtl8169.o COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o +COBJS-$(CONFIG_SH_ETHER) += sh_eth.o COBJS-$(CONFIG_DRIVER_SMC91111) += smc91111.o COBJS-$(CONFIG_DRIVER_SMC911X) += smc911x.o COBJS-$(CONFIG_TIGON3) += tigon3.o bcm570x_autoneg.o 5701rls.o @@ -68,7 +69,6 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o -COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c)

From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu --- drivers/net/Makefile | 1 + drivers/net/xilinx_ll_temac.c | 543 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 544 insertions(+), 0 deletions(-) create mode 100644 drivers/net/xilinx_ll_temac.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 128dc11..ed64787 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.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_ll_temac.c b/drivers/net/xilinx_ll_temac.c new file mode 100644 index 0000000..d1e63e2 --- /dev/null +++ b/drivers/net/xilinx_ll_temac.c @@ -0,0 +1,543 @@ +/* + * + * Xilinx xps_ll_temac ethernet driver for u-boot + * + * Author: Yoshio Kashiwagi kashiwagi@co-nss.co.jp + * + * Copyright (C) 2008 Nissin Systems Co.,Ltd. + * March 2008 created + * + * Copyright (C) 2008 - 2009 Michal Simek monstr@monstr.eu + * June 2008 Microblaze optimalization, FIFO mode support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <config.h> +#include <common.h> +#include <net.h> +#include <malloc.h> +#include <asm/processor.h> +#include <asm/io.h> + +#ifdef XILINX_LLTEMAC_FIFO_BASEADDR +# define FIFO_MODE 1 +#elif XILINX_LLTEMAC_SDMA_CTRL_BASEADDR +# define SDMA_MODE 1 +#else +# error Unsupported mode +#endif + +#undef ETH_HALTING + +#ifdef SDMA_MODE +/* XPS_LL_TEMAC SDMA registers definition */ +# define TX_NXTDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x00) +# define TX_CURBUF_ADDR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x04) +# define TX_CURBUF_LENGTH (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x08) +# define TX_CURDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x0c) +# define TX_TAILDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x10) +# define TX_CHNL_CTRL (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x14) +# define TX_IRQ_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x18) +# define TX_CHNL_STS (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x1c) + +# define RX_NXTDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x20) +# define RX_CURBUF_ADDR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x24) +# define RX_CURBUF_LENGTH (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x28) +# define RX_CURDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x2c) +# define RX_TAILDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x30) +# define RX_CHNL_CTRL (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x34) +# define RX_IRQ_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x38) +# define RX_CHNL_STS (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x3c) + +# define DMA_CONTROL_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x40) +#endif + +/* XPS_LL_TEMAC direct registers definition */ +#define TEMAC_RAF0 (XILINX_LLTEMAC_BASEADDR + 0x00) +#define TEMAC_TPF0 (XILINX_LLTEMAC_BASEADDR + 0x04) +#define TEMAC_IFGP0 (XILINX_LLTEMAC_BASEADDR + 0x08) +#define TEMAC_IS0 (XILINX_LLTEMAC_BASEADDR + 0x0c) +#define TEMAC_IP0 (XILINX_LLTEMAC_BASEADDR + 0x10) +#define TEMAC_IE0 (XILINX_LLTEMAC_BASEADDR + 0x14) + +#define TEMAC_MSW0 (XILINX_LLTEMAC_BASEADDR + 0x20) +#define TEMAC_LSW0 (XILINX_LLTEMAC_BASEADDR + 0x24) +#define TEMAC_CTL0 (XILINX_LLTEMAC_BASEADDR + 0x28) +#define TEMAC_RDY0 (XILINX_LLTEMAC_BASEADDR + 0x2c) + +#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 + +static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32))); +static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32))); + +struct xps_ll_temac_private { + int idx; + unsigned char dev_addr[6]; +}; + +#ifdef DEBUG +/* undirect hostif write to ll_temac */ +static void xps_ll_temac_hostif_set(int emac, int phy_addr, + int reg_addr, int phy_data) +{ + out_be32((u32 *)TEMAC_LSW0, phy_data); + 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(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(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)); +} + +/* undirect read from ll_temac */ +int xps_ll_temac_indirect_get(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); +} + +#ifdef DEBUG +/* read from phy */ +static void read_phy_reg (int phy_addr) +{ + int j, result; + printf("phy%d ",phy_addr); + for ( j = 0; j < 32; j++) { + result = xps_ll_temac_hostif_get(0, phy_addr, j); + printf("%d: 0x%x ", j, result); + } + puts("\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(void) +{ + 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(0, phy_addr, 1) & 0x24) == 0x24)) + ; + + if(phy_addr == -1) { + for(i = 31; i >= 0; i--) { + result = xps_ll_temac_hostif_get(0, i, 1); + if((result & 0x0ffff) != 0x0ffff) { +#ifdef DEBUG + printf ("phy %x result %x\n", i, result); +#endif + phy_addr = i; + break; + } + } + } + + /* get PHY id */ + i = (xps_ll_temac_hostif_get(0, phy_addr, 2) << 16) | \ + xps_ll_temac_hostif_get(0, phy_addr, 3); +#ifdef DEBUG + printf("LL_TEMAC: Phy ID 0x%x\n", i); +#endif + +#ifdef DEBUG + xps_ll_temac_hostif_set(0, 0, 0, 0x8000); /* phy reset */ +#endif + /* FIXME this part will be replaced by PHY lib */ + /* s3e boards */ + if (i == 0x7c0a3) { + xps_ll_temac_indirect_set(0, EMMC, 0x40000000); /* 100BASE-T/FD */ + link = 1; + return 1; + } + + /* Marwell 88e1111 id - ml50x */ + if (i == 0x1410cc2) { + result = xps_ll_temac_hostif_get(0, phy_addr, 5); + if((result & 0x8000) == 0x8000) { + xps_ll_temac_indirect_set(0, EMMC, 0x80000000); + printf("1000BASE-T/FD\n"); + link = 1; + } else if((result & 0x4000) == 0x4000) { + xps_ll_temac_indirect_set(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(void) +{ + 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); +} +#endif + +#ifdef SDMA_MODE +static int xps_ll_temac_send_sdma(unsigned char *buffer, int length) +{ + if( xps_ll_temac_phy_ctrl() == 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(void) +{ + 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 +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); + +} + +static int xps_ll_temac_send_fifo(unsigned char *buffer, int length) +{ + u32 *buf = 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() +{ + int len, len2, i, val; + int *buf; + buf = &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 (&rx_buffer, len); + } + return 0; +} +#endif + +/* setup mac addr */ +static int xps_ll_temac_addr_setup(struct xps_ll_temac_private * lp) +{ + char * env_p; + char * end; + int i, val; + + env_p = getenv("ethaddr"); + if (env_p == NULL) { + printf("cannot get enviroment for "ethaddr".\n"); + return -1; + } + + for (i = 0; i < 6; i++) { + lp->dev_addr[i] = env_p ? simple_strtoul(env_p, &end, 16) : 0; + if (env_p) env_p = (*end) ? end + 1 : end; + } + + /* set up unicast MAC address filter */ + val = ((lp->dev_addr[3] << 24) | (lp->dev_addr[2] << 16) | + (lp->dev_addr[1] << 8) | (lp->dev_addr[0] )); + xps_ll_temac_indirect_set(0, UAW0, val); + val = (lp->dev_addr[5] << 8) | lp->dev_addr[4] ; + xps_ll_temac_indirect_set(0, UAW1, val); + + return 0; +} + +static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis) +{ + struct xps_ll_temac_private *lp = (struct xps_ll_temac_private *)dev->priv; + +#ifdef SDMA_MODE + xps_ll_temac_bd_init(); +#endif +#ifdef FIFO_MODE + ll_fifo->tdfr = 0x000000a5; /* set fifo lenght */ + ll_fifo->rdfr = 0x000000a5; + + /* ll_fifo->isr = 0x0; */ + /* ll_fifo->ier = 0x0; */ +#endif + xps_ll_temac_indirect_set(0, MC, MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_100MHz); + + xps_ll_temac_addr_setup(lp); + xps_ll_temac_indirect_set(0, AFM, 0x00000000); /* Promiscuos mode disable */ + xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver */ + xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable Transmitter */ + +} + +#ifdef ETH_HALTING +static int xps_ll_temac_halt(void) +{ + xps_ll_temac_indirect_set(0, RCW1, 0x00000000); /* Disable Receiver */ + xps_ll_temac_indirect_set(0, TC, 0x00000000); /* Disable Transmitter */ + +#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 */ +void eth_halt(void){ + link = 0; +#ifdef ETH_HALTING + xps_ll_temac_halt(); +#endif +} + +int eth_init(bd_t *bis) +{ + static int first = 1; + struct eth_device *dev; + struct xps_ll_temac_private *lp; +#if DEBUG + int i; +#endif + + if(!first) + return 0; + first = 0; + dev = (struct eth_device *) calloc(1, sizeof(struct eth_device)); + if (NULL == dev) + return 0; + + lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct xps_ll_temac_private)); + if (lp == NULL) + return 0; + dev->priv = lp; + sprintf(dev->name, "eth0"); + + xps_ll_temac_init(dev, bis); + + printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n", + dev->name, 0, XILINX_LLTEMAC_BASEADDR); + +#if DEBUG + for(i = 0;i < 32;i++) { + read_phy_reg(i); + } +#endif + xps_ll_temac_phy_ctrl(); + return 1; +} + +int eth_send(volatile void *packet, int length) +{ +#ifdef SDMA_MODE + return xps_ll_temac_send_sdma((unsigned char *)packet, length); +#endif +#ifdef FIFO_MODE + return xps_ll_temac_send_fifo((unsigned char *)packet, length); +#endif +} + +int eth_rx(void) +{ +#ifdef SDMA_MODE + return xps_ll_temac_recv_sdma(); +#endif +#ifdef FIFO_MODE + return xps_ll_temac_recv_fifo(); +#endif +}

Hi Ben,
Could you check and pull ll temac driver to your net repo. I prepared net branch in my microblaze repo. (It is based on my master branch which Wolfgang merged but it hasn't in his branch yet).
Thanks, Michal
The following changes since commit e7f325be9edeb84bb457301776bbac1f7257dafc: Michal Simek (1): microblaze: Use cache functions (especially cache status)
are available in the git repository at:
git://git.denx.de/u-boot-microblaze.git net
Michal Simek (1): net: Add Xilinx LL Temac driver
drivers/net/Makefile | 1 + drivers/net/xilinx_ll_temac.c | 549 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 550 insertions(+), 0 deletions(-) create mode 100644 drivers/net/xilinx_ll_temac.c
From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu
drivers/net/Makefile | 1 + drivers/net/xilinx_ll_temac.c | 543 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 544 insertions(+), 0 deletions(-) create mode 100644 drivers/net/xilinx_ll_temac.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 128dc11..ed64787 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.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_ll_temac.c b/drivers/net/xilinx_ll_temac.c new file mode 100644 index 0000000..d1e63e2 --- /dev/null +++ b/drivers/net/xilinx_ll_temac.c @@ -0,0 +1,543 @@ +/*
- Xilinx xps_ll_temac ethernet driver for u-boot
- Author: Yoshio Kashiwagi kashiwagi@co-nss.co.jp
- Copyright (C) 2008 Nissin Systems Co.,Ltd.
- March 2008 created
- Copyright (C) 2008 - 2009 Michal Simek monstr@monstr.eu
- June 2008 Microblaze optimalization, FIFO mode support
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
- */
+#include <config.h> +#include <common.h> +#include <net.h> +#include <malloc.h> +#include <asm/processor.h> +#include <asm/io.h>
+#ifdef XILINX_LLTEMAC_FIFO_BASEADDR +# define FIFO_MODE 1 +#elif XILINX_LLTEMAC_SDMA_CTRL_BASEADDR +# define SDMA_MODE 1 +#else +# error Unsupported mode +#endif
+#undef ETH_HALTING
+#ifdef SDMA_MODE +/* XPS_LL_TEMAC SDMA registers definition */ +# define TX_NXTDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x00) +# define TX_CURBUF_ADDR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x04) +# define TX_CURBUF_LENGTH (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x08) +# define TX_CURDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x0c) +# define TX_TAILDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x10) +# define TX_CHNL_CTRL (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x14) +# define TX_IRQ_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x18) +# define TX_CHNL_STS (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x1c)
+# define RX_NXTDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x20) +# define RX_CURBUF_ADDR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x24) +# define RX_CURBUF_LENGTH (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x28) +# define RX_CURDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x2c) +# define RX_TAILDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x30) +# define RX_CHNL_CTRL (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x34) +# define RX_IRQ_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x38) +# define RX_CHNL_STS (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x3c)
+# define DMA_CONTROL_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x40) +#endif
+/* XPS_LL_TEMAC direct registers definition */ +#define TEMAC_RAF0 (XILINX_LLTEMAC_BASEADDR + 0x00) +#define TEMAC_TPF0 (XILINX_LLTEMAC_BASEADDR + 0x04) +#define TEMAC_IFGP0 (XILINX_LLTEMAC_BASEADDR + 0x08) +#define TEMAC_IS0 (XILINX_LLTEMAC_BASEADDR + 0x0c) +#define TEMAC_IP0 (XILINX_LLTEMAC_BASEADDR + 0x10) +#define TEMAC_IE0 (XILINX_LLTEMAC_BASEADDR + 0x14)
+#define TEMAC_MSW0 (XILINX_LLTEMAC_BASEADDR + 0x20) +#define TEMAC_LSW0 (XILINX_LLTEMAC_BASEADDR + 0x24) +#define TEMAC_CTL0 (XILINX_LLTEMAC_BASEADDR + 0x28) +#define TEMAC_RDY0 (XILINX_LLTEMAC_BASEADDR + 0x2c)
+#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
+static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32))); +static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32)));
+struct xps_ll_temac_private {
- int idx;
- unsigned char dev_addr[6];
+};
+#ifdef DEBUG +/* undirect hostif write to ll_temac */ +static void xps_ll_temac_hostif_set(int emac, int phy_addr,
int reg_addr, int phy_data)
+{
- out_be32((u32 *)TEMAC_LSW0, phy_data);
- 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(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(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));
+}
+/* undirect read from ll_temac */ +int xps_ll_temac_indirect_get(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);
+}
+#ifdef DEBUG +/* read from phy */ +static void read_phy_reg (int phy_addr) +{
- int j, result;
- printf("phy%d ",phy_addr);
- for ( j = 0; j < 32; j++) {
result = xps_ll_temac_hostif_get(0, phy_addr, j);
printf("%d: 0x%x ", j, result);
- }
- puts("\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(void) +{
- 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(0, phy_addr, 1) & 0x24) == 0x24))
;
- if(phy_addr == -1) {
for(i = 31; i >= 0; i--) {
result = xps_ll_temac_hostif_get(0, i, 1);
if((result & 0x0ffff) != 0x0ffff) {
+#ifdef DEBUG
printf ("phy %x result %x\n", i, result);
+#endif
phy_addr = i;
break;
}
}
- }
- /* get PHY id */
- i = (xps_ll_temac_hostif_get(0, phy_addr, 2) << 16) | \
xps_ll_temac_hostif_get(0, phy_addr, 3);
+#ifdef DEBUG
- printf("LL_TEMAC: Phy ID 0x%x\n", i);
+#endif
+#ifdef DEBUG
- xps_ll_temac_hostif_set(0, 0, 0, 0x8000); /* phy reset */
+#endif
- /* FIXME this part will be replaced by PHY lib */
- /* s3e boards */
- if (i == 0x7c0a3) {
xps_ll_temac_indirect_set(0, EMMC, 0x40000000); /* 100BASE-T/FD */
link = 1;
return 1;
- }
- /* Marwell 88e1111 id - ml50x */
- if (i == 0x1410cc2) {
result = xps_ll_temac_hostif_get(0, phy_addr, 5);
if((result & 0x8000) == 0x8000) {
xps_ll_temac_indirect_set(0, EMMC, 0x80000000);
printf("1000BASE-T/FD\n");
link = 1;
} else if((result & 0x4000) == 0x4000) {
xps_ll_temac_indirect_set(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(void) +{
- 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);
+} +#endif
+#ifdef SDMA_MODE +static int xps_ll_temac_send_sdma(unsigned char *buffer, int length) +{
- if( xps_ll_temac_phy_ctrl() == 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(void) +{
- 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 +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);
+}
+static int xps_ll_temac_send_fifo(unsigned char *buffer, int length) +{
- u32 *buf = 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() +{
- int len, len2, i, val;
- int *buf;
- buf = &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 (&rx_buffer, len);
- }
- return 0;
+} +#endif
+/* setup mac addr */ +static int xps_ll_temac_addr_setup(struct xps_ll_temac_private * lp) +{
- char * env_p;
- char * end;
- int i, val;
- env_p = getenv("ethaddr");
- if (env_p == NULL) {
printf("cannot get enviroment for \"ethaddr\".\n");
return -1;
- }
- for (i = 0; i < 6; i++) {
lp->dev_addr[i] = env_p ? simple_strtoul(env_p, &end, 16) : 0;
if (env_p) env_p = (*end) ? end + 1 : end;
- }
- /* set up unicast MAC address filter */
- val = ((lp->dev_addr[3] << 24) | (lp->dev_addr[2] << 16) |
(lp->dev_addr[1] << 8) | (lp->dev_addr[0] ));
- xps_ll_temac_indirect_set(0, UAW0, val);
- val = (lp->dev_addr[5] << 8) | lp->dev_addr[4] ;
- xps_ll_temac_indirect_set(0, UAW1, val);
- return 0;
+}
+static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis) +{
- struct xps_ll_temac_private *lp = (struct xps_ll_temac_private *)dev->priv;
+#ifdef SDMA_MODE
- xps_ll_temac_bd_init();
+#endif +#ifdef FIFO_MODE
- ll_fifo->tdfr = 0x000000a5; /* set fifo lenght */
- ll_fifo->rdfr = 0x000000a5;
- /* ll_fifo->isr = 0x0; */
- /* ll_fifo->ier = 0x0; */
+#endif
- xps_ll_temac_indirect_set(0, MC, MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_100MHz);
- xps_ll_temac_addr_setup(lp);
- xps_ll_temac_indirect_set(0, AFM, 0x00000000); /* Promiscuos mode disable */
- xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver */
- xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable Transmitter */
+}
+#ifdef ETH_HALTING +static int xps_ll_temac_halt(void) +{
- xps_ll_temac_indirect_set(0, RCW1, 0x00000000); /* Disable Receiver */
- xps_ll_temac_indirect_set(0, TC, 0x00000000); /* Disable Transmitter */
+#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 */ +void eth_halt(void){
- link = 0;
+#ifdef ETH_HALTING
- xps_ll_temac_halt();
+#endif +}
+int eth_init(bd_t *bis) +{
- static int first = 1;
- struct eth_device *dev;
- struct xps_ll_temac_private *lp;
+#if DEBUG
- int i;
+#endif
- if(!first)
return 0;
- first = 0;
- dev = (struct eth_device *) calloc(1, sizeof(struct eth_device));
- if (NULL == dev)
return 0;
- lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct xps_ll_temac_private));
- if (lp == NULL)
return 0;
- dev->priv = lp;
- sprintf(dev->name, "eth0");
- xps_ll_temac_init(dev, bis);
- printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
dev->name, 0, XILINX_LLTEMAC_BASEADDR);
+#if DEBUG
- for(i = 0;i < 32;i++) {
read_phy_reg(i);
- }
+#endif
- xps_ll_temac_phy_ctrl();
- return 1;
+}
+int eth_send(volatile void *packet, int length) +{ +#ifdef SDMA_MODE
- return xps_ll_temac_send_sdma((unsigned char *)packet, length);
+#endif +#ifdef FIFO_MODE
- return xps_ll_temac_send_fifo((unsigned char *)packet, length);
+#endif +}
+int eth_rx(void) +{ +#ifdef SDMA_MODE
- return xps_ll_temac_recv_sdma();
+#endif +#ifdef FIFO_MODE
- return xps_ll_temac_recv_fifo();
+#endif +}

Hi Ben,
Hi Michal,
I'm really sorry for taking so long getting to this. Mostly little things:
it's ok you are busy guy. I removed uninteresting part of code. I added all your reported things to u-boot-microblaze.git net branch. Thanks for pull.
+#ifdef DEBUG +/* read from phy */ +static void read_phy_reg (int phy_addr) +{
- int j, result;
- printf("phy%d ",phy_addr);
- for ( j = 0; j < 32; j++) {
result = xps_ll_temac_hostif_get(0, phy_addr, j);
printf("%d: 0x%x ", j, result);
- }
- puts("\n");
+} +#endif
You only use this function in one place. Why not move this code to that place and use debug()
You are right that currently is this function use only once but that's for this code. When will be new board with different phy, it is easy to use this function in different place too. The second reason is that eth_init is long and added this function to it just cause that function will be longer than now. It is atomic function.
+static int phy_addr = -1; +static int link = 0;
+/* setting ll_temac and phy to proper setting */ +static int xps_ll_temac_phy_ctrl(void) +{
- 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(0, phy_addr, 1) & 0x24) == 0x24))
;
- if(phy_addr == -1) {
for(i = 31; i >= 0; i--) {
result = xps_ll_temac_hostif_get(0, i, 1);
if((result & 0x0ffff) != 0x0ffff) {
+#ifdef DEBUG
printf ("phy %x result %x\n", i, result);
+#endif
fixed debug here too.
phy_addr = i;
break;
}
}
- }
- /* get PHY id */
- i = (xps_ll_temac_hostif_get(0, phy_addr, 2) << 16) | \
xps_ll_temac_hostif_get(0, phy_addr, 3);
+#ifdef DEBUG
- printf("LL_TEMAC: Phy ID 0x%x\n", i);
Please use debug() instead
fixed.
+#endif
+#ifdef DEBUG
- xps_ll_temac_hostif_set(0, 0, 0, 0x8000); /* phy reset */
+#endif
- /* FIXME this part will be replaced by PHY lib */
- /* s3e boards */
- if (i == 0x7c0a3) {
xps_ll_temac_indirect_set(0, EMMC, 0x40000000); /* 100BASE-T/FD */
link = 1;
return 1;
- }
- /* Marwell 88e1111 id - ml50x */
- if (i == 0x1410cc2) {
result = xps_ll_temac_hostif_get(0, phy_addr, 5);
if((result & 0x8000) == 0x8000) {
xps_ll_temac_indirect_set(0, EMMC, 0x80000000);
printf("1000BASE-T/FD\n");
link = 1;
} else if((result & 0x4000) == 0x4000) {
xps_ll_temac_indirect_set(0, EMMC, 0x40000000);
printf("100BASE-T/FD\n");
link = 1;
} else {
printf("Unsupported mode\n");
link = 0;
}
return 1;
- }
- return 0;
+}
+#ifdef FIFO_MODE +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, \
This line's way too long.
Yes I know about. It was fixed in net branch.
- ll_fifo->ier, ll_fifo->rdfr, ll_fifo->rdfo, ll_fifo->rlf);
+}
+#ifdef ETH_HALTING +static int xps_ll_temac_halt(void) +{
- xps_ll_temac_indirect_set(0, RCW1, 0x00000000); /* Disable Receiver */
- xps_ll_temac_indirect_set(0, TC, 0x00000000); /* Disable Transmitter */
+#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 */ +void eth_halt(void){
- link = 0;
+#ifdef ETH_HALTING
- xps_ll_temac_halt();
+#endif +}
+int eth_init(bd_t *bis) +{
- static int first = 1;
- struct eth_device *dev;
- struct xps_ll_temac_private *lp;
+#if DEBUG
- int i;
+#endif
I normally don't like this, but move the variable declaration to where it's used to avoid 2 #ifs
I don't like it too but ok.
- if(!first)
return 0;
- first = 0;
- dev = (struct eth_device *) calloc(1, sizeof(struct eth_device));
- if (NULL == dev)
return 0;
- lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct
xps_ll_temac_private));
- if (lp == NULL)
return 0;
- dev->priv = lp;
- sprintf(dev->name, "eth0");
- xps_ll_temac_init(dev, bis);
- printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
dev->name, 0, XILINX_LLTEMAC_BASEADDR);
+#if DEBUG
- for(i = 0;i < 32;i++) {
read_phy_reg(i);
- }
+#endif
- xps_ll_temac_phy_ctrl();
- return 1;
+}
regards, B en
Thanks, Michal
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Dear Michal,
In message 4981658C.7070503@monstr.eu you wrote:
I'm really sorry for taking so long getting to this. Mostly little things:
it's ok you are busy guy. I removed uninteresting part of code. I added all your reported things to u-boot-microblaze.git net branch. Thanks for pull.
What exactly is the state of this today? It seems this did not hit mainline yet?
Best regards,
Wolfgang Denk

Hi Wolfgang and Ben,
Dear Michal,
In message 4981658C.7070503@monstr.eu you wrote:
I'm really sorry for taking so long getting to this. Mostly little things:
it's ok you are busy guy. I removed uninteresting part of code. I added all your reported things to u-boot-microblaze.git net branch. Thanks for pull.
What exactly is the state of this today? It seems this did not hit mainline yet?
Yes, this driver is not in mainline. Ben wanted to changed this driver to new network driver style. I tried to do it but I my toolchain had a problem with weak function. I see two solution. 1. Add old style driver without new net multi interface 2. Add new style driver and microblaze community just comment one line in eth.c (this line int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));)
Both solution are possible. If you agree with me, I'll send new version driver for comments.
And of course the best solution is update my toolchain but there we have some problems.
Thanks, Michal
Best regards,
Wolfgang Denk

Hi Michal,
I'm really sorry for taking so long getting to this. Mostly little things:
monstr@monstr.eu wrote:
From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu
drivers/net/Makefile | 1 + drivers/net/xilinx_ll_temac.c | 543 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 544 insertions(+), 0 deletions(-) create mode 100644 drivers/net/xilinx_ll_temac.c
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 128dc11..ed64787 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.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_ll_temac.c b/drivers/net/xilinx_ll_temac.c new file mode 100644 index 0000000..d1e63e2 --- /dev/null +++ b/drivers/net/xilinx_ll_temac.c @@ -0,0 +1,543 @@ +/*
- Xilinx xps_ll_temac ethernet driver for u-boot
- Author: Yoshio Kashiwagi kashiwagi@co-nss.co.jp
- Copyright (C) 2008 Nissin Systems Co.,Ltd.
- March 2008 created
- Copyright (C) 2008 - 2009 Michal Simek monstr@monstr.eu
- June 2008 Microblaze optimalization, FIFO mode support
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
- */
+#include <config.h> +#include <common.h> +#include <net.h> +#include <malloc.h> +#include <asm/processor.h> +#include <asm/io.h>
+#ifdef XILINX_LLTEMAC_FIFO_BASEADDR +# define FIFO_MODE 1 +#elif XILINX_LLTEMAC_SDMA_CTRL_BASEADDR +# define SDMA_MODE 1 +#else +# error Unsupported mode +#endif
+#undef ETH_HALTING
+#ifdef SDMA_MODE +/* XPS_LL_TEMAC SDMA registers definition */ +# define TX_NXTDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x00) +# define TX_CURBUF_ADDR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x04) +# define TX_CURBUF_LENGTH (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x08) +# define TX_CURDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x0c) +# define TX_TAILDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x10) +# define TX_CHNL_CTRL (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x14) +# define TX_IRQ_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x18) +# define TX_CHNL_STS (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x1c)
+# define RX_NXTDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x20) +# define RX_CURBUF_ADDR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x24) +# define RX_CURBUF_LENGTH (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x28) +# define RX_CURDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x2c) +# define RX_TAILDESC_PTR (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x30) +# define RX_CHNL_CTRL (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x34) +# define RX_IRQ_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x38) +# define RX_CHNL_STS (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x3c)
+# define DMA_CONTROL_REG (XILINX_LLTEMAC_SDMA_CTRL_BASEADDR + 0x40) +#endif
+/* XPS_LL_TEMAC direct registers definition */ +#define TEMAC_RAF0 (XILINX_LLTEMAC_BASEADDR + 0x00) +#define TEMAC_TPF0 (XILINX_LLTEMAC_BASEADDR + 0x04) +#define TEMAC_IFGP0 (XILINX_LLTEMAC_BASEADDR + 0x08) +#define TEMAC_IS0 (XILINX_LLTEMAC_BASEADDR + 0x0c) +#define TEMAC_IP0 (XILINX_LLTEMAC_BASEADDR + 0x10) +#define TEMAC_IE0 (XILINX_LLTEMAC_BASEADDR + 0x14)
+#define TEMAC_MSW0 (XILINX_LLTEMAC_BASEADDR + 0x20) +#define TEMAC_LSW0 (XILINX_LLTEMAC_BASEADDR + 0x24) +#define TEMAC_CTL0 (XILINX_LLTEMAC_BASEADDR + 0x28) +#define TEMAC_RDY0 (XILINX_LLTEMAC_BASEADDR + 0x2c)
+#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
+static unsigned char tx_buffer[ETHER_MTU] __attribute((aligned(32))); +static unsigned char rx_buffer[ETHER_MTU] __attribute((aligned(32)));
+struct xps_ll_temac_private {
- int idx;
- unsigned char dev_addr[6];
+};
+#ifdef DEBUG +/* undirect hostif write to ll_temac */ +static void xps_ll_temac_hostif_set(int emac, int phy_addr,
int reg_addr, int phy_data)
+{
- out_be32((u32 *)TEMAC_LSW0, phy_data);
- 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(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(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));
+}
+/* undirect read from ll_temac */ +int xps_ll_temac_indirect_get(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);
+}
+#ifdef DEBUG +/* read from phy */ +static void read_phy_reg (int phy_addr) +{
- int j, result;
- printf("phy%d ",phy_addr);
- for ( j = 0; j < 32; j++) {
result = xps_ll_temac_hostif_get(0, phy_addr, j);
printf("%d: 0x%x ", j, result);
- }
- puts("\n");
+} +#endif
You only use this function in one place. Why not move this code to that place and use debug()
+static int phy_addr = -1; +static int link = 0;
+/* setting ll_temac and phy to proper setting */ +static int xps_ll_temac_phy_ctrl(void) +{
- 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(0, phy_addr, 1) & 0x24) == 0x24))
;
- if(phy_addr == -1) {
for(i = 31; i >= 0; i--) {
result = xps_ll_temac_hostif_get(0, i, 1);
if((result & 0x0ffff) != 0x0ffff) {
+#ifdef DEBUG
printf ("phy %x result %x\n", i, result);
+#endif
phy_addr = i;
break;
}
}
- }
- /* get PHY id */
- i = (xps_ll_temac_hostif_get(0, phy_addr, 2) << 16) | \
xps_ll_temac_hostif_get(0, phy_addr, 3);
+#ifdef DEBUG
- printf("LL_TEMAC: Phy ID 0x%x\n", i);
Please use debug() instead
+#endif
+#ifdef DEBUG
- xps_ll_temac_hostif_set(0, 0, 0, 0x8000); /* phy reset */
+#endif
- /* FIXME this part will be replaced by PHY lib */
- /* s3e boards */
- if (i == 0x7c0a3) {
xps_ll_temac_indirect_set(0, EMMC, 0x40000000); /* 100BASE-T/FD */
link = 1;
return 1;
- }
- /* Marwell 88e1111 id - ml50x */
- if (i == 0x1410cc2) {
result = xps_ll_temac_hostif_get(0, phy_addr, 5);
if((result & 0x8000) == 0x8000) {
xps_ll_temac_indirect_set(0, EMMC, 0x80000000);
printf("1000BASE-T/FD\n");
link = 1;
} else if((result & 0x4000) == 0x4000) {
xps_ll_temac_indirect_set(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(void) +{
- 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);
+} +#endif
+#ifdef SDMA_MODE +static int xps_ll_temac_send_sdma(unsigned char *buffer, int length) +{
- if( xps_ll_temac_phy_ctrl() == 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(void) +{
- 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 +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, \
This line's way too long.
- ll_fifo->ier, ll_fifo->rdfr, ll_fifo->rdfo, ll_fifo->rlf);
+}
+static int xps_ll_temac_send_fifo(unsigned char *buffer, int length) +{
- u32 *buf = 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() +{
- int len, len2, i, val;
- int *buf;
- buf = &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 (&rx_buffer, len);
- }
- return 0;
+} +#endif
+/* setup mac addr */ +static int xps_ll_temac_addr_setup(struct xps_ll_temac_private * lp) +{
- char * env_p;
- char * end;
- int i, val;
- env_p = getenv("ethaddr");
- if (env_p == NULL) {
printf("cannot get enviroment for \"ethaddr\".\n");
return -1;
- }
- for (i = 0; i < 6; i++) {
lp->dev_addr[i] = env_p ? simple_strtoul(env_p, &end, 16) : 0;
if (env_p) env_p = (*end) ? end + 1 : end;
- }
- /* set up unicast MAC address filter */
- val = ((lp->dev_addr[3] << 24) | (lp->dev_addr[2] << 16) |
(lp->dev_addr[1] << 8) | (lp->dev_addr[0] ));
- xps_ll_temac_indirect_set(0, UAW0, val);
- val = (lp->dev_addr[5] << 8) | lp->dev_addr[4] ;
- xps_ll_temac_indirect_set(0, UAW1, val);
- return 0;
+}
+static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis) +{
- struct xps_ll_temac_private *lp = (struct xps_ll_temac_private *)dev->priv;
+#ifdef SDMA_MODE
- xps_ll_temac_bd_init();
+#endif +#ifdef FIFO_MODE
- ll_fifo->tdfr = 0x000000a5; /* set fifo lenght */
- ll_fifo->rdfr = 0x000000a5;
- /* ll_fifo->isr = 0x0; */
- /* ll_fifo->ier = 0x0; */
+#endif
- xps_ll_temac_indirect_set(0, MC, MDIO_ENABLE_MASK | MDIO_CLOCK_DIV_100MHz);
- xps_ll_temac_addr_setup(lp);
- xps_ll_temac_indirect_set(0, AFM, 0x00000000); /* Promiscuos mode disable */
- xps_ll_temac_indirect_set(0, RCW1, 0x10000000); /* Enable Receiver */
- xps_ll_temac_indirect_set(0, TC, 0x10000000); /* Enable Transmitter */
+}
+#ifdef ETH_HALTING +static int xps_ll_temac_halt(void) +{
- xps_ll_temac_indirect_set(0, RCW1, 0x00000000); /* Disable Receiver */
- xps_ll_temac_indirect_set(0, TC, 0x00000000); /* Disable Transmitter */
+#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 */ +void eth_halt(void){
- link = 0;
+#ifdef ETH_HALTING
- xps_ll_temac_halt();
+#endif +}
+int eth_init(bd_t *bis) +{
- static int first = 1;
- struct eth_device *dev;
- struct xps_ll_temac_private *lp;
+#if DEBUG
- int i;
+#endif
I normally don't like this, but move the variable declaration to where it's used to avoid 2 #ifs
- if(!first)
return 0;
- first = 0;
- dev = (struct eth_device *) calloc(1, sizeof(struct eth_device));
- if (NULL == dev)
return 0;
- lp = (struct xps_ll_temac_private *) calloc(1, sizeof(struct xps_ll_temac_private));
- if (lp == NULL)
return 0;
- dev->priv = lp;
- sprintf(dev->name, "eth0");
- xps_ll_temac_init(dev, bis);
- printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
dev->name, 0, XILINX_LLTEMAC_BASEADDR);
+#if DEBUG
- for(i = 0;i < 32;i++) {
read_phy_reg(i);
- }
+#endif
- xps_ll_temac_phy_ctrl();
- return 1;
+}
+int eth_send(volatile void *packet, int length) +{ +#ifdef SDMA_MODE
- return xps_ll_temac_send_sdma((unsigned char *)packet, length);
+#endif +#ifdef FIFO_MODE
- return xps_ll_temac_send_fifo((unsigned char *)packet, length);
+#endif +}
+int eth_rx(void) +{ +#ifdef SDMA_MODE
- return xps_ll_temac_recv_sdma();
+#endif +#ifdef FIFO_MODE
- return xps_ll_temac_recv_fifo();
+#endif +}
regards, B en

Dear monstr@monstr.eu,
In message d4fd46d3b2d27747b728da37fad3ebca3732d837.1231154122.git.monstr@monstr.eu you wrote: ...
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
I have to admit that I rather sort this by the name of the CONFIG_ variable. Seeing "P" here between two "D"s looks strange to me.
Please don't do this.
COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o -COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
Of course this is still wrong, like some others.
Best regards,
Wolfgang Denk

Dear monstr@monstr.eu,
In message d4fd46d3b2d27747b728da37fad3ebca3732d837.1231154122.git.monstr@monstr.eu you wrote:
From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu
drivers/net/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
Sorry, this doesn't apply either:
Applying: part_efi: Fix partition size calculation due to inclusive ending LBA. error: patch failed: disk/part_efi.c:163 error: disk/part_efi.c: patch does not apply Using index info to reconstruct a base tree... error: patch failed: disk/part_efi.c:163 error: disk/part_efi.c: patch does not apply Did you hand edit your patch? It does not apply to blobs recorded in its index. Cannot fall back to three-way merge. Patch failed at 0001.
Please rebase and repost. Thanks.
Best regards,
Wolfgang Denk

monstr@monstr.eu wrote:
From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu
drivers/net/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..128dc11 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o @@ -54,11 +55,11 @@ COBJS-$(CONFIG_NS8382X) += ns8382x.o COBJS-$(CONFIG_DRIVER_NS9750_ETHERNET) += ns9750_eth.o COBJS-$(CONFIG_PCNET) += pcnet.o COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o -COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o COBJS-$(CONFIG_RTL8139) += rtl8139.o COBJS-$(CONFIG_RTL8169) += rtl8169.o COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o +COBJS-$(CONFIG_SH_ETHER) += sh_eth.o COBJS-$(CONFIG_DRIVER_SMC91111) += smc91111.o COBJS-$(CONFIG_DRIVER_SMC911X) += smc911x.o COBJS-$(CONFIG_TIGON3) += tigon3.o bcm570x_autoneg.o 5701rls.o @@ -68,7 +69,6 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o -COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c)
Applied to net repo.
thanks, Ben

Dear monstr@monstr.eu,
In message d4fd46d3b2d27747b728da37fad3ebca3732d837.1231154122.git.monstr@monstr.eu you wrote:
From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu
drivers/net/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..128dc11 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
What makes you think that CONFIG_PPC4xx_EMAC has a good place between CONFIG_DRIVER_3C589 and CONFIG_DRIVER_AX88180?
COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o @@ -54,11 +55,11 @@ COBJS-$(CONFIG_NS8382X) += ns8382x.o COBJS-$(CONFIG_DRIVER_NS9750_ETHERNET) += ns9750_eth.o COBJS-$(CONFIG_PCNET) += pcnet.o COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o -COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
that was ok here.
COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o
...while this isn't.
COBJS-$(CONFIG_RTL8139) += rtl8139.o COBJS-$(CONFIG_RTL8169) += rtl8169.o COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o +COBJS-$(CONFIG_SH_ETHER) += sh_eth.o COBJS-$(CONFIG_DRIVER_SMC91111) += smc91111.o COBJS-$(CONFIG_DRIVER_SMC911X) += smc911x.o COBJS-$(CONFIG_TIGON3) += tigon3.o bcm570x_autoneg.o 5701rls.o @@ -68,7 +69,6 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o -COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
Actually we should perform a global s/CONFIG_DRIVER_/CONFIG_/, me thinks.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear monstr@monstr.eu,
In message d4fd46d3b2d27747b728da37fad3ebca3732d837.1231154122.git.monstr@monstr.eu you wrote:
From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu
drivers/net/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..128dc11 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
What makes you think that CONFIG_PPC4xx_EMAC has a good place between CONFIG_DRIVER_3C589 and CONFIG_DRIVER_AX88180?
COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o @@ -54,11 +55,11 @@ COBJS-$(CONFIG_NS8382X) += ns8382x.o COBJS-$(CONFIG_DRIVER_NS9750_ETHERNET) += ns9750_eth.o COBJS-$(CONFIG_PCNET) += pcnet.o COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o -COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
that was ok here.
COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o
...while this isn't.
COBJS-$(CONFIG_RTL8139) += rtl8139.o COBJS-$(CONFIG_RTL8169) += rtl8169.o COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o +COBJS-$(CONFIG_SH_ETHER) += sh_eth.o COBJS-$(CONFIG_DRIVER_SMC91111) += smc91111.o COBJS-$(CONFIG_DRIVER_SMC911X) += smc911x.o COBJS-$(CONFIG_TIGON3) += tigon3.o bcm570x_autoneg.o 5701rls.o @@ -68,7 +69,6 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o -COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
Actually we should perform a global s/CONFIG_DRIVER_/CONFIG_/, me thinks.
Agreed. Can you do it Michal, or should I (for net, anyway)?
Best regards,
Wolfgang Denk
regards, Ben

Hi Ben and Wolfgang,
In message d4fd46d3b2d27747b728da37fad3ebca3732d837.1231154122.git.monstr@monstr.eu you wrote:
From: Michal Simek monstr@monstr.eu
Signed-off-by: Michal Simek monstr@monstr.eu
drivers/net/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..128dc11 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
What makes you think that CONFIG_PPC4xx_EMAC has a good place between CONFIG_DRIVER_3C589 and CONFIG_DRIVER_AX88180?
From my point of view make me more sense to rename 4xx_enec.c file to correspond
with driver name. I mean if the config is CONFIG_PPC4xx_EMAC the filename should be ppc4xx_emac.c or in second case CONFIG_4XX_ENET for current 4xx_enet.c file.
From these two choices I like the first one.
COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o @@ -54,11 +55,11 @@ COBJS-$(CONFIG_NS8382X) += ns8382x.o COBJS-$(CONFIG_DRIVER_NS9750_ETHERNET) += ns9750_eth.o COBJS-$(CONFIG_PCNET) += pcnet.o COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o -COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
that was ok here.
COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o
...while this isn't.
COBJS-$(CONFIG_RTL8139) += rtl8139.o COBJS-$(CONFIG_RTL8169) += rtl8169.o COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o +COBJS-$(CONFIG_SH_ETHER) += sh_eth.o COBJS-$(CONFIG_DRIVER_SMC91111) += smc91111.o COBJS-$(CONFIG_DRIVER_SMC911X) += smc911x.o COBJS-$(CONFIG_TIGON3) += tigon3.o bcm570x_autoneg.o 5701rls.o @@ -68,7 +69,6 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o -COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
Actually we should perform a global s/CONFIG_DRIVER_/CONFIG_/, me thinks.
Agreed. Can you do it Michal, or should I (for net, anyway)?
I would like to describe what happen. I sent to mailing list two patches. One with Makefile sort and second with LL_TEMAC. First patch just sort some labels in drivers/net/Makefile. Wolfgang sent that he don't like it and he reject this patch. I haven't wanted to sort any Makefile labels I just wanted to add LL_TEMAC driver. Makefile sort was not my point. Then Ben add only Makefile sort patch (because of some small drivers violations) to net repo and send pull request to Wolfgang and he merged it to his repo.
My point was and is only add LL_TEMAC driver to u-boot not sorting labels in net repo. BEN: Could you please add that driver to your repo? and if you can please sort labels to correct way.
Thanks, Michal
Best regards,
Wolfgang Denk
regards, Ben

On Tuesday 10 February 2009, Michal Simek wrote:
+++ b/drivers/net/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
What makes you think that CONFIG_PPC4xx_EMAC has a good place between CONFIG_DRIVER_3C589 and CONFIG_DRIVER_AX88180?
From my point of view make me more sense to rename 4xx_enec.c file to correspond with driver name. I mean if the config is CONFIG_PPC4xx_EMAC the filename should be ppc4xx_emac.c or in second case CONFIG_4XX_ENET for current 4xx_enet.c file. From these two choices I like the first one.
Yes, I also think it makes sense to rename this driver to "ppc4xx_emac.c". If nobody objects I'll send a patch doing this shortly.
Best regards, Stefan
===================================================================== DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de =====================================================================

Dear Michal Simek,
In message 49913792.9060008@monstr.eu you wrote:
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
What makes you think that CONFIG_PPC4xx_EMAC has a good place between CONFIG_DRIVER_3C589 and CONFIG_DRIVER_AX88180?
From my point of view make me more sense to rename 4xx_enec.c file to correspond with driver name. I mean if the config is CONFIG_PPC4xx_EMAC the filename should be ppc4xx_emac.c or in second case CONFIG_4XX_ENET for current 4xx_enet.c file. From these two choices I like the first one.
Well, that's IMO for the PPC4xx custodian to decide.
Stefan, what do you think?
I would like to describe what happen. I sent to mailing list two patches. One with Makefile sort and second with LL_TEMAC. First patch just sort some labels in drivers/net/Makefile. Wolfgang sent that he don't like it and he reject this patch. I haven't wanted to sort any Makefile labels I just wanted to add LL_TEMAC driver. Makefile sort was not my point.
I'm aware of this. But this is how contributing to U-Boot works : you just want to add a tiny piece of code here, and you will find yourself involved in some bigger cleanup all over the place. That's what happens to me all day, and to many others, so please help to carry that burdon. Thanks.
Best regards,
Wolfgang Denk

Dear Wolfgang,
Dear Michal Simek,
In message 49913792.9060008@monstr.eu you wrote:
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
What makes you think that CONFIG_PPC4xx_EMAC has a good place between CONFIG_DRIVER_3C589 and CONFIG_DRIVER_AX88180?
From my point of view make me more sense to rename 4xx_enec.c file to correspond with driver name. I mean if the config is CONFIG_PPC4xx_EMAC the filename should be ppc4xx_emac.c or in second case CONFIG_4XX_ENET for current 4xx_enet.c file. From these two choices I like the first one.
Well, that's IMO for the PPC4xx custodian to decide.
Stefan, what do you think?
I would like to describe what happen. I sent to mailing list two patches. One with Makefile sort and second with LL_TEMAC. First patch just sort some labels in drivers/net/Makefile. Wolfgang sent that he don't like it and he reject this patch. I haven't wanted to sort any Makefile labels I just wanted to add LL_TEMAC driver. Makefile sort was not my point.
I'm aware of this. But this is how contributing to U-Boot works : you just want to add a tiny piece of code here, and you will find yourself involved in some bigger cleanup all over the place. That's what happens to me all day, and to many others, so please help to carry that burdon. Thanks.
Yes I know that's why I sent sort Makefile patch in that pack.
Regards, Michal
Best regards,
Wolfgang Denk

On Tue, Feb 10, 2009 at 1:09 AM, Michal Simek monstr@monstr.eu wrote:
Dear Wolfgang,
Dear Michal Simek,
In message 49913792.9060008@monstr.eu you wrote:
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o +COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
What makes you think that CONFIG_PPC4xx_EMAC has a good place between CONFIG_DRIVER_3C589 and CONFIG_DRIVER_AX88180?
From my point of view make me more sense to rename 4xx_enec.c file to
correspond
with driver name. I mean if the config is CONFIG_PPC4xx_EMAC the
filename should
be ppc4xx_emac.c or in second case CONFIG_4XX_ENET for current
4xx_enet.c file.
From these two choices I like the first one.
Well, that's IMO for the PPC4xx custodian to decide.
Stefan, what do you think?
I would like to describe what happen. I sent to mailing list two
patches. One
with Makefile sort and second with LL_TEMAC. First patch just sort some
labels
in drivers/net/Makefile. Wolfgang sent that he don't like it and he
reject this
patch. I haven't wanted to sort any Makefile labels I just wanted to add LL_TEMAC driver. Makefile sort was not my point.
I'm aware of this. But this is how contributing to U-Boot works : you just want to add a tiny piece of code here, and you will find yourself involved in some bigger cleanup all over the place. That's what happens to me all day, and to many others, so please help to carry that burdon. Thanks.
Yes I know that's why I sent sort Makefile patch in that pack.
Regards, Michal
Best regards,
Wolfgang Denk
-- Michal Simek, Ing. (M.Eng) w: www.monstr.eu p: +42-0-721842854
OK, I'll send a clean up patch later today or tonight.
regards, Ben
participants (5)
-
Ben Warren
-
Michal Simek
-
monstr@monstr.eu
-
Stefan Roese
-
Wolfgang Denk