summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Makefile5
-rw-r--r--drivers/net/bfin_mac.c357
-rw-r--r--drivers/net/bfin_mac.h31
-rw-r--r--drivers/net/dnet.c395
-rw-r--r--drivers/net/dnet.h166
-rw-r--r--drivers/net/e1000.c1
-rw-r--r--drivers/net/macb.c31
-rw-r--r--drivers/net/mcfmii.c25
-rw-r--r--drivers/net/mpc5xxx_fec.c28
-rw-r--r--drivers/net/sh_eth.c355
-rw-r--r--drivers/net/sh_eth.h12
-rw-r--r--drivers/net/smc911x.c79
-rw-r--r--drivers/net/tsec.c5
13 files changed, 1074 insertions, 416 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 631336ab4..a360a5065 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -26,12 +26,14 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libnet.a
COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o
+COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o
COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o
COBJS-$(CONFIG_DRIVER_CS8900) += cs8900.o
COBJS-$(CONFIG_TULIP) += dc2114x.o
COBJS-$(CONFIG_DRIVER_DM9000) += dm9000x.o
+COBJS-$(CONFIG_DNET) += dnet.o
COBJS-$(CONFIG_E1000) += e1000.o
COBJS-$(CONFIG_EEPRO100) += eepro100.o
COBJS-$(CONFIG_ENC28J60) += enc28j60.o
@@ -54,11 +56,11 @@ COBJS-$(CONFIG_NS8382X) += ns8382x.o
COBJS-$(CONFIG_DRIVER_NS9750_ETHERNET) += ns9750_eth.o
COBJS-$(CONFIG_PCNET) += pcnet.o
COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o
-COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o
COBJS-$(CONFIG_RTL8139) += rtl8139.o
COBJS-$(CONFIG_RTL8169) += rtl8169.o
COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o
+COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
COBJS-$(CONFIG_DRIVER_SMC91111) += smc91111.o
COBJS-$(CONFIG_DRIVER_SMC911X) += smc911x.o
COBJS-$(CONFIG_TIGON3) += tigon3.o bcm570x_autoneg.o 5701rls.o
@@ -68,7 +70,6 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o
COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
-COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 504fd100a..23f934aee 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -12,6 +12,8 @@
#include <netdev.h>
#include <command.h>
#include <malloc.h>
+#include <miiphy.h>
+#include <linux/mii.h>
#include <asm/blackfin.h>
#include <asm/mach-common/bits/dma.h>
@@ -20,16 +22,15 @@
#include "bfin_mac.h"
-#ifdef CONFIG_POST
-#include <post.h>
+#ifndef CONFIG_PHY_ADDR
+# define CONFIG_PHY_ADDR 1
+#endif
+#ifndef CONFIG_PHY_CLOCK_FREQ
+# define CONFIG_PHY_CLOCK_FREQ 2500000
#endif
-#undef DEBUG_ETHERNET
-
-#ifdef DEBUG_ETHERNET
-#define DEBUGF(fmt, args...) printf(fmt, ##args)
-#else
-#define DEBUGF(fmt, args...)
+#ifdef CONFIG_POST
+#include <post.h>
#endif
#define RXBUF_BASE_ADDR 0xFF900000
@@ -38,42 +39,61 @@
#define TOUT_LOOP 1000000
-ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT];
-ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX];
+static ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT];
+static ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX];
static u16 txIdx; /* index of the current RX buffer */
static u16 rxIdx; /* index of the current TX buffer */
-u16 PHYregs[NO_PHY_REGS]; /* u16 PHYADDR; */
-
/* DMAx_CONFIG values at DMA Restart */
-const ADI_DMA_CONFIG_REG rxdmacfg = {
- .b_DMA_EN = 1, /* enabled */
- .b_WNR = 1, /* write to memory */
- .b_WDSIZE = 2, /* wordsize is 32 bits */
- .b_DMA2D = 0,
- .b_RESTART = 0,
- .b_DI_SEL = 0,
- .b_DI_EN = 0, /* no interrupt */
- .b_NDSIZE = 5, /* 5 half words is desc size */
- .b_FLOW = 7 /* large desc flow */
+static const union {
+ u16 data;
+ ADI_DMA_CONFIG_REG reg;
+} txdmacfg = {
+ .reg = {
+ .b_DMA_EN = 1, /* enabled */
+ .b_WNR = 0, /* read from memory */
+ .b_WDSIZE = 2, /* wordsize is 32 bits */
+ .b_DMA2D = 0,
+ .b_RESTART = 0,
+ .b_DI_SEL = 0,
+ .b_DI_EN = 0, /* no interrupt */
+ .b_NDSIZE = 5, /* 5 half words is desc size */
+ .b_FLOW = 7 /* large desc flow */
+ },
};
-const ADI_DMA_CONFIG_REG txdmacfg = {
- .b_DMA_EN = 1, /* enabled */
- .b_WNR = 0, /* read from memory */
- .b_WDSIZE = 2, /* wordsize is 32 bits */
- .b_DMA2D = 0,
- .b_RESTART = 0,
- .b_DI_SEL = 0,
- .b_DI_EN = 0, /* no interrupt */
- .b_NDSIZE = 5, /* 5 half words is desc size */
- .b_FLOW = 7 /* large desc flow */
-};
+static int bfin_miiphy_wait(void)
+{
+ /* poll the STABUSY bit */
+ while (bfin_read_EMAC_STAADD() & STABUSY)
+ continue;
+ return 0;
+}
+
+static int bfin_miiphy_read(char *devname, uchar addr, uchar reg, ushort *val)
+{
+ if (bfin_miiphy_wait())
+ return 1;
+ bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STABUSY);
+ if (bfin_miiphy_wait())
+ return 1;
+ *val = bfin_read_EMAC_STADAT();
+ return 0;
+}
+
+static int bfin_miiphy_write(char *devname, uchar addr, uchar reg, ushort val)
+{
+ if (bfin_miiphy_wait())
+ return 1;
+ bfin_write_EMAC_STADAT(val);
+ bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STAOP | STABUSY);
+ return 0;
+}
int bfin_EMAC_initialize(bd_t *bis)
{
struct eth_device *dev;
- dev = (struct eth_device *)malloc(sizeof(*dev));
+ dev = malloc(sizeof(*dev));
if (dev == NULL)
hang();
@@ -89,6 +109,10 @@ int bfin_EMAC_initialize(bd_t *bis)
eth_register(dev);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+ miiphy_register(dev->name, bfin_miiphy_read, bfin_miiphy_write);
+#endif
+
return 0;
}
@@ -119,8 +143,8 @@ static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet,
txbuf[txIdx]->FrmData->NoBytes = length;
memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length);
txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData;
- *pDMA2_NEXT_DESC_PTR = &txbuf[txIdx]->Dma[0];
- *pDMA2_CONFIG = *(u16 *) (void *)(&txdmacfg);
+ *pDMA2_NEXT_DESC_PTR = txbuf[txIdx]->Dma;
+ *pDMA2_CONFIG = txdmacfg.data;
*pEMAC_OPMODE |= TE;
for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) {
@@ -136,7 +160,7 @@ static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet,
else
txIdx++;
out:
- DEBUGF("BFIN EMAC send: length = %d\n", length);
+ debug("BFIN EMAC send: length = %d\n", length);
return result;
}
@@ -182,51 +206,141 @@ static int bfin_EMAC_recv(struct eth_device *dev)
*
*************************************************************/
+/* MDC = SCLK / MDC_freq / 2 - 1 */
+#define MDC_FREQ_TO_DIV(mdc_freq) (get_sclk() / (mdc_freq) / 2 - 1)
+
+static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
+{
+ u16 phydat;
+ size_t count;
+
+ /* Enable PHY output */
+ *pVR_CTL |= CLKBUFOE;
+
+ /* Set all the pins to peripheral mode */
+#ifdef CONFIG_RMII
+ /* grab RMII pins */
+# if defined(__ADSPBF51x__)
+ *pPORTF_MUX = (*pPORTF_MUX & \
+ ~(PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
+ PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
+ *pPORTF_FER |= PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
+ *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
+ *pPORTG_FER |= PG0 | PG1 | PG2;
+# elif defined(__ADSPBF52x__)
+ *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
+ *pPORTG_FER |= PG14 | PG15;
+ *pPORTH_MUX = (*pPORTH_MUX & ~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK)) | \
+ PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2;
+ *pPORTH_FER |= PH0 | PH1 | PH2 | PH3 | PH4 | PH5 | PH6 | PH7 | PH8;
+# else
+ *pPORTH_FER |= PH0 | PH1 | PH4 | PH5 | PH6 | PH8 | PH9 | PH14 | PH15;
+# endif
+#else
+ /* grab MII & RMII pins */
+# if defined(__ADSPBF51x__)
+ *pPORTF_MUX = (*pPORTF_MUX & \
+ ~(PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK | PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK)) | \
+ PORT_x_MUX_0_FUNC_1 | PORT_x_MUX_1_FUNC_1 | PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1;
+ *pPORTF_FER |= PF0 | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15;
+ *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_0_MASK) | PORT_x_MUX_0_FUNC_1;
+ *pPORTG_FER |= PG0 | PG1 | PG2;
+# elif defined(__ADSPBF52x__)
+ *pPORTG_MUX = (*pPORTG_MUX & ~PORT_x_MUX_6_MASK) | PORT_x_MUX_6_FUNC_2;
+ *pPORTG_FER |= PG14 | PG15;
+ *pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2;
+ *pPORTH_FER = -1; /* all pins */
+# else
+ *pPORTH_FER = -1; /* all pins */
+# endif
+#endif
+
+ /* Odd word alignment for Receive Frame DMA word */
+ /* Configure checksum support and rcve frame word alignment */
+ bfin_write_EMAC_SYSCTL(RXDWA | RXCKS | SET_MDCDIV(MDC_FREQ_TO_DIV(CONFIG_PHY_CLOCK_FREQ)));
+
+ /* turn on auto-negotiation and wait for link to come up */
+ bfin_miiphy_write(dev->name, CONFIG_PHY_ADDR, MII_BMCR, BMCR_ANENABLE);
+ count = 0;
+ while (1) {
+ ++count;
+ if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_BMSR, &phydat))
+ return -1;
+ if (phydat & BMSR_LSTATUS)
+ break;
+ if (count > 30000) {
+ printf("%s: link down, check cable\n", dev->name);
+ return -1;
+ }
+ udelay(100);
+ }
+
+ /* see what kind of link we have */
+ if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_LPA, &phydat))
+ return -1;
+ if (phydat & LPA_DUPLEX)
+ *opmode = FDMODE;
+ else
+ *opmode = 0;
+
+ bfin_write_EMAC_MMC_CTL(RSTC | CROLL);
+
+ /* Initialize the TX DMA channel registers */
+ *pDMA2_X_COUNT = 0;
+ *pDMA2_X_MODIFY = 4;
+ *pDMA2_Y_COUNT = 0;
+ *pDMA2_Y_MODIFY = 0;
+
+ /* Initialize the RX DMA channel registers */
+ *pDMA1_X_COUNT = 0;
+ *pDMA1_X_MODIFY = 4;
+ *pDMA1_Y_COUNT = 0;
+ *pDMA1_Y_MODIFY = 0;
+
+ return 0;
+}
+
static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
{
u32 opmode;
int dat;
int i;
- DEBUGF("Eth_init: ......\n");
+ debug("Eth_init: ......\n");
txIdx = 0;
rxIdx = 0;
-/* Initialize System Register */
- if (SetupSystemRegs(&dat) < 0)
+ /* Initialize System Register */
+ if (bfin_miiphy_init(dev, &dat) < 0)
return -1;
-/* Initialize EMAC address */
+ /* Initialize EMAC address */
bfin_EMAC_setup_addr(bd);
-/* Initialize TX and RX buffer */
+ /* Initialize TX and RX buffer */
for (i = 0; i < PKTBUFSRX; i++) {
rxbuf[i] = SetupRxBuffer(i);
if (i > 0) {
- rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR =
- &(rxbuf[i]->Dma[0]);
+ rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR = rxbuf[i]->Dma;
if (i == (PKTBUFSRX - 1))
- rxbuf[i]->Dma[1].NEXT_DESC_PTR =
- &(rxbuf[0]->Dma[0]);
+ rxbuf[i]->Dma[1].NEXT_DESC_PTR = rxbuf[0]->Dma;
}
}
for (i = 0; i < TX_BUF_CNT; i++) {
txbuf[i] = SetupTxBuffer(i);
if (i > 0) {
- txbuf[i - 1]->Dma[1].NEXT_DESC_PTR =
- &(txbuf[i]->Dma[0]);
+ txbuf[i - 1]->Dma[1].NEXT_DESC_PTR = txbuf[i]->Dma;
if (i == (TX_BUF_CNT - 1))
- txbuf[i]->Dma[1].NEXT_DESC_PTR =
- &(txbuf[0]->Dma[0]);
+ txbuf[i]->Dma[1].NEXT_DESC_PTR = txbuf[0]->Dma;
}
}
/* Set RX DMA */
- *pDMA1_NEXT_DESC_PTR = &rxbuf[0]->Dma[0];
- *pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG);
+ *pDMA1_NEXT_DESC_PTR = rxbuf[0]->Dma;
+ *pDMA1_CONFIG = rxbuf[0]->Dma[0].CONFIG_DATA;
/* Wait MII done */
- PollMdcDone();
+ bfin_miiphy_wait();
/* We enable only RX here */
/* ASTP : Enable Automatic Pad Stripping
@@ -240,7 +354,7 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
else
opmode = ASTP | PSF;
opmode |= RE;
-#ifdef CONFIG_BFIN_MAC_RMII
+#ifdef CONFIG_RMII
opmode |= TE | RMII;
#endif
/* Turn on the EMAC */
@@ -250,7 +364,7 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
static void bfin_EMAC_halt(struct eth_device *dev)
{
- DEBUGF("Eth_halt: ......\n");
+ debug("Eth_halt: ......\n");
/* Turn off the EMAC */
*pEMAC_OPMODE = 0x00000000;
/* Turn off the EMAC RX DMA */
@@ -271,125 +385,6 @@ void bfin_EMAC_setup_addr(bd_t *bd)
bd->bi_enetaddr[5] << 8;
}
-static void PollMdcDone(void)
-{
- /* poll the STABUSY bit */
- while (*pEMAC_STAADD & STABUSY) ;
-}
-
-static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data)
-{
- PollMdcDone();
-
- *pEMAC_STADAT = Data;
-
- *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
- STAOP | STAIE | STABUSY;
-}
-
-/*********************************************************************************
- * Read an off-chip register in a PHY through the MDC/MDIO port *
- *********************************************************************************/
-static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr)
-{
- u16 Data;
-
- PollMdcDone();
-
- *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
- STAIE | STABUSY;
-
- PollMdcDone();
-
- Data = (u16) * pEMAC_STADAT;
-
- PHYregs[RegAddr] = Data; /* save shadow copy */
-
- return Data;
-}
-
-#if 0 /* dead code ? */
-static void SoftResetPHY(void)
-{
- u16 phydat;
- /* set the reset bit */
- WrPHYReg(PHYADDR, PHY_MODECTL, PHY_RESET);
- /* and clear it again */
- WrPHYReg(PHYADDR, PHY_MODECTL, 0x0000);
- do {
- /* poll until reset is complete */
- phydat = RdPHYReg(PHYADDR, PHY_MODECTL);
- } while ((phydat & PHY_RESET) != 0);
-}
-#endif
-
-static int SetupSystemRegs(int *opmode)
-{
- u16 sysctl, phydat;
- int count = 0;
- /* Enable PHY output */
- *pVR_CTL |= CLKBUFOE;
- /* Set all the pins to peripheral mode */
-
-#ifndef CONFIG_BFIN_MAC_RMII
- *pPORTH_FER = 0xFFFF;
-#ifdef __ADSPBF52x__
- *pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2;
-#endif
-#else
-#if defined(__ADSPBF536__) || defined(__ADSPBF537__)
- *pPORTH_FER = 0xC373;
-#endif
-#ifdef __ADSPBF52x__
- *pPORTH_FER = 0x01FF;
- *pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2;
-#endif
-#endif
- /* MDC = 2.5 MHz */
- sysctl = SET_MDCDIV(24);
- /* Odd word alignment for Receive Frame DMA word */
- /* Configure checksum support and rcve frame word alignment */
- sysctl |= RXDWA | RXCKS;
- *pEMAC_SYSCTL = sysctl;
- /* auto negotiation on */
- /* full duplex */
- /* 100 Mbps */
- phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET;
- WrPHYReg(PHYADDR, PHY_MODECTL, phydat);
- do {
- udelay(1000);
- phydat = RdPHYReg(PHYADDR, PHY_MODESTAT);
- if (count > 3000) {
- printf
- ("Link is down, please check your network connection\n");
- return -1;
- }
- count++;
- } while (!(phydat & 0x0004));
-
- phydat = RdPHYReg(PHYADDR, PHY_ANLPAR);
-
- if ((phydat & 0x0100) || (phydat & 0x0040))
- *opmode = FDMODE;
- else
- *opmode = 0;
-
- *pEMAC_MMC_CTL = RSTC | CROLL;
-
- /* Initialize the TX DMA channel registers */
- *pDMA2_X_COUNT = 0;
- *pDMA2_X_MODIFY = 4;
- *pDMA2_Y_COUNT = 0;
- *pDMA2_Y_MODIFY = 0;
-
- /* Initialize the RX DMA channel registers */
- *pDMA1_X_COUNT = 0;
- *pDMA1_X_MODIFY = 4;
- *pDMA1_Y_COUNT = 0;
- *pDMA1_Y_MODIFY = 0;
- return 0;
-}
-
ADI_ETHER_BUFFER *SetupRxBuffer(int no)
{
ADI_ETHER_FRAME_BUFFER *frmbuf;
@@ -397,10 +392,8 @@ ADI_ETHER_BUFFER *SetupRxBuffer(int no)
int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */
int total_size = nobytes_buffer + RECV_BUFSIZE;
- buf = (ADI_ETHER_BUFFER *) (RXBUF_BASE_ADDR + no * total_size);
- frmbuf =
- (ADI_ETHER_FRAME_BUFFER *) (RXBUF_BASE_ADDR + no * total_size +
- nobytes_buffer);
+ buf = (void *) (RXBUF_BASE_ADDR + no * total_size);
+ frmbuf = (void *) (RXBUF_BASE_ADDR + no * total_size + nobytes_buffer);
memset(buf, 0x00, nobytes_buffer);
buf->FrmData = frmbuf;
@@ -416,7 +409,7 @@ ADI_ETHER_BUFFER *SetupRxBuffer(int no)
buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */
/* set up second desc to point to status word */
- buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]);
+ buf->Dma[1].NEXT_DESC_PTR = buf->Dma;
buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum;
buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */
buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */
@@ -435,10 +428,8 @@ ADI_ETHER_BUFFER *SetupTxBuffer(int no)
int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */
int total_size = nobytes_buffer + RECV_BUFSIZE;
- buf = (ADI_ETHER_BUFFER *) (TXBUF_BASE_ADDR + no * total_size);
- frmbuf =
- (ADI_ETHER_FRAME_BUFFER *) (TXBUF_BASE_ADDR + no * total_size +
- nobytes_buffer);
+ buf = (void *) (TXBUF_BASE_ADDR + no * total_size);
+ frmbuf = (void *) (TXBUF_BASE_ADDR + no * total_size + nobytes_buffer);
memset(buf, 0x00, nobytes_buffer);
buf->FrmData = frmbuf;
diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h
index c8a94d0c9..084f53334 100644
--- a/drivers/net/bfin_mac.h
+++ b/drivers/net/bfin_mac.h
@@ -9,29 +9,8 @@
#ifndef __BFIN_MAC_H__
#define __BFIN_MAC_H__
-#define PHYADDR 0x01
-#define NO_PHY_REGS 0x20
-
-#define DEFAULT_PHY_PHYID1 0x0007
-#define DEFAULT_PHY_PHYID2 0xC0A3
-#define PHY_MODECTL 0x00
-#define PHY_MODESTAT 0x01
-#define PHY_PHYID1 0x02
-#define PHY_PHYID2 0x03
-#define PHY_ANAR 0x04
-#define PHY_ANLPAR 0x05
-#define PHY_ANER 0x06
-
-#define PHY_RESET 0x8000
-#define PHY_ANEG_EN 0x1000
-#define PHY_DUPLEX 0x0100
-#define PHY_SPD_SET 0x2000
-
#define RECV_BUFSIZE (0x614)
-typedef volatile u32 reg32;
-typedef volatile u16 reg16;
-
typedef struct ADI_DMA_CONFIG_REG {
u16 b_DMA_EN:1; /* 0 Enabled */
u16 b_WNR:1; /* 1 Direction */
@@ -56,7 +35,10 @@ typedef struct adi_ether_frame_buffer {
typedef struct dma_descriptor {
struct dma_descriptor *NEXT_DESC_PTR;
u32 START_ADDR;
- ADI_DMA_CONFIG_REG CONFIG;
+ union {
+ u16 CONFIG_DATA;
+ ADI_DMA_CONFIG_REG CONFIG;
+ };
} DMA_DESCRIPTOR;
/* 10 bytes/struct in 12 bytes */
@@ -79,11 +61,6 @@ static void bfin_EMAC_halt(struct eth_device *dev);
static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, int length);
static int bfin_EMAC_recv(struct eth_device *dev);
-static void PollMdcDone(void);
-static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data);
-static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr);
-static int SetupSystemRegs(int *opmode);
-
static void bfin_EMAC_setup_addr(bd_t *bd);
#endif
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
new file mode 100644
index 000000000..bfe87faa2
--- /dev/null
+++ b/drivers/net/dnet.c
@@ -0,0 +1,395 @@
+/*
+ * Dave Ethernet Controller driver
+ *
+ * Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+
+#ifndef CONFIG_DNET_AUTONEG_TIMEOUT
+#define CONFIG_DNET_AUTONEG_TIMEOUT 5000000 /* default value */
+#endif
+
+#include <net.h>
+#include <malloc.h>
+#include <linux/mii.h>
+
+#include <miiphy.h>
+#include <asm/io.h>
+
+#include "dnet.h"
+
+struct dnet_device {
+ struct dnet_registers *regs;
+ const struct device *dev;
+ struct eth_device netdev;
+ unsigned short phy_addr;
+};
+
+/* get struct dnet_device from given struct netdev */
+#define to_dnet(_nd) container_of(_nd, struct dnet_device, netdev)
+
+/* function for reading internal MAC register */
+u16 dnet_readw_mac(struct dnet_device *dnet, u16 reg)
+{
+ u16 data_read;
+
+ /* issue a read */
+ writel(reg, &dnet->regs->MACREG_ADDR);
+
+ /* since a read/write op to the MAC is very slow,
+ * we must wait before reading the data */
+ udelay(1);
+
+ /* read data read from the MAC register */
+ data_read = readl(&dnet->regs->MACREG_DATA);
+
+ /* all done */
+ return data_read;
+}
+
+/* function for writing internal MAC register */
+void dnet_writew_mac(struct dnet_device *dnet, u16 reg, u16 val)
+{
+ /* load data to write */
+ writel(val, &dnet->regs->MACREG_DATA);
+
+ /* issue a write */
+ writel(reg | DNET_INTERNAL_WRITE, &dnet->regs->MACREG_ADDR);
+
+ /* since a read/write op to the MAC is very slow,
+ * we must wait before exiting */
+ udelay(1);
+}
+
+static void dnet_mdio_write(struct dnet_device *dnet, u8 reg, u16 value)
+{
+ u16 tmp;
+
+ debug(DRIVERNAME "dnet_mdio_write %02x:%02x <- %04x\n",
+ dnet->phy_addr, reg, value);
+
+ while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
+ DNET_INTERNAL_GMII_MNG_CMD_FIN))
+ ;
+
+ /* prepare for a write operation */
+ tmp = (1 << 13);
+
+ /* only 5 bits allowed for register offset */
+ reg &= 0x1f;
+
+ /* prepare reg_value for a write */
+ tmp |= (dnet->phy_addr << 8);
+ tmp |= reg;
+
+ /* write data to write first */
+ dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_DAT_REG, value);
+
+ /* write control word */
+ dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp);
+
+ while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
+ DNET_INTERNAL_GMII_MNG_CMD_FIN))
+ ;
+}
+
+static u16 dnet_mdio_read(struct dnet_device *dnet, u8 reg)
+{
+ u16 value;
+
+ while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
+ DNET_INTERNAL_GMII_MNG_CMD_FIN))
+ ;
+
+ /* only 5 bits allowed for register offset*/
+ reg &= 0x1f;
+
+ /* prepare reg_value for a read */
+ value = (dnet->phy_addr << 8);
+ value |= reg;
+
+ /* write control word */
+ dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG, value);
+
+ /* wait for end of transfer */
+ while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
+ DNET_INTERNAL_GMII_MNG_CMD_FIN))
+ ;
+
+ value = dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_DAT_REG);
+
+ debug(DRIVERNAME "dnet_mdio_read %02x:%02x <- %04x\n",
+ dnet->phy_addr, reg, value);
+
+ return value;
+}
+
+static int dnet_send(struct eth_device *netdev, volatile void *packet,
+ int length)
+{
+ struct dnet_device *dnet = to_dnet(netdev);
+ int i, len, wrsz;
+ unsigned int *bufp;
+ unsigned int tx_cmd;
+
+ debug(DRIVERNAME "[%s] Sending %u bytes\n", __func__, length);
+
+ /* frame size (words) */
+ len = (length + 3) >> 2;
+
+ bufp = (unsigned int *) (((u32)packet) & 0xFFFFFFFC);
+ wrsz = (u32)length + 3;
+ wrsz += ((u32)packet) & 0x3;
+ wrsz >>= 2;
+ tx_cmd = ((((unsigned int)(packet)) & 0x03) << 16) | (u32)length;
+
+ /* check if there is enough room for the current frame */
+ if (wrsz < (DNET_FIFO_SIZE - readl(&dnet->regs->TX_FIFO_WCNT))) {
+ for (i = 0; i < wrsz; i++)
+ writel(*bufp++, &dnet->regs->TX_DATA_FIFO);
+ /*
+ * inform MAC that a packet's written and ready
+ * to be shipped out
+ */
+ writel(tx_cmd, &dnet->regs->TX_LEN_FIFO);
+ } else {
+ printf(DRIVERNAME "No free space (actual %d, required %d "
+ "(words))\n", DNET_FIFO_SIZE -
+ readl(&dnet->regs->TX_FIFO_WCNT), wrsz);
+ }
+
+ /* No one cares anyway */
+ return 0;
+}
+
+
+static int dnet_recv(struct eth_device *netdev)
+{
+ struct dnet_device *dnet = to_dnet(netdev);
+ unsigned int *data_ptr;
+ int pkt_len, poll, i;
+ u32 cmd_word;
+
+ debug("Waiting for pkt (polling)\n");
+ poll = 50;
+ while ((readl(&dnet->regs->RX_FIFO_WCNT) >> 16) == 0) {
+ udelay(10); /* wait 10 usec */
+ if (--poll == 0)
+ return 0; /* no pkt available */
+ }
+
+ cmd_word = readl(&dnet->regs->RX_LEN_FIFO);
+ pkt_len = cmd_word & 0xFFFF;
+
+ debug("Got pkt with size %d bytes\n", pkt_len);
+
+ if (cmd_word & 0xDF180000)
+ printf("%s packet receive error %x\n", __func__, cmd_word);
+
+ data_ptr = (unsigned int *) NetRxPackets[0];
+
+ for (i = 0; i < (pkt_len + 3) >> 2; i++)
+ *data_ptr++ = readl(&dnet->regs->RX_DATA_FIFO);
+
+ NetReceive(NetRxPackets[0], pkt_len + 5); /* ok + 5 ?? */
+
+ return 0;
+}
+
+static void dnet_set_hwaddr(struct eth_device *netdev)
+{
+ struct dnet_device *dnet = to_dnet(netdev);
+ u16 tmp;
+
+ tmp = cpu_to_be16(*((u16 *)netdev->enetaddr));
+ dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_0_REG, tmp);
+ tmp = cpu_to_be16(*((u16 *)(netdev->enetaddr + 2)));
+ dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_1_REG, tmp);
+ tmp = cpu_to_be16(*((u16 *)(netdev->enetaddr + 4)));
+ dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
+}
+
+static void dnet_phy_reset(struct dnet_device *dnet)
+{
+ struct eth_device *netdev = &dnet->netdev;
+ int i;
+ u16 status, adv;
+
+ adv = ADVERTISE_CSMA | ADVERTISE_ALL;
+ dnet_mdio_write(dnet, MII_ADVERTISE, adv);
+ printf("%s: Starting autonegotiation...\n", netdev->name);
+ dnet_mdio_write(dnet, MII_BMCR, (BMCR_ANENABLE
+ | BMCR_ANRESTART));
+
+ for (i = 0; i < CONFIG_DNET_AUTONEG_TIMEOUT / 100; i++) {
+ status = dnet_mdio_read(dnet, MII_BMSR);
+ if (status & BMSR_ANEGCOMPLETE)
+ break;
+ udelay(100);
+ }
+
+ if (status & BMSR_ANEGCOMPLETE)
+ printf("%s: Autonegotiation complete\n", netdev->name);
+ else
+ printf("%s: Autonegotiation timed out (status=0x%04x)\n",
+ netdev->name, status);
+}
+
+static int dnet_phy_init(struct dnet_device *dnet)
+{
+ struct eth_device *netdev = &dnet->netdev;
+ u16 phy_id, status, adv, lpa;
+ int media, speed, duplex;
+ int i;
+ u32 ctl_reg;
+
+ /* Find a PHY */
+ for (i = 0; i < 32; i++) {
+ dnet->phy_addr = i;
+ phy_id = dnet_mdio_read(dnet, MII_PHYSID1);
+ if (phy_id != 0xffff) {
+ /* ok we found it */
+ printf("Found PHY at address %d PHYID (%04x:%04x)\n",
+ i, phy_id,
+ dnet_mdio_read(dnet, MII_PHYSID2));
+ break;
+ }
+ }
+
+ /* Check if the PHY is up to snuff... */
+ phy_id = dnet_mdio_read(dnet, MII_PHYSID1);
+ if (phy_id == 0xffff) {
+ printf("%s: No PHY present\n", netdev->name);
+ return -1;
+ }
+
+ status = dnet_mdio_read(dnet, MII_BMSR);
+ if (!(status & BMSR_LSTATUS)) {
+ /* Try to re-negotiate if we don't have link already. */
+ dnet_phy_reset(dnet);
+
+ for (i = 0; i < CONFIG_DNET_AUTONEG_TIMEOUT / 100; i++) {
+ status = dnet_mdio_read(dnet, MII_BMSR);
+ if (status & BMSR_LSTATUS)
+ break;
+ udelay(100);
+ }
+ }
+
+ if (!(status & BMSR_LSTATUS)) {
+ printf("%s: link down (status: 0x%04x)\n",
+ netdev->name, status);
+ return -1;
+ } else {
+ adv = dnet_mdio_read(dnet, MII_ADVERTISE);
+ lpa = dnet_mdio_read(dnet, MII_LPA);
+ media = mii_nway_result(lpa & adv);
+ speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
+ ? 1 : 0);
+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+ /* 1000BaseT ethernet is not supported */
+ printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
+ netdev->name,
+ speed ? "100" : "10",
+ duplex ? "full" : "half",
+ lpa);
+
+ ctl_reg = dnet_readw_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG);
+
+ if (duplex)
+ ctl_reg &= ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP);
+ else
+ ctl_reg |= DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP;
+
+ dnet_writew_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg);
+
+ return 0;
+ }
+}
+
+static int dnet_init(struct eth_device *netdev, bd_t *bd)
+{
+ struct dnet_device *dnet = to_dnet(netdev);
+ u32 config;
+
+ /*
+ * dnet_halt should have been called at some point before now,
+ * so we'll assume the controller is idle.
+ */
+
+ /* set hardware address */
+ dnet_set_hwaddr(netdev);
+
+ if (dnet_phy_init(dnet) < 0)
+ return -1;
+
+ /* flush rx/tx fifos */
+ writel(DNET_SYS_CTL_RXFIFOFLUSH | DNET_SYS_CTL_TXFIFOFLUSH,
+ &dnet->regs->SYS_CTL);
+ udelay(1000);
+ writel(0, &dnet->regs->SYS_CTL);
+
+ config = dnet_readw_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG);
+
+ config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE |
+ DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST |
+ DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL |
+ DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS;
+
+ dnet_writew_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG, config);
+
+ /* Enable TX and RX */
+ dnet_writew_mac(dnet, DNET_INTERNAL_MODE_REG,
+ DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN);
+
+ return 0;
+}
+
+static void dnet_halt(struct eth_device *netdev)
+{
+ struct dnet_device *dnet = to_dnet(netdev);
+
+ /* Disable TX and RX */
+ dnet_writew_mac(dnet, DNET_INTERNAL_MODE_REG, 0);
+}
+
+int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr)
+{
+ struct dnet_device *dnet;
+ struct eth_device *netdev;
+ unsigned int dev_capa;
+
+ dnet = malloc(sizeof(struct dnet_device));
+ if (!dnet) {
+ printf("Error: Failed to allocate memory for DNET%d\n", id);
+ return -1;
+ }
+ memset(dnet, 0, sizeof(struct dnet_device));
+
+ netdev = &dnet->netdev;
+
+ dnet->regs = (struct dnet_registers *)regs;
+ dnet->phy_addr = phy_addr;
+
+ sprintf(netdev->name, "dnet%d", id);
+ netdev->init = dnet_init;
+ netdev->halt = dnet_halt;
+ netdev->send = dnet_send;
+ netdev->recv = dnet_recv;
+
+ dev_capa = readl(&dnet->regs->VERCAPS) & 0xFFFF;
+ debug("%s: has %smdio, %sirq, %sgigabit, %sdma \n", netdev->name,
+ (dev_capa & DNET_HAS_MDIO) ? "" : "no ",
+ (dev_capa & DNET_HAS_IRQ) ? "" : "no ",
+ (dev_capa & DNET_HAS_GIGABIT) ? "" : "no ",
+ (dev_capa & DNET_HAS_DMA) ? "" : "no ");
+
+ eth_register(netdev);
+
+ return 0;
+}
diff --git a/drivers/net/dnet.h b/drivers/net/dnet.h
new file mode 100644
index 000000000..fdb4fd2d3
--- /dev/null
+++ b/drivers/net/dnet.h
@@ -0,0 +1,166 @@
+/*
+ * Dave Ethernet Controller driver
+ *
+ * Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DRIVERS_DNET_H__
+#define __DRIVERS_DNET_H__
+
+#define DRIVERNAME "dnet"
+
+struct dnet_registers {
+ /* ALL DNET FIFO REGISTERS */
+ u32 RX_LEN_FIFO;
+ u32 RX_DATA_FIFO;
+ u32 TX_LEN_FIFO;
+ u32 TX_DATA_FIFO;
+ u32 pad1[0x3c];
+ /* ALL DNET CONTROL/STATUS REGISTERS */
+ u32 VERCAPS;
+ u32 INTR_SRC;
+ u32 INTR_ENB;
+ u32 RX_STATUS;
+ u32 TX_STATUS;
+ u32 RX_FRAMES_CNT;
+ u32 TX_FRAMES_CNT;
+ u32 RX_FIFO_TH;
+ u32 TX_FIFO_TH;
+ u32 SYS_CTL;
+ u32 PAUSE_TMR;
+ u32 RX_FIFO_WCNT;
+ u32 TX_FIFO_WCNT;
+ u32 pad2[0x33];
+ /* ALL DNET MAC REGISTERS */
+ u32 MACREG_DATA; /* Mac-Reg Data */
+ u32 MACREG_ADDR; /* Mac-Reg Addr */
+ u32 pad3[0x3e];
+ /* ALL DNET RX STATISTICS COUNTERS */
+ u32 RX_PKT_IGNR_CNT;
+ u32 RX_LEN_CHK_ERR_CNT;
+ u32 RX_LNG_FRM_CNT;
+ u32 RX_SHRT_FRM_CNT;
+ u32 RX_IPG_VIOL_CNT;
+ u32 RX_CRC_ERR_CNT;
+ u32 RX_OK_PKT_CNT;
+ u32 RX_CTL_FRM_CNT;
+ u32 RX_PAUSE_FRM_CNT;
+ u32 RX_MULTICAST_CNT;
+ u32 RX_BROADCAST_CNT;
+ u32 RX_VLAN_TAG_CNT;
+ u32 RX_PRE_SHRINK_CNT;
+ u32 RX_DRIB_NIB_CNT;
+ u32 RX_UNSUP_OPCD_CNT;
+ u32 RX_BYTE_CNT;
+ u32 pad4[0x30];
+ /* DNET TX STATISTICS COUNTERS */
+ u32 TX_UNICAST_CNT;
+ u32 TX_PAUSE_FRM_CNT;
+ u32 TX_MULTICAST_CNT;
+ u32 TX_BRDCAST_CNT;
+ u32 TX_VLAN_TAG_CNT;
+ u32 TX_BAD_FCS_CNT;
+ u32 TX_JUMBO_CNT;
+ u32 TX_BYTE_CNT;
+};
+
+/* SOME INTERNAL MAC-CORE REGISTER */
+#define DNET_INTERNAL_MODE_REG 0x0
+#define DNET_INTERNAL_RXTX_CONTROL_REG 0x2
+#define DNET_INTERNAL_MAX_PKT_SIZE_REG 0x4
+#define DNET_INTERNAL_IGP_REG 0x8
+#define DNET_INTERNAL_MAC_ADDR_0_REG 0xa
+#define DNET_INTERNAL_MAC_ADDR_1_REG 0xc
+#define DNET_INTERNAL_MAC_ADDR_2_REG 0xe
+#define DNET_INTERNAL_TX_RX_STS_REG 0x12
+#define DNET_INTERNAL_GMII_MNG_CTL_REG 0x14
+#define DNET_INTERNAL_GMII_MNG_DAT_REG 0x16
+
+#define DNET_INTERNAL_GMII_MNG_CMD_FIN (1 << 14)
+
+#define DNET_INTERNAL_WRITE (1 << 31)
+
+/* MAC-CORE REGISTER FIELDS */
+
+/* MAC-CORE MODE REGISTER FIELDS */
+#define DNET_INTERNAL_MODE_GBITEN (1 << 0)
+#define DNET_INTERNAL_MODE_FCEN (1 << 1)
+#define DNET_INTERNAL_MODE_RXEN (1 << 2)
+#define DNET_INTERNAL_MODE_TXEN (1 << 3)
+
+/* MAC-CORE RXTX CONTROL REGISTER FIELDS */
+#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME (1 << 8)
+#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST (1 << 7)
+#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST (1 << 4)
+#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE (1 << 3)
+#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS (1 << 2)
+#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS (1 << 1)
+#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC (1 << 0)
+#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL (1 << 6)
+#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP (1 << 5)
+
+/* SYSTEM CONTROL REGISTER FIELDS */
+#define DNET_SYS_CTL_IGNORENEXTPKT (1 << 0)
+#define DNET_SYS_CTL_SENDPAUSE (1 << 2)
+#define DNET_SYS_CTL_RXFIFOFLUSH (1 << 3)
+#define DNET_SYS_CTL_TXFIFOFLUSH (1 << 4)
+
+/* TX STATUS REGISTER FIELDS */
+#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY (1 << 2)
+#define DNET_TX_STATUS_FIFO_ALMOST_FULL (1 << 1)
+
+/* INTERRUPT SOURCE REGISTER FIELDS */
+#define DNET_INTR_SRC_TX_PKTSENT (1 << 0)
+#define DNET_INTR_SRC_TX_FIFOAF (1 << 1)
+#define DNET_INTR_SRC_TX_FIFOAE (1 << 2)
+#define DNET_INTR_SRC_TX_DISCFRM (1 << 3)
+#define DNET_INTR_SRC_TX_FIFOFULL (1 << 4)
+#define DNET_INTR_SRC_RX_CMDFIFOAF (1 << 8)
+#define DNET_INTR_SRC_RX_CMDFIFOFF (1 << 9)
+#define DNET_INTR_SRC_RX_DATAFIFOFF (1 << 10)
+#define DNET_INTR_SRC_TX_SUMMARY (1 << 16)
+#define DNET_INTR_SRC_RX_SUMMARY (1 << 17)
+#define DNET_INTR_SRC_PHY (1 << 19)
+
+/* INTERRUPT ENABLE REGISTER FIELDS */
+#define DNET_INTR_ENB_TX_PKTSENT (1 << 0)
+#define DNET_INTR_ENB_TX_FIFOAF (1 << 1)
+#define DNET_INTR_ENB_TX_FIFOAE (1 << 2)
+#define DNET_INTR_ENB_TX_DISCFRM (1 << 3)
+#define DNET_INTR_ENB_TX_FIFOFULL (1 << 4)
+#define DNET_INTR_ENB_RX_PKTRDY (1 << 8)
+#define DNET_INTR_ENB_RX_FIFOAF (1 << 9)
+#define DNET_INTR_ENB_RX_FIFOERR (1 << 10)
+#define DNET_INTR_ENB_RX_ERROR (1 << 11)
+#define DNET_INTR_ENB_RX_FIFOFULL (1 << 12)
+#define DNET_INTR_ENB_RX_FIFOAE (1 << 13)
+#define DNET_INTR_ENB_TX_SUMMARY (1 << 16)
+#define DNET_INTR_ENB_RX_SUMMARY (1 << 17)
+#define DNET_INTR_ENB_GLOBAL_ENABLE (1 << 18)
+
+/*
+ * Capabilities. Used by the driver to know the capabilities that
+ * the ethernet controller inside the FPGA have.
+ */
+
+#define DNET_HAS_MDIO (1 << 0)
+#define DNET_HAS_IRQ (1 << 1)
+#define DNET_HAS_GIGABIT (1 << 2)
+#define DNET_HAS_DMA (1 << 3)
+
+#define DNET_HAS_MII (1 << 4) /* or GMII */
+#define DNET_HAS_RMII (1 << 5) /* or RGMII */
+
+#define DNET_CAPS_MASK 0xFFFF
+
+#define DNET_FIFO_SIZE 2048 /* 2K x 32 bit */
+#define DNET_FIFO_TX_DATA_AF_TH (DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */
+#define DNET_FIFO_TX_DATA_AE_TH (384)
+
+#define DNET_FIFO_RX_CMD_AF_TH (1 << 16) /* just one frame inside the FIFO */
+
+#endif
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 2dcaa2c91..a52749d78 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -82,6 +82,7 @@ static struct pci_device_id supported[] = {
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541ER},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541GI_LF},
+ {}
};
/* Function forward declarations */
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 98e8c73ca..af0409bd2 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -317,6 +317,30 @@ static void macb_phy_reset(struct macb_device *macb)
netdev->name, status);
}
+#ifdef CONFIG_MACB_SEARCH_PHY
+static int macb_phy_find(struct macb_device *macb)
+{
+ int i;
+ u16 phy_id;
+
+ /* Search for PHY... */
+ for (i = 0; i < 32; i++) {
+ macb->phy_addr = i;
+ phy_id = macb_mdio_read(macb, MII_PHYSID1);
+ if (phy_id != 0xffff) {
+ printf("%s: PHY present at %d\n", macb->netdev.name, i);
+ return 1;
+ }
+ }
+
+ /* PHY isn't up to snuff */
+ printf("%s: PHY not found", macb->netdev.name);
+
+ return 0;
+}
+#endif /* CONFIG_MACB_SEARCH_PHY */
+
+
static int macb_phy_init(struct macb_device *macb)
{
struct eth_device *netdev = &macb->netdev;
@@ -325,6 +349,13 @@ static int macb_phy_init(struct macb_device *macb)
int media, speed, duplex;
int i;
+#ifdef CONFIG_MACB_SEARCH_PHY
+ /* Auto-detect phy_addr */
+ if (!macb_phy_find(macb)) {
+ return 0;
+ }
+#endif /* CONFIG_MACB_SEARCH_PHY */
+
/* Check if the PHY is up to snuff... */
phy_id = macb_mdio_read(macb, MII_PHYSID1);
if (phy_id == 0xffff) {
diff --git a/drivers/net/mcfmii.c b/drivers/net/mcfmii.c
index 2b733c66e..4f1c0a012 100644
--- a/drivers/net/mcfmii.c
+++ b/drivers/net/mcfmii.c
@@ -226,7 +226,8 @@ void __mii_init(void)
volatile FEC_T *fecp;
struct eth_device *dev;
int miispd = 0, i = 0;
- u16 autoneg = 0;
+ u16 status = 0;
+ u16 linkgood = 0;
/* retrieve from register structure */
dev = eth_get_dev();
@@ -250,22 +251,32 @@ void __mii_init(void)
info->phy_addr = mii_discover_phy(dev);
-#define AUTONEGLINK (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)
while (i < MCFFEC_TOUT_LOOP) {
- autoneg = 0;
- miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &autoneg);
+ status = 0;
i++;
+ /* Read PHY control register */
+ miiphy_read(dev->name, info->phy_addr, PHY_BMCR, &status);
- if ((autoneg & AUTONEGLINK) == AUTONEGLINK)
+ /* If phy set to autonegotiate, wait for autonegotiation done,
+ * if phy is not autonegotiating, just wait for link up.
+ */
+ if ((status & PHY_BMCR_AUTON) == PHY_BMCR_AUTON) {
+ linkgood = (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS);
+ } else {
+ linkgood = PHY_BMSR_LS;
+ }
+ /* Read PHY status register */
+ miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &status);
+ if ((status & linkgood) == linkgood)
break;
udelay(500);
}
if (i >= MCFFEC_TOUT_LOOP) {
- printf("Auto Negotiation not complete\n");
+ printf("Link UP timeout\n");
}
- /* adapt to the half/full speed settings */
+ /* adapt to the duplex and speed settings of the phy */
info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16;
info->dup_spd |= miiphy_speed(dev->name, info->phy_addr);
}
diff --git a/drivers/net/mpc5xxx_fec.c b/drivers/net/mpc5xxx_fec.c
index f8618b172..2bf901e13 100644
--- a/drivers/net/mpc5xxx_fec.c
+++ b/drivers/net/mpc5xxx_fec.c
@@ -19,9 +19,6 @@ DECLARE_GLOBAL_DATA_PTR;
/* #define DEBUG 0x28 */
-#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
- defined(CONFIG_MPC5xxx_FEC)
-
#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif
@@ -891,28 +888,11 @@ int mpc5xxx_fec_initialize(bd_t * bis)
fec->eth = (ethernet_regs *)MPC5XXX_FEC;
fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
-#if defined(CONFIG_CANMB) || \
- defined(CONFIG_CM5200) || \
- defined(CONFIG_HMI1001) || \
- defined(CONFIG_ICECUBE) || \
- defined(CONFIG_INKA4X0) || \
- defined(CONFIG_JUPITER) || \
- defined(CONFIG_MCC200) || \
- defined(CONFIG_MOTIONPRO) || \
- defined(CONFIG_MUCMC52) || \
- defined(CONFIG_O2DNT) || \
- defined(CONFIG_PM520) || \
- defined(CONFIG_TOP5200) || \
- defined(CONFIG_TQM5200) || \
- defined(CONFIG_UC101) || \
- defined(CONFIG_V38B) || \
- defined(CONFIG_MUNICES)
-# ifndef CONFIG_FEC_10MBIT
+#if defined(CONFIG_MPC5xxx_FEC_MII100)
fec->xcv_type = MII100;
-# else
+#elif defined(CONFIG_MPC5xxx_FEC_MII10)
fec->xcv_type = MII10;
-# endif
-#elif defined(CONFIG_TOTAL5200)
+#elif defined(CONFIG_MPC5xxx_FEC_SEVENWIRE)
fec->xcv_type = SEVENWIRE;
#else
#error fec->xcv_type not initialized.
@@ -1064,5 +1044,3 @@ static uint32 local_crc32(char *string, unsigned int crc_value, int len)
/**/ return crc;
}
#endif /* DEBUG */
-
-#endif /* CONFIG_MPC5xxx_FEC */
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 9e3cf98b3..ebe858894 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -24,6 +24,7 @@
#include <common.h>
#include <malloc.h>
#include <net.h>
+#include <netdev.h>
#include <asm/errno.h>
#include <asm/io.h>
@@ -36,12 +37,7 @@
# error "Please define CONFIG_SH_ETHER_PHY_ADDR"
#endif
-extern int eth_init(bd_t *bd);
-extern void eth_halt(void);
-extern int eth_rx(void);
-extern int eth_send(volatile void *packet, int length);
-
-static struct dev_info_s *dev;
+#define SH_ETH_PHY_DELAY 50000
/*
* Bits are written to the PHY serially using the
@@ -89,7 +85,7 @@ static void sh_eth_mii_ind_bus_release(int port)
udelay(1);
}
-static int sh_eth_mii_read_phy_bits(int port, u32 * val, int len)
+static void sh_eth_mii_read_phy_bits(int port, u32 *val, int len)
{
int i;
u32 pir;
@@ -106,8 +102,6 @@ static int sh_eth_mii_read_phy_bits(int port, u32 * val, int len)
outl(0, PIR(port));
udelay(1);
}
-
- return 0;
}
#define PHY_INIT 0xFFFFFFFF
@@ -183,26 +177,23 @@ static void sh_eth_mii_write_phy_reg(int port, u8 phy_addr, int reg, u16 val)
sh_eth_mii_ind_bus_release(port);
}
-void eth_halt(void)
-{
-}
-
-int eth_send(volatile void *packet, int len)
+int sh_eth_send(struct eth_device *dev, volatile void *packet, int len)
{
- int port = dev->port;
- struct port_info_s *port_info = &dev->port_info[port];
- int timeout;
- int rc = 0;
+ struct sh_eth_dev *eth = dev->priv;
+ int port = eth->port, ret = 0, timeout;
+ struct sh_eth_info *port_info = &eth->port_info[port];
if (!packet || len > 0xffff) {
- printf("eth_send: Invalid argument\n");
- return -EINVAL;
+ printf(SHETHER_NAME ": %s: Invalid argument\n", __func__);
+ ret = -EINVAL;
+ goto err;
}
/* packet must be a 4 byte boundary */
if ((int)packet & (4 - 1)) {
- printf("eth_send: packet not 4 byte alligned\n");
- return -EFAULT;
+ printf(SHETHER_NAME ": %s: packet not 4 byte alligned\n", __func__);
+ ret = -EFAULT;
+ goto err;
}
/* Update tx descriptor */
@@ -224,24 +215,25 @@ int eth_send(volatile void *packet, int len)
udelay(100);
if (timeout < 0) {
- printf("eth_send: transmit timeout\n");
- rc = -1;
+ printf(SHETHER_NAME ": transmit timeout\n");
+ ret = -ETIMEDOUT;
goto err;
}
-err:
port_info->tx_desc_cur++;
if (port_info->tx_desc_cur >= port_info->tx_desc_base + NUM_TX_DESC)
port_info->tx_desc_cur = port_info->tx_desc_base;
- return rc;
+ return ret;
+err:
+ return ret;
}
-int eth_rx(void)
+int sh_eth_recv(struct eth_device *dev)
{
- int port = dev->port;
- struct port_info_s *port_info = &dev->port_info[port];
- int len = 0;
+ struct sh_eth_dev *eth = dev->priv;
+ int port = eth->port, len = 0;
+ struct sh_eth_info *port_info = &eth->port_info[port];
volatile u8 *packet;
/* Check if the rx descriptor is ready */
@@ -275,10 +267,10 @@ int eth_rx(void)
}
#define EDMR_INIT_CNT 1000
-static int sh_eth_reset(struct dev_info_s *dev)
+static int sh_eth_reset(struct sh_eth_dev *eth)
{
- int port = dev->port;
- int i;
+ int port = eth->port;
+ int ret = 0, i;
/* Start e-dmac transmitter and receiver */
outl(EDSR_ENALL, EDSR(port));
@@ -292,33 +284,36 @@ static int sh_eth_reset(struct dev_info_s *dev)
}
if (i == EDMR_INIT_CNT) {
- printf("Error: Software reset timeout\n");
- return -1;
+ printf(SHETHER_NAME ": Software reset timeout\n");
+ ret = -EIO;
}
- return 0;
+
+ return ret;
}
-static int sh_eth_tx_desc_init(struct dev_info_s *dev)
+static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
{
- int port = dev->port;
- struct port_info_s *port_info = &dev->port_info[port];
+ int port = eth->port, i, ret = 0;
u32 tmp_addr;
+ struct sh_eth_info *port_info = &eth->port_info[port];
struct tx_desc_s *cur_tx_desc;
- int i;
- /* Allocate tx descriptors. They must be TX_DESC_SIZE bytes
- aligned */
- if (!(port_info->tx_desc_malloc = malloc(NUM_TX_DESC *
+ /*
+ * Allocate tx descriptors. They must be TX_DESC_SIZE bytes aligned
+ */
+ port_info->tx_desc_malloc = malloc(NUM_TX_DESC *
sizeof(struct tx_desc_s) +
- TX_DESC_SIZE - 1))) {
- printf("Error: malloc failed\n");
- return -ENOMEM;
+ TX_DESC_SIZE - 1);
+ if (!port_info->tx_desc_malloc) {
+ printf(SHETHER_NAME ": malloc failed\n");
+ ret = -ENOMEM;
+ goto err;
}
+
tmp_addr = (u32) (((int)port_info->tx_desc_malloc + TX_DESC_SIZE - 1) &
~(TX_DESC_SIZE - 1));
/* Make sure we use a P2 address (non-cacheable) */
port_info->tx_desc_base = (struct tx_desc_s *)ADDR_TO_P2(tmp_addr);
-
port_info->tx_desc_cur = port_info->tx_desc_base;
/* Initialize all descriptors */
@@ -340,26 +335,30 @@ static int sh_eth_tx_desc_init(struct dev_info_s *dev)
outl(ADDR_TO_PHY(cur_tx_desc), TDFXR(port));
outl(0x01, TDFFR(port));/* Last discriptor bit */
- return 0;
+err:
+ return ret;
}
-static int sh_eth_rx_desc_init(struct dev_info_s *dev)
+static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
{
- int port = dev->port;
- struct port_info_s *port_info = &dev->port_info[port];
- u32 tmp_addr;
+ int port = eth->port, i , ret = 0;
+ struct sh_eth_info *port_info = &eth->port_info[port];
struct rx_desc_s *cur_rx_desc;
+ u32 tmp_addr;
u8 *rx_buf;
- int i;
- /* Allocate rx descriptors. They must be RX_DESC_SIZE bytes
- aligned */
- if (!(port_info->rx_desc_malloc = malloc(NUM_RX_DESC *
+ /*
+ * Allocate rx descriptors. They must be RX_DESC_SIZE bytes aligned
+ */
+ port_info->rx_desc_malloc = malloc(NUM_RX_DESC *
sizeof(struct rx_desc_s) +
- RX_DESC_SIZE - 1))) {
- printf("Error: malloc failed\n");
- return -ENOMEM;
+ RX_DESC_SIZE - 1);
+ if (!port_info->rx_desc_malloc) {
+ printf(SHETHER_NAME ": malloc failed\n");
+ ret = -ENOMEM;
+ goto err;
}
+
tmp_addr = (u32) (((int)port_info->rx_desc_malloc + RX_DESC_SIZE - 1) &
~(RX_DESC_SIZE - 1));
/* Make sure we use a P2 address (non-cacheable) */
@@ -367,15 +366,17 @@ static int sh_eth_rx_desc_init(struct dev_info_s *dev)
port_info->rx_desc_cur = port_info->rx_desc_base;
- /* Allocate rx data buffers. They must be 32 bytes aligned and in
- P2 area */
- if (!(port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE +
- 31))) {
- printf("Error: malloc failed\n");
- free(port_info->rx_desc_malloc);
- port_info->rx_desc_malloc = NULL;
- return -ENOMEM;
+ /*
+ * Allocate rx data buffers. They must be 32 bytes aligned and in
+ * P2 area
+ */
+ port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + 31);
+ if (!port_info->rx_buf_malloc) {
+ printf(SHETHER_NAME ": malloc failed\n");
+ ret = -ENOMEM;
+ goto err_buf_malloc;
}
+
tmp_addr = (u32)(((int)port_info->rx_buf_malloc + (32 - 1)) &
~(32 - 1));
port_info->rx_buf_base = (u8 *)ADDR_TO_P2(tmp_addr);
@@ -399,18 +400,31 @@ static int sh_eth_rx_desc_init(struct dev_info_s *dev)
outl(ADDR_TO_PHY(cur_rx_desc), RDFXR(port));
outl(RDFFR_RDLF, RDFFR(port));
- return 0;
+ return ret;
+
+err_buf_malloc:
+ free(port_info->rx_desc_malloc);
+ port_info->rx_desc_malloc = NULL;
+
+err:
+ return ret;
}
-static void sh_eth_desc_free(struct dev_info_s *dev)
+static void sh_eth_tx_desc_free(struct sh_eth_dev *eth)
{
- int port = dev->port;
- struct port_info_s *port_info = &dev->port_info[port];
+ int port = eth->port;
+ struct sh_eth_info *port_info = &eth->port_info[port];
if (port_info->tx_desc_malloc) {
free(port_info->tx_desc_malloc);
port_info->tx_desc_malloc = NULL;
}
+}
+
+static void sh_eth_rx_desc_free(struct sh_eth_dev *eth)
+{
+ int port = eth->port;
+ struct sh_eth_info *port_info = &eth->port_info[port];
if (port_info->rx_desc_malloc) {
free(port_info->rx_desc_malloc);
@@ -423,36 +437,48 @@ static void sh_eth_desc_free(struct dev_info_s *dev)
}
}
-static int sh_eth_desc_init(struct dev_info_s *dev)
+static int sh_eth_desc_init(struct sh_eth_dev *eth)
{
- int rc;
+ int ret = 0;
- if ((rc = sh_eth_tx_desc_init(dev)) || (rc = sh_eth_rx_desc_init(dev))) {
- sh_eth_desc_free(dev);
- return rc;
- }
+ ret = sh_eth_tx_desc_init(eth);
+ if (ret)
+ goto err_tx_init;
- return 0;
+ ret = sh_eth_rx_desc_init(eth);
+ if (ret)
+ goto err_rx_init;
+
+ return ret;
+err_rx_init:
+ sh_eth_tx_desc_free(eth);
+
+err_tx_init:
+ return ret;
}
-static int sh_eth_phy_config(struct dev_info_s *dev)
+static int sh_eth_phy_config(struct sh_eth_dev *eth)
{
- int port = dev->port;
- struct port_info_s *port_info = &dev->port_info[port];
- int timeout;
+ int port = eth->port, timeout, ret = 0;
+ struct sh_eth_info *port_info = &eth->port_info[port];
u32 val;
+
/* Reset phy */
- sh_eth_mii_write_phy_reg(port, port_info->phy_addr, PHY_CTRL, PHY_C_RESET);
+ sh_eth_mii_write_phy_reg
+ (port, port_info->phy_addr, PHY_CTRL, PHY_C_RESET);
timeout = 10;
while (timeout--) {
- val = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, PHY_CTRL);
+ val = sh_eth_mii_read_phy_reg(port,
+ port_info->phy_addr, PHY_CTRL);
if (!(val & PHY_C_RESET))
break;
- udelay(50000);
+ udelay(SH_ETH_PHY_DELAY);
}
+
if (timeout < 0) {
- printf("%s phy reset timeout\n", __func__);
- return -1;
+ printf(SHETHER_NAME ": phy reset timeout\n");
+ ret = -EIO;
+ goto err_tout;
}
/* Advertise 100/10 baseT full/half duplex */
@@ -467,23 +493,27 @@ static int sh_eth_phy_config(struct dev_info_s *dev)
val = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 1);
if (val & PHY_S_ANEGC)
break;
- udelay(50000);
+
+ udelay(SH_ETH_PHY_DELAY);
}
+
if (timeout < 0) {
- printf("sh_eth_phy_config() phy auto-negotiation failed\n");
- return -1;
+ printf(SHETHER_NAME ": phy auto-negotiation failed\n");
+ ret = -ETIMEDOUT;
+ goto err_tout;
}
- return 0;
+ return ret;
+
+err_tout:
+ return ret;
}
-static int sh_eth_config(struct dev_info_s *dev, bd_t * bd)
+static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
{
- int port = dev->port;
- struct port_info_s *port_info = &dev->port_info[port];
- u32 val;
- u32 phy_status;
- int rc;
+ int port = eth->port, ret = 0;
+ u32 val, phy_status;
+ struct sh_eth_info *port_info = &eth->port_info[port];
/* Configure e-dmac registers */
outl((inl(EDMR(port)) & ~EMDR_DESC_R) | EDMR_EL, EDMR(port));
@@ -513,20 +543,20 @@ static int sh_eth_config(struct dev_info_s *dev, bd_t * bd)
outl(TPAUSER_TPAUSE, TPAUSER(port));
/* Configure phy */
- if ((rc = sh_eth_phy_config(dev)))
- return rc;
-
+ ret = sh_eth_phy_config(eth);
+ if (ret) {
+ printf(SHETHER_NAME ":i phy config timeout\n");
+ goto err_phy_cfg;
+ }
/* Read phy status to finish configuring the e-mac */
- phy_status = sh_eth_mii_read_phy_reg(dev->port,
- dev->port_info[dev->port].phy_addr,
- 1);
+ phy_status = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 1);
/* Set the transfer speed */
if (phy_status & (PHY_S_100X_F|PHY_S_100X_H)) {
- printf("100Base/");
+ printf(SHETHER_NAME ": 100Base/");
outl(GECMR_100B, GECMR(port));
} else {
- printf("10Base/");
+ printf(SHETHER_NAME ": 10Base/");
outl(GECMR_10B, GECMR(port));
}
@@ -538,27 +568,34 @@ static int sh_eth_config(struct dev_info_s *dev, bd_t * bd)
printf("Half\n");
outl((ECMR_CHG_DM|ECMR_RE|ECMR_TE), ECMR(port));
}
- return 0;
+
+ return ret;
+
+err_phy_cfg:
+ return ret;
}
-static int sh_eth_start(struct dev_info_s *dev)
+static void sh_eth_start(struct sh_eth_dev *eth)
{
/*
* Enable the e-dmac receiver only. The transmitter will be enabled when
* we have something to transmit
*/
- outl(EDRRR_R, EDRRR(dev->port));
+ outl(EDRRR_R, EDRRR(eth->port));
+}
- return 0;
+static void sh_eth_stop(struct sh_eth_dev *eth)
+{
+ outl(~EDRRR_R, EDRRR(eth->port));
}
static int sh_eth_get_mac(bd_t *bd)
{
char *s, *e;
- int i;
s = getenv("ethaddr");
if (s != NULL) {
+ int i;
for (i = 0; i < 6; ++i) {
bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0;
if (s)
@@ -570,34 +607,92 @@ static int sh_eth_get_mac(bd_t *bd)
return 0;
}
-int eth_init(bd_t *bd)
+int sh_eth_init(struct eth_device *dev, bd_t *bd)
{
- int rc;
- /* Allocate main device information structure */
- if (!(dev = malloc(sizeof(*dev)))) {
- printf("eth_init: malloc failed\n");
- return -ENOMEM;
- }
+ int ret = 0;
+ struct sh_eth_dev *eth = dev->priv;
- memset(dev, 0, sizeof(*dev));
+ ret = sh_eth_reset(eth);
+ if (ret)
+ goto err;
- dev->port = CONFIG_SH_ETHER_USE_PORT;
- dev->port_info[dev->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR;
+ ret = sh_eth_desc_init(eth);
+ if (ret)
+ goto err;
- sh_eth_get_mac(bd);
+ ret = sh_eth_config(eth, bd);
+ if (ret)
+ goto err_config;
+
+ sh_eth_start(eth);
+
+ return ret;
- if ((rc = sh_eth_reset(dev)) || (rc = sh_eth_desc_init(dev)))
+err_config:
+ sh_eth_tx_desc_free(eth);
+ sh_eth_rx_desc_free(eth);
+
+err:
+ return ret;
+}
+
+void sh_eth_halt(struct eth_device *dev)
+{
+ struct sh_eth_dev *eth = dev->priv;
+
+ sh_eth_reset(eth);
+ sh_eth_stop(eth);
+}
+
+int sh_eth_initialize(bd_t *bd)
+{
+ int ret = 0;
+ struct sh_eth_dev *eth = NULL;
+ struct eth_device *dev = NULL;
+
+ eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev));
+ if (!eth) {
+ printf(SHETHER_NAME ": %s: malloc failed\n", __func__);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ dev = (struct eth_device *)malloc(sizeof(struct eth_device));
+ if (!dev) {
+ printf(SHETHER_NAME ": %s: malloc failed\n", __func__);
+ ret = -ENOMEM;
goto err;
+ }
+ memset(dev, 0, sizeof(struct eth_device));
+ memset(eth, 0, sizeof(struct sh_eth_dev));
- if ((rc = sh_eth_config(dev, bd)) || (rc = sh_eth_start(dev)))
- goto err_desc;
+ eth->port = CONFIG_SH_ETHER_USE_PORT;
+ eth->port_info[eth->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR;
- return 0;
+ dev->priv = (void *)eth;
+ dev->iobase = 0;
+ dev->init = sh_eth_init;
+ dev->halt = sh_eth_halt;
+ dev->send = sh_eth_send;
+ dev->recv = sh_eth_recv;
+ eth->port_info[eth->port].dev = dev;
+
+ sprintf(dev->name, SHETHER_NAME);
+
+ /* Register Device to EtherNet subsystem */
+ eth_register(dev);
+
+ sh_eth_get_mac(bd);
+
+ return ret;
-err_desc:
- sh_eth_desc_free(dev);
err:
- free(dev);
- printf("eth_init: Failed\n");
- return rc;
+ if (dev)
+ free(dev);
+
+ if (eth)
+ free(eth);
+
+ printf(SHETHER_NAME ": Failed\n");
+ return ret;
}
diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
index 9cf0ea0b9..e153849e3 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/sh_eth.h
@@ -20,6 +20,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <netdev.h>
#include <asm/types.h>
#define SHETHER_NAME "sh_eth"
@@ -48,7 +49,7 @@
#define TX_DESC_PADDING 4
#define TX_DESC_SIZE (12 + TX_DESC_PADDING)
-/* Tx descriptor. We always use 4 bytes of padding */
+/* Tx descriptor. We always use 3 bytes of padding */
struct tx_desc_s {
volatile u32 td0;
u32 td1;
@@ -72,7 +73,7 @@ struct rx_desc_s {
u32 padding;
};
-struct port_info_s {
+struct sh_eth_info {
struct tx_desc_s *tx_desc_malloc;
struct tx_desc_s *tx_desc_base;
struct tx_desc_s *tx_desc_cur;
@@ -83,11 +84,12 @@ struct port_info_s {
u8 *rx_buf_base;
u8 mac_addr[6];
u8 phy_addr;
+ struct eth_device *dev;
};
-struct dev_info_s {
+struct sh_eth_dev {
int port;
- struct port_info_s port_info[MAX_PORT_NUM];
+ struct sh_eth_info port_info[MAX_PORT_NUM];
};
/* Register Address */
@@ -166,7 +168,7 @@ enum DMAC_T_BIT {
/* GECMR */
enum GECMR_BIT {
- GECMR_1000B = 0x01, GECMR_100B = 0x40, GECMR_10B = 0x00,
+ GECMR_1000B = 0x01, GECMR_100B = 0x04, GECMR_10B = 0x00,
};
/* EDRRR*/
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 648c94cbb..9cc4fce00 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -34,21 +34,24 @@
#endif
#if defined (CONFIG_DRIVER_SMC911X_32_BIT)
-static inline u32 reg_read(u32 addr)
+static inline u32 __smc911x_reg_read(u32 addr)
{
return *(volatile u32*)addr;
}
-static inline void reg_write(u32 addr, u32 val)
+u32 smc911x_reg_read(u32 addr) __attribute__((weak, alias("__smc911x_reg_read")));
+
+static inline void __smc911x_reg_write(u32 addr, u32 val)
{
*(volatile u32*)addr = val;
}
+void smc911x_reg_write(u32 addr, u32 val) __attribute__((weak, alias("__smc911x_reg_write")));
#elif defined (CONFIG_DRIVER_SMC911X_16_BIT)
-static inline u32 reg_read(u32 addr)
+static inline u32 smc911x_reg_read(u32 addr)
{
volatile u16 *addr_16 = (u16 *)addr;
return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16));
}
-static inline void reg_write(u32 addr, u32 val)
+static inline void smc911x_reg_write(u32 addr, u32 val)
{
*(volatile u16*)addr = (u16)val;
*(volatile u16*)(addr + 2) = (u16)(val >> 16);
@@ -58,9 +61,9 @@ static inline void reg_write(u32 addr, u32 val)
#endif /* CONFIG_DRIVER_SMC911X_16_BIT */
u32 pkt_data_pull(u32 addr) \
- __attribute__ ((weak, alias ("reg_read")));
+ __attribute__ ((weak, alias ("smc911x_reg_read")));
void pkt_data_push(u32 addr, u32 val) \
- __attribute__ ((weak, alias ("reg_write")));
+ __attribute__ ((weak, alias ("smc911x_reg_write")));
#define mdelay(n) udelay((n)*1000)
@@ -381,6 +384,7 @@ void pkt_data_push(u32 addr, u32 val) \
#define CHIP_9116 0x116
#define CHIP_9117 0x117
#define CHIP_9118 0x118
+#define CHIP_9211 0x9211
#define CHIP_9215 0x115a
#define CHIP_9216 0x116a
#define CHIP_9217 0x117a
@@ -396,6 +400,7 @@ static const struct chip_id chip_ids[] = {
{ CHIP_9116, "LAN9116" },
{ CHIP_9117, "LAN9117" },
{ CHIP_9118, "LAN9118" },
+ { CHIP_9211, "LAN9211" },
{ CHIP_9215, "LAN9215" },
{ CHIP_9216, "LAN9216" },
{ CHIP_9217, "LAN9217" },
@@ -407,22 +412,22 @@ static const struct chip_id chip_ids[] = {
u32 smc911x_get_mac_csr(u8 reg)
{
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
;
- reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ smc911x_reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
;
- return reg_read(MAC_CSR_DATA);
+ return smc911x_reg_read(MAC_CSR_DATA);
}
void smc911x_set_mac_csr(u8 reg, u32 data)
{
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
;
- reg_write(MAC_CSR_DATA, data);
- reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ smc911x_reg_write(MAC_CSR_DATA, data);
+ smc911x_reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
;
}
@@ -496,10 +501,10 @@ static int smc911x_phy_reset(void)
{
u32 reg;
- reg = reg_read(PMT_CTRL);
+ reg = smc911x_reg_read(PMT_CTRL);
reg &= ~0xfffff030;
reg |= PMT_CTRL_PHY_RST;
- reg_write(PMT_CTRL, reg);
+ smc911x_reg_write(PMT_CTRL, reg);
mdelay(100);
@@ -541,13 +546,13 @@ static void smc911x_reset(void)
int timeout;
/* Take out of PM setting first */
- if (reg_read(PMT_CTRL) & PMT_CTRL_READY) {
+ if (smc911x_reg_read(PMT_CTRL) & PMT_CTRL_READY) {
/* Write to the bytetest will take out of powerdown */
- reg_write(BYTE_TEST, 0x0);
+ smc911x_reg_write(BYTE_TEST, 0x0);
timeout = 10;
- while (timeout-- && !(reg_read(PMT_CTRL) & PMT_CTRL_READY))
+ while (timeout-- && !(smc911x_reg_read(PMT_CTRL) & PMT_CTRL_READY))
udelay(10);
if (!timeout) {
printf(DRIVERNAME
@@ -557,12 +562,12 @@ static void smc911x_reset(void)
}
/* Disable interrupts */
- reg_write(INT_EN, 0);
+ smc911x_reg_write(INT_EN, 0);
- reg_write(HW_CFG, HW_CFG_SRST);
+ smc911x_reg_write(HW_CFG, HW_CFG_SRST);
timeout = 1000;
- while (timeout-- && reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)
+ while (timeout-- && smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)
udelay(10);
if (!timeout) {
@@ -572,23 +577,23 @@ static void smc911x_reset(void)
/* Reset the FIFO level and flow control settings */
smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN);
- reg_write(AFC_CFG, 0x0050287F);
+ smc911x_reg_write(AFC_CFG, 0x0050287F);
/* Set to LED outputs */
- reg_write(GPIO_CFG, 0x70070000);
+ smc911x_reg_write(GPIO_CFG, 0x70070000);
}
static void smc911x_enable(void)
{
/* Enable TX */
- reg_write(HW_CFG, 8 << 16 | HW_CFG_SF);
+ smc911x_reg_write(HW_CFG, 8 << 16 | HW_CFG_SF);
- reg_write(GPT_CFG, GPT_CFG_TIMER_EN | 10000);
+ smc911x_reg_write(GPT_CFG, GPT_CFG_TIMER_EN | 10000);
- reg_write(TX_CFG, TX_CFG_TX_ON);
+ smc911x_reg_write(TX_CFG, TX_CFG_TX_ON);
/* no padding to start of packets */
- reg_write(RX_CFG, 0);
+ smc911x_reg_write(RX_CFG, 0);
smc911x_set_mac_csr(MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS);
@@ -600,13 +605,13 @@ int eth_init(bd_t *bd)
printf(DRIVERNAME ": initializing\n");
- val = reg_read(BYTE_TEST);
+ val = smc911x_reg_read(BYTE_TEST);
if (val != 0x87654321) {
printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
goto err_out;
}
- val = reg_read(ID_REV) >> 16;
+ val = smc911x_reg_read(ID_REV) >> 16;
for (i = 0; chip_ids[i].id != 0; i++) {
if (chip_ids[i].id == val) break;
}
@@ -640,8 +645,8 @@ int eth_send(volatile void *packet, int length)
u32 tmplen;
u32 status;
- reg_write(TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | length);
- reg_write(TX_DATA_FIFO, length);
+ smc911x_reg_write(TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | length);
+ smc911x_reg_write(TX_DATA_FIFO, length);
tmplen = (length + 3) / 4;
@@ -649,12 +654,12 @@ int eth_send(volatile void *packet, int length)
pkt_data_push(TX_DATA_FIFO, *data++);
/* wait for transmission */
- while (!((reg_read(TX_FIFO_INF) & TX_FIFO_INF_TSUSED) >> 16));
+ while (!((smc911x_reg_read(TX_FIFO_INF) & TX_FIFO_INF_TSUSED) >> 16));
/* get status. Ignore 'no carrier' error, it has no meaning for
* full duplex operation
*/
- status = reg_read(TX_STATUS_FIFO) & (TX_STS_LOC | TX_STS_LATE_COLL |
+ status = smc911x_reg_read(TX_STATUS_FIFO) & (TX_STS_LOC | TX_STS_LATE_COLL |
TX_STS_MANY_COLL | TX_STS_MANY_DEFER | TX_STS_UNDERRUN);
if (!status)
@@ -681,11 +686,11 @@ int eth_rx(void)
u32 pktlen, tmplen;
u32 status;
- if ((reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) {
- status = reg_read(RX_STATUS_FIFO);
+ if ((smc911x_reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) {
+ status = smc911x_reg_read(RX_STATUS_FIFO);
pktlen = (status & RX_STS_PKT_LEN) >> 16;
- reg_write(RX_CFG, 0);
+ smc911x_reg_write(RX_CFG, 0);
tmplen = (pktlen + 2+ 3) / 4;
while (tmplen--)
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index fbc9a6dd0..9edba6a7b 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -158,6 +158,7 @@ int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
/* Reset the MAC */
priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
+ udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
@@ -1141,6 +1142,9 @@ struct phy_info phy_info_M88E1118 = {
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{0x16, 0x0002, NULL}, /* Change Page Number */
{0x15, 0x1070, NULL}, /* Delay RGMII TX and RX */
+ {0x16, 0x0003, NULL}, /* Change Page Number */
+ {0x10, 0x021e, NULL}, /* Adjust LED control */
+ {0x16, 0x0000, NULL}, /* Change Page Number */
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
@@ -1152,6 +1156,7 @@ struct phy_info phy_info_M88E1118 = {
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
+ {MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_88E1011_PHY_STATUS, miim_read,
&mii_parse_88E1011_psr},