[U-Boot] [PATCH 1/6] net: ll_temac: Add LL TEMAC driver to u-boot

Michal Simek monstr at monstr.eu
Thu Jan 26 16:07:34 CET 2012


Hi Stephan,

Stephan Linz wrote:
> 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.
> 
> Signed-off-by: Stephan Linz <linz at li-pro.net>
> ---
> 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

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.


> 
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index f4f7ea3..430f90c 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -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)
> diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c
> new file mode 100644
> index 0000000..7124561
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac.c
> @@ -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 <linz at li-pro.net>
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * 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;
> +	}
> +
> +	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.


> +	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.

> +
> +	return count;
> +}
> diff --git a/drivers/net/xilinx_ll_temac_fifo.c b/drivers/net/xilinx_ll_temac_fifo.c
> new file mode 100644
> index 0000000..99a287d
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac_fifo.c
> @@ -0,0 +1,143 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * FIFO sub-controller
> + *
> + * Copyright (C) 2011 - 2012 Stephan Linz <linz at li-pro.net>
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * 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;
> +}
> diff --git a/drivers/net/xilinx_ll_temac_mdio.c b/drivers/net/xilinx_ll_temac_mdio.c
> new file mode 100644
> index 0000000..9e3a5fb
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac_mdio.c
> @@ -0,0 +1,165 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * MDIO bus access
> + *
> + * Copyright (C) 2011 - 2012 Stephan Linz <linz at li-pro.net>
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * 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);
> +}
> diff --git a/drivers/net/xilinx_ll_temac_sdma.c b/drivers/net/xilinx_ll_temac_sdma.c
> new file mode 100644
> index 0000000..ae29d2a
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac_sdma.c
> @@ -0,0 +1,370 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * SDMA sub-controller
> + *
> + * Copyright (C) 2011 - 2012 Stephan Linz <linz at li-pro.net>
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * 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;
> +
> +	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];


> +		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;
> +
> +	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;


> +	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;
> +}
> diff --git a/include/netdev.h b/include/netdev.h
> index b0c21d5..bf95f88 100644
> --- a/include/netdev.h
> +++ b/include/netdev.h
> @@ -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.


>  
>  /* Boards with PCI network controllers can call this from their board_eth_init()
>   * function to initialize whatever's on board.
> diff --git a/include/xilinx_ll_temac.h b/include/xilinx_ll_temac.h
> new file mode 100644
> index 0000000..8b86611
> --- /dev/null
> +++ b/include/xilinx_ll_temac.h
> @@ -0,0 +1,430 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * LL_TEMAC interface
> + *
> + * Copyright (C) 2011 - 2012 Stephan Linz <linz at li-pro.net>
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * 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>
> +
> +#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.


> +
> +/* 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
> +
> +#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.


> +
> +/* 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)
> +#   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?

> +
> +#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.

> +
> +#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.





> +
> +/*
> + * 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 *);
> +	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

-- 
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


More information about the U-Boot mailing list