Skip to contentSkip to conversation

LL TEMAC v9 refactored

U-Boot New Stephan Linz 4 participants 13 messages Jan 21, 2012 – Jan 28, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Back to the discussion from the last three months I have refactored the LL TEMAC driver again. The version v9 is ready to next review and testing (I hope the last one). I myself have tested it successfully on an ML605 (TEMAC hard core) and on a SP3ADSP1800 (TEMAC soft core). Thanks to Marek, Wolfgang, Andy, Mike and Michal to review v4..8. Special thanks to Ricardo. He has tested the driver v6 on a Xilinx Virtex5 FX (PPC440) platform.

To use the driver on Microblaze, you will need all additional platform patches by Michal Simek and me. All related patches are bundled on patchwork:
- http://patchwork.ozlabs.org/bundle/rexut/net-ll_temac/

@Michal: Please merge the patches into the custodian git tree for final testing.

@Ricardo: Please could you test again the new v9 patch on your PPC440 platform.

Signature · 8 lines
Best regards,
Stephan Linz
______________________________________________________________________________
MB-Ref: http://www.li-pro.de/xilinx_mb:mbref:start
OpenDCC: http://www.li-pro.net/opendcc.phtml
PC/M: http://www.li-pro.net/pcm.phtml
Sourceforge: http://sourceforge.net/users/slz
Gitorious: https://gitorious.org/~slz
#1 lore raw

PATCH 1/6 net: ll_temac: Add LL TEMAC driver to u-boot

Xilinx LocalLink Tri-Mode Ether MAC driver can be
used by Xilinx Microblaze or Xilinx ppc405/440 in
SDMA and FIFO mode. DCR or XPS bus can be used.

The driver uses and requires MII and PHYLIB.

CP: 4 warnings: 'Use of volatile is usually wrong' I won't fix this, because it depends on the network driver subsystem.

---
v9: Remove private Rx/Tx transfer buffer for SDMA and FIFO.
Use the PktBuf infrastruct from upper network layer. Review all the recv/send functions for SDMA and FIFO mode and insert more detailed comments.
Test with tftp put/get on ML605 and SP3ADSP1800.

v8: Remove deprecated interface: miiphy_register()
Implement MDIO bus/phy access code as independent part of driver. Make the direct PHY access code accessible for upper layer like the MDIO command.
Define proper device names for TEMAC and MII interfaces. Support of TEMAC0 and TEMAC1 at same time is prepared and should work.

v7: Call udelay() in polling loops to avoid unintended watchdog reset
Define well known timeout values in usec
Handle timeouts as error situations
Reduce duplicated code in SDMA operations
Add a real and plausible PHY detect mask
Remove ETH_HALTING code exclusion
Code cleanup as recommended
Fix typos

v6: Code cleanup with ./tools/checkpatch.pl

v5: Remove more endless loops
Remove useless parenthesis in pointer operations Move phyaddr predefinition on top
Remove supernumerary newlines
Remove parenthesis around numbers (globally)

v4: Separate fifo and sdma code from driver core
Split sdma code into separate DCR and XPS bus access code Add extensive register struct definitions and enumerations Add new callbacks into fifo an sdma code
Prepare CDMAC buffer handling to be unique for every instance Separate Xilinx specific indirect DCR access, so we can move to arch Remove useless 'emac' parameter from indirect access helper functions Correct MDIO clock setup.
Remove endless loops
Common code beautifying

v3: Use helper functions for fifo mode
Use helper functions for indirect accesses
Code cleanup
Add comments for MAGIC values
Simplify code in fifo mode

v2: Remove helper function for access to temac
Remove SDMA/FIFO/DCR macros and configure it in board Setup mac by write_hwaddr

---
 drivers/net/Makefile               |    2 +
 drivers/net/xilinx_ll_temac.c      |  386 ++++++++++++++++++++++++++++++++
 drivers/net/xilinx_ll_temac_fifo.c |  143 ++++++++++++
 drivers/net/xilinx_ll_temac_mdio.c |  165 ++++++++++++++
 drivers/net/xilinx_ll_temac_sdma.c |  370 +++++++++++++++++++++++++++++++
 include/netdev.h                   |    1 +
 include/xilinx_ll_temac.h          |  430 ++++++++++++++++++++++++++++++++++++
 include/xilinx_ll_temac_fifo.h     |  122 ++++++++++
 include/xilinx_ll_temac_mdio.h     |   53 +++++
 include/xilinx_ll_temac_sdma.h     |  281 +++++++++++++++++++++++
 10 files changed, 1953 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/xilinx_ll_temac.c
 create mode 100644 drivers/net/xilinx_ll_temac_fifo.c
 create mode 100644 drivers/net/xilinx_ll_temac_mdio.c
 create mode 100644 drivers/net/xilinx_ll_temac_sdma.c
 create mode 100644 include/xilinx_ll_temac.h
 create mode 100644 include/xilinx_ll_temac_fifo.h
 create mode 100644 include/xilinx_ll_temac_mdio.h
 create mode 100644 include/xilinx_ll_temac_sdma.h
drivers/net/Makefile +2 -0
index f4f7ea3..430f90c 100644
@@ -77,6 +77,8 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
 COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
+		xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
 
 COBJS	:= $(sort $(COBJS-y))
 SRCS	:= $(COBJS:.o=.c)
drivers/net/xilinx_ll_temac.c new file +386 -0

386 lines not on this page · raw message

drivers/net/xilinx_ll_temac_fifo.c new file +143 -0

143 lines not on this page · raw message

drivers/net/xilinx_ll_temac_mdio.c new file +165 -0

165 lines not on this page · raw message

drivers/net/xilinx_ll_temac_sdma.c new file +370 -0

370 lines not on this page · raw message

include/netdev.h +1 -0
index b0c21d5..bf95f88 100644
@@ -102,6 +102,7 @@ int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
 							unsigned long dma_addr);
 int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
 							int txpp, int rxpp);
+int xilinx_ll_temac_standard_init(bd_t *bis);
 
 /* Boards with PCI network controllers can call this from their board_eth_init()
  * function to initialize whatever's on board.
include/xilinx_ll_temac.h new file +430 -0

430 lines not on this page · raw message

include/xilinx_ll_temac_fifo.h new file +122 -0

122 lines not on this page · raw message

include/xilinx_ll_temac_mdio.h new file +53 -0

53 lines not on this page · raw message

include/xilinx_ll_temac_sdma.h new file +281 -0

281 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#2 lore raw

PATCH 1/6 net: ll_temac: Add LL TEMAC driver to u-boot

Hi Stephan,

Quoted 75 lines · Stephan Linz

Xilinx LocalLink Tri-Mode Ether MAC driver can be
used by Xilinx Microblaze or Xilinx ppc405/440 in
SDMA and FIFO mode. DCR or XPS bus can be used.

The driver uses and requires MII and PHYLIB.

CP: 4 warnings: 'Use of volatile is usually wrong' I won't fix this, because it depends on the network driver subsystem.

---
v9: Remove private Rx/Tx transfer buffer for SDMA and FIFO.
Use the PktBuf infrastruct from upper network layer. Review all the recv/send functions for SDMA and FIFO mode and insert more detailed comments.
Test with tftp put/get on ML605 and SP3ADSP1800.

v8: Remove deprecated interface: miiphy_register()
Implement MDIO bus/phy access code as independent part of driver. Make the direct PHY access code accessible for upper layer like the MDIO command.
Define proper device names for TEMAC and MII interfaces. Support of TEMAC0 and TEMAC1 at same time is prepared and should work.

v7: Call udelay() in polling loops to avoid unintended watchdog reset
Define well known timeout values in usec
Handle timeouts as error situations
Reduce duplicated code in SDMA operations
Add a real and plausible PHY detect mask
Remove ETH_HALTING code exclusion
Code cleanup as recommended
Fix typos

v6: Code cleanup with ./tools/checkpatch.pl

v5: Remove more endless loops
Remove useless parenthesis in pointer operations Move phyaddr predefinition on top
Remove supernumerary newlines
Remove parenthesis around numbers (globally)

v4: Separate fifo and sdma code from driver core
Split sdma code into separate DCR and XPS bus access code Add extensive register struct definitions and enumerations Add new callbacks into fifo an sdma code
Prepare CDMAC buffer handling to be unique for every instance Separate Xilinx specific indirect DCR access, so we can move to arch Remove useless 'emac' parameter from indirect access helper functions Correct MDIO clock setup.
Remove endless loops
Common code beautifying

v3: Use helper functions for fifo mode
Use helper functions for indirect accesses
Code cleanup
Add comments for MAGIC values
Simplify code in fifo mode

v2: Remove helper function for access to temac
Remove SDMA/FIFO/DCR macros and configure it in board Setup mac by write_hwaddr

---
 drivers/net/Makefile               |    2 +
 drivers/net/xilinx_ll_temac.c      |  386 ++++++++++++++++++++++++++++++++
 drivers/net/xilinx_ll_temac_fifo.c |  143 ++++++++++++
 drivers/net/xilinx_ll_temac_mdio.c |  165 ++++++++++++++
 drivers/net/xilinx_ll_temac_sdma.c |  370 +++++++++++++++++++++++++++++++
 include/netdev.h                   |    1 +
 include/xilinx_ll_temac.h          |  430 ++++++++++++++++++++++++++++++++++++
 include/xilinx_ll_temac_fifo.h     |  122 ++++++++++
 include/xilinx_ll_temac_mdio.h     |   53 +++++
 include/xilinx_ll_temac_sdma.h     |  281 +++++++++++++++++++++++
 10 files changed, 1953 insertions(+), 0 deletions(-)
Quoted 8 lines
 create mode 100644 drivers/net/xilinx_ll_temac.c
 create mode 100644 drivers/net/xilinx_ll_temac_fifo.c
 create mode 100644 drivers/net/xilinx_ll_temac_mdio.c
 create mode 100644 drivers/net/xilinx_ll_temac_sdma.c
 create mode 100644 include/xilinx_ll_temac.h
 create mode 100644 include/xilinx_ll_temac_fifo.h
 create mode 100644 include/xilinx_ll_temac_mdio.h
 create mode 100644 include/xilinx_ll_temac_sdma.h

Wolfgang: I just wanted to know what it is the rule for adding headers. I would prefer to add these headers to drivers/net/ folder instead include.

Quoted 381 lines
drivers/net/Makefile +2 -0
index f4f7ea3..430f90c 100644
@@ -77,6 +77,8 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
 COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
+		xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
 
 COBJS	:= $(sort $(COBJS-y))
 SRCS	:= $(COBJS:.o=.c)
drivers/net/xilinx_ll_temac.c new file +361 -0
new file mode 100644
index 0000000..7124561
@@ -0,0 +1,386 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * supports SDMA or FIFO access and MDIO bus communication
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <[email protected]>
+ * Copyright (C) 2008 - 2011 Michal Simek <[email protected]>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi at co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]:	[0]/ip_documentation/xps_ll_temac.pdf
+ * [A]:	[0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <miiphy.h>
+
+#include <xilinx_ll_temac.h>
+#include <xilinx_ll_temac_fifo.h>
+#include <xilinx_ll_temac_sdma.h>
+#include <xilinx_ll_temac_mdio.h>
+
+#if !defined(CONFIG_MII)
+# error "LL_TEMAC requires MII -- missing CONFIG_MII"
+#endif
+
+#if !defined(CONFIG_PHYLIB)
+# error "LL_TEMAC requires PHYLIB -- missing CONFIG_PHYLIB"
+#endif
+
+/* Ethernet interface ready status */
+int ll_temac_check_status(struct temac_reg *regs, u32 mask)
+{
+	unsigned timeout = 50;	/* 1usec * 50 = 50usec */
+
+	/*
+	 * Quote from LL TEMAC documentation: The bits in the RDY
+	 * register are asserted when there is no access in progress.
+	 * When an access is in progress, a bit corresponding to the
+	 * type of access is automatically de-asserted. The bit is
+	 * automatically re-asserted when the access is complete.
+	 */
+	while (timeout && (!(in_be32(&regs->rdy) & mask))) {
+		timeout--;
+		udelay(1);
+	}
+
+	if (!timeout) {
+		printf("%s: Timeout on 0x%08x @%p\n", __func__,
+				mask, &regs->rdy);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Indirect write to ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
+ * page 23, second paragraph, The use of CTL0 register or CTL1 register
+ */
+int ll_temac_indirect_set(struct temac_reg *regs, u16 regn, u32 reg_data)
+{
+	out_be32(&regs->lsw, (reg_data & MLSW_MASK));
+	out_be32(&regs->ctl, CTL_WEN | (regn & CTL_ADDR_MASK));
+
+	if (ll_temac_check_status(regs, RSE_CFG_WR))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Indirect read from ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
+ * page 23, second paragraph, The use of CTL0 register or CTL1 register
+ */
+int ll_temac_indirect_get(struct temac_reg *regs, u16 regn, u32* reg_data)
+{
+	out_be32(&regs->ctl, (regn & CTL_ADDR_MASK));
+
+	if (ll_temac_check_status(regs, RSE_CFG_RR))
+		return 0;
+
+	*reg_data = in_be32(&regs->lsw) & MLSW_MASK;
+	return 1;
+}
+
+/* setting sub-controller and ll_temac to proper setting */
+static int ll_temac_setup_ctrl(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+
+	if (ll_temac->ctrlreset && ll_temac->ctrlreset(dev))
+		return 0;
+
+	if (ll_temac->ctrlinit && ll_temac->ctrlinit(dev))
+		return 0;
+
+	/* Promiscuous mode disable */
+	if (!ll_temac_indirect_set(regs, TEMAC_AFM, 0))
+		return 0;
+
+	/* Enable Receiver - RX bit */
+	if (!ll_temac_indirect_set(regs, TEMAC_RCW1, RCW1_RX))
+		return 0;
+
+	/* Enable Transmitter - TX bit */
+	if (!ll_temac_indirect_set(regs, TEMAC_TC, TC_TX))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Configure ll_temac based on negotiated speed and duplex
+ * reported by PHY handling code
+ */
+static int ll_temac_adjust_link(struct eth_device *dev)
+{
+	unsigned int speed, emmc_reg;
+	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+	struct ll_temac *ll_temac = dev->priv;
+	struct phy_device *phydev = ll_temac->phydev;
+
+	if (!phydev->link) {
+		printf("%s: No link.\n", phydev->dev->name);
+		return 0;
+	}
+
+	switch (phydev->speed) {
+	case 1000:
+		speed = EMMC_LSPD_1000;
+		break;
+	case 100:
+		speed = EMMC_LSPD_100;
+		break;
+	case 10:
+		speed = EMMC_LSPD_10;
+		break;
+	default:
+		return 0;
+	}
+
+	if (!ll_temac_indirect_get(regs, TEMAC_EMMC, &emmc_reg))
+		return 0;
+
+	emmc_reg &= ~EMMC_LSPD_MASK;
+	emmc_reg |= speed;
+
+	if (!ll_temac_indirect_set(regs, TEMAC_EMMC, emmc_reg))
+		return 0;
+
+	printf("%s: PHY is %s with %dbase%s, %s%s\n",
+			dev->name, phydev->drv->name,
+			phydev->speed, (phydev->port == PORT_TP) ? "T" : "X",
+			(phydev->duplex) ? "FDX" : "HDX",
+			(phydev->port == PORT_OTHER) ? ", unkown mode" : "");
+
+	return 1;
+}
+
+/* setup mac addr */
+static int ll_temac_setup_mac_addr(struct eth_device *dev)
+{
+	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+	u32 val;
+
+	/* set up unicast MAC address filter */
+	val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) |
+			(dev->enetaddr[1] << 8) | (dev->enetaddr[0]));
+	val &= UAW0_UADDR_MASK;
+
+	if (!ll_temac_indirect_set(regs, TEMAC_UAW0, val))
+		return 1;
+
+	val = ((dev->enetaddr[5] << 8) | dev->enetaddr[4]);
+	val &= UAW1_UADDR_MASK;
+
+	if (!ll_temac_indirect_set(regs, TEMAC_UAW1, val))
+		return 1;
+
+	return 0;
+}
+
+/* halt device */
+static void ll_temac_halt(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+
+	/* Disable Receiver */
+	ll_temac_indirect_set(regs, TEMAC_RCW0, 0);
+
+	/* Disable Transmitter */
+	ll_temac_indirect_set(regs, TEMAC_TC, 0);
+
+	if (ll_temac->ctrlhalt)
+		ll_temac->ctrlhalt(dev);
+
+	/* Shut down the PHY, as needed */
+	phy_shutdown(ll_temac->phydev);
+}
+
+static int ll_temac_init(struct eth_device *dev, bd_t *bis)
+{
+	struct ll_temac *ll_temac = dev->priv;
+
+	printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
+		dev->name, dev->index, dev->iobase);
+
+	if (!ll_temac_setup_ctrl(dev))
+		return -1;
+
+	/* Start up the PHY */
+	phy_startup(ll_temac->phydev);
+
+	if (!ll_temac_adjust_link(dev)) {
+		ll_temac_halt(dev);
+		return -1;
+	}
+
+	/* If there's no link, fail */
+	return ll_temac->phydev->link ? 0 : -1;
+}
+
+/*
+ * Discover which PHY is attached to the device, and configure it
+ * properly.  If the PHY is not recognized, then return 0
+ * (failure).  Otherwise, return 1
+ */
+static int ll_temac_phy_init(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	struct phy_device *phydev;
+	unsigned int supported = PHY_GBIT_FEATURES;
+
+	/* interface - look at driver/net/tsec.c */
+	phydev = phy_connect(ll_temac->bus, ll_temac->phyaddr,
+			dev, PHY_INTERFACE_MODE_NONE);
+
+	phydev->supported &= supported;
+	phydev->advertising = phydev->supported;
+
+	ll_temac->phydev = phydev;
+
+	phy_config(phydev);
+
+	return 1;
+}
+
+/*
+ * Initialize a single ll_temac devices
+ *
+ * Returns the result of ll_temac phy interface that were initialized
+ */
+int xilinx_ll_temac_initialize(bd_t *bis, struct ll_temac_info *devinf)
+{
+	struct eth_device *dev;
+	struct ll_temac *ll_temac;
+
+	dev = calloc(1, sizeof(*dev));
+	if (dev == NULL)
+		return 0;
+
+	ll_temac = calloc(1, sizeof(struct ll_temac));
+	if (ll_temac == NULL) {
+		free(dev);
+		return 0;
+	}
+
+	strncpy(dev->name, devinf->devname, NAMESIZE);
+	dev->iobase = devinf->base_addr;
+
+	dev->priv = ll_temac;
+	dev->init = ll_temac_init;
+	dev->halt = ll_temac_halt;
+	dev->write_hwaddr = ll_temac_setup_mac_addr;
+
+	ll_temac->ctrladdr = devinf->ctrl_addr;
+	if (devinf->flags & LL_TEMAC_M_SDMA_PLB) {
+#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
+		if (devinf->flags & LL_TEMAC_M_SDMA_DCR) {
+			ll_temac_collect_xldcr_sdma_reg_addr(dev);
+			ll_temac->in32 = ll_temac_xldcr_in32;
+			ll_temac->out32 = ll_temac_xldcr_out32;
+		} else
+#endif
+		{
+			ll_temac_collect_xlplb_sdma_reg_addr(dev);
+			ll_temac->in32 = ll_temac_xlplb_in32;
+			ll_temac->out32 = ll_temac_xlplb_out32;
+		}
+		ll_temac->ctrlinit = ll_temac_init_sdma;
+		ll_temac->ctrlhalt = ll_temac_halt_sdma;
+		ll_temac->ctrlreset = ll_temac_reset_sdma;
+		dev->recv = ll_temac_recv_sdma;
+		dev->send = ll_temac_send_sdma;
+	} else {
+		ll_temac->in32 = NULL;
+		ll_temac->out32 = NULL;
+		ll_temac->ctrlinit = NULL;
+		ll_temac->ctrlhalt = NULL;
+		ll_temac->ctrlreset = ll_temac_reset_fifo;
+		dev->recv = ll_temac_recv_fifo;
+		dev->send = ll_temac_send_fifo;
+	}
+
+	/* Link to specified MDIO bus */
+	strncpy(ll_temac->mdio_busname, devinf->mdio_busname, MDIO_NAME_LEN);
+	ll_temac->bus = miiphy_get_dev_by_name(ll_temac->mdio_busname);
+
+	/* Looking for a valid PHY address if it is not yet set */
+	if (devinf->phyaddr == -1)
+		ll_temac->phyaddr = ll_temac_phy_addr(ll_temac->bus);
+	else
+		ll_temac->phyaddr = devinf->phyaddr;
+
+	eth_register(dev);
+
+	/* Try to initialize PHY here, and return */
+	return ll_temac_phy_init(dev);
+}
+
+/*
+ * Initialize a single ll_temac device with its mdio bus behind ll_temac
+ *
+ * Returns 1 if the ll_temac device and the mdio bus were initialized
+ * otherwise returns 0
+ */
+static int xilinx_ll_temac_eth_init(bd_t *bis, struct ll_temac_info *devinf)
+{
+	struct ll_temac_mdio_info mdioinf;
+	int ret;
+
+	mdioinf.name = devinf->mdio_busname;
+	mdioinf.regs = (struct temac_reg *)devinf->base_addr;
+	ret = xilinx_ll_temac_mdio_initialize(bis, &mdioinf);
+	if (ret >= 0) {
+		ret = xilinx_ll_temac_initialize(bis, devinf);
+		if (ret > 0)
+			return 1;
+	}
+

drivers/net/xilinx_ll_temac.c line 371

Quoted 10 lines
drivers/net/xilinx_ll_temac.c new file +10 -0
+	return 0;
+}
+
+/*
+ * Initialize all the ll_temac devices
+ *
+ * Returns the number of ll_temac devices that were initialized
+ */
+int xilinx_ll_temac_standard_init(bd_t *bis)
+{

name seems to me bogus because I can't see any non-standard init.

drivers/net/xilinx_ll_temac.c line 383

Quoted 12 lines
drivers/net/xilinx_ll_temac.c new file +12 -0
+	struct ll_temac_info devinf;
+	int count = 0;
+
+#if defined(CONFIG_XILINX_LL_TEMAC0_BASE_ADDR)
+	SET_STD_LL_TEMAC_INFO(devinf, 0);
+	count += xilinx_ll_temac_eth_init(bis, &devinf);
+#endif
+
+#if defined(CONFIG_XILINX_LL_TEMAC1_BASE_ADDR)
+	SET_STD_LL_TEMAC_INFO(devinf, 1);
+	count += xilinx_ll_temac_eth_init(bis, &devinf);
+#endif

I understand what you want to do but it seems to me better
to call xilinx_ll_temac_eth_init(bis, BASE_ADDR, DMA/FIFO, flags, phyaddr) or similar instead of trying to do it in smarter way which must be extend if you want to use more than 2 IPs.

Quoted 505 lines
drivers/net/xilinx_ll_temac.c new file +3 -0
+
+	return count;
+}
drivers/net/xilinx_ll_temac_fifo.c new file +143 -0
new file mode 100644
index 0000000..99a287d
@@ -0,0 +1,143 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * FIFO sub-controller
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <[email protected]>
+ * Copyright (C) 2008 - 2011 Michal Simek <[email protected]>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi at co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * CREDITS: tsec driver
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [F]:	[0]/ip_documentation/xps_ll_fifo.pdf
+ * [S]:	[0]/ip_documentation/xps_ll_temac.pdf
+ * [A]:	[0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+
+#include <asm/types.h>
+#include <asm/io.h>
+
+#include <xilinx_ll_temac.h>
+#include <xilinx_ll_temac_fifo.h>
+
+int ll_temac_reset_fifo(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
+
+	out_be32(&fifo_ctrl->tdfr, LL_FIFO_TDFR_KEY);
+	out_be32(&fifo_ctrl->rdfr, LL_FIFO_RDFR_KEY);
+	out_be32(&fifo_ctrl->isr, ~0UL);
+	out_be32(&fifo_ctrl->ier, 0);
+
+	return 0;
+}
+
+int ll_temac_recv_fifo(struct eth_device *dev)
+{
+	int i, length = 0;
+	u32 *buf = (u32 *)NetRxPackets[0];
+	struct ll_temac *ll_temac = dev->priv;
+	struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
+
+	if (in_be32(&fifo_ctrl->isr) & LL_FIFO_ISR_RC) {
+
+		/* reset isr */
+		out_be32(&fifo_ctrl->isr, ~0UL);
+
+		/*
+		 * MAYBE here:
+		 *   while (fifo_ctrl->isr);
+		 */
+
+		/*
+		 * The length is written (into RLR) by the XPS LL FIFO
+		 * when the packet is received across the RX LocalLink
+		 * interface and the receive data FIFO had enough
+		 * locations that all of the packet data has been saved.
+		 * The RLR should only be read when a receive packet is
+		 * available for processing (the receive occupancy is
+		 * not zero). Once the RLR is read, the receive packet
+		 * data should be read from the receive data FIFO before
+		 * the RLR is read again.
+		 *
+		 * [F] page 17, Receive Length Register (RLR)
+		 */
+		if (in_be32(&fifo_ctrl->rdfo) & LL_FIFO_RDFO_MASK) {
+			length = in_be32(&fifo_ctrl->rlf) & LL_FIFO_RLF_MASK;
+		} else {
+			printf("%s: Got error, no receive occupancy\n",
+					__func__);
+			return -1;
+		}
+
+		if (length > PKTSIZE_ALIGN) {
+			printf("%s: Got error, receive package too big (%i)\n",
+					__func__, length);
+			ll_temac_reset_fifo(dev);
+			return -1;
+		}
+
+		for (i = 0; i < length; i += 4)
+			*buf++ = in_be32(&fifo_ctrl->rdfd);
+
+		NetReceive(NetRxPackets[0], length);
+	}
+
+	return 0;
+}
+
+int ll_temac_send_fifo(struct eth_device *dev, volatile void *packet,
+							int length)
+{
+	int i;
+	u32 *buf = (u32 *)packet;
+	struct ll_temac *ll_temac = dev->priv;
+	struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
+
+	if (length < LL_FIFO_TLF_MIN) {
+		printf("%s: Got error, transmit package too small (%i)\n",
+				__func__, length);
+		return -1;
+	}
+
+	if (length > LL_FIFO_TLF_MAX) {
+		printf("%s: Got error, transmit package too big (%i)\n",
+				__func__, length);
+		return -1;
+	}
+
+	for (i = 0; i < length; i += 4)
+		out_be32(&fifo_ctrl->tdfd, *buf++);
+
+	/*
+	 * Once the packet length is written to the TLR it is
+	 * automatically moved to the transmit data FIFO with
+	 * the packet data freeing up the TLR for another value.
+	 * The packet length must be written to the TLR after
+	 * the packet data is written to the transmit data FIFO.
+	 * It is not valid to write data for multiple packets
+	 * to the transmit data FIFO before writing the packet
+	 * length values.
+	 *
+	 * [F] page 17, Transmit Length Register (TLR)
+	 */
+	out_be32(&fifo_ctrl->tlf, length);
+
+	return 0;
+}
drivers/net/xilinx_ll_temac_mdio.c new file +165 -0
new file mode 100644
index 0000000..9e3a5fb
@@ -0,0 +1,165 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * MDIO bus access
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <[email protected]>
+ * Copyright (C) 2008 - 2011 Michal Simek <[email protected]>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi at co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * CREDITS: tsec driver
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]:	[0]/ip_documentation/xps_ll_temac.pdf
+ * [A]:	[0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <malloc.h>
+#include <asm/io.h>
+
+#include <xilinx_ll_temac.h>
+#include <xilinx_ll_temac_mdio.h>
+
+/*
+ * Prior to PHY access, the MDIO clock must be setup. This driver will set a
+ * safe default that should work with PLB bus speeds of up to 150 MHz and keep
+ * the MDIO clock below 2.5 MHz. If the user wishes faster access to the PHY
+ * then the clock divisor can be set to a different value by setting the
+ * correct bus speed value with CONFIG_XILINX_LL_TEMAC_CLK.
+ */
+#if !defined(CONFIG_XILINX_LL_TEMAC_CLK)
+#define MDIO_CLOCK_DIV		MC_CLKDIV_10(150000000)
+#else
+#define MDIO_CLOCK_DIV		MC_CLKDIV_25(CONFIG_XILINX_LL_TEMAC_CLK)
+#endif
+
+static int ll_temac_mdio_setup(struct mii_dev *bus)
+{
+	struct temac_reg *regs = (struct temac_reg *)bus->priv;
+
+	/* setup MDIO clock */
+	ll_temac_indirect_set(regs, TEMAC_MC,
+			MC_MDIOEN | (MDIO_CLOCK_DIV & MC_CLKDIV_MASK));
+
+	return 0;
+}
+
+/*
+ * Indirect MII PHY read via ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
+ * page 67, Using the MII Management to Access PHY Registers
+ */
+int ll_temac_local_mdio_read(struct temac_reg *regs, int addr, int devad,
+				int regnum)
+{
+	out_be32(&regs->lsw,
+		((addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) |
+		(regnum & LSW_REGAD_MASK));
+	out_be32(&regs->ctl, TEMAC_MIIMAI);
+
+	ll_temac_check_status(regs, RSE_MIIM_RR);
+
+	return in_be32(&regs->lsw) & LSW_REGDAT_MASK;
+}
+
+/*
+ * Indirect MII PHY write via ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
+ * page 67, Using the MII Management to Access PHY Registers
+ */
+void ll_temac_local_mdio_write(struct temac_reg *regs, int addr, int devad,
+				int regnum, u16 value)
+{
+	out_be32(&regs->lsw, (value & LSW_REGDAT_MASK));
+	out_be32(&regs->ctl, CTL_WEN | TEMAC_MIIMWD);
+
+	out_be32(&regs->lsw,
+		((addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) |
+		(regnum & LSW_REGAD_MASK));
+	out_be32(&regs->ctl, CTL_WEN | TEMAC_MIIMAI);
+
+	ll_temac_check_status(regs, RSE_MIIM_WR);
+}
+
+int ll_temac_phy_read(struct mii_dev *bus, int addr, int devad, int regnum)
+{
+	struct temac_reg *regs = (struct temac_reg *)bus->priv;
+
+	return ll_temac_local_mdio_read(regs, addr, devad, regnum);
+}
+
+int ll_temac_phy_write(struct mii_dev *bus, int addr, int devad, int regnum,
+			u16 value)
+{
+	struct temac_reg *regs = (struct temac_reg *)bus->priv;
+
+	ll_temac_local_mdio_write(regs, addr, devad, regnum, value);
+
+	return 0;
+}
+
+/*
+ * Use MII register 1 (MII status register) to detect PHY
+ *
+ * A Mask used to verify certain PHY features (register content)
+ * in the PHY detection register:
+ *  Auto-negotiation support, 10Mbps half/full duplex support
+ */
+#define PHY_DETECT_REG		MII_BMSR
+#define PHY_DETECT_MASK		(BMSR_10FULL | BMSR_10HALF | BMSR_ANEGCAPABLE)
+
+/* Looking for a valid PHY address */
+int ll_temac_phy_addr(struct mii_dev *bus)
+{
+	struct temac_reg *regs = (struct temac_reg *)bus->priv;
+	unsigned short val;
+	unsigned int phy;
+
+	for (phy = PHY_MAX_ADDR; phy >= 0; phy--) {
+		val = ll_temac_local_mdio_read(regs, phy, 0, PHY_DETECT_REG);
+		if ((val != 0xFFFF) &&
+		((val & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+			/* Found a valid PHY address */
+			return phy;
+		}
+	}
+
+	return -1;
+}
+
+int xilinx_ll_temac_mdio_initialize(bd_t *bis, struct ll_temac_mdio_info *info)
+{
+	struct mii_dev *bus = mdio_alloc();
+
+	if (!bus) {
+		printf("Failed to allocate LL_TEMAC MDIO bus: %s\n",
+				info->name);
+		return -1;
+	}
+
+	bus->read = ll_temac_phy_read;
+	bus->write = ll_temac_phy_write;
+	bus->reset = NULL;
+	sprintf(bus->name, info->name);
+
+	bus->priv = info->regs;
+
+	ll_temac_mdio_setup(bus);
+	return mdio_register(bus);
+}
drivers/net/xilinx_ll_temac_sdma.c new file +176 -0
new file mode 100644
index 0000000..ae29d2a
@@ -0,0 +1,370 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * SDMA sub-controller
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <[email protected]>
+ * Copyright (C) 2008 - 2011 Michal Simek <[email protected]>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi at co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * CREDITS: tsec driver
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [M]:	[0]/ip_documentation/mpmc.pdf
+ * [S]:	[0]/ip_documentation/xps_ll_temac.pdf
+ * [A]:	[0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+
+#include <asm/types.h>
+#include <asm/io.h>
+
+#include <xilinx_ll_temac.h>
+#include <xilinx_ll_temac_sdma.h>
+
+#define TX_BUF_CNT		2
+
+static unsigned int rx_idx;	/* index of the current RX buffer */
+static unsigned int tx_idx;	/* index of the current TX buffer */
+
+struct rtx_cdmac_bd {
+	struct cdmac_bd rx[PKTBUFSRX];
+	struct cdmac_bd tx[TX_BUF_CNT];
+};
+
+/*
+ * DMA Buffer Descriptor alignment
+ *
+ * If the address contained in the Next Descriptor Pointer register is not
+ * 8-word aligned or reaches beyond the range of available memory, the SDMA
+ * halts processing and sets the CDMAC_BD_STCTRL_ERROR bit in the respective
+ * status register (tx_chnl_sts or rx_chnl_sts).
+ *
+ * [1]: [0]/ip_documentation/mpmc.pdf
+ *      page 161, Next Descriptor Pointer
+ */
+static struct rtx_cdmac_bd cdmac_bd __aligned(32);
+
+#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
+
+/*
+ * Indirect DCR access operations mi{ft}dcr_xilinx() espacialy
+ * for Xilinx PowerPC implementations on FPGA.
+ *
+ * FIXME: This part should go up to arch/powerpc -- but where?
+ */
+#include <asm/processor.h>
+#define XILINX_INDIRECT_DCR_ADDRESS_REG	0
+#define XILINX_INDIRECT_DCR_ACCESS_REG	1
+inline unsigned mifdcr_xilinx(const unsigned dcrn)
+{
+	mtdcr(XILINX_INDIRECT_DCR_ADDRESS_REG, dcrn);
+	return mfdcr(XILINX_INDIRECT_DCR_ACCESS_REG);
+}
+inline void mitdcr_xilinx(const unsigned dcrn, int val)
+{
+	mtdcr(XILINX_INDIRECT_DCR_ADDRESS_REG, dcrn);
+	mtdcr(XILINX_INDIRECT_DCR_ACCESS_REG, val);
+}
+
+/* Xilinx Device Control Register (DCR) in/out accessors */
+inline unsigned ll_temac_xldcr_in32(phys_addr_t addr)
+{
+	return mifdcr_xilinx((const unsigned)addr);
+}
+inline void ll_temac_xldcr_out32(phys_addr_t addr, unsigned value)
+{
+	mitdcr_xilinx((const unsigned)addr, value);
+}
+
+void ll_temac_collect_xldcr_sdma_reg_addr(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	phys_addr_t dmac_ctrl = ll_temac->ctrladdr;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+	ra[TX_NXTDESC_PTR]   = dmac_ctrl + TX_NXTDESC_PTR;
+	ra[TX_CURBUF_ADDR]   = dmac_ctrl + TX_CURBUF_ADDR;
+	ra[TX_CURBUF_LENGTH] = dmac_ctrl + TX_CURBUF_LENGTH;
+	ra[TX_CURDESC_PTR]   = dmac_ctrl + TX_CURDESC_PTR;
+	ra[TX_TAILDESC_PTR]  = dmac_ctrl + TX_TAILDESC_PTR;
+	ra[TX_CHNL_CTRL]     = dmac_ctrl + TX_CHNL_CTRL;
+	ra[TX_IRQ_REG]       = dmac_ctrl + TX_IRQ_REG;
+	ra[TX_CHNL_STS]      = dmac_ctrl + TX_CHNL_STS;
+	ra[RX_NXTDESC_PTR]   = dmac_ctrl + RX_NXTDESC_PTR;
+	ra[RX_CURBUF_ADDR]   = dmac_ctrl + RX_CURBUF_ADDR;
+	ra[RX_CURBUF_LENGTH] = dmac_ctrl + RX_CURBUF_LENGTH;
+	ra[RX_CURDESC_PTR]   = dmac_ctrl + RX_CURDESC_PTR;
+	ra[RX_TAILDESC_PTR]  = dmac_ctrl + RX_TAILDESC_PTR;
+	ra[RX_CHNL_CTRL]     = dmac_ctrl + RX_CHNL_CTRL;
+	ra[RX_IRQ_REG]       = dmac_ctrl + RX_IRQ_REG;
+	ra[RX_CHNL_STS]      = dmac_ctrl + RX_CHNL_STS;
+	ra[DMA_CONTROL_REG]  = dmac_ctrl + DMA_CONTROL_REG;
+}
+
+#endif /* CONFIG_XILINX_440 || ONFIG_XILINX_405 */
+
+/* Xilinx Processor Local Bus (PLB) in/out accessors */
+inline unsigned ll_temac_xlplb_in32(phys_addr_t addr)
+{
+	return in_be32((void *)addr);
+}
+inline void ll_temac_xlplb_out32(phys_addr_t addr, unsigned value)
+{
+	out_be32((void *)addr, value);
+}
+
+/* collect all register addresses for Xilinx PLB in/out accessors */
+void ll_temac_collect_xlplb_sdma_reg_addr(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+	ra[TX_NXTDESC_PTR]   = (phys_addr_t)&sdma_ctrl->tx_nxtdesc_ptr;
+	ra[TX_CURBUF_ADDR]   = (phys_addr_t)&sdma_ctrl->tx_curbuf_addr;
+	ra[TX_CURBUF_LENGTH] = (phys_addr_t)&sdma_ctrl->tx_curbuf_length;
+	ra[TX_CURDESC_PTR]   = (phys_addr_t)&sdma_ctrl->tx_curdesc_ptr;
+	ra[TX_TAILDESC_PTR]  = (phys_addr_t)&sdma_ctrl->tx_taildesc_ptr;
+	ra[TX_CHNL_CTRL]     = (phys_addr_t)&sdma_ctrl->tx_chnl_ctrl;
+	ra[TX_IRQ_REG]       = (phys_addr_t)&sdma_ctrl->tx_irq_reg;
+	ra[TX_CHNL_STS]      = (phys_addr_t)&sdma_ctrl->tx_chnl_sts;
+	ra[RX_NXTDESC_PTR]   = (phys_addr_t)&sdma_ctrl->rx_nxtdesc_ptr;
+	ra[RX_CURBUF_ADDR]   = (phys_addr_t)&sdma_ctrl->rx_curbuf_addr;
+	ra[RX_CURBUF_LENGTH] = (phys_addr_t)&sdma_ctrl->rx_curbuf_length;
+	ra[RX_CURDESC_PTR]   = (phys_addr_t)&sdma_ctrl->rx_curdesc_ptr;
+	ra[RX_TAILDESC_PTR]  = (phys_addr_t)&sdma_ctrl->rx_taildesc_ptr;
+	ra[RX_CHNL_CTRL]     = (phys_addr_t)&sdma_ctrl->rx_chnl_ctrl;
+	ra[RX_IRQ_REG]       = (phys_addr_t)&sdma_ctrl->rx_irq_reg;
+	ra[RX_CHNL_STS]      = (phys_addr_t)&sdma_ctrl->rx_chnl_sts;
+	ra[DMA_CONTROL_REG]  = (phys_addr_t)&sdma_ctrl->dma_control_reg;
+}
+
+/* Check for TX and RX channel errors. */
+static inline int ll_temac_sdma_error(struct eth_device *dev)
+{
+	int err;
+	struct ll_temac *ll_temac = dev->priv;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+	err = ll_temac->in32(ra[TX_CHNL_STS]) & CHNL_STS_ERROR;
+	err |= ll_temac->in32(ra[RX_CHNL_STS]) & CHNL_STS_ERROR;
+
+	return err;
+}
+
+int ll_temac_init_sdma(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	struct cdmac_bd *rx_dp;
+	struct cdmac_bd *tx_dp;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+	int i;
+

drivers/net/xilinx_ll_temac_sdma.c line 186

Quoted 10 lines
drivers/net/xilinx_ll_temac_sdma.c new file +10 -0
+	printf("%s: SDMA: %d Rx buffers, %d Tx buffers\n",
+			dev->name, PKTBUFSRX, TX_BUF_CNT);
+
+	/* Initialize the Rx Buffer descriptors */
+	for (i = 0; i < PKTBUFSRX; i++) {
+		rx_dp = &cdmac_bd.rx[i];
+		memset(rx_dp, 0, sizeof(*rx_dp));
+		rx_dp->next_p = rx_dp;
+		rx_dp->buf_len = PKTSIZE_ALIGN;
+		rx_dp->phys_buf_p = NetRxPackets[i];

xilinx_ll_temac_sdma.c: In function 'll_temac_init_sdma':
xilinx_ll_temac_sdma.c:186: warning: assignment discards qualifiers from pointer target type

- rx_dp->phys_buf_p = NetRxPackets[i];
+ rx_dp->phys_buf_p = (u8 *)NetRxPackets[i];

Quoted 147 lines
drivers/net/xilinx_ll_temac_sdma.c new file +147 -0
+		flush_cache((u32)rx_dp->phys_buf_p, PKTSIZE_ALIGN);
+	}
+	flush_cache((u32)cdmac_bd.rx, sizeof(cdmac_bd.rx));
+
+	/* Initialize the TX Buffer Descriptors */
+	for (i = 0; i < TX_BUF_CNT; i++) {
+		tx_dp = &cdmac_bd.tx[i];
+		memset(tx_dp, 0, sizeof(*tx_dp));
+		tx_dp->next_p = tx_dp;
+	}
+	flush_cache((u32)cdmac_bd.tx, sizeof(cdmac_bd.tx));
+
+	/* Reset index counter to the Rx and Tx Buffer descriptors */
+	rx_idx = tx_idx = 0;
+
+	/* initial Rx DMA start by writing to respective TAILDESC_PTR */
+	ll_temac->out32(ra[RX_CURDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+	ll_temac->out32(ra[RX_TAILDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+
+	return 0;
+}
+
+int ll_temac_halt_sdma(struct eth_device *dev)
+{
+	unsigned timeout = 50;	/* 1usec * 50 = 50usec */
+	struct ll_temac *ll_temac = dev->priv;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+	/*
+	 * Soft reset the DMA
+	 *
+	 * Quote from MPMC documentation: Writing a 1 to this field
+	 * forces the DMA engine to shutdown and reset itself. After
+	 * setting this bit, software must poll it until the bit is
+	 * cleared by the DMA. This indicates that the reset process
+	 * is done and the pipeline has been flushed.
+	 */
+	ll_temac->out32(ra[DMA_CONTROL_REG], DMA_CONTROL_RESET);
+	while (timeout && (ll_temac->in32(ra[DMA_CONTROL_REG])
+					& DMA_CONTROL_RESET)) {
+		timeout--;
+		udelay(1);
+	}
+
+	if (!timeout) {
+		printf("%s: Timeout\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int ll_temac_reset_sdma(struct eth_device *dev)
+{
+	u32 r;
+	struct ll_temac *ll_temac = dev->priv;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+	/* Soft reset the DMA.  */
+	if (ll_temac_halt_sdma(dev))
+		return -1;
+
+	/* Now clear the interrupts.  */
+	r = ll_temac->in32(ra[TX_CHNL_CTRL]);
+	r &= ~CHNL_CTRL_IRQ_MASK;
+	ll_temac->out32(ra[TX_CHNL_CTRL], r);
+
+	r = ll_temac->in32(ra[RX_CHNL_CTRL]);
+	r &= ~CHNL_CTRL_IRQ_MASK;
+	ll_temac->out32(ra[RX_CHNL_CTRL], r);
+
+	/* Now ACK pending IRQs.  */
+	ll_temac->out32(ra[TX_IRQ_REG], IRQ_REG_IRQ_MASK);
+	ll_temac->out32(ra[RX_IRQ_REG], IRQ_REG_IRQ_MASK);
+
+	/* Set tail-ptr mode, disable errors for both channels.  */
+	ll_temac->out32(ra[DMA_CONTROL_REG],
+			/* Enable use of tail pointer register */
+			DMA_CONTROL_TPE |
+			/* Disable error when 2 or 4 bit coalesce cnt overfl */
+			DMA_CONTROL_RXOCEID |
+			/* Disable error when 2 or 4 bit coalesce cnt overfl */
+			DMA_CONTROL_TXOCEID);
+
+	return 0;
+}
+
+int ll_temac_recv_sdma(struct eth_device *dev)
+{
+	int length, pb_idx;
+	struct cdmac_bd *rx_dp = &cdmac_bd.rx[rx_idx];
+	struct ll_temac *ll_temac = dev->priv;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+	if (ll_temac_sdma_error(dev)) {
+
+		if (ll_temac_reset_sdma(dev))
+			return -1;
+
+		ll_temac_init_sdma(dev);
+	}
+
+	flush_cache((u32)rx_dp, sizeof(*rx_dp));
+
+	if (!(rx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED))
+		return 0;
+
+	if (rx_dp->sca.stctrl & (CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP)) {
+		pb_idx = rx_idx;
+		length = rx_dp->sca.app[4] & CDMAC_BD_APP4_RXBYTECNT_MASK;
+	} else {
+		pb_idx = -1;
+		length = 0;
+		printf("%s: Got part of package, unsupported (%x)\n",
+				__func__, rx_dp->sca.stctrl);
+	}
+
+	/* flip the buffer */
+	flush_cache((u32)rx_dp->phys_buf_p, length);
+
+	/* reset the current descriptor */
+	rx_dp->sca.stctrl = 0;
+	rx_dp->sca.app[4] = 0;
+	flush_cache((u32)rx_dp, sizeof(*rx_dp));
+
+	/* Find next empty buffer descriptor, preparation for next iteration */
+	rx_idx = (rx_idx + 1) % PKTBUFSRX;
+	rx_dp = &cdmac_bd.rx[rx_idx];
+	flush_cache((u32)rx_dp, sizeof(*rx_dp));
+
+	/* DMA start by writing to respective TAILDESC_PTR */
+	ll_temac->out32(ra[RX_CURDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+	ll_temac->out32(ra[RX_TAILDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+
+	if (length > 0 && pb_idx != -1)
+		NetReceive(NetRxPackets[pb_idx], length);
+
+	return 0;
+}
+
+int ll_temac_send_sdma(struct eth_device *dev, volatile void *packet,
+							int length)
+{
+	unsigned timeout = 50;	/* 1usec * 50 = 50usec */
+	struct cdmac_bd *tx_dp = &cdmac_bd.tx[tx_idx];
+	struct ll_temac *ll_temac = dev->priv;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;

drivers/net/xilinx_ll_temac_sdma.c line 343

Quoted 10 lines
drivers/net/xilinx_ll_temac_sdma.c new file +10 -0
+
+	if (ll_temac_sdma_error(dev)) {
+
+		if (ll_temac_reset_sdma(dev))
+			return -1;
+
+		ll_temac_init_sdma(dev);
+	}
+
+	tx_dp->phys_buf_p = packet;

xilinx_ll_temac_sdma.c: In function 'll_temac_send_sdma':
xilinx_ll_temac_sdma.c:343: warning: assignment discards qualifiers from pointer target type

- tx_dp->phys_buf_p = packet;
+ tx_dp->phys_buf_p = (u8 *)packet;

Quoted 32 lines
drivers/net/xilinx_ll_temac_sdma.c new file +27 -0
+	tx_dp->buf_len = length;
+	tx_dp->sca.stctrl = CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP |
+			CDMAC_BD_STCTRL_STOP_ON_END;
+
+	flush_cache((u32)packet, length);
+	flush_cache((u32)tx_dp, sizeof(*tx_dp));
+
+	/* DMA start by writing to respective TAILDESC_PTR */
+	ll_temac->out32(ra[TX_CURDESC_PTR], (int)tx_dp);
+	ll_temac->out32(ra[TX_TAILDESC_PTR], (int)tx_dp);
+
+	/* Find next empty buffer descriptor, preparation for next iteration */
+	tx_idx = (tx_idx + 1) % TX_BUF_CNT;
+	tx_dp = &cdmac_bd.tx[tx_idx];
+
+	do {
+		flush_cache((u32)tx_dp, sizeof(*tx_dp));
+		udelay(1);
+	} while (timeout-- && !(tx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED));
+
+	if (!timeout) {
+		printf("%s: Timeout\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
include/netdev.h +0 -0
index b0c21d5..bf95f88 100644

include/netdev.h int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr, · line 105

Quoted 4 lines
include/netdev.h +1 -0
@@ -102,6 +102,7 @@ int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
 							unsigned long dma_addr);
 int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
 							int txpp, int rxpp);
+int xilinx_ll_temac_standard_init(bd_t *bis);

I don't like this solution - some comments below above.

Quoted 38 lines
include/netdev.h +0 -0
 /* Boards with PCI network controllers can call this from their board_eth_init()
  * function to initialize whatever's on board.
include/xilinx_ll_temac.h new file +29 -0
new file mode 100644
index 0000000..8b86611
@@ -0,0 +1,430 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * LL_TEMAC interface
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <[email protected]>
+ * Copyright (C) 2008 - 2011 Michal Simek <[email protected]>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi at co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]:	[0]/ip_documentation/xps_ll_temac.pdf
+ * [A]:	[0]/application_notes/xapp1041.pdf
+ */
+#ifndef _XILINX_LL_TEMAC_
+#define _XILINX_LL_TEMAC_
+
+#include <config.h>
+#include <net.h>
+#include <phy.h>

include/xilinx_ll_temac.h line 39

Quoted 10 lines
include/xilinx_ll_temac.h new file +10 -0
+#include <miiphy.h>
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+#include <xilinx_ll_temac_sdma.h>
+
+#if !defined(__BIG_ENDIAN)
+# error LL_TEMAC requires big endianess
+#endif

Not sure if is good to have this in header - you have two limitations in xilinx_ll_temac.c for MII and PHYLIB. IMHO will be good to add this there too.

This chcecking is also at three places.

Quoted 8 lines
include/xilinx_ll_temac.h new file +8 -0
+
+/* default ETH device name */
+#if !defined(CONFIG_XILINX_LL_TEMAC0_NAME)
+#define CONFIG_XILINX_LL_TEMAC0_NAME		"LLTEMAC0"
+#endif
+
+#if !defined(CONFIG_XILINX_LL_TEMAC1_NAME)
+#define CONFIG_XILINX_LL_TEMAC1_NAME		"LLTEMAC1"

include/xilinx_ll_temac.h line 57

Quoted 10 lines
include/xilinx_ll_temac.h new file +10 -0
+#endif
+
+/* default MII device name */
+#if !defined(CONFIG_XILINX_LL_TEMAC0_MII_NAME)
+#define CONFIG_XILINX_LL_TEMAC0_MII_NAME	"LLTEMAC0_MII"
+#endif
+
+#if !defined(CONFIG_XILINX_LL_TEMAC1_MII_NAME)
+#define CONFIG_XILINX_LL_TEMAC1_MII_NAME	"LLTEMAC1_MII"
+#endif

People likes games with names but I think it is completely OK just choose standard one and create it.
Even more IMHO name should contain address because if you want to use more none will remember which IP is 0/1/2/etc.

In axi driver I use
sprintf(dev->name, "aximac.%lx", base_addr);
which seems to me the best.

The same argument for MII name.

Quoted 56 lines
include/xilinx_ll_temac.h new file +56 -0
+
+/* default PHY device address on MII */
+#if !defined(CONFIG_PHY_ADDR)
+#define CONFIG_PHY_ADDR		-1
+#endif
+#define CONFIG_PHY0_ADDR	CONFIG_PHY_ADDR
+
+#if !defined(CONFIG_PHY1_ADDR)
+#define CONFIG_PHY1_ADDR	-1
+#endif
+
+/* default parameters for LLTEMAC0 */
+#if defined(XILINX_LLTEMAC_BASEADDR)
+# if !defined(XILINX_LL_TEMAC0_BASE_ADDR)
+#  define CONFIG_XILINX_LL_TEMAC0_BASE_ADDR	XILINX_LLTEMAC_BASEADDR
+# endif
+# if defined(XILINX_LLTEMAC_FIFO_BASEADDR)
+#  if !defined(XILINX_LL_TEMAC0_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC0_CTRL_ADDR	XILINX_LLTEMAC_FIFO_BASEADDR
+#  endif
+#  if !defined(XILINX_LL_TEMAC0_CTRL_MODE)
+#   define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE	LL_TEMAC_M_FIFO
+#  endif
+# elif defined(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR)
+#  if !defined(XILINX_LL_TEMAC0_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC0_CTRL_ADDR	XILINX_LLTEMAC_SDMA_CTRL_BASEADDR
+#  endif
+#  if (XILINX_LLTEMAC_SDMA_USE_DCR == 1)
+#   if !defined(XILINX_LL_TEMAC0_CTRL_MODE)
+#    define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE	LL_TEMAC_M_SDMA_DCR
+#   endif
+#  else
+#    define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE	LL_TEMAC_M_SDMA_PLB
+#  endif
+# else
+#  error "missing sub-controller base address for LLTEMAC0"
+# endif
+#endif
+
+/* default parameters for LLTEMAC1 */
+#if defined(XILINX_LLTEMAC_BASEADDR1)
+# if !defined(XILINX_LL_TEMAC1_BASE_ADDR)
+#  define CONFIG_XILINX_LL_TEMAC1_BASE_ADDR	XILINX_LLTEMAC_BASEADDR1
+# endif
+# if defined(XILINX_LLTEMAC_FIFO_BASEADDR1)
+#  if !defined(XILINX_LL_TEMAC1_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC1_CTRL_ADDR	XILINX_LLTEMAC_FIFO_BASEADDR1
+#  endif
+#  if !defined(XILINX_LL_TEMAC1_CTRL_MODE)
+#   define CONFIG_XILINX_LL_TEMAC1_CTRL_MODE	LL_TEMAC_M_FIFO
+#  endif
+# elif defined(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR1)
+#  if !defined(XILINX_LL_TEMAC1_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC1_CTRL_ADDR	XILINX_LLTEMAC_SDMA_CTRL_BASEADDR1
+#  endif
+#  if (XILINX_LLTEMAC_SDMA_USE_DCR == 1)

include/xilinx_ll_temac.h line 123

Quoted 10 lines
include/xilinx_ll_temac.h new file +10 -0
+#   if !defined(XILINX_LL_TEMAC1_CTRL_MODE)
+#    define CONFIG_XILINX_LL_TEMAC1_CTRL_MODE	LL_TEMAC_M_SDMA_DCR
+#   endif
+#  else
+#    define CONFIG_XILINX_LL_TEMAC1_CTRL_MODE	LL_TEMAC_M_SDMA_PLB
+#  endif
+# else
+#  error "missing sub-controller base address for LLTEMAC1"
+# endif
+#endif

It seems to me that this is a lot of code which just do nothing interesting. There is a lot of if/else/endif to even read it. Why not to do configuration directly in board specific file?

include/xilinx_ll_temac.h line 133

Quoted 10 lines
include/xilinx_ll_temac.h new file +10 -0
+
+#define STD_LL_TEMAC_INFO(num) \
+{ \
+	.devname = CONFIG_XILINX_LL_TEMAC##num##_NAME, \
+	.base_addr = CONFIG_XILINX_LL_TEMAC##num##_BASE_ADDR, \
+	.ctrl_addr = CONFIG_XILINX_LL_TEMAC##num##_CTRL_ADDR, \
+	.flags = CONFIG_XILINX_LL_TEMAC##num##_CTRL_MODE, \
+	.mdio_busname = CONFIG_XILINX_LL_TEMAC##num##_MII_NAME, \
+	.phyaddr = CONFIG_PHY##num##_ADDR, \
+}

This is completely unused.

include/xilinx_ll_temac.h line 143

Quoted 10 lines
include/xilinx_ll_temac.h new file +10 -0
+
+#define SET_STD_LL_TEMAC_INFO(x, num) \
+{ \
+	x.devname = CONFIG_XILINX_LL_TEMAC##num##_NAME; \
+	x.base_addr = CONFIG_XILINX_LL_TEMAC##num##_BASE_ADDR; \
+	x.ctrl_addr = CONFIG_XILINX_LL_TEMAC##num##_CTRL_ADDR; \
+	x.flags = CONFIG_XILINX_LL_TEMAC##num##_CTRL_MODE; \
+	x.mdio_busname = CONFIG_XILINX_LL_TEMAC##num##_MII_NAME; \
+	x.phyaddr = CONFIG_PHY##num##_ADDR; \
+}

This configuration things seems to me completely weird. My preference is to do it in board file without any helper function.

Quoted 262 lines
include/xilinx_ll_temac.h new file +262 -0
+
+/*
+ * TEMAC Memory and Register Definition
+ *
+ * [1]:	[0]/ip_documentation/xps_ll_temac.pdf
+ *	page 19, Memory and Register Descriptions
+ */
+struct temac_reg {
+	/* direct soft registers (low part) */
+	u32 raf;	/* Reset and Address Filter */
+	u32 tpf;	/* Transmit Pause Frame */
+	u32 ifgp;	/* Transmit Inter Frame Gap Adjustment */
+	u32 is;		/* Interrupt Status */
+	u32 ip;		/* Interrupt Pending */
+	u32 ie;		/* Interrupt Enable */
+	u32 ttag;	/* Transmit VLAN Tag */
+	u32 rtag;	/* Receive VLAN Tag */
+	/* hard TEMAC registers */
+	u32 msw;	/* Most Significant Word Data */
+	u32 lsw;	/* Least Significant Word Data */
+	u32 ctl;	/* Control */
+	u32 rdy;	/* Ready Status */
+	/* direct soft registers (high part) */
+	u32 uawl;	/* Unicast Address Word Lower */
+	u32 uawu;	/* Unicast Address Word Upper */
+	u32 tpid0;	/* VLAN TPID Word 0 */
+	u32 tpid1;	/* VLAN TPID Word 1 */
+};
+
+/* Reset and Address Filter Registers (raf), [1] p25 */
+#define RAF_SR			(1 << 13)
+#define RAF_EMFE		(1 << 12)
+#define RAF_NFE			(1 << 11)
+#define RAF_RVSTM_POS		9
+#define RAF_RVSTM_MASK		(3 << RAF_RVSTM_POS)
+#define RAF_TVSTM_POS		7
+#define RAF_TVSTM_MASK		(3 << RAF_TVSTM_POS)
+#define RAF_RVTM_POS		5
+#define RAF_RVTM_MASK		(3 << RAF_RVTM_POS)
+#define RAF_TVTM_POS		3
+#define RAF_TVTM_MASK		(3 << RAF_TVTM_POS)
+#define RAF_BCREJ		(1 << 2)
+#define RAF_MCREJ		(1 << 1)
+#define RAF_HTRST		(1 << 0)
+
+/* Transmit Pause Frame Registers (tpf), [1] p28 */
+#define TPF_TPFV_POS		0
+#define TPF_TPFV_MASK		(0xFFFF << TPF_TPFV_POS)
+
+/* Transmit Inter Frame Gap Adjustment Registers (ifgp), [1] p28 */
+#define IFGP_POS		0
+#define IFGP_MASK		(0xFF << IFGP_POS)
+
+/* Interrupt Status, Pending, Enable Registers (is, ip, ie), [1] p29-33 */
+#define ISPE_MR			(1 << 7)
+#define ISPE_RDL		(1 << 6)
+#define ISPE_TC			(1 << 5)
+#define ISPE_RFO		(1 << 4)
+#define ISPE_RR			(1 << 3)
+#define ISPE_RC			(1 << 2)
+#define ISPE_AN			(1 << 1)
+#define ISPE_HAC		(1 << 0)
+
+/* Transmit, Receive VLAN Tag Registers (ttag, rtag), [1] p34-35 */
+#define TRTAG_TPID_POS		16
+#define TRTAG_TPID_MASK		(0xFFFF << TRTAG_TPID_POS)
+#define TRTAG_PRIO_POS		13
+#define TRTAG_PRIO_MASK		(7 << TRTAG_PRIO_POS)
+#define TRTAG_CFI		(1 << 12)
+#define TRTAG_VID_POS		0
+#define TRTAG_VID_MASK		(0xFFF << TRTAG_VID_POS)
+
+/* Most, Least Significant Word Data Register (msw, lsw), [1] p46 */
+#define MLSW_POS		0
+#define MLSW_MASK		(~0UL << MLSW_POS)
+
+/* LSW Data Register for PHY addresses (lsw), [1] p66 */
+#define LSW_REGAD_POS		0
+#define LSW_REGAD_MASK		(0x1F << LSW_REGAD_POS)
+#define LSW_PHYAD_POS		5
+#define LSW_PHYAD_MASK		(0x1F << LSW_PHYAD_POS)
+
+/* LSW Data Register for PHY data (lsw), [1] p66 */
+#define LSW_REGDAT_POS		0
+#define LSW_REGDAT_MASK		(0xFFFF << LSW_REGDAT_POS)
+
+/* Control Register (ctl), [1] p47 */
+#define CTL_WEN			(1 << 15)
+#define CTL_ADDR_POS		0
+#define CTL_ADDR_MASK		(0x3FF << CTL_ADDR_POS)
+
+/* Ready Status Register Ethernet (rdy), [1] p48 */
+#define RSE_HACS_RDY		(1 << 14)
+#define RSE_CFG_WR		(1 << 6)
+#define RSE_CFG_RR		(1 << 5)
+#define RSE_AF_WR		(1 << 4)
+#define RSE_AF_RR		(1 << 3)
+#define RSE_MIIM_WR		(1 << 2)
+#define RSE_MIIM_RR		(1 << 1)
+#define RSE_FABR_RR		(1 << 0)
+
+/* Unicast Address Word Lower, Upper Registers (uawl, uawu), [1] p35-36 */
+#define UAWL_UADDR_POS		0
+#define UAWL_UADDR_MASK		(~0UL << UAWL_UADDR_POS)
+#define UAWU_UADDR_POS		0
+#define UAWU_UADDR_MASK		(0xFFFF << UAWU_UADDR_POS)
+
+/* VLAN TPID Word 0, 1 Registers (tpid0, tpid1), [1] p37 */
+#define TPID0_V0_POS		0
+#define TPID0_V0_MASK		(0xFFFF << TPID0_V0_POS)
+#define TPID0_V1_POS		16
+#define TPID0_V1_MASK		(0xFFFF << TPID0_V1_POS)
+#define TPID1_V2_POS		0
+#define TPID1_V2_MASK		(0xFFFF << TPID1_V2_POS)
+#define TPID1_V3_POS		16
+#define TPID1_V3_MASK		(0xFFFF << TPID1_V3_POS)
+
+/*
+ * TEMAC Indirectly Addressable Register Index Enumeration
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [1]:	[0]/ip_documentation/xps_ll_temac.pdf
+ *	page 23, PLB Indirectly Addressable TEMAC Registers
+ */
+enum temac_ctrl {
+	TEMAC_RCW0	= 0x200,
+	TEMAC_RCW1	= 0x240,
+	TEMAC_TC	= 0x280,
+	TEMAC_FCC	= 0x2C0,
+	TEMAC_EMMC	= 0x300,
+	TEMAC_PHYC	= 0x320,
+	TEMAC_MC	= 0x340,
+	TEMAC_UAW0	= 0x380,
+	TEMAC_UAW1	= 0x384,
+	TEMAC_MAW0	= 0x388,
+	TEMAC_MAW1	= 0x38C,
+	TEMAC_AFM	= 0x390,
+	TEMAC_TIS	= 0x3A0,
+	TEMAC_TIE	= 0x3A4,
+	TEMAC_MIIMWD	= 0x3B0,
+	TEMAC_MIIMAI	= 0x3B4
+};
+
+/* Receive Configuration Word 0, 1 Registers (RCW0, RCW1), [1] p50-51 */
+#define RCW0_PADDR_POS		0
+#define RCW0_PADDR_MASK		(~0UL << RCW_PADDR_POS)
+#define RCW1_RST		(1 << 31)
+#define RCW1_JUM		(1 << 30)
+#define RCW1_FCS		(1 << 29)
+#define RCW1_RX			(1 << 28)
+#define RCW1_VLAN		(1 << 27)
+#define RCW1_HD			(1 << 26)
+#define RCW1_LT_DIS		(1 << 25)
+#define RCW1_PADDR_POS		0
+#define RCW1_PADDR_MASK		(0xFFFF << RCW_PADDR_POS)
+
+/* Transmit Configuration Registers (TC), [1] p52 */
+#define TC_RST			(1 << 31)
+#define TC_JUM			(1 << 30)
+#define TC_FCS			(1 << 29)
+#define TC_TX			(1 << 28)
+#define TC_VLAN			(1 << 27)
+#define TC_HD			(1 << 26)
+#define TC_IFG			(1 << 25)
+
+/* Flow Control Configuration Registers (FCC), [1] p54 */
+#define FCC_FCTX		(1 << 30)
+#define FCC_FCRX		(1 << 29)
+
+/* Ethernet MAC Mode Configuration Registers (EMMC), [1] p54 */
+#define EMMC_LSPD_POS		30
+#define EMMC_LSPD_MASK		(3 << EMMC_LSPD_POS)
+#define EMMC_LSPD_1000		(2 << EMMC_LSPD_POS)
+#define EMMC_LSPD_100		(1 << EMMC_LSPD_POS)
+#define EMMC_LSPD_10		0
+#define EMMC_RGMII		(1 << 29)
+#define EMMC_SGMII		(1 << 28)
+#define EMMC_GPCS		(1 << 27)
+#define EMMC_HOST		(1 << 26)
+#define EMMC_TX16		(1 << 25)
+#define EMMC_RX16		(1 << 24)
+
+/* RGMII/SGMII Configuration Registers (PHYC), [1] p56 */
+#define PHYC_SLSPD_POS		30
+#define PHYC_SLSPD_MASK		(3 << EMMC_SLSPD_POS)
+#define PHYC_SLSPD_1000		(2 << EMMC_SLSPD_POS)
+#define PHYC_SLSPD_100		(1 << EMMC_SLSPD_POS)
+#define PHYC_SLSPD_10		0
+#define PHYC_RLSPD_POS		2
+#define PHYC_RLSPD_MASK		(3 << EMMC_RLSPD_POS)
+#define PHYC_RLSPD_1000		(2 << EMMC_RLSPD_POS)
+#define PHYC_RLSPD_100		(1 << EMMC_RLSPD_POS)
+#define PHYC_RLSPD_10		0
+#define PHYC_RGMII_HD		(1 << 1)
+#define PHYC_RGMII_LINK		(1 << 0)
+
+/* Management Configuration Registers (MC), [1] p57 */
+#define MC_MDIOEN		(1 << 6)
+#define MC_CLKDIV_POS		0
+#define MC_CLKDIV_MASK		(0x3F << MC_CLKDIV_POS)
+
+/*
+ *             fHOSTCLK          fMDC =                  fHOSTCLK
+ * fMDC = -------------------   --------->   MC_CLKDIV = -------- - 1
+ *        (1 + MC_CLKDIV) * 2    2.5 MHz                   5MHz
+ */
+#define MC_CLKDIV(f, m)		((f / (2 * m)) - 1)
+#define MC_CLKDIV_25(f)		MC_CLKDIV(f, 2500000)
+#define MC_CLKDIV_20(f)		MC_CLKDIV(f, 2000000)
+#define MC_CLKDIV_15(f)		MC_CLKDIV(f, 1500000)
+#define MC_CLKDIV_10(f)		MC_CLKDIV(f, 1000000)
+
+/* Unicast Address Word 0, 1 Registers (UAW0, UAW1), [1] p58-59 */
+#define UAW0_UADDR_POS		0
+#define UAW0_UADDR_MASK		(~0UL << UAW0_UADDR_POS)
+#define UAW1_UADDR_POS		0
+#define UAW1_UADDR_MASK		(0xFFFF << UAW1_UADDR_POS)
+
+/* Multicast Address Word 0, 1 Registers (MAW0, MAW1), [1] p60 */
+#define MAW0_MADDR_POS		0
+#define MAW0_MADDR_MASK		(~0UL << MAW0_MADDR_POS)
+#define MAW1_RNW		(1 << 23)
+#define MAW1_MAIDX_POS		16
+#define MAW1_MAIDX_MASK		(3 << MAW1_MAIDX_POS)
+#define MAW1_MADDR_POS		0
+#define MAW1_MADDR_MASK		(0xFFFF << MAW1_MADDR_POS)
+
+/* Address Filter Mode Registers (AFM), [1] p63 */
+#define AFM_PM			(1 << 31)
+
+/* Interrupt Status, Enable Registers (TIS, TIE), [1] p63-65 */
+#define TISE_CFG_W		(1 << 6)
+#define TISE_CFG_R		(1 << 5)
+#define TISE_AF_W		(1 << 4)
+#define TISE_AF_R		(1 << 3)
+#define TISE_MIIM_W		(1 << 2)
+#define TISE_MIIM_R		(1 << 1)
+#define TISE_FABR_R		(1 << 0)
+
+/* MII Management Write Data Registers (MIIMWD), [1] p66 */
+#define MIIMWD_DATA_POS		0
+#define MIIMWD_DATA_MASK	(0xFFFF << MIIMWD_DATA_POS)
+
+/* Ethernet interface ready status */
+int ll_temac_check_status(struct temac_reg *regs, u32 mask);
+
+/* Indirect write to ll_temac. */
+int ll_temac_indirect_set(struct temac_reg *regs, u16 regn, u32 reg_data);
+
+/* Indirect read from ll_temac. */
+int ll_temac_indirect_get(struct temac_reg *regs, u16 regn, u32* reg_data);
+
+struct ll_temac {
+	phys_addr_t		ctrladdr;
+	phys_addr_t		sdma_reg_addr[SDMA_CTRL_REGNUMS];
+
+	unsigned		(*in32)(phys_addr_t);
+	void			(*out32)(phys_addr_t, unsigned);
+
+	int			(*ctrlinit) (struct eth_device *);
+	int			(*ctrlhalt) (struct eth_device *);

include/xilinx_ll_temac.h line 415

Quoted 10 lines
include/xilinx_ll_temac.h new file +10 -0
+	int			(*ctrlreset) (struct eth_device *);
+
+	int			phyaddr;
+	struct phy_device	*phydev;
+	struct mii_dev		*bus;
+	char			mdio_busname[MDIO_NAME_LEN];
+};
+
+struct ll_temac_info {
+	int			flags;

probably u32?

Others patches looks good.

Michal

Signature · 4 lines
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
#3 lore raw

PATCH 1/6 net: ll_temac: Add LL TEMAC driver to u-boot

Am Donnerstag, den 26.01.2012, 16:07 +0100 schrieb Michal Simek:

Quoted 1 line

Hi Stephan,

Hi Michal,

Quoted 28 lines
Quoted 17 lines · Stephan Linz

Xilinx LocalLink Tri-Mode Ether MAC driver can be
used by Xilinx Microblaze or Xilinx ppc405/440 in
SDMA and FIFO mode. DCR or XPS bus can be used.

--snip--

---
 drivers/net/Makefile               |    2 +
 drivers/net/xilinx_ll_temac.c      |  386 ++++++++++++++++++++++++++++++++
 drivers/net/xilinx_ll_temac_fifo.c |  143 ++++++++++++
 drivers/net/xilinx_ll_temac_mdio.c |  165 ++++++++++++++
 drivers/net/xilinx_ll_temac_sdma.c |  370 +++++++++++++++++++++++++++++++
 include/netdev.h                   |    1 +
 include/xilinx_ll_temac.h          |  430 ++++++++++++++++++++++++++++++++++++
 include/xilinx_ll_temac_fifo.h     |  122 ++++++++++
 include/xilinx_ll_temac_mdio.h     |   53 +++++
 include/xilinx_ll_temac_sdma.h     |  281 +++++++++++++++++++++++
 10 files changed, 1953 insertions(+), 0 deletions(-)
Quoted 8 lines
 create mode 100644 drivers/net/xilinx_ll_temac.c
 create mode 100644 drivers/net/xilinx_ll_temac_fifo.c
 create mode 100644 drivers/net/xilinx_ll_temac_mdio.c
 create mode 100644 drivers/net/xilinx_ll_temac_sdma.c
 create mode 100644 include/xilinx_ll_temac.h
 create mode 100644 include/xilinx_ll_temac_fifo.h
 create mode 100644 include/xilinx_ll_temac_mdio.h
 create mode 100644 include/xilinx_ll_temac_sdma.h
Quoted 2 lines

Wolfgang: I just wanted to know what it is the rule for adding headers. I would prefer to add these headers to drivers/net/ folder instead include.

Hm, the reason was the more and more growing up of public interfaces, for example xilinx_ll_temac_mdio_initialize() and xilinx_ll_temac_initialize() can be used outside of the driver instead of it's own standard setup. Yes, I've read your consider, see below. But if I want to use the xilinx_ll_temac_initialize() outside I need to export the interface, especially mode flag definitions (FIFO/SDMA/DCR). So I need public access to the header.

@Wolfgang: What will be the best solution here?

Quoted 49 lines
Quoted 35 lines
drivers/net/Makefile +23 -1
index f4f7ea3..430f90c 100644
@@ -77,6 +77,8 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
 COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
 COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
+		xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
--snip--
+
+/*
+ * Initialize a single ll_temac device with its mdio bus behind ll_temac
+ *
+ * Returns 1 if the ll_temac device and the mdio bus were initialized
+ * otherwise returns 0
+ */
+static int xilinx_ll_temac_eth_init(bd_t *bis, struct ll_temac_info *devinf)
+{
+	struct ll_temac_mdio_info mdioinf;
+	int ret;
+
+	mdioinf.name = devinf->mdio_busname;
+	mdioinf.regs = (struct temac_reg *)devinf->base_addr;
+	ret = xilinx_ll_temac_mdio_initialize(bis, &mdioinf);
+	if (ret >= 0) {
+		ret = xilinx_ll_temac_initialize(bis, devinf);
+		if (ret > 0)
+			return 1;
+	}
+

drivers/net/Makefile COBJS-$(CONFIG_ULI526X) += uli526x.o

Quoted 10 lines
drivers/net/Makefile +10 -0
+	return 0;
+}
+
+/*
+ * Initialize all the ll_temac devices
+ *
+ * Returns the number of ll_temac devices that were initialized
+ */
+int xilinx_ll_temac_standard_init(bd_t *bis)
+{

name seems to me bogus because I can't see any non-standard init.

Quoted 15 lines

drivers/net/Makefile

Quoted 12 lines
drivers/net/Makefile +12 -0
+	struct ll_temac_info devinf;
+	int count = 0;
+
+#if defined(CONFIG_XILINX_LL_TEMAC0_BASE_ADDR)
+	SET_STD_LL_TEMAC_INFO(devinf, 0);
+	count += xilinx_ll_temac_eth_init(bis, &devinf);
+#endif
+
+#if defined(CONFIG_XILINX_LL_TEMAC1_BASE_ADDR)
+	SET_STD_LL_TEMAC_INFO(devinf, 1);
+	count += xilinx_ll_temac_eth_init(bis, &devinf);
+#endif

I understand what you want to do but it seems to me better
to call xilinx_ll_temac_eth_init(bis, BASE_ADDR, DMA/FIFO, flags, phyaddr)

I believe, function with more than three arguments is bad code. So I've introduced a driver information struct, We can bundle all the specific IP options in this struct.

Quoted 2 lines

or similar instead of trying to do it in smarter way which must be extend if you want to use more than 2 IPs.

The same problem would be in board init code. You must decide which address, mode, and subaddress you have to use. By implementation of a "standard initialization" we can avoid a blow out board init code.

I think there is a natural limit of available IPs. We just need to find this and adapt the code. Here I've typed on 2 IPs. We can easly expand to 4 or 6 IPs as default.

Please note, this function should implement THE standard case. You are free to use the underlaying functions for MDIO and MAC initialization in any other case outside the driver code.

Quoted 34 lines
Quoted 20 lines
drivers/net/Makefile +3 -0
+
+	return count;
+}
drivers/net/xilinx_ll_temac_sdma.c new file +10 -0
new file mode 100644
index 0000000..ae29d2a
@@ -0,0 +1,370 @@
+--snip--
+
+int ll_temac_init_sdma(struct eth_device *dev)
+{
+	struct ll_temac *ll_temac = dev->priv;
+	struct cdmac_bd *rx_dp;
+	struct cdmac_bd *tx_dp;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;
+	int i;
+

drivers/net/xilinx_ll_temac_sdma.c line 20

Quoted 10 lines
drivers/net/xilinx_ll_temac_sdma.c new file +10 -0
+	printf("%s: SDMA: %d Rx buffers, %d Tx buffers\n",
+			dev->name, PKTBUFSRX, TX_BUF_CNT);
+
+	/* Initialize the Rx Buffer descriptors */
+	for (i = 0; i < PKTBUFSRX; i++) {
+		rx_dp = &cdmac_bd.rx[i];
+		memset(rx_dp, 0, sizeof(*rx_dp));
+		rx_dp->next_p = rx_dp;
+		rx_dp->buf_len = PKTSIZE_ALIGN;
+		rx_dp->phys_buf_p = NetRxPackets[i];

xilinx_ll_temac_sdma.c: In function 'll_temac_init_sdma':
xilinx_ll_temac_sdma.c:186: warning: assignment discards qualifiers from pointer target type

Review

Quoted 2 lines
(quoted diff) +1 -1
-               rx_dp->phys_buf_p = NetRxPackets[i];
+               rx_dp->phys_buf_p = (u8 *)NetRxPackets[i];

Oops, I'll fix it quickly.

Quoted 26 lines
Quoted 11 lines
drivers/net/xilinx_ll_temac_sdma.c new file +9 -0
+--snip--
+
+int ll_temac_send_sdma(struct eth_device *dev, volatile void *packet,
+							int length)
+{
+	unsigned timeout = 50;	/* 1usec * 50 = 50usec */
+	struct cdmac_bd *tx_dp = &cdmac_bd.tx[tx_idx];
+	struct ll_temac *ll_temac = dev->priv;
+	phys_addr_t *ra = ll_temac->sdma_reg_addr;

drivers/net/xilinx_ll_temac_sdma.c line 343

Quoted 10 lines
drivers/net/xilinx_ll_temac_sdma.c new file +10 -0
+
+	if (ll_temac_sdma_error(dev)) {
+
+		if (ll_temac_reset_sdma(dev))
+			return -1;
+
+		ll_temac_init_sdma(dev);
+	}
+
+	tx_dp->phys_buf_p = packet;

xilinx_ll_temac_sdma.c: In function 'll_temac_send_sdma':
xilinx_ll_temac_sdma.c:343: warning: assignment discards qualifiers from pointer target type

Review

Quoted 2 lines
(quoted diff) +1 -1
-       tx_dp->phys_buf_p = packet;
+       tx_dp->phys_buf_p = (u8 *)packet;

The same here (see above).

Quoted 33 lines
Quoted 33 lines
drivers/net/xilinx_ll_temac_sdma.c new file +27 -0
+	tx_dp->buf_len = length;
+	tx_dp->sca.stctrl = CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP |
+			CDMAC_BD_STCTRL_STOP_ON_END;
+
+	flush_cache((u32)packet, length);
+	flush_cache((u32)tx_dp, sizeof(*tx_dp));
+
+	/* DMA start by writing to respective TAILDESC_PTR */
+	ll_temac->out32(ra[TX_CURDESC_PTR], (int)tx_dp);
+	ll_temac->out32(ra[TX_TAILDESC_PTR], (int)tx_dp);
+
+	/* Find next empty buffer descriptor, preparation for next iteration */
+	tx_idx = (tx_idx + 1) % TX_BUF_CNT;
+	tx_dp = &cdmac_bd.tx[tx_idx];
+
+	do {
+		flush_cache((u32)tx_dp, sizeof(*tx_dp));
+		udelay(1);
+	} while (timeout-- && !(tx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED));
+
+	if (!timeout) {
+		printf("%s: Timeout\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
include/netdev.h +0 -0
index b0c21d5..bf95f88 100644
Quoted 8 lines

include/netdev.h int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr, · line 105

Quoted 5 lines
include/netdev.h +1 -0
@@ -102,6 +102,7 @@ int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
 							unsigned long dma_addr);
 int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
 							int txpp, int rxpp);
+int xilinx_ll_temac_standard_init(bd_t *bis);

I don't like this solution - some comments below above.

see my comments ... above and below

Quoted 44 lines
Quoted 44 lines
include/netdev.h +0 -0
 /* Boards with PCI network controllers can call this from their board_eth_init()
  * function to initialize whatever's on board.
include/xilinx_ll_temac.h new file +33 -0
new file mode 100644
index 0000000..8b86611
@@ -0,0 +1,430 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * LL_TEMAC interface
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <[email protected]>
+ * Copyright (C) 2008 - 2011 Michal Simek <[email protected]>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi at co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]:	[0]/ip_documentation/xps_ll_temac.pdf
+ * [A]:	[0]/application_notes/xapp1041.pdf
+ */
+#ifndef _XILINX_LL_TEMAC_
+#define _XILINX_LL_TEMAC_
+
+#include <config.h>
+#include <net.h>
+#include <phy.h>
+#include <miiphy.h>
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
Quoted 8 lines

include/xilinx_ll_temac.h line 39

Quoted 6 lines
include/xilinx_ll_temac.h new file +6 -0
+
+#include <xilinx_ll_temac_sdma.h>
+
+#if !defined(__BIG_ENDIAN)
+# error LL_TEMAC requires big endianess
+#endif

Not sure if is good to have this in header

All headers are not compliant to little endian. The structs and defines declared inside can only be used for a big endian controller on a big endian cpu. Currently we will never see a XPS_LL_TEMAC IP core on a little endian PPC or Microblaze system, or not? So I've blocked bad endianess here.

Quoted 2 lines

- you have two limitations in xilinx_ll_temac.c for MII and PHYLIB. IMHO will be good to add this there too.

Hm, yes. a good place would be in xilinx_ll_temac_mdio.c too. I'll fix it.

Quoted 19 lines

This chcecking is also at three places.

Quoted 15 lines
include/xilinx_ll_temac.h new file +15 -0
+
+/* default ETH device name */
+#if !defined(CONFIG_XILINX_LL_TEMAC0_NAME)
+#define CONFIG_XILINX_LL_TEMAC0_NAME		"LLTEMAC0"
+#endif
+
+#if !defined(CONFIG_XILINX_LL_TEMAC1_NAME)
+#define CONFIG_XILINX_LL_TEMAC1_NAME		"LLTEMAC1"
+#endif
+
+/* default MII device name */
+#if !defined(CONFIG_XILINX_LL_TEMAC0_MII_NAME)
+#define CONFIG_XILINX_LL_TEMAC0_MII_NAME	"LLTEMAC0_MII"
+#endif
+
Quoted 8 lines

include/xilinx_ll_temac.h line 57

Quoted 3 lines
include/xilinx_ll_temac.h new file +3 -0
+#if !defined(CONFIG_XILINX_LL_TEMAC1_MII_NAME)
+#define CONFIG_XILINX_LL_TEMAC1_MII_NAME	"LLTEMAC1_MII"
+#endif

People likes games with names but I think it is completely OK just choose standard one and create it.
Even more IMHO name should contain address because if you want to use more none will remember which IP is 0/1/2/etc.

Hm, but you can see it on console output. The base address will printed out and we know about the enumeration.

Quoted 3 lines

In axi driver I use
sprintf(dev->name, "aximac.%lx", base_addr);
which seems to me the best.

On this way we can never change the name outside the driver. The name would be fixed forever. If you need your own namespace then use the corresponding configuration options, example for the first IP:
CONFIG_XILINX_LL_TEMAC0_NAME -- This can done in combination of xparameters.h and configs/microblaze-generic.h. If you need a dynamic namespace (your case) then do not use the "standard initialization". You can setup your own driver information struct in board init code by a dynamically generated string and have a direct call to the underlaying functions for MDIO and MAC initialization.

Quoted 2 lines

The same argument for MII name.

same here

Quoted 23 lines
Quoted 23 lines
include/xilinx_ll_temac.h new file +21 -0
+
+/* default PHY device address on MII */
+#if !defined(CONFIG_PHY_ADDR)
+#define CONFIG_PHY_ADDR		-1
+#endif
+#define CONFIG_PHY0_ADDR	CONFIG_PHY_ADDR
+
+#if !defined(CONFIG_PHY1_ADDR)
+#define CONFIG_PHY1_ADDR	-1
+#endif
+
+/* default parameters for LLTEMAC0 */
+#if defined(XILINX_LLTEMAC_BASEADDR)
+# if !defined(XILINX_LL_TEMAC0_BASE_ADDR)
+#  define CONFIG_XILINX_LL_TEMAC0_BASE_ADDR	XILINX_LLTEMAC_BASEADDR
+# endif
+# if defined(XILINX_LLTEMAC_FIFO_BASEADDR)
+#  if !defined(XILINX_LL_TEMAC0_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC0_CTRL_ADDR	XILINX_LLTEMAC_FIFO_BASEADDR
+#  endif
+#  if !defined(XILINX_LL_TEMAC0_CTRL_MODE)
Quoted 8 lines

include/xilinx_ll_temac.h line 86

Quoted 8 lines
include/xilinx_ll_temac.h new file +8 -0
+#   define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE	LL_TEMAC_M_FIFO
+#  endif
+# elif defined(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR)
+#  if !defined(XILINX_LL_TEMAC0_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC0_CTRL_ADDR	XILINX_LLTEMAC_SDMA_CTRL_BASEADDR
+#  endif
+#  if (XILINX_LLTEMAC_SDMA_USE_DCR == 1)
+#   if !defined(XILINX_LL_TEMAC0_CTRL_MODE)

grr, have to check CONFIG_XILINX_LL_TEMAC0_CTRL_MODE will fix it ...

Quoted 20 lines
Quoted 20 lines
include/xilinx_ll_temac.h new file +20 -0
+#    define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE	LL_TEMAC_M_SDMA_DCR
+#   endif
+#  else
+#    define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE	LL_TEMAC_M_SDMA_PLB
+#  endif
+# else
+#  error "missing sub-controller base address for LLTEMAC0"
+# endif
+#endif
+
+/* default parameters for LLTEMAC1 */
+#if defined(XILINX_LLTEMAC_BASEADDR1)
+# if !defined(XILINX_LL_TEMAC1_BASE_ADDR)
+#  define CONFIG_XILINX_LL_TEMAC1_BASE_ADDR	XILINX_LLTEMAC_BASEADDR1
+# endif
+# if defined(XILINX_LLTEMAC_FIFO_BASEADDR1)
+#  if !defined(XILINX_LL_TEMAC1_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC1_CTRL_ADDR	XILINX_LLTEMAC_FIFO_BASEADDR1
+#  endif
+#  if !defined(XILINX_LL_TEMAC1_CTRL_MODE)
Quoted 8 lines

include/xilinx_ll_temac.h line 114

Quoted 8 lines
include/xilinx_ll_temac.h new file +8 -0
+#   define CONFIG_XILINX_LL_TEMAC1_CTRL_MODE	LL_TEMAC_M_FIFO
+#  endif
+# elif defined(XILINX_LLTEMAC_SDMA_CTRL_BASEADDR1)
+#  if !defined(XILINX_LL_TEMAC1_CTRL_ADDR)
+#   define CONFIG_XILINX_LL_TEMAC1_CTRL_ADDR	XILINX_LLTEMAC_SDMA_CTRL_BASEADDR1
+#  endif
+#  if (XILINX_LLTEMAC_SDMA_USE_DCR == 1)
+#   if !defined(XILINX_LL_TEMAC1_CTRL_MODE)

... same here ...

Quoted 5 lines
Quoted 5 lines
include/xilinx_ll_temac.h new file +5 -0
+#    define CONFIG_XILINX_LL_TEMAC1_CTRL_MODE	LL_TEMAC_M_SDMA_DCR
+#   endif
+#  else
+#    define CONFIG_XILINX_LL_TEMAC1_CTRL_MODE	LL_TEMAC_M_SDMA_PLB
+#  endif
Quoted 8 lines

include/xilinx_ll_temac.h line 123

Quoted 4 lines
include/xilinx_ll_temac.h new file +4 -0
+# else
+#  error "missing sub-controller base address for LLTEMAC1"
+# endif
+#endif

It seems to me that this is a lot of code which just do nothing interesting. There is a lot of if/else/endif to even read it. Why not to do configuration directly in board specific file?

Yes, it is an ugly part. There are some stupid redefinitions -- for example

XILINX_LLTEMAC_BASEADDR to CONFIG_XILINX_LL_TEMAC0_BASE_ADDR

But there are two reasons for this:

1) XILINX_LLTEMAC_BASEADDR should be XILINX_LLTEMAC_BASEADDR0 or XILINX_LLTEMAC0_BASEADDR -- so we can use CPP to handle it directly inside the SET_STD_LL_TEMAC_INFO(num) macro

2) Each U-Boot configuration variable have to begin with CONFIG_ (see README)

The best solution here would be a new (better) syntax in xparameters.h -- for example:

#define CONFIG_XILINX_LL_TEMAC0_BASE_ADDR      0x44000000
#define CONFIG_XILINX_LL_TEMAC0_CTRL_ADDR      0x42000180
#define CONFIG_XILINX_LL_TEMAC1_BASE_ADDR      0x44000040
#define CONFIG_XILINX_LL_TEMAC1_CTRL_ADDR      0x42000200

This would reduce this part of code to nearly zero.

Furthermore we could define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE with the right mode value directly in xparameters.h -- for example:

#define CONFIG_XILINX_LL_TEMAC0_CTRL_MODE 0 /* FIFO */
#define CONFIG_XILINX_LL_TEMAC1_CTRL_MODE 1 /* SDMA by PLB */

The xparameters.h header is an auto-generated file. We can change/expand the generator. Within the meaning of U-Boot we have to change because it will be included by the generic board configuration and there we need a proper U-Boot configuration syntax.

We should discuss it in details.

Quoted 13 lines

include/xilinx_ll_temac.h line 133

Quoted 11 lines
include/xilinx_ll_temac.h new file +10 -0
+
+#define STD_LL_TEMAC_INFO(num) \
+{ \
+	.devname = CONFIG_XILINX_LL_TEMAC##num##_NAME, \
+	.base_addr = CONFIG_XILINX_LL_TEMAC##num##_BASE_ADDR, \
+	.ctrl_addr = CONFIG_XILINX_LL_TEMAC##num##_CTRL_ADDR, \
+	.flags = CONFIG_XILINX_LL_TEMAC##num##_CTRL_MODE, \
+	.mdio_busname = CONFIG_XILINX_LL_TEMAC##num##_MII_NAME, \
+	.phyaddr = CONFIG_PHY##num##_ADDR, \
+}

This is completely unused.

Yes, but usefull if you want to make a static driver configuration array outside the driver, for example in a specific (not the generic) board init. So I left it here as an part of the public driver interface.

Quoted 15 lines

include/xilinx_ll_temac.h line 143

Quoted 11 lines
include/xilinx_ll_temac.h new file +10 -0
+
+#define SET_STD_LL_TEMAC_INFO(x, num) \
+{ \
+	x.devname = CONFIG_XILINX_LL_TEMAC##num##_NAME; \
+	x.base_addr = CONFIG_XILINX_LL_TEMAC##num##_BASE_ADDR; \
+	x.ctrl_addr = CONFIG_XILINX_LL_TEMAC##num##_CTRL_ADDR; \
+	x.flags = CONFIG_XILINX_LL_TEMAC##num##_CTRL_MODE; \
+	x.mdio_busname = CONFIG_XILINX_LL_TEMAC##num##_MII_NAME; \
+	x.phyaddr = CONFIG_PHY##num##_ADDR; \
+}

This configuration things seems to me completely weird. My preference is to do it in board file without any helper function.

So you have to make it twice or multiple. Each board file have to implement all the wired redefinitions or decisions based on the definitions from xparameters.h -- you will implement the same code in board/xilinx/microblaze-generic/ and board/xilinx/ppc405-generic/ and board/xilinx/ppc440-generic/ and this for more than 2 IPs ...

Do you prefer this really?

Quoted 2 lines

--snip--

Quoted 4 lines

include/xilinx_ll_temac.h line 415

Quoted 2 lines
include/xilinx_ll_temac.h new file +2 -0
+struct ll_temac_info {
+	int			flags;

probably u32?

mybe, but it is an internal value -- uncritically here.

Quoted 2 lines

Others patches looks good.

:)

Signature · 8 lines
Best regards,
Stephan Linz
______________________________________________________________________________
MB-Ref: http://www.li-pro.de/xilinx_mb:mbref:start
OpenDCC: http://www.li-pro.net/opendcc.phtml
PC/M: http://www.li-pro.net/pcm.phtml
Sourceforge: http://sourceforge.net/users/slz
Gitorious: https://gitorious.org/~slz
#4 lore raw

PATCH 2/6 microblaze: Enable several ethernet driver compilation

In reply to Stephan Linz

NET_MULTI enables to use several ethernet drivers but microblaze-generic platform config file select only one driver.

---
 include/configs/microblaze-generic.h |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)
include/configs/microblaze-generic.h +6 -4
index 03a6f5a..29a86d1 100644
@@ -65,11 +65,12 @@
 
 /* ethernet */
 #undef CONFIG_SYS_ENET
-#ifdef XILINX_EMACLITE_BASEADDR
-# define CONFIG_XILINX_EMACLITE		1
+#if defined(XILINX_EMACLITE_BASEADDR)
+# define CONFIG_XILINX_EMACLITE	1
 # define CONFIG_SYS_ENET
-#elif XILINX_LLTEMAC_BASEADDR
-# define CONFIG_XILINX_LL_TEMAC		1
+#endif
+#if defined(XILINX_LLTEMAC_BASEADDR) || defined(XILINX_LLTEMAC_BASEADDR1)
+# define CONFIG_XILINX_LL_TEMAC	1
 # define CONFIG_SYS_ENET
 #endif
 #if defined(XILINX_AXIEMAC_BASEADDR)
@@ -312,6 +313,7 @@
 #define	CONFIG_SERVERIP		192.168.0.5
 #define	CONFIG_GATEWAYIP	192.168.0.1
 #define	CONFIG_ETHADDR		00:E0:0C:00:00:FD
+#define	CONFIG_ETH1ADDR		00:E0:0C:00:00:FC
 
 /* architecture dependent code */
 #define	CONFIG_SYS_USR_EXCEP	/* user exception */
Signature · 1 line
1.7.0.4
#5 lore raw

PATCH 2/6 microblaze: Enable several ethernet driver compilation

Quoted 3 lines · On Saturday 21 January 2012 16:02:54 Stephan Linz wrote:

NET_MULTI enables to use several ethernet drivers but microblaze-generic platform config file select only one driver.

NET_MULTI no longer exists because the code is always enabled now :)

Quoted 2 lines

#define CONFIG_ETHADDR 00:E0:0C:00:00:FD
+#define CONFIG_ETH1ADDR 00:E0:0C:00:00:FC

err, i think these need to get dropped. boards should not be hardcoding mac addresses in their configs.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120126/ad17a3e5/attachment.pgp>

#6 lore raw

PATCH 2/6 microblaze: Enable several ethernet driver compilation

Hi Mike,

Am Donnerstag, den 26.01.2012, 22:58 -0500 schrieb Mike Frysinger:

Quoted 6 lines · On Saturday 21 January 2012 16:02:54 Stephan Linz wrote:
Quoted 3 lines

NET_MULTI enables to use several ethernet drivers but microblaze-generic platform config file select only one driver.

NET_MULTI no longer exists because the code is always enabled now :)

right, that is not defined anywhere -- the comment means that we will use the multipple network interface support from U-Boot. I can write a more precise comment ...

Quoted 6 lines
Quoted 3 lines

#define CONFIG_ETHADDR 00:E0:0C:00:00:FD
+#define CONFIG_ETH1ADDR 00:E0:0C:00:00:FC

err, i think these need to get dropped. boards should not be hardcoding mac addresses in their configs.

OK, I think so too. I can left at least one MAC address as it was in the original board configuration. I think we need this for a rapid system startup without a default configuration in ROM. IMHO there are many many boards that are going this way ...

Signature · 8 lines
Best regards,
Stephan Linz
______________________________________________________________________________
MB-Ref: http://www.li-pro.de/xilinx_mb:mbref:start
OpenDCC: http://www.li-pro.net/opendcc.phtml
PC/M: http://www.li-pro.net/pcm.phtml
Sourceforge: http://sourceforge.net/users/slz
Gitorious: https://gitorious.org/~slz
#7 lore raw

PATCH 2/6 microblaze: Enable several ethernet driver compilation

Quoted 5 lines · On Saturday 28 January 2012 03:55:47 Stephan Linz wrote:

Am Donnerstag, den 26.01.2012, 22:58 -0500 schrieb Mike Frysinger:

Quoted 4 lines · On Saturday 21 January 2012 16:02:54 Stephan Linz wrote:
Quoted 2 lines

#define CONFIG_ETHADDR 00:E0:0C:00:00:FD
+#define CONFIG_ETH1ADDR 00:E0:0C:00:00:FC

Quoted 7 lines
Quoted 2 lines

err, i think these need to get dropped. boards should not be hardcoding mac addresses in their configs.

OK, I think so too. I can left at least one MAC address as it was in the original board configuration. I think we need this for a rapid system startup without a default configuration in ROM. IMHO there are many many boards that are going this way ...

hardcoding mac addrs have been NAK-ed in the past by Wolfgang every time and i don't think it's changing
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120128/b24a11a9/attachment.pgp>

#8 lore raw

PATCH 2/6 microblaze: Enable several ethernet driver compilation

In reply to Stephan Linz

Dear Stephan Linz,

Quoted 11 lines · In message <1327740947.3638.16.camel@keto> you wrote:
Quoted 6 lines
Quoted 3 lines

#define CONFIG_ETHADDR 00:E0:0C:00:00:FD
+#define CONFIG_ETH1ADDR 00:E0:0C:00:00:FC

err, i think these need to get dropped. boards should not be hardcoding mac addresses in their configs.

OK, I think so too. I can left at least one MAC address as it was in the original board configuration. I think we need this for a rapid system startup without a default configuration in ROM. IMHO there are many many boards that are going this way ...

Please drop it. As Mike pointed out, it is not acceptable for mainline code.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
What was sliced bread the greatest thing since?
#9 lore raw

PATCH 3/6 microblaze: Wire up LL_TEMAC driver initialization

In reply to Stephan Linz

Initialize ll_temac driver.

---
 .../xilinx/microblaze-generic/microblaze-generic.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
board/xilinx/microblaze-generic/microblaze-generic.c +5 -0
index c4c13a6..517b2f1 100644
@@ -90,5 +90,10 @@ int board_eth_init(bd_t *bis)
 	ret |= xilinx_emaclite_initialize(bis, XILINX_EMACLITE_BASEADDR,
 			txpp, rxpp);
 #endif
+
+#ifdef CONFIG_XILINX_LL_TEMAC
+	ret |= xilinx_ll_temac_standard_init(bis);
+#endif
+
 	return ret;
 }
Signature · 1 line
1.7.0.4
#10 lore raw

PATCH 4/6 microblaze: Enable phylib and mii support

In reply to Stephan Linz

From: Michal Simek <[email protected]>

Enable phylib and mii support for LLTEMAC or AXI EMAC ethernet drivers on Microblaze systems.

---
 include/configs/microblaze-generic.h |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)
include/configs/microblaze-generic.h +21 -0
index 29a86d1..ec2e49e 100644
@@ -340,4 +340,25 @@
 #define CONFIG_FIT		1
 #define CONFIG_OF_LIBFDT	1
 
+#if defined(CONFIG_XILINX_LL_TEMAC) || defined(CONFIG_XILINX_AXIEMAC)
+# define CONFIG_MII		1
+# define CONFIG_CMD_MII		1
+# define CONFIG_PHY_GIGE	1
+# define CONFIG_SYS_FAULT_ECHO_LINK_DOWN	1
+# define CONFIG_PHYLIB		1
+# define CONFIG_PHY_ATHEROS	1
+# define CONFIG_PHY_BROADCOM	1
+# define CONFIG_PHY_DAVICOM	1
+# define CONFIG_PHY_LXT		1
+# define CONFIG_PHY_MARVELL	1
+# define CONFIG_PHY_MICREL	1
+# define CONFIG_PHY_NATSEMI	1
+# define CONFIG_PHY_REALTEK	1
+# define CONFIG_PHY_VITESSE	1
+#else
+# undef CONFIG_MII
+# undef CONFIG_CMD_MII
+# undef CONFIG_PHYLIB
+#endif
+
 #endif	/* __CONFIG_H */
Signature · 1 line
1.7.0.4
#11 lore raw

PATCH 5/6 microblaze: Enable TFTP put command

In reply to Stephan Linz
---
 include/configs/microblaze-generic.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
include/configs/microblaze-generic.h +1 -0
index ec2e49e..a4cdcd8 100644
@@ -256,6 +256,7 @@
 #else
 # define CONFIG_CMD_PING
 # define CONFIG_CMD_DHCP
+# define CONFIG_CMD_TFTPPUT
 #endif
 
 #if defined(CONFIG_SYSTEMACE)
Signature · 1 line
1.7.0.4
#12 lore raw

PATCH 6/6 microblaze: Add faked LL_TEMAC driver configuration

In reply to Stephan Linz

Expand the specific configuration for the microblaze-generic board in xparameters.h with a faked setup to enable the LL_TEMAC driver.

Note: From now the microblaze-generic board is no longer a valid board configuration for a real piece of hardware. Rather than, we use the file config.mk and xparameters.h as a faked board configuration to force the compilation of all potential driver code for Microblaze systems.

---
 board/xilinx/microblaze-generic/config.mk     |    6 ++++--
 board/xilinx/microblaze-generic/xparameters.h |   12 ++++++++++--
 2 files changed, 14 insertions(+), 4 deletions(-)
board/xilinx/microblaze-generic/config.mk +4 -2
index f8d7e26..9fd1015 100644
@@ -21,8 +21,10 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 # MA 02111-1307 USA
 #
-# CAUTION: This file is automatically generated by libgen.
-# Version: Xilinx EDK 6.3 EDK_Gmm.12.3
+# CAUTION: This file is a faked configuration !!!
+#          There is no real target for the microblaze-generic
+#          configuration. You have to replace this file with
+#          the generated file from your Xilinx design flow.
 #
 
 CONFIG_SYS_TEXT_BASE = 0x29000000
board/xilinx/microblaze-generic/xparameters.h +10 -2
index fae03bf..fcbd55e 100644
@@ -21,8 +21,10 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  *
- * CAUTION: This file is automatically generated by libgen.
- * Version: Xilinx EDK 8.2.02 EDK_Im_Sp2.4
+ * CAUTION: This file is a faked configuration !!!
+ *          There is no real target for the microblaze-generic
+ *          configuration. You have to replace this file with
+ *          the generated file from your Xilinx design flow.
  */
 
 #define XILINX_BOARD_NAME	microblaze-generic
@@ -69,3 +71,9 @@
 
 /* Ethernet controller is Ethernet_MAC */
 #define XILINX_EMACLITE_BASEADDR       0x40C00000
+
+/* Ethernet controller is Ethernet_MAC */
+#define XILINX_LLTEMAC_BASEADDR			0x44000000
+#define XILINX_LLTEMAC_SDMA_CTRL_BASEADDR	0x42000180
+#define XILINX_LLTEMAC_BASEADDR1		0x44000040
+#define XILINX_LLTEMAC_SDMA_CTRL_BASEADDR1	0x42000200
Signature · 1 line
1.7.0.4