[U-Boot] [PATCH 1/2] LPC2468 support

Ben Warren biggerbadderben at gmail.com
Tue Apr 28 18:43:38 CEST 2009


Hi Remco,

Remco Poelstra wrote:
> This patch includes support for the LPC2468 processor from NXP.
>
> Signed-off-by: Remco Poelstra <remco.poelstra+u-boot at duran-audio.com>
> ---
> It now also includes support for the ethernet interface.
> It does not include any changes to flash related code, until it's known
> where to put it. Stefan was right that the unreferenced function are needed
> by the board code.
> Neither does it contain any significant changes to the interrupt code,
> waiting for the patch to clean it up.
> I would be gratefull if the patch can be applied before then, I can then help
> clean up the code, instead of staying behind.
> Concerning thumb code: As explained earlier, it is needed to call the internal
> IAP functions. These are seldom used, so there is no performance penalty.
>   
Please break this up into orthogonal patches by functionality.  I'll 
comment on the net driver here, but will likely have more comments once 
the major issues are taken care of :) :
<snip>
> diff --git a/drivers/net/lpc2468_eth.c b/drivers/net/lpc2468_eth.c
> new file mode 100644
> index 0000000..b16e404
> --- /dev/null
> +++ b/drivers/net/lpc2468_eth.c
> @@ -0,0 +1,494 @@
> +/*
> + * (C) Copyright 2009 Duran Audio B.V. <www.duran-audio.com>
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + *
> + * 18-03-2009 Updated for U-boot 2009.3
> + * by Remco Poelstra <remco.poelstra+u-boot at duran-audio.com>
> + * Based on sample code from NXP
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <net.h>
> +#include <asm/io.h>
> +#include <asm/arch/immap.h>
> +#include "lpc2468_eth.h"
> +
> +/******************************************************************************
> + * Local variables
> + *****************************************************************************/
> +
> +static unsigned char macAddr[6];
> +static volatile int phyAddr = 0x1000;
> +static int eth_initialized = 0;
> +mac_2468_t *mac=&(((immap_t *)CONFIG_SYS_IMMAP)->ahb.mac);
>   
Please encapsulate these in a 'priv' data structure.  More on that later...
> +
> +/******************************************************************************
> + * Local functions
> + *****************************************************************************/
> +
> +static void writePhy (u32 phyReg, u32 phyData)
> +{
> +
> +	/* write command */
> +	writel (0x0, &(mac->mcmd));
> +
> +	/* [12:8] == PHY addr, [4:0]=0x00(BMCR) register addr */
> +	writel ((phyAddr | phyReg), &(mac->madr));
> +	writel (phyData, &(mac->mwtd));
>   
I don't know if 'writel' and 'readl' are the correct accessors for ARM.  
Hopefully somebody'll chime in on that.
> +	while (readl (&(mac->mind)) != 0) ;
> +}
> +
> +static u32 readPhy (u32 phyReg)
> +{
> +
> +	/* read command */
> +	writel (0x1, &(mac->mcmd));
> +
> +	/* [12:8] == PHY addr, [4:0]=0x00(BMCR) register addr */
> +	writel ((phyAddr | phyReg), &(mac->madr));
> +
> +	while (readl (&(mac->mind)) != 0);
> +
> +	writel (0x0, &(mac->mcmd));
> +
> +	return readl (&(mac->mrdd));
> +}
> +
> +static int emac_start_xmit (volatile void *buf, int length)
> +{
> +
> +	u32 txProduceIndex = 0;
> +	u32 txConsumeIndex = 0;
> +	u8 *pData = 0;
> +	u32 len = length;
> +	u32 sendLen = 0;
> +	u32 *tx_desc_addr = NULL;
> +
> +	txProduceIndex = readl (&(mac->txproduceindex));
> +	txConsumeIndex = readl (&(mac->txconsumeindex));
> +
> +	if (txConsumeIndex != txProduceIndex) {
> +		/* TODO why return here? This just means that the transmit array isn't empty */
>   
Good question...  Please resolve before submitting.
> +		printf ("emac: emac_tx transmit array isn't empty\n");
> +		return -1;
> +	}
> +
> +	if (txProduceIndex == EMAC_TX_DESCRIPTOR_COUNT) {
> +		/* should never happen */
> +		printf ("emac: emac_tx produce index == count\n");
> +	}
> +
> +	if (len > 0) {
> +		pData = (u8 *) EMAC_TX_BUFFER_ADDR;
> +		memcpy (pData, (void *)buf, length);
> +
> +		do {
> +			tx_desc_addr =
> +			    (u32 *) (TX_DESCRIPTOR_ADDR + txProduceIndex * 8);
> +
> +			sendLen = len;
> +			if (sendLen > EMAC_BLOCK_SIZE) {
> +				sendLen = EMAC_BLOCK_SIZE;
> +			} else {
> +				/* last fragment */
> +				sendLen |= EMAC_TX_DESC_LAST;
> +			}
> +
> +			writel ((unsigned long) pData, tx_desc_addr);
> +			tx_desc_addr++;
> +			writel ((u32) (EMAC_TX_DESC_INT | (sendLen - 1)),
> +				tx_desc_addr);
> +
> +			txProduceIndex++;
> +			if (txProduceIndex == EMAC_TX_DESCRIPTOR_COUNT) {
> +				txProduceIndex = 0;
> +			}
> +
> +			writel (txProduceIndex, &(mac->txproduceindex));
> +
> +			len -= (sendLen & ~EMAC_TX_DESC_LAST);
> +			pData += (sendLen & ~EMAC_TX_DESC_LAST);
> +		} while (len > 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static void emac_rx (void)
> +{
> +	u32 rxProduceIndex = 0;
> +	u32 rxConsumeIndex = 0;
> +	u32 *rxStatusAddr = 0;
> +	u32 recvSize = 0;
> +	u32 *recvAddr = 0;
> +
> +	/* the input parameter, EMCBuf, needs to be word aligned */
> +
> +	rxProduceIndex = readl (&(mac->rxproduceindex));
> +	rxConsumeIndex = readl (&(mac->rxconsumeindex));
> +
> +	/* consume the received packets */
> +	while (rxConsumeIndex != rxProduceIndex) {
> +
> +		rxStatusAddr = (u32 *) (RX_STATUS_ADDR + rxConsumeIndex * 8);
> +
> +		recvSize = readl (rxStatusAddr);
> +
> +		if ((recvSize & RX_DESC_STATUS_LAST) == 0) {
> +			/* TODO: could this occur when EMAC_BLOCK_SIZE == 0x0600? */
> +			printf ("emac_rx: NOT LAST fragment\n");
> +		}
> +
> +		recvSize = (recvSize & DESC_SIZE_MASK) + 1;
> +
> +		recvAddr = (u32 *) (RX_DESCRIPTOR_ADDR + rxConsumeIndex * 8);
> +
> +		/* TODO: allocate buffer? */
> +		NetReceive ((uchar *) (readl (recvAddr) /*inBuf */ ),
> +			    recvSize);
> +
> +		rxConsumeIndex++;
> +		if (rxConsumeIndex == EMAC_RX_DESCRIPTOR_COUNT) {
> +			rxConsumeIndex = 0;
> +		}
> +
> +		writel (rxConsumeIndex, &(mac->rxconsumeindex));
> +
> +	}
> +
> +}
> +
> +static void emac_interrupt (void)
> +{
>   
Do you really intend to use interrupts?  If this is dead code, please 
remove it.
> +	volatile u32 regValue = 0;
> +
> +	regValue = readl (&(mac->intstatus));
> +
> +	do {
> +		if (regValue == 0) {
> +			break;
> +		}
> +
> +		if (regValue & EMAC_INT_RXOVERRUN) {
> +			writel (EMAC_INT_RXOVERRUN, &(mac->intclear));
> +			printf ("rxOverrun\n");
> +			break;
> +		}
> +
> +		if (regValue & EMAC_INT_RXERROR) {
> +			writel (EMAC_INT_RXERROR, &(mac->intclear));
> +		}
> +
> +		if (regValue & EMAC_INT_RXFINISHED) {
> +			writel (EMAC_INT_RXFINISHED, &(mac->intclear));
> +		}
> +
> +		if (regValue & EMAC_INT_RXDONE) {
> +			writel (EMAC_INT_RXDONE, &(mac->intclear));
> +			emac_rx ();
> +		}
> +
> +		if (regValue & EMAC_INT_TXUNDERRUN) {
> +			printf ("TX underrun\n");
> +			writel (EMAC_INT_TXUNDERRUN, &(mac->intclear));
> +			break;
> +		}
> +
> +		if (regValue & EMAC_INT_TXERROR) {
> +			printf ("TX err\n");
> +			writel (EMAC_INT_TXERROR, &(mac->intclear));
> +			break;
> +		}
> +
> +		if (regValue & EMAC_INT_TXFINISHED) {
> +			writel (EMAC_INT_TXFINISHED, &(mac->intclear));
> +		}
> +
> +		if (regValue & EMAC_INT_TXDONE) {
> +			writel (EMAC_INT_TXDONE, &(mac->intclear));
> +		}
> +
> +	} while (0);
> +}
> +
> +static int emac_open (void)
> +{
> +	/* enable Rx & Tx */
> +	BFS32 (&(mac->command), CMD_RX_ENABLE);
> +	BFS32 (&(mac->command), CMD_TX_ENABLE);
> +	BFS32 (&(mac->command), CMD_PASS_RX_FILTER);
> +	BFS32 (&(mac->mac1), 0x01);
> +
> +	return 0;
> +}
> +
> +static void emac_close (void)
> +{
> +	/* disable Rx6 Tx */
> +	BFC32 (&(mac->command), CMD_RX_ENABLE);
> +	BFC32 (&(mac->command), CMD_TX_ENABLE);
> +	BFC32 (&(mac->mac1), 0x01);
> +}
> +
> +static int phyInit (void)
> +{
> +	int i = 0;
> +	u32 regValue = 0;
> +	u32 timeout = 0;
> +
> +	writel (0x801C, &(mac->mcfg));	/* host clock divided by 28,
> +					   no suppress preamble,
> +					   no scan increment */
> +
> +	for (i = 0; i < 0x40; i++)
> +		asm volatile ("  nop");
> +
> +	/* MII Mgmt. Divided by 28. */
> +	writel (0x001C, &(mac->mcfg));
> +	writel (0x0, &(mac->mcmd));
> +
> +	for (i = 0; i < 0x100; i++)
> +		asm volatile ("  nop");
> +
> +	/*Reset the PHY */
> +	writePhy (PHY_BMCR, BMCR_RESET);
> +	udelay (100);
> +
> +	timeout = MII_BMSR_TIMEOUT * 4;
> +	while (timeout != 0) {
> +		regValue = readPhy (PHY_BMCR);
> +		if ((regValue & BMCR_RESET) == 0x0000) {
> +			/* reset bit has been cleared */
> +			break;
> +		}
> +		timeout--;
> +	}
> +
> +	if (timeout == 0) {
> +		printf ("  Error: phyInit failed to reset PHY\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static void emacTxDescriptorInit (void)
> +{
> +	int i = 0;
> +	u32 *txDescAddr = NULL;
> +	u32 *txStatusAddr = NULL;
> +
> +	/* base address of tx descriptor array */
> +	writel (TX_DESCRIPTOR_ADDR, &(mac->txdescriptor));
> +
> +	/* base address of tx status */
> +	writel (TX_STATUS_ADDR, &(mac->txstatus));
> +
> +	/* number of tx descriptors */
> +	writel (EMAC_TX_DESCRIPTOR_COUNT - 1, &(mac->txdescriptornumber));
> +
> +	for (i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++) {
> +		txDescAddr = (u32 *) (TX_DESCRIPTOR_ADDR + i * 8);
> +		writel ((EMAC_TX_BUFFER_ADDR + i * EMAC_BLOCK_SIZE),
> +			(unsigned long)txDescAddr);
> +
> +		/* control field in descriptor */
> +		txDescAddr++;
> +		writel ((EMAC_TX_DESC_INT | (EMAC_BLOCK_SIZE - 1)),
> +			(unsigned long)txDescAddr);
> +	}
> +
> +	for (i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++) {
> +
> +		txStatusAddr = (u32 *) (TX_STATUS_ADDR + i * 4);
> +
> +		/* set status info to 0 */
> +		writel (0x0, (unsigned long)txStatusAddr);
> +	}
> +
> +	writel (0x0, &(mac->txproduceindex));
> +}
> +
> +static void emacRxDescriptorInit (void)
> +{
> +	int i;
> +	u32 *rxDescAddr = NULL;
> +	u32 *rxStatusAddr = NULL;
> +
> +	/* base address of rx descriptor array */
> +	writel (RX_DESCRIPTOR_ADDR, &(mac->rxdescriptor));
> +
> +	/* base address of rx status */
> +	writel (RX_STATUS_ADDR, &(mac->rxstatus));
> +
> +	/* number of rx descriptors */
> +	writel (EMAC_RX_DESCRIPTOR_COUNT - 1, &(mac->rxdescriptornumber));
> +
> +	for (i = 0; i < EMAC_RX_DESCRIPTOR_COUNT; i++) {
> +		rxDescAddr = (u32 *) (RX_DESCRIPTOR_ADDR + i * 8);
> +
> +		writel ((EMAC_RX_BUFFER_ADDR + i * EMAC_BLOCK_SIZE),
> +		(unsigned long)rxDescAddr);
> +
> +		rxDescAddr++;
> +
> +		writel ((EMAC_RX_DESC_INT |
> +			((EMAC_BLOCK_SIZE - 1) & DESC_SIZE_MASK)),
> +			(unsigned long)rxDescAddr);
> +	}
> +
> +	for (i = 0; i < EMAC_RX_DESCRIPTOR_COUNT; i++) {
> +		/* RX status, two words, status info. and status hash CRC. */
> +		rxStatusAddr = (u32 *) (RX_STATUS_ADDR + i * 8);
> +		writel (0x0, (unsigned long)rxStatusAddr);
> +		rxStatusAddr++;
> +		writel (0x0, (unsigned long)rxStatusAddr);
> +	}
> +
> +	writel (0x0, &(mac->rxconsumeindex));
> +}
> +
> +static int emacInit (void)
> +{
> +	int i = 0;
> +	pin_connect_2468_t *pin_connect=&(((immap_t *)CONFIG_SYS_IMMAP)->apb.pin_connect);
> +
> +	/* turn on the ethernet MAC clock in PCONP, bit 30 */
> +	BFS32 (&(((immap_t *)CONFIG_SYS_IMMAP)->apb.sys_con.pconp), PCONP_EMAC_CLOCK);
> +  /*-----------------------------------------------------------------------
> +   * write to PINSEL2/3 to select the PHY functions on P1[17:0]
> +   *-----------------------------------------------------------------------*/
> +
> +	/* documentation needs to be updated */
> +	writel (0x55555555, &(pin_connect->pinsel2));	/* selects P1[0,1,4,8,9,10,14,15] */
> +	writel (0x00000005, &(pin_connect->pinsel3));	/* selects P1[17:16] */
>   
This looks to me like board code.  If it is, it doesn't belong in this 
driver.
> +
> +	/*reset MAC modules, tx, mcs_tx, rx, mcs_rx, simulation and soft reset*/
> +	writel (0xCF00, &(mac->mac1));
> +
> +	/* reset datapaths and host registers */
> +	writel (0x0038, &(mac->command));
> +
> +	/* short delay after reset */
> +	for (i = 0; i < 0x40; i++)
> +		asm volatile ("  nop");
> +
> +	/*Remove reset conditions*/
> +	writel (0x0, &(mac->mac1));
> +
> +	/*disable Tx*/
> +	BFC32 (&(mac->command), CMD_TX_ENABLE);
> +
> +	/*disable Rx*/
> +	BFC32 (&(mac->command), CMD_RX_ENABLE);
> +
> +	/*initialize MAC2 to default value
> +	  TODO don't thinkt this is necessary??  m_nic_write(EMAC_MAC2, 0x0);*/
> +	writel (0x030, &(mac->mac2));
> +
> +	/*non back-to-back Inter-Packet-Gap register
> +	  The manual recommends the value 0x12 */
> +	writel (0x12, &(mac->ipgr));
> +
> +	/*collision window/retry register. Using recommended value from manual*/
> +	writel (0x370F, &(mac->clrt));
> +
> +	/* intialize PHY. */
> +	if (phyInit () < 0)
> +		return -1;
> +
> +	/* write the mac address */
> +	writel ((macAddr[5] << 8 | macAddr[4]), &(mac->sa0));
> +	writel ((macAddr[3] << 8 | macAddr[2]), &(mac->sa1));
> +	writel ((macAddr[1] << 8 | macAddr[0]), &(mac->sa2));
> +
> +	printf ("emac: MAC address = %2x:%2x:%2x:%2x:%2x:%2x\n",
> +	     macAddr[0],
> +	     macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
> +
> +	emacTxDescriptorInit ();
> +	emacRxDescriptorInit ();
> +
> +	/* pass all receive frames */
> +	BFS32 (&(mac->mac1), 0x002);
> +
> +	/* set up the Rx filter
> +	   [0]-AllUnicast, [1]-AllBroadCast, [2]-AllMulticast, [3]-UnicastHash
> +	   [4]-MulticastHash, [5]-Perfect, [12]-MagicPacketEnWoL,
> +	   [13]-RxFilterEnWoL
> +	   PUT32(MAC_RXFILTERCTRL, 0x0022); */
> +	writel (0x003F, &(mac->rxfilterctrl));	/*Pass everything */
> +
> +	/* clear all interrupts */
> +	writel (0xFFFF, &(mac->intclear));
> +
> +	/* enable interrupts (not SoftInt and WoL) */
> +	writel (0x00FF, &(mac->intenable));
> +
> +	return 0;
> +}
> +
> +/* ##############################
> + * u-boot interface
> + * ##############################
> + */
> +
>   
Please don't use this old API.  Instead, use the CONFIG_NET_MULTI API 
where a 'struct eth_device' is allocated, initialized and filled.  This 
struct contains a 'priv' field that you can use to store the static 
variables that were defined at the top of the driver.  The API you've 
used is on its way out.  You'll find plenty of examples in drivers/net.
> +/*
> + * Returns 0 when failes otherwise 1
> + */
> +int eth_init (bd_t * bis)
> +{
> +	int ret;
> +	if (!eth_initialized) {
> +		if (!eth_getenv_enetaddr ("ethaddr", macAddr)) {
> +			printf ("Failed to get MAC address from environment\n");
> +			return 1;
> +		}
> +
> +		ret = emacInit ();
> +		if (ret != 0) {
> +			return ret;
> +		}
> +
> +		eth_initialized = 1;
> +	}
> +
> +	emac_open ();
> +	return 0;
> +}
> +
> +int eth_send (volatile void *packet, int length)
> +{
> +	emac_start_xmit (packet, length);
> +	return 0;
> +}
> +
> +/*-----------------------------------------------------------------------------
> + * Check for received packets. Call NetReceive for each packet. The return
> + * value is ignored by the caller.
> + */
> +int eth_rx (void)
> +{
> +	emac_interrupt ();
> +	return 0;
> +}
> +
> +void eth_halt (void)
> +{
> +	emac_close ();
> +}
> diff --git a/drivers/net/lpc2468_eth.h b/drivers/net/lpc2468_eth.h
> new file mode 100644
> index 0000000..b1c4671
> --- /dev/null
> +++ b/drivers/net/lpc2468_eth.h
> @@ -0,0 +1,159 @@
> +#ifndef LPC2468_ETH_H
> +#define LPC2468_ETH_H
> +
> +/******************************************************************************
> + * Typedefs and defines
> + *****************************************************************************/
> +#define MAX_PHY_INIT_RETRY 10
> +
> +/* EMAC MODULE ID   */
> +#define OLD_EMAC_MODULE_ID  ((0x3902 << 16) | 0x2000)
> +
> +/* MAC registers and parameters */
> +#define PCONP_EMAC_CLOCK    0x40000000
> +
> +#define SPEED_100           1
> +#define SPEED_10            0
> +#define FULL_DUPLEX         1
> +#define HALF_DUPLEX         0
> +
> +#define EMAC_RAM_ADDR       0x7FE00000
> +#define EMAC_RAM_SIZE       0x00004000
> +
> +#define EMAC_TX_DESCRIPTOR_COUNT    5
> +#define EMAC_RX_DESCRIPTOR_COUNT    4
> +
> +/*
> + * (Rx|Tx)Descriptor ::
> + *   [4] packet  - base address of the buffer containing the data
> + *   [4] control - control information
> + */
> +#define TX_DESCRIPTOR_SIZE  (EMAC_TX_DESCRIPTOR_COUNT * 8)
> +#define RX_DESCRIPTOR_SIZE  (EMAC_RX_DESCRIPTOR_COUNT * 8)
> +
> +/*
> + * TxStatus ::
> + *   [4] status
> + */
> +#define TX_STATUS_SIZE      (EMAC_TX_DESCRIPTOR_COUNT * 4)
> +
> +/*
> + * RxStatus ::
> + *   [4] status        - receive status flags
> + *   [4] statusHashCRC - concat of dest addr hash CRC and src addr CRC
> + */
> +#define RX_STATUS_SIZE      (EMAC_RX_DESCRIPTOR_COUNT * 8)
> +
> +#define TOTAL_DESCRIPTOR_SIZE   (TX_DESCRIPTOR_SIZE + RX_DESCRIPTOR_SIZE + TX_STATUS_SIZE + RX_STATUS_SIZE)
> +
> +/* descriptors are placed at the end of the emac address space */
> +#define EMAC_DESCRIPTOR_ADDR    (EMAC_RAM_ADDR + EMAC_RAM_SIZE - TOTAL_DESCRIPTOR_SIZE)
> +
> +#define TX_DESCRIPTOR_ADDR  EMAC_DESCRIPTOR_ADDR
> +#define TX_STATUS_ADDR      (EMAC_DESCRIPTOR_ADDR + TX_DESCRIPTOR_SIZE)
> +#define RX_DESCRIPTOR_ADDR  (TX_STATUS_ADDR + TX_STATUS_SIZE)
> +#define RX_STATUS_ADDR      (RX_DESCRIPTOR_ADDR + RX_DESCRIPTOR_SIZE)
> +
> +#define EMAC_DMA_ADDR       EMAC_RAM_ADDR
> +#define EMAC_DMA_SIZE       EMAC_RAM_ADDR + EMAC_RAM_END - TOTAL_DESCRIPTOR_SIZE
> +
> +#define EMAC_BLOCK_SIZE         0x600
> +#define EMAC_TX_BLOCK_NUM       5
> +#define EMAC_RX_BLOCK_NUM       5
> +#define TOTAL_EMAC_BLOCK_NUM    10
> +
> +#define EMAC_BUFFER_SIZE    (EMAC_BLOCK_SIZE * (EMAC_TX_BLOCK_NUM + EMAC_RX_BLOCK_NUM ))
> +#define EMAC_TX_BUFFER_ADDR EMAC_RAM_ADDR
> +#define EMAC_RX_BUFFER_ADDR (EMAC_RAM_ADDR + EMAC_BLOCK_SIZE * EMAC_TX_BLOCK_NUM)
> +
> +/* EMAC Descriptor TX and RX Control fields */
> +#define EMAC_TX_DESC_INT        0x80000000
> +#define EMAC_TX_DESC_LAST       0x40000000
> +#define EMAC_TX_DESC_CRC        0x20000000
> +#define EMAC_TX_DESC_PAD        0x10000000
> +#define EMAC_TX_DESC_HUGE       0x08000000
> +#define EMAC_TX_DESC_OVERRIDE   0x04000000
> +
> +#define EMAC_RX_DESC_INT        0x80000000
> +
> +/* EMAC Descriptor status related definition */
> +#define TX_DESC_STATUS_ERR      0x80000000
> +#define TX_DESC_STATUS_NODESC   0x40000000
> +#define TX_DESC_STATUS_UNDERRUN 0x20000000
> +#define TX_DESC_STATUS_LCOL     0x10000000
> +#define TX_DESC_STATUS_ECOL     0x08000000
> +#define TX_DESC_STATUS_EDEFER   0x04000000
> +#define TX_DESC_STATUS_DEFER    0x02000000
> +#define TX_DESC_STATUS_COLCNT   0x01E00000	/* four bits, it's a mask, not exact count */
> +
> +#define RX_DESC_STATUS_ERR      0x80000000
> +#define RX_DESC_STATUS_LAST     0x40000000
> +#define RX_DESC_STATUS_NODESC   0x20000000
> +#define RX_DESC_STATUS_OVERRUN  0x10000000
> +#define RX_DESC_STATUS_ALGNERR  0x08000000
> +#define RX_DESC_STATUS_RNGERR   0x04000000
> +#define RX_DESC_STATUS_LENERR   0x02000000
> +#define RX_DESC_STATUS_SYMERR   0x01000000
> +#define RX_DESC_STATUS_CRCERR   0x00800000
> +#define RX_DESC_STATUS_BCAST    0x00400000
> +#define RX_DESC_STATUS_MCAST    0x00200000
> +#define RX_DESC_STATUS_FAILFLT  0x00100000
> +#define RX_DESC_STATUS_VLAN     0x00080000
> +#define RX_DESC_STATUS_CTLFRAM  0x00040000
> +
> +#define DESC_SIZE_MASK          0x000007FF	/* 11 bits for both TX and RX */
> +
> +/* EMAC interrupt controller related definition */
> +#define EMAC_INT_RXOVERRUN  0x01 << 0
> +#define EMAC_INT_RXERROR    0x01 << 1
> +#define EMAC_INT_RXFINISHED 0x01 << 2
> +#define EMAC_INT_RXDONE     0x01 << 3
> +#define EMAC_INT_TXUNDERRUN 0x01 << 4
> +#define EMAC_INT_TXERROR    0x01 << 5
> +#define EMAC_INT_TXFINISHED 0x01 << 6
> +#define EMAC_INT_TXDONE     0x01 << 7
> +#define EMAC_INT_SOFTINT    0x01 << 12
> +#define EMAC_INT_WOL        0x01 << 13
> +
> +#define PHY_BMCR        0x0000
> +#define PHY_BMSR        0x0001
> +#define PHY_PHYIDR1     0x0002
> +#define PHY_PHYIDR2     0x0003
> +#define PHY_ANAR        0x0004
> +#define PHY_ANLPAR      0x0005
> +#define PHY_ANLPARNP    0x0005
> +#define PHY_ANER        0x0006
> +#define PHY_ANNPTR      0x0007
> +
>   
Please use the definitions in include/miiphy.h for all these standard 
IEEE802.3 registers.
> +/* BMCR setting */
> +#define BMCR_RESET          0x8000
> +#define BMCR_LOOPBACK       0x4000
> +#define BMCR_SPEED_100      0x2000
> +#define BMCR_AN             0x1000
> +#define BMCR_POWERDOWN      0x0800
> +#define BMCR_ISOLATE        0x0400
> +#define BMCR_RE_AN          0x0200
> +#define BMCR_DUPLEX         0x0100
> +
> +/* BMSR setting */
> +#define BMSR_100BE_T4       0x8000
> +#define BMSR_100TX_FULL     0x4000
> +#define BMSR_100TX_HALF     0x2000
> +#define BMSR_10BE_FULL      0x1000
> +#define BMSR_10BE_HALF      0x0800
> +#define BMSR_AUTO_DONE      0x0020
> +#define BMSR_REMOTE_FAULT   0x0010
> +#define BMSR_NO_AUTO        0x0008
> +#define BMSR_LINK_ESTABLISHED   0x0004
> +
> +#define MII_BMSR_TIMEOUT    0x1000000
> +
> +#define CMD_RX_ENABLE 0x01
> +#define CMD_TX_ENABLE 0x02
> +#define CMD_PASS_RX_FILTER 0x80
> +
> +/* Helper macros */
> +#define BFS32(reg,value) writel( (readl(reg)|=(value)) ,reg)
> +#define BFC32(reg,value) writel( (readl(reg)&=(~value)) ,reg)
>   
Could you make these macro names a bit more descriptive please?

Thanks a lot!  This is a very good start.

regards,
Ben


More information about the U-Boot mailing list