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

Ben Warren
2009-04-28T16:43:38Z

Hi Remco,

Remco Poelstra wrote:
> This patch includes support for the LPC2468 processor from NXP.
>
> Signed-off-by: Remco Poelstra <remco.poelstra+u-boot@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@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