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

Marek Vasut marek.vasut at gmail.com
Sun Nov 27 12:09:39 CET 2011


> 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.
> 
> Signed-off-by: Stephan Linz <linz at li-pro.net>
> ---
> 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      |  399
> ++++++++++++++++++++++++++++++++++ drivers/net/xilinx_ll_temac.h      | 
> 305 ++++++++++++++++++++++++++ drivers/net/xilinx_ll_temac_fifo.c |   93
> ++++++++
>  drivers/net/xilinx_ll_temac_fifo.h |  112 ++++++++++
>  drivers/net/xilinx_ll_temac_sdma.c |  413
> ++++++++++++++++++++++++++++++++++++ drivers/net/xilinx_ll_temac_sdma.h | 
> 280 ++++++++++++++++++++++++ include/netdev.h                   |    2 +
>  8 files changed, 1606 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/xilinx_ll_temac.c
>  create mode 100644 drivers/net/xilinx_ll_temac.h
>  create mode 100644 drivers/net/xilinx_ll_temac_fifo.c
>  create mode 100644 drivers/net/xilinx_ll_temac_fifo.h
>  create mode 100644 drivers/net/xilinx_ll_temac_sdma.c
>  create mode 100644 drivers/net/xilinx_ll_temac_sdma.h
> 
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index d3df82e..14d71a7 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -76,6 +76,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_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..39f3a8b
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac.c
> @@ -0,0 +1,399 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * supports SDMA or FIFO access
> + *
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * Copyright (C) 2008 - 2011 PetaLogix
> + *
> + * Copyright (C) 2011 Stepahn Linz <linz at li-pro.net>
> + *
> + * 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.
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <net.h>
> +#include <malloc.h>
> +#include <asm/io.h>
> +#include <phy.h>
> +#include <miiphy.h>
> +
> +#include "xilinx_ll_temac.h"
> +
> +#undef ETH_HALTING
> +
> +#if !defined(CONFIG_MII) || !defined(CONFIG_CMD_MII)
> +# error "LL_TEMAC requires MII -- CONFIG_MII has to be defined!"
> +#endif

Why CONFIG_CMD_MII, the error says only CONFIG_MII

> +
> +#if !defined(CONFIG_PHYLIB)
> +# error "LL_TEMAC requires PHYLIB -- CONFIG_PHYLIB has to be defined!"
> +#endif
> +
> +/*
> + * 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
> +

One newline
> +
> +/* Data buffer for LL TEMAC Rx and Tx direction */
> +static unsigned char rx_buffer[PKTSIZE_ALIGN]
> __attribute((aligned(DMAALIGN))); +static unsigned char
> tx_buffer[PKTSIZE_ALIGN] __attribute((aligned(DMAALIGN))); +
> +
> +/* CDMAC buffer descriptor for LL TEMAC Rx and Tx buffer handling */
> +static struct cdmac_bd rx_descr __attribute((aligned(DMAALIGN)));
> +static struct cdmac_bd tx_descr __attribute((aligned(DMAALIGN)));
> +

Can this global stuff be wrapped into the functions somehow? So it's not global.

> +
> +static inline void xps_ll_temac_check_status(struct temac_reg *regs, u32
> mask) +{
> +	unsigned timeout = 2000;

Magic timeout ?

> +	while (timeout && (!(in_be32(&regs->rdy) & mask)))
> +		timeout--;
> +	if (!timeout)
> +		printf("%s: Timeout\n", __func__);
> +}
> +
> +/*
> + * Undirect hostif write to ll_temac.
> + *
> + *
> http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.
> pdf + * page 67, Using the MII Management to Access PHY Registers
> + */
> +static void xps_ll_temac_hostif_set(struct eth_device *dev, u8 phy_addr,
> +					u8 reg_addr, u16 phy_data)
> +{
> +	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
> +
> +	out_be32(&regs->lsw, (phy_data & LSW_REGDAT_MASK));
> +	out_be32(&regs->ctl, CTL_WEN | TEMAC_MIIMWD);
> +	out_be32(&regs->lsw,
> +		((phy_addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) |
> +		(reg_addr & LSW_REGAD_MASK));
> +	out_be32(&regs->ctl, CTL_WEN | TEMAC_MIIMAI);
> +	xps_ll_temac_check_status(regs, RSE_MIIM_WR);
> +}
> +
> +/*
> + * Undirect hostif read to ll_temac.
> + *
> + *
> http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.
> pdf + * page 67, Using the MII Management to Access PHY Registers
> + */
> +static u16 xps_ll_temac_hostif_get(struct eth_device *dev, u8 phy_addr,
> +					u8 reg_addr)
> +{
> +	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
> +
> +	out_be32(&regs->lsw,
> +		((phy_addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) |
> +		(reg_addr & LSW_REGAD_MASK));
> +	out_be32(&regs->ctl, TEMAC_MIIMAI);
> +	xps_ll_temac_check_status(regs, RSE_MIIM_RR);
> +	return in_be32(&regs->lsw) & LSW_REGDAT_MASK;
> +}
> +
> +/*
> + * Undirect 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 + */
> +static void xps_ll_temac_indirect_set(struct eth_device *dev, u16 regn,
> +					u32 reg_data)
> +{
> +	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
> +
> +	out_be32(&regs->lsw, (reg_data & MLSW_MASK));
> +	out_be32(&regs->ctl, CTL_WEN | (regn & CTL_ADDR_MASK));
> +	xps_ll_temac_check_status(regs, RSE_CFG_WR);
> +}
> +
> +/*
> + * Undirect 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 + */
> +static u32 xps_ll_temac_indirect_get(struct eth_device *dev, u16 regn)
> +{
> +	struct temac_reg *regs = (struct temac_reg *)dev->iobase;
> +
> +	out_be32(&regs->ctl, (regn & CTL_ADDR_MASK));
> +	xps_ll_temac_check_status(regs, RSE_CFG_RR);
> +	return in_be32(&regs->lsw) & MLSW_MASK;
> +}
> +
> +#ifdef DEBUG
> +static inline void read_phy_reg(struct eth_device *dev, u8 phy_addr)
> +{
> +	int j, result;
> +	debug("phy%d ", phy_addr);
> +	for (j = 0; j < 32; j++) {
> +		result = xps_ll_temac_hostif_get(dev, phy_addr, j);
> +		debug("%d: 0x%x ", j, result);
> +	}
> +	debug("\n");
> +}
> +#endif
> +
> +/* setting ll_temac and phy to proper setting */
> +static int xps_ll_temac_phy_ctrl(struct eth_device *dev)
> +{
> +	int i;
> +	unsigned int temp, speed;
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct phy_device *phydev;
> +
> +	u32 supported = SUPPORTED_10baseT_Half |
> +			SUPPORTED_10baseT_Full |
> +			SUPPORTED_100baseT_Half |
> +			SUPPORTED_100baseT_Full |
> +			SUPPORTED_1000baseT_Half |
> +			SUPPORTED_1000baseT_Full;
> +
> +	if (ll_temac->phyaddr == -1) {
> +		for (i = 31; i >= 0; i--) {
> +			temp = xps_ll_temac_hostif_get(dev, i, 1);
> +			if ((temp & 0x0ffff) != 0x0ffff) {
> +				debug("phy %x result %x\n", i, temp);
> +				ll_temac->phyaddr = i;
> +				break;
> +			}
> +		}
> +	}
> +
> +	/* interface - look at tsec */
> +	phydev = phy_connect(ll_temac->bus, ll_temac->phyaddr, dev, 0);
> +
> +	phydev->supported &= supported;
> +	phydev->advertising = phydev->supported;
> +	ll_temac->phydev = phydev;
> +	phy_config(phydev);
> +	phy_startup(phydev);
> +
> +	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;
> +	}
> +	temp = xps_ll_temac_indirect_get(dev, TEMAC_EMMC);
> +	temp &= ~EMMC_LSPD_MASK;
> +	temp |= speed;
> +	xps_ll_temac_indirect_set(dev, TEMAC_EMMC, temp);
> +
> +	return 1;
> +}
> +
> +/* setup mac addr */
> +static int ll_temac_addr_setup(struct eth_device *dev)
> +{
> +	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;
> +	xps_ll_temac_indirect_set(dev, TEMAC_UAW0, val);
> +
> +	val = ((dev->enetaddr[5] << 8) | dev->enetaddr[4]);
> +	val &= UAW1_UADDR_MASK;
> +	xps_ll_temac_indirect_set(dev, TEMAC_UAW1, val);
> +
> +	return 0;
> +}
> +
> +static int xps_ll_temac_init(struct eth_device *dev, bd_t *bis)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +
> +	if (ll_temac->ctrlreset)
> +		if (ll_temac->ctrlreset(dev))
> +			return -1;
> +
> +	if (ll_temac->ctrlinit)
> +		ll_temac->ctrlinit(dev);
> +
> +	xps_ll_temac_indirect_set(dev, TEMAC_MC,
> +			MC_MDIOEN | (MDIO_CLOCK_DIV & MC_CLKDIV_MASK));
> +
> +	/* Promiscuous mode disable */
> +	xps_ll_temac_indirect_set(dev, TEMAC_AFM, 0);
> +
> +	/* Enable Receiver - RX bit */
> +	xps_ll_temac_indirect_set(dev, TEMAC_RCW1, RCW1_RX);
> +
> +	/* Enable Transmitter - TX bit */
> +	xps_ll_temac_indirect_set(dev, TEMAC_TC, TC_TX);
> +
> +	return 0;
> +}
> +
> +/* halt device */
> +static void ll_temac_halt(struct eth_device *dev)
> +{
> +#ifdef ETH_HALTING
> +	struct ll_temac *ll_temac = dev->priv;
> +
> +	/* Disable Receiver */
> +	xps_ll_temac_indirect_set(dev, TEMAC_RCW0, 0);
> +
> +	/* Disable Transmitter */
> +	xps_ll_temac_indirect_set(dev, TEMAC_TC, 0);
> +
> +	if (ll_temac->ctrlhalt)
> +		ll_temac->ctrlhalt(dev);
> +#endif
> +}
> +
> +static int ll_temac_init(struct eth_device *dev, bd_t *bis)
> +{
> +#if DEBUG
> +	int i;
> +#endif
> +	xps_ll_temac_init(dev, bis);
> +
> +	printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
> +		dev->name, 0, dev->iobase);
> +
> +#if DEBUG
> +	for (i = 0; i < 32; i++)
> +		read_phy_reg(dev, i);
> +#endif
> +
> +	if (!xps_ll_temac_phy_ctrl(dev)) {
> +		ll_temac_halt(dev);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ll_temac_miiphy_read(const char *devname, unsigned char addr,
> +				unsigned char reg, unsigned short *value)
> +{
> +	struct eth_device *dev = eth_get_dev();
> +
> +	*value = xps_ll_temac_hostif_get(dev, addr, reg);
> +
> +	debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *value);
> +	return 0;
> +}
> +
> +static int ll_temac_miiphy_write(const char *devname, unsigned char addr,
> +				unsigned char reg, unsigned short value)
> +{
> +	struct eth_device *dev = eth_get_dev();
> +	debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, value);
> +
> +	xps_ll_temac_hostif_set(dev, addr, reg, value);
> +
> +	return 0;
> +}
> +
> +static int ll_temac_bus_reset(struct mii_dev *bus)
> +{
> +	debug("Just bus reset\n");
> +	return 0;
> +}
> +
> +/*
> + * bis:		board information
> + * base_addr:	LL TEMAC register bank
> + * ctrl_addr:	LL TEMAC sub-controller register bank (FIFO or SDMA)
> + * mode:	driver mode bit flags (see xilinx_ll_temac.h)
> + */
> +int xilinx_ll_temac_initialize(bd_t *bis, unsigned long base_addr,
> +				int mode, unsigned long ctrl_addr)
> +{
> +	struct eth_device *dev;
> +	struct ll_temac *ll_temac;
> +
> +	dev = calloc(1, sizeof(*dev));
> +	if (dev == NULL)
> +		return -1;
> +
> +	dev->priv = calloc(1, sizeof(struct ll_temac));
> +	if (dev->priv == NULL) {
> +		free(dev);
> +		return -1;
> +	}
> +
> +	ll_temac = dev->priv;
> +
> +	sprintf(dev->name, "Xlltem.%lx", base_addr);
> +
> +	dev->iobase = base_addr;
> +	ll_temac->ctrladdr = ctrl_addr;
> +	ll_temac->rx_bp = rx_buffer;
> +	ll_temac->tx_bp = tx_buffer;
> +	ll_temac->rx_dp = &rx_descr;
> +	ll_temac->tx_dp = &tx_descr;
> +
> +#ifdef CONFIG_PHY_ADDR
> +	ll_temac->phyaddr = CONFIG_PHY_ADDR;
> +#else
> +	ll_temac->phyaddr = -1;
> +#endif

Maybe move this at the begining

#ifndef	CONFIG_PHY_ADDR
#define CONFIG_PHY_ADDR -1
#endif

> +
> +	dev->init = ll_temac_init;
> +	dev->halt = ll_temac_halt;
> +	dev->write_hwaddr = ll_temac_addr_setup;
> +
> +	if (mode & M_SDMA) {
> +#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
> +		if (mode & M_DCR) {
> +			ll_temac->ctrlinit = ll_temac_init_dmac;
> +			ll_temac->ctrlhalt = ll_temac_halt_dmac;
> +			ll_temac->ctrlreset = ll_temac_reset_dmac;
> +			dev->recv = ll_temac_recv_dmac;
> +			dev->send = ll_temac_send_dmac;
> +		} else
> +#endif
> +		{
> +			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->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;
> +	}
> +
> +	eth_register(dev);
> +
> +	miiphy_register(dev->name, ll_temac_miiphy_read, ll_temac_miiphy_write);
> +	ll_temac->bus = miiphy_get_dev_by_name(dev->name);
> +	ll_temac->bus->reset = ll_temac_bus_reset;
> +	return 1;
> +}
> diff --git a/drivers/net/xilinx_ll_temac.h b/drivers/net/xilinx_ll_temac.h
> new file mode 100644
> index 0000000..03dbb29
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac.h
> @@ -0,0 +1,305 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * private interface
> + *
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * Copyright (C) 2008 - 2011 PetaLogix
> + *
> + * Copyright (C) 2011 Stepahn Linz <linz at li-pro.net>
> + *
> + * 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.
> + */
> +#ifndef _XILINX_LL_TEMAC_
> +#define _XILINX_LL_TEMAC_
> +
> +#include <net.h>
> +#include <phy.h>
> +#include <miiphy.h>
> +#include <asm/byteorder.h>
> +
> +#include "xilinx_ll_temac_fifo.h"
> +#include "xilinx_ll_temac_sdma.h"
> +
> +#if !defined(__BIG_ENDIAN)
> +# error LL_TEMAC requires big endianess
> +#endif
> +
> +struct ll_temac {
> +	int	ctrladdr;
> +	void	(*ctrlinit) (struct eth_device*);
> +	int	(*ctrlhalt) (struct eth_device*);
> +	int	(*ctrlreset) (struct eth_device*);
> +
> +	unsigned char		*rx_bp;
> +	unsigned char		*tx_bp;
> +
> +	struct cdmac_bd		*rx_dp;
> +	struct cdmac_bd		*tx_dp;
> +
> +	int			phyaddr;
> +	struct phy_device	*phydev;
> +	struct mii_dev		*bus;
> +};
> +
> +/*
> + * Driver mode bit flags
> + *
> + * FIXME: this should going up to include -- but where?
> + */
> +#define M_FIFO		(0)		/* use FIFO Ctrl */
> +#define M_SDMA		(1 << 0)	/* use SDMA Ctrl */
> +#define M_DCR		(1 << 1)	/* use DCR Bus */
> +
> +

One newline
> +/*
> + * TEMAC Memory and Register Definition
> + *
> + *
> [1]:	http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_t
> emac.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
> + *
> + *
> [1]:	http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_t
> emac.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)
> +
> +
> +#endif /* _XILINX_LL_TEMAC_ */
> diff --git a/drivers/net/xilinx_ll_temac_fifo.c
> b/drivers/net/xilinx_ll_temac_fifo.c new file mode 100644
> index 0000000..02800d5
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac_fifo.c
> @@ -0,0 +1,93 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * FIFO interface
> + *
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * Copyright (C) 2008 - 2011 PetaLogix
> + *
> + * Copyright (C) 2011 Stepahn Linz <linz at li-pro.net>
> + *
> + * 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.
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <net.h>
> +
> +#include <asm/types.h>
> +#include <asm/io.h>
> +
> +#include "xilinx_ll_temac.h"
> +
> +#ifdef DEBUG
> +static void debugll(struct eth_device *dev, int count)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
> +	printf("FIFO: %d isr 0x%08x, ier 0x%08x, rdfr 0x%08x, "
> +		"rdfo 0x%08x rlr 0x%08x\n", count,
> +		in_be32(&fifo_ctrl->isr), in_be32(&fifo_ctrl->ier),
> +		in_be32(&fifo_ctrl->rdfr), in_be32(&fifo_ctrl->rdfo),
> +		in_be32(&fifo_ctrl->rlf));
> +}
> +#endif
> +
> +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)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
> +	u32 i, len = 0;
> +	u32 *buf = (u32 *)&(ll_temac->rx_bp);
> +
> +	if (in_be32(&fifo_ctrl->isr) & LL_FIFO_ISR_RC) {
> +		out_be32(&fifo_ctrl->isr, ~0UL); /* reset isr */
> +
> +		/* while (fifo_ctrl->isr); */
> +		len = in_be32(&fifo_ctrl->rlf) & LL_FIFO_RLF_MASK;
> +
> +		for (i = 0; i < len; i += 4)
> +			*buf++ = in_be32(&fifo_ctrl->rdfd);
> +
> +#ifdef DEBUG
> +		debugll(dev, 1);
> +#endif
> +		NetReceive((uchar *)&(ll_temac->rx_bp), len);

Do you need those parenthesis ?

> +	}
> +	return len;
> +}
> +
> +int ll_temac_send_fifo(struct eth_device *dev,
> +			volatile void *buffer, int length)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
> +	u32 *buf = (u32 *)buffer;
> +	u32 i;
> +
> +	for (i = 0; i < length; i += 4)
> +		out_be32(&fifo_ctrl->tdfd, *buf++);
> +
> +	out_be32(&fifo_ctrl->tlf, length);
> +	return 0;
> +}
> diff --git a/drivers/net/xilinx_ll_temac_fifo.h
> b/drivers/net/xilinx_ll_temac_fifo.h new file mode 100644
> index 0000000..c8fcd96
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac_fifo.h
> @@ -0,0 +1,112 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * FIFO interface
> + *
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * Copyright (C) 2008 - 2011 PetaLogix
> + *
> + * Copyright (C) 2011 Stepahn Linz <linz at li-pro.net>
> + *
> + * 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.
> + */
> +#ifndef _XILINX_LL_TEMAC_FIFO_
> +#define _XILINX_LL_TEMAC_FIFO_
> +
> +#include <net.h>
> +#include <asm/types.h>
> +#include <asm/byteorder.h>
> +
> +#if !defined(__BIG_ENDIAN)
> +# error LL_TEMAC requires big endianess
> +#endif
> +
> +/*
> + * FIFO Register Definition
> + *
> + * Used for memory mapped access from and to (Rd/Td) the LocalLink (LL)
> TEMAC via + * the 2 kb full duplex FIFO Controller -- one for each.
> + *
> + * [1]:
> http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_fifo.p
> df + *      page 10, Registers Definition
> + */
> +struct fifo_ctrl {
> +	u32 isr;	/* Interrupt Status Register (RW) */
> +	u32 ier;	/* Interrupt Enable Register (RW) */
> +	u32 tdfr;	/* Transmit Data FIFO Reset (WO) */
> +	u32 tdfv;	/* Transmit Data FIFO Vacancy (RO) */
> +	u32 tdfd;	/* Transmit Data FIFO 32bit wide Data write port (WO) */
> +	u32 tlf;	/* Transmit Length FIFO (WO) */
> +	u32 rdfr;	/* Receive Data FIFO Reset (WO) */
> +	u32 rdfo;	/* Receive Data FIFO Occupancy (RO) */
> +	u32 rdfd;	/* Receive Data FIFO 32bit wide Data read port (RO) */
> +	u32 rlf;	/* Receive Length FIFO (RO) */
> +	u32 llr;	/* LocalLink Reset (WO) */
> +};
> +
> +/* Interrupt Status Register (ISR), [1] p11 */
> +#define LL_FIFO_ISR_RPURE	(1 << 31) /* Receive Packet Underrun Read Error
> */ +#define LL_FIFO_ISR_RPORE	(1 << 30) /* Receive Packet Overrun Read
> Error */ +#define LL_FIFO_ISR_RPUE	(1 << 29) /* Receive Packet Underrun
> Error */ +#define LL_FIFO_ISR_TPOE	(1 << 28) /* Transmit Packet Overrun
> Error */ +#define LL_FIFO_ISR_TC		(1 << 27) /* Transmit Complete 
*/
> +#define LL_FIFO_ISR_RC		(1 << 26) /* Receive Complete */
> +#define LL_FIFO_ISR_TSE		(1 << 25) /* Transmit Size Error */
> +#define LL_FIFO_ISR_TRC		(1 << 24) /* Transmit Reset Complete */
> +#define LL_FIFO_ISR_RRC		(1 << 23) /* Receive Reset Complete */
> +
> +/* Interrupt Enable Register (IER), [1] p12/p13 */
> +#define LL_FIFO_IER_RPURE	(1 << 31) /* Receive Packet Underrun Read Error
> */ +#define LL_FIFO_IER_RPORE	(1 << 30) /* Receive Packet Overrun Read
> Error */ +#define LL_FIFO_IER_RPUE	(1 << 29) /* Receive Packet Underrun
> Error */ +#define LL_FIFO_IER_TPOE	(1 << 28) /* Transmit Packet Overrun
> Error */ +#define LL_FIFO_IER_TC		(1 << 27) /* Transmit Complete 
*/
> +#define LL_FIFO_IER_RC		(1 << 26) /* Receive Complete */
> +#define LL_FIFO_IER_TSE		(1 << 25) /* Transmit Size Error */
> +#define LL_FIFO_IER_TRC		(1 << 24) /* Transmit Reset Complete */
> +#define LL_FIFO_IER_RRC		(1 << 23) /* Receive Reset Complete */
> +
> +/* Transmit Data FIFO Reset (TDFR), [1] p13/p14 */
> +#define LL_FIFO_TDFR_KEY	(0x000000A5UL)
> +
> +/* Transmit Data FIFO Vacancy (TDFV), [1] p14 */
> +#define LL_FIFO_TDFV_POS	(0)
> +#define LL_FIFO_TDFV_MASK	(0x000001FFUL << LL_FIFO_TDFV_POS)
> +
> +/* Transmit Length FIFO (TLF), [1] p16/p17 */
> +#define LL_FIFO_TLF_POS		(0)
> +#define LL_FIFO_TLF_MASK	(0x000007FFUL << LL_FIFO_TLF_POS)
> +
> +/* Receive Data FIFO Reset (RDFR), [1] p15 */
> +#define LL_FIFO_RDFR_KEY	(0x000000A5UL)
> +
> +/* Receive Data FIFO Occupancy (RDFO), [1] p16 */
> +#define LL_FIFO_RDFO_POS	(0)

Drop parenthesis around (0), please fix globally

> +#define LL_FIFO_RDFO_MASK	(0x000001FFUL << LL_FIFO_RDFO_POS)
> +
> +/* Receive Length FIFO (TLF), [1] p17/p18 */
> +#define LL_FIFO_RLF_POS		(0)
> +#define LL_FIFO_RLF_MASK	(0x000007FFUL << LL_FIFO_RLF_POS)
> +
> +/* LocalLink Reset (LLR), [1] p18 */
> +#define LL_FIFO_LLR_KEY		(0x000000A5UL)

Here too

> +
> +
> +/* reset FIFO and IRQ, disable interrupts */
> +int ll_temac_reset_fifo(struct eth_device *dev);
> +
> +/* receive buffered data from FIFO (polling ISR) */
> +int ll_temac_recv_fifo(struct eth_device *dev);
> +
> +/* send buffered data to FIFO */
> +int ll_temac_send_fifo(struct eth_device *dev,
> +			volatile void *buffer, int length);
> +
> +#endif /* _XILINX_LL_TEMAC_FIFO_ */
> diff --git a/drivers/net/xilinx_ll_temac_sdma.c
> b/drivers/net/xilinx_ll_temac_sdma.c new file mode 100644
> index 0000000..6a7f2ca
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac_sdma.c
> @@ -0,0 +1,413 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * SDMA interface
> + *
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * Copyright (C) 2008 - 2011 PetaLogix
> + *
> + * Copyright (C) 2011 Stepahn Linz <linz at li-pro.net>
> + *
> + * 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.
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <net.h>
> +
> +#include <asm/types.h>
> +#include <asm/io.h>
> +
> +#include "xilinx_ll_temac.h"
> +
> +
> +#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 going up to arch/powerpc -- but where?
> + */
> +#include <asm/processor.h>
> +#define XILINX_INDIRECT_DCR_ADDRESS_REG	0
> +#define XILINX_INDIRECT_DCR_ACCESS_REG	1
> +unsigned mifdcr_xilinx(const unsigned dcrn)
> +{
> +	mtdcr(XILINX_INDIRECT_DCR_ADDRESS_REG, dcrn);
> +	return mfdcr(XILINX_INDIRECT_DCR_ACCESS_REG);
> +}
> +unsigned mitdcr_xilinx(const unsigned dcrn, int val)
> +{
> +	mtdcr(XILINX_INDIRECT_DCR_ADDRESS_REG, dcrn);
> +	mtdcr(XILINX_INDIRECT_DCR_ACCESS_REG, val);
> +}
> +#endif
> +
> +
> +/* Check for TX and RX channel errrors. */
> +static inline int ll_temac_dma_error(struct eth_device *dev)
> +{
> +	int err;
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
> +
> +	err = in_be32(&sdma_ctrl->tx_chnl_sts) & CHNL_STS_ERROR;
> +	err |= in_be32(&sdma_ctrl->rx_chnl_sts) & CHNL_STS_ERROR;
> +	return err;
> +}
> +
> +
> +void ll_temac_init_sdma(struct eth_device *dev)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
> +	struct cdmac_bd *rx_dp = ll_temac->rx_dp;
> +	struct cdmac_bd *tx_dp = ll_temac->tx_dp;
> +
> +	memset(tx_dp, 0, sizeof(*tx_dp));
> +	memset(rx_dp, 0, sizeof(*rx_dp));
> +
> +	/* from LL TEMAC (Rx) */
> +	rx_dp->phys_buf_p = ll_temac->rx_bp;
> +
> +	rx_dp->next_p = rx_dp;
> +	rx_dp->buf_len = PKTSIZE_ALIGN;
> +	flush_cache((u32)rx_dp, sizeof(*tx_dp));
> +	flush_cache((u32)rx_dp->phys_buf_p, PKTSIZE_ALIGN);
> +
> +	out_be32(&sdma_ctrl->rx_curdesc_ptr, (u32)rx_dp);
> +	out_be32(&sdma_ctrl->rx_taildesc_ptr, (u32)rx_dp);
> +	out_be32(&sdma_ctrl->rx_nxtdesc_ptr, (u32)rx_dp); /* setup first fd */
> +
> +	/* to LL TEMAC (Tx) */
> +	tx_dp->phys_buf_p = ll_temac->tx_bp;
> +	tx_dp->next_p = tx_dp;
> +
> +	flush_cache((u32)tx_dp, sizeof(*tx_dp));
> +	out_be32(&sdma_ctrl->tx_curdesc_ptr, (u32)tx_dp);
> +}
> +
> +int ll_temac_halt_sdma(struct eth_device *dev)
> +{
> +	u32 timeout = 2000;
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
> +
> +	/*
> +	 * 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.
> +	 */
> +	out_be32(&sdma_ctrl->dma_control_reg, DMA_CONTROL_RESET);
> +	while (timeout && (in_be32(&sdma_ctrl->dma_control_reg)
> +					& DMA_CONTROL_RESET))
> +		timeout--;
> +
> +	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;
> +	struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
> +
> +	/* Soft reset the DMA.  */
> +	if (ll_temac_halt_sdma(dev))
> +		return 1;
> +
> +	/* Now clear the interrupts.  */
> +	r = in_be32(&sdma_ctrl->tx_chnl_ctrl);
> +	r &= ~CHNL_CTRL_IRQ_MASK;
> +	out_be32(&sdma_ctrl->tx_chnl_ctrl, r);
> +
> +	r = in_be32(&sdma_ctrl->rx_chnl_ctrl);
> +	r &= ~CHNL_CTRL_IRQ_MASK;
> +	out_be32(&sdma_ctrl->rx_chnl_ctrl, r);
> +
> +	/* Now ACK pending IRQs.  */
> +	out_be32(&sdma_ctrl->tx_irq_reg, IRQ_REG_IRQ_MASK);
> +	out_be32(&sdma_ctrl->rx_irq_reg, IRQ_REG_IRQ_MASK);
> +
> +	/* Set tail-ptr mode, disable errors for both channels.  */
> +	out_be32(&sdma_ctrl->dma_control_reg,
> +			/* Enable use of tail pointer register */
> +			DMA_CONTROL_TPE |
> +			/* Disable error when 2 or 4 bit coalesce counter 
overflows */
> +			DMA_CONTROL_RXOCEID |
> +			/* Disable error when 2 or 4 bit coalesce counter 
overflows */
> +			DMA_CONTROL_TXOCEID);
> +
> +	return 0;
> +}
> +
> +int ll_temac_recv_sdma(struct eth_device *dev)
> +{
> +	int length;
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
> +	struct cdmac_bd *rx_dp = ll_temac->rx_dp;
> +
> +	if (ll_temac_dma_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;
> +
> +	/*
> +	 * Read out the packet info and start the DMA
> +	 * onto the second buffer to enable the ethernet rx
> +	 * path to run in parallel with sw processing
> +	 * packets.
> +	 */
> +	length = rx_dp->sca.app[4] & CDMAC_BD_APP4_RXBYTECNT_MASK;
> +	if (length > 0)
> +		NetReceive(rx_dp->phys_buf_p, length);
> +
> +	/* flip the buffer and re-enable the DMA.  */
> +	flush_cache((u32)rx_dp->phys_buf_p, length);
> +
> +	rx_dp->buf_len = PKTSIZE_ALIGN;
> +	rx_dp->sca.stctrl = 0;
> +	rx_dp->sca.app[4] = 0;
> +
> +	flush_cache((u32)rx_dp, sizeof(*rx_dp));
> +	out_be32(&sdma_ctrl->rx_taildesc_ptr, (u32)rx_dp);
> +
> +	return length;
> +}
> +
> +int ll_temac_send_sdma(struct eth_device *dev,
> +				volatile void *buffer, int length)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +	struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
> +	struct cdmac_bd *tx_dp = ll_temac->tx_dp;
> +
> +	if (ll_temac_dma_error(dev)) {
> +		if (ll_temac_reset_sdma(dev))
> +			return -1;
> +		ll_temac_init_sdma(dev);
> +	}
> +
> +	memcpy(ll_temac->tx_bp, (void *)buffer, length);
> +	flush_cache((u32)ll_temac->tx_bp, length);
> +
> +	tx_dp->sca.stctrl = CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP |
> +			CDMAC_BD_STCTRL_STOP_ON_END;
> +	tx_dp->buf_len = length;
> +	flush_cache((u32)tx_dp, sizeof(*tx_dp));
> +
> +	out_be32(&sdma_ctrl->tx_curdesc_ptr, (u32)tx_dp);
> +	out_be32(&sdma_ctrl->tx_taildesc_ptr, (u32)tx_dp); /* DMA start */
> +
> +	do {
> +		flush_cache((u32)tx_dp, sizeof(*tx_dp));
> +	} while (!(tx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED));
> +
> +	return 0;
> +}
> +
> +
> +#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
> +
> +/* Check for TX and RX channel errrors. */
> +static inline int ll_temac_dmac_error(struct eth_device *dev)
> +{
> +	int err;
> +	struct ll_temac *ll_temac = dev->priv;
> +	unsigned dmac_ctrl = ll_temac->ctrladdr;
> +
> +	err = mifdcr_xilinx(dmac_ctrl + TX_CHNL_STS) & CHNL_STS_ERROR;
> +	err |= mifdcr_xilinx(dmac_ctrl + RX_CHNL_STS) & CHNL_STS_ERROR;
> +	return err;
> +}
> +
> +
> +void ll_temac_init_dmac(struct eth_device *dev)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +	unsigned dmac_ctrl = ll_temac->ctrladdr;
> +	struct cdmac_bd *rx_dp = ll_temac->rx_dp;
> +	struct cdmac_bd *tx_dp = ll_temac->tx_dp;
> +
> +	memset(tx_dp, 0, sizeof(*tx_dp));
> +	memset(rx_dp, 0, sizeof(*rx_dp));
> +
> +	/* from LL TEMAC (Rx) */
> +	rx_dp->phys_buf_p = ll_temac->rx_bp;
> +
> +	rx_dp->next_p = rx_dp;
> +	rx_dp->buf_len = PKTSIZE_ALIGN;
> +	flush_cache((u32)rx_dp, sizeof(*tx_dp));
> +	flush_cache((u32)rx_dp->phys_buf_p, PKTSIZE_ALIGN);
> +
> +	mitdcr_xilinx(dmac_ctrl + RX_CURDESC_PTR, (u32)rx_dp);
> +	mitdcr_xilinx(dmac_ctrl + RX_TAILDESC_PTR, (u32)rx_dp);
> +	mitdcr_xilinx(dmac_ctrl + RX_NXTDESC_PTR, (u32)rx_dp); /* setup first fd
> */ +
> +	/* to LL TEMAC (Tx) */
> +	tx_dp->phys_buf_p = ll_temac->tx_bp;
> +	tx_dp->next_p = tx_dp;
> +
> +	flush_cache((u32)tx_dp, sizeof(*tx_dp));
> +	mitdcr_xilinx(dmac_ctrl + TX_CURDESC_PTR, (u32)rx_dp);
> +}
> +
> +int ll_temac_halt_dmac(struct eth_device *dev)
> +{
> +	u32 timeout = 2000;
> +	struct ll_temac *ll_temac = dev->priv;
> +	unsigned dmac_ctrl = ll_temac->ctrladdr;
> +
> +	/*
> +	 * 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.
> +	 */
> +	mitdcr_xilinx(dmac_ctrl + DMA_CONTROL_REG, DMA_CONTROL_RESET);
> +	while (timeout && (mifdcr_xilinx(dmac_ctrl + DMA_CONTROL_REG)
> +					& DMA_CONTROL_RESET))
> +		timeout--;
> +
> +	if (!timeout) {
> +		printf("%s: Timeout\n", __func__);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +int ll_temac_reset_dmac(struct eth_device *dev)
> +{
> +	u32 r;
> +	struct ll_temac *ll_temac = dev->priv;
> +	unsigned dmac_ctrl = ll_temac->ctrladdr;
> +
> +	/* Soft reset the DMA.  */
> +	if (ll_temac_halt_dmac(dev))
> +		return 1;
> +
> +	/* Now clear the interrupts.  */
> +	r = mifdcr_xilinx(dmac_ctrl + TX_CHNL_CTRL);
> +	r &= ~CHNL_CTRL_IRQ_MASK;
> +	mitdcr_xilinx(dmac_ctrl + TX_CHNL_CTRL, r);
> +
> +	r = mifdcr_xilinx(dmac_ctrl + RX_CHNL_CTRL);
> +	r &= ~CHNL_CTRL_IRQ_MASK;
> +	mitdcr_xilinx(dmac_ctrl + RX_CHNL_CTRL, r);
> +
> +	/* Now ACK pending IRQs.  */
> +	mitdcr_xilinx(dmac_ctrl + TX_IRQ_REG, IRQ_REG_IRQ_MASK);
> +	mitdcr_xilinx(dmac_ctrl + RX_IRQ_REG, IRQ_REG_IRQ_MASK);
> +
> +	/* Set tail-ptr mode, disable errors for both channels.  */
> +	mitdcr_xilinx(dmac_ctrl + DMA_CONTROL_REG,
> +			/* Enable use of tail pointer register */
> +			DMA_CONTROL_TPE |
> +			/* Disable error when 2 or 4 bit coalesce counter 
overflows */
> +			DMA_CONTROL_RXOCEID |
> +			/* Disable error when 2 or 4 bit coalesce counter 
overflows */
> +			DMA_CONTROL_TXOCEID);
> +
> +	return 0;
> +}
> +
> +int ll_temac_recv_dmac(struct eth_device *dev)
> +{
> +	int length;
> +	struct ll_temac *ll_temac = dev->priv;
> +	unsigned dmac_ctrl = ll_temac->ctrladdr;
> +	struct cdmac_bd *rx_dp = ll_temac->rx_dp;
> +
> +	if (ll_temac_dmac_error(dev)) {
> +		if (ll_temac_reset_dmac(dev))
> +			return -1;
> +		ll_temac_init_dmac(dev);
> +	}
> +
> +	flush_cache((u32)rx_dp, sizeof(*rx_dp));
> +
> +	if (!(rx_dp.sca.stctrl & CDMAC_BD_STCTRL_COMPLETED))
> +		return 0;
> +
> +	/*
> +	 * Read out the packet info and start the DMA
> +	 * onto the second buffer to enable the ethernet rx
> +	 * path to run in parallel with sw processing
> +	 * packets.
> +	 */
> +	length = rx_dp->sca.app[4] & CDMAC_BD_APP4_RXBYTECNT_MASK;
> +	if (length > 0)
> +		NetReceive(rx_dp->phys_buf_p, length);
> +
> +	/* flip the buffer and re-enable the DMA.  */
> +	flush_cache((u32)rx_dp->phys_buf_p, length);
> +
> +	rx_dp->buf_len = PKTSIZE_ALIGN;
> +	rx_dp->sca.stctrl = 0;
> +	rx_dp->sca.app[4] = 0;
> +
> +	flush_cache((u32)rx_dp, sizeof(*rx_dp));
> +	mitdcr_xilinx(dmac_ctrl + RX_TAILDESC_PTR, (u32)rx_dp);
> +
> +	return length;
> +}
> +
> +int ll_temac_send_dmac(struct eth_device *dev,
> +				volatile void *buffer, int length)
> +{
> +	struct ll_temac *ll_temac = dev->priv;
> +	unsigned dmac_ctrl = ll_temac->ctrladdr;
> +	struct cdmac_bd *tx_dp = ll_temac->tx_dp;
> +
> +	if (ll_temac_dmac_error(dev)) {
> +		if (ll_temac_reset_dmac(dev))
> +			return -1;
> +		ll_temac_init_dmac(dev);
> +	}
> +
> +	memcpy(ll_temac->tx_bp, (void *)buffer, length);
> +	flush_cache((u32)ll_temac->tx_bp, length);
> +
> +	tx_dp->sca.stctrl = CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP |
> +			CDMAC_BD_STCTRL_STOP_ON_END;
> +	tx_dp->buf_len = length;
> +	flush_cache((u32)tx_dp, sizeof(*tx_dp));
> +
> +	mitdcr_xilinx(dmac_ctrl + TX_CURDESC_PTR, (u32)tx_dp);
> +	mitdcr_xilinx(dmac_ctrl + TX_TAILDESC_PTR, (u32)tx_dp); /* DMA start */
> +
> +	do {
> +		flush_cache((u32)tx_dp, sizeof(*tx_dp));
> +	} while (!(tx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED));
> +
> +	return 0;
> +}

Maybe make functions used only in local scope static ?

> +
> +#endif /* CONFIG_XILINX_440 || CONFIG_XILINX_405 */
> diff --git a/drivers/net/xilinx_ll_temac_sdma.h
> b/drivers/net/xilinx_ll_temac_sdma.h new file mode 100644
> index 0000000..45e63f6
> --- /dev/null
> +++ b/drivers/net/xilinx_ll_temac_sdma.h
> @@ -0,0 +1,280 @@
> +/*
> + * Xilinx xps_ll_temac ethernet driver for u-boot
> + *
> + * SDMA interface
> + *
> + * Copyright (C) 2008 - 2011 Michal Simek <monstr at monstr.eu>
> + * Copyright (C) 2008 - 2011 PetaLogix
> + *
> + * Copyright (C) 2011 Stepahn Linz <linz at li-pro.net>
> + *
> + * 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.
> + */
> +#ifndef _XILINX_LL_TEMAC_SDMA_
> +#define _XILINX_LL_TEMAC_SDMA_
> +
> +#include <net.h>
> +#include <asm/types.h>
> +#include <asm/byteorder.h>
> +
> +#if !defined(__BIG_ENDIAN)
> +# error LL_TEMAC requires big endianess
> +#endif
> +
> +#if defined(CONFIG_SYS_CACHELINE_SIZE)
> +#define DMAALIGN CONFIG_SYS_CACHELINE_SIZE
> +#else
> +/* we expact to live in a 32 bit processor environment */
> +#define DMAALIGN 32
> +#endif
> +
> +
> +/*
> + * DMA Buffer Descriptor for CDMAC
> + *
> + * Used for data connection from and to (Rx/Tx) the LocalLink (LL) TEMAC
> via + * the Communications Direct Memory Access Controller (CDMAC) -- one
> for each. + *
> + * overview:
> + *     
> ftp://ftp.xilinx.com/pub/documentation/misc/mpmc_getting_started.pdf + *
> + * [1]:
> http://www.xilinx.com/support/documentation/ip_documentation/mpmc.pdf + * 
>     page 140, DMA Operation Descriptors
> + *
> + * [2]:	
http://www.xilinx.com/support/documentation/user_guides/ug200.pdf
> + *	page 229, DMA Controller -- Descriptor Format
> + *
> + *
> [3]:	http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_t
> emac.pdf + *	page 72, Transmit LocalLink Frame Format
> + *	page 73, Receive LocalLink Frame Format
> + */
> +struct cdmac_bd {
> +	struct cdmac_bd *next_p;	/* Next Descriptor Pointer */
> +	u8 *phys_buf_p;			/* Buffer Address */
> +	u32 buf_len;			/* Buffer Length */
> +	union {
> +		u8 stctrl;		/* Status/Control the DMA transfer */
> +		u32 app[5];		/* application specific data */
> +	} __attribute__ ((packed, aligned(1))) sca;
> +};
> +
> +/* CDMAC Descriptor Status and Control (stctrl), [1] p140, [2] p230 */
> +#define CDMAC_BD_STCTRL_ERROR		(1 << 7)
> +#define CDMAC_BD_STCTRL_IRQ_ON_END	(1 << 6)
> +#define CDMAC_BD_STCTRL_STOP_ON_END	(1 << 5)
> +#define CDMAC_BD_STCTRL_COMPLETED	(1 << 4)
> +#define CDMAC_BD_STCTRL_SOP		(1 << 3)
> +#define CDMAC_BD_STCTRL_EOP		(1 << 2)
> +#define CDMAC_BD_STCTRL_DMACHBUSY	(1 << 1)
> +
> +/* CDMAC Descriptor APP0: Transmit LocalLink Footer Word 3, [3] p72 */
> +#define CDMAC_BD_APP0_TXCSCNTRL		(1 << 0)
> +
> +/* CDMAC Descriptor APP1: Transmit LocalLink Footer Word 4, [3] p73 */
> +#define CDMAC_BD_APP1_TXCSBEGIN_POS	(16)
> +#define CDMAC_BD_APP1_TXCSBEGIN_MASK	(0xFFFF <<
> CDMAC_BD_APP1_TXCSBEGIN_POS) +#define CDMAC_BD_APP1_TXCSINSERT_POS	(0)
> +#define CDMAC_BD_APP1_TXCSINSERT_MASK	(0xFFFF <<
> CDMAC_BD_APP1_TXCSINSERT_POS) +
> +/* CDMAC Descriptor APP2: Transmit LocalLink Footer Word 5, [3] p73 */
> +#define CDMAC_BD_APP2_TXCSINIT_POS	(0)
> +#define CDMAC_BD_APP2_TXCSINIT_MASK	(0xFFFF << CDMAC_BD_APP2_TXCSINIT_POS)
> +
> +/* CDMAC Descriptor APP0: Receive LocalLink Footer Word 3, [3] p73 */
> +#define CDMAC_BD_APP0_MADDRU_POS	(0)
> +#define CDMAC_BD_APP0_MADDRU_MASK	(0xFFFF << CDMAC_BD_APP0_MADDRU_POS)
> +
> +/* CDMAC Descriptor APP1: Receive LocalLink Footer Word 4, [3] p74 */
> +#define CDMAC_BD_APP1_MADDRL_POS	(0)
> +#define CDMAC_BD_APP1_MADDRL_MASK	(~0UL << CDMAC_BD_APP1_MADDRL_POS)
> +
> +/* CDMAC Descriptor APP2: Receive LocalLink Footer Word 5, [3] p74 */
> +#define CDMAC_BD_APP2_BCAST_FRAME	(1 << 2)
> +#define CDMAC_BD_APP2_IPC_MCAST_FRAME	(1 << 1)
> +#define CDMAC_BD_APP2_MAC_MCAST_FRAME	(1 << 0)
> +
> +/* CDMAC Descriptor APP3: Receive LocalLink Footer Word 6, [3] p74 */
> +#define CDMAC_BD_APP3_TLTPID_POS	(16)
> +#define CDMAC_BD_APP3_TLTPID_MASK	(0xFFFF << CDMAC_BD_APP3_TLTPID_POS)
> +#define CDMAC_BD_APP3_RXCSRAW_POS	(0)
> +#define CDMAC_BD_APP3_RXCSRAW_MASK	(0xFFFF << CDMAC_BD_APP3_RXCSRAW_POS)
> +
> +/* CDMAC Descriptor APP4: Receive LocalLink Footer Word 7, [3] p74 */
> +#define CDMAC_BD_APP4_VLANTAG_POS	(16)
> +#define CDMAC_BD_APP4_VLANTAG_MASK	(0xFFFF << CDMAC_BD_APP4_VLANTAG_POS)
> +#define CDMAC_BD_APP4_RXBYTECNT_POS	(0)
> +#define CDMAC_BD_APP4_RXBYTECNT_MASK	(0x3FFF <<
> CDMAC_BD_APP4_RXBYTECNT_POS) +
> +
> +/*
> + * SDMA Register Definition
> + *
> + *
> [1]:	http://www.xilinx.com/support/documentation/ip_documentation/mpmc.pdf
> + *	page 54, SDMA Register Summary
> + *	page 160, SDMA Registers
> + *
> + * [2]:	
http://www.xilinx.com/support/documentation/user_guides/ug200.pdf
> + *	page 244, DMA Controller -- Programming Interface and Registers
> + */
> +struct sdma_ctrl {
> +	/* Transmit Registers */
> +	u32 tx_nxtdesc_ptr;	/* TX Next Description Pointer */
> +	u32 tx_curbuf_addr;	/* TX Current Buffer Address */
> +	u32 tx_curbuf_length;	/* TX Current Buffer Length */
> +	u32 tx_curdesc_ptr;	/* TX Current Descriptor Pointer */
> +	u32 tx_taildesc_ptr;	/* TX Tail Descriptor Pointer */
> +	u32 tx_chnl_ctrl;	/* TX Channel Control */
> +	u32 tx_irq_reg;		/* TX Interrupt Register */
> +	u32 tx_chnl_sts;	/* TX Status Register */
> +	/* Receive Registers */
> +	u32 rx_nxtdesc_ptr;	/* RX Next Descriptor Pointer */
> +	u32 rx_curbuf_addr;	/* RX Current Buffer Address */
> +	u32 rx_curbuf_length;	/* RX Current Buffer Length */
> +	u32 rx_curdesc_ptr;	/* RX Current Descriptor Pointer */
> +	u32 rx_taildesc_ptr;	/* RX Tail Descriptor Pointer */
> +	u32 rx_chnl_ctrl;	/* RX Channel Control */
> +	u32 rx_irq_reg;		/* RX Interrupt Register */
> +	u32 rx_chnl_sts;	/* RX Status Register */
> +	/* Control Registers */
> +	u32 dma_control_reg;	/* DMA Control Register */
> +};
> +
> +/* Rx/Tx Channel Control Register (*_chnl_ctrl), [1] p163, [2] p246/p252
> */ +#define CHNL_CTRL_ITO_POS	(24)
> +#define CHNL_CTRL_ITO_MASK	(0xFF << CHNL_CTRL_ITO_POS)
> +#define CHNL_CTRL_IC_POS	(16)
> +#define CHNL_CTRL_IC_MASK	(0xFF << CHNL_CTRL_IC_POS)
> +#define CHNL_CTRL_MSBADDR_POS	(12)
> +#define CHNL_CTRL_MSBADDR_MASK	(0xF << CHNL_CTRL_MSBADDR_POS)
> +#define CHNL_CTRL_AME		(1 << 11)
> +#define CHNL_CTRL_OBWC		(1 << 10)
> +#define CHNL_CTRL_IOE		(1 << 9)
> +#define CHNL_CTRL_LIC		(1 << 8)
> +#define CHNL_CTRL_IE		(1 << 7)
> +#define CHNL_CTRL_IEE		(1 << 2)
> +#define CHNL_CTRL_IDE		(1 << 1)
> +#define CHNL_CTRL_ICE		(1 << 0)
> +
> +/* All interrupt enable bits */
> +#define CHNL_CTRL_IRQ_MASK	(CHNL_CTRL_IE | \
> +				 CHNL_CTRL_IEE | \
> +				 CHNL_CTRL_IDE | \
> +				 CHNL_CTRL_ICE)
> +
> +/* Rx/Tx Interrupt Status Register (*_irq_reg), [1] p164, [2] p247/p253 */
> +#define IRQ_REG_DTV_POS		(24)
> +#define IRQ_REG_DTV_MASK	(0xFF << IRQ_REG_DTV_POS)
> +#define IRQ_REG_CCV_POS		(16)
> +#define IRQ_REG_CCV_MASK	(0xFF << IRQ_REG_CCV_POS)
> +#define IRQ_REG_WRCQ_EMPTY	(1 << 14)
> +#define IRQ_REG_CIC_POS		(10)
> +#define IRQ_REG_CIC_MASK	(0xF << IRQ_REG_CIC_POS)
> +#define IRQ_REG_DIC_POS		(8)
> +#define IRQ_REG_DIC_MASK	(3 << 8)
> +#define IRQ_REG_PLB_RD_NMI	(1 << 4)
> +#define IRQ_REG_PLB_WR_NMI	(1 << 3)
> +#define IRQ_REG_EI		(1 << 2)
> +#define IRQ_REG_DI		(1 << 1)
> +#define IRQ_REG_CI		(1 << 0)
> +
> +/* All interrupt bits */
> +#define IRQ_REG_IRQ_MASK	(IRQ_REG_PLB_RD_NMI | \
> +				 IRQ_REG_PLB_WR_NMI | \
> +				 IRQ_REG_EI | IRQ_REG_DI | IRQ_REG_CI)
> +
> +/* Rx/Tx Channel Status Register (*_chnl_sts), [1] p165, [2] p249/p255 */
> +#define CHNL_STS_ERROR_TAIL	(1 << 21)
> +#define CHNL_STS_ERROR_CMP	(1 << 20)
> +#define CHNL_STS_ERROR_ADDR	(1 << 19)
> +#define CHNL_STS_ERROR_NXTP	(1 << 18)
> +#define CHNL_STS_ERROR_CURP	(1 << 17)
> +#define CHNL_STS_ERROR_BSYWR	(1 << 16)
> +#define CHNL_STS_ERROR		(1 << 7)
> +#define CHNL_STS_IOE		(1 << 6)
> +#define CHNL_STS_SOE		(1 << 5)
> +#define CHNL_STS_CMPLT		(1 << 4)
> +#define CHNL_STS_SOP		(1 << 3)
> +#define CHNL_STS_EOP		(1 << 2)
> +#define CHNL_STS_EBUSY		(1 << 1)
> +
> +/* DMA Control Register (dma_control_reg), [1] p166, [2] p256 */
> +#define DMA_CONTROL_PLBED	(1 << 5)
> +#define DMA_CONTROL_RXOCEID	(1 << 4)
> +#define DMA_CONTROL_TXOCEID	(1 << 3)
> +#define DMA_CONTROL_TPE		(1 << 2)
> +#define DMA_CONTROL_RESET	(1 << 0)
> +
> +
> +/* initialize both Rx/Tx buffer descriptors */
> +void ll_temac_init_sdma(struct eth_device *dev);
> +
> +/* halt both Rx/Tx transfers */
> +int ll_temac_halt_sdma(struct eth_device *dev);
> +
> +/* reset SDMA and IRQ, disable interrupts and errors */
> +int ll_temac_reset_sdma(struct eth_device *dev);
> +
> +/* receive buffered data from SDMA (polling ISR) */
> +int ll_temac_recv_sdma(struct eth_device *dev);
> +
> +/* send buffered data to SDMA */
> +int ll_temac_send_sdma(struct eth_device *dev,
> +			volatile void *buffer, int length);
> +
> +
> +#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
> +
> +/*
> + * DMAC Register Index Enumeration
> + *
> + * [2]:	
http://www.xilinx.com/support/documentation/user_guides/ug200.pdf
> + *	page 244, DMA Controller -- Programming Interface and Registers
> + */
> +enum dmac_ctrl {
> +	TX_NXTDESC_PTR = 0,
> +	TX_CURBUF_ADDR,
> +	TX_CURBUF_LENGTH,
> +	TX_CURDESC_PTR,
> +	TX_TAILDESC_PTR,
> +	TX_CHNL_CTRL,
> +	TX_IRQ_REG,
> +	TX_CHNL_STS,
> +	RX_NXTDESC_PTR,
> +	RX_CURBUF_ADDR,
> +	RX_CURBUF_LENGTH,
> +	RX_CURDESC_PTR,
> +	RX_TAILDESC_PTR,
> +	RX_CHNL_CTRL,
> +	RX_IRQ_REG,
> +	RX_CHNL_STS,
> +	DMA_CONTROL_REG
> +};
> +
> +
> +/* initialize both Rx/Tx buffer descriptors */
> +void ll_temac_init_dmac(struct eth_device *dev);
> +
> +/* halt both Rx/Tx transfers */
> +int ll_temac_halt_dmac(struct eth_device *dev);
> +
> +/* reset SDMA and IRQ, disable interrupts and errors */
> +int ll_temac_reset_dmac(struct eth_device *dev);
> +
> +/* receive buffered data from SDMA (polling ISR) */
> +int ll_temac_recv_dmac(struct eth_device *dev);
> +
> +/* send buffered data to SDMA */
> +int ll_temac_send_dmac(struct eth_device *dev,
> +			volatile void *buffer, int length);
> +
> +
> +#endif /* CONFIG_XILINX_440 || CONFIG_XILINX_405 */
> +
> +#endif /* _XILINX_LL_TEMAC_SDMA_ */
> diff --git a/include/netdev.h b/include/netdev.h
> index 04d9f75..061c1f1 100644
> --- a/include/netdev.h
> +++ b/include/netdev.h
> @@ -100,6 +100,8 @@ 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_initialize(bd_t *bis, unsigned long base_addr,
> +						int mode, unsigned long ctrl);
> 
>  /* Boards with PCI network controllers can call this from their
> board_eth_init() * function to initialize whatever's on board.

M


More information about the U-Boot mailing list