Skip to content
Snippets Groups Projects
Commit cea655a2 authored by Wolfgang Denk's avatar Wolfgang Denk
Browse files

Add support for the second Ethernet interface for the 'PPChameleon' board.

parent a56bd922
Branches
Tags
No related merge requests found
......@@ -2,6 +2,9 @@
Changes since U-Boot 1.1.1:
======================================================================
* Add support for the second Ethernet interface for the 'PPChameleon'
board.
* Patch by Dave Peverley, 30 Apr 2004:
Add support for OMAP730 Perseus2 Development board
......
......@@ -86,17 +86,17 @@
#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || \
( defined(CONFIG_440) && !defined(CONFIG_NET_MULTI))
#if !defined(CONFIG_NET_MULTI) || !defined(CONFIG_405EP)
/* 405GP, 440 with !CONFIG_NET_MULTI. For 440 only EMAC0 is supported */
#define EMAC_NUM_DEV 1
#else
/* 440EP && CONFIG_NET_MULTI */
#define EMAC_NUM_DEV 2
#endif
#define EMAC_RESET_TIMEOUT 1000 /* 1000 ms reset timeout */
#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */
#define NUM_TX_BUFF 1
/* AS.HARNOIS
* Use PKTBUFSRX (include/net.h) instead of setting NUM_RX_BUFF again
* These both variables are used to define the same thing!
* #define NUM_RX_BUFF 4
*/
#define NUM_RX_BUFF PKTBUFSRX
/* Ethernet Transmit and Receive Buffers */
/* AS.HARNOIS
* In the same way ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from
......@@ -105,11 +105,9 @@
#define ENET_MAX_MTU PKTSIZE
#define ENET_MAX_MTU_ALIGNED PKTSIZE_ALIGN
static char *txbuf_ptr;
/* define the number of channels implemented */
#define EMAC_RXCHL 1
#define EMAC_TXCHL 1
#define EMAC_RXCHL EMAC_NUM_DEV
#define EMAC_TXCHL EMAC_NUM_DEV
/*-----------------------------------------------------------------------------+
* Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal
......@@ -118,92 +116,66 @@ static char *txbuf_ptr;
#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)
#define MAL_UIC_DEF (UIC_MAL_RXEOB | MAL_UIC_ERR)
#define EMAC_UIC_DEF UIC_ENET
#define EMAC_UIC_DEF1 UIC_ENET1
#define SEL_UIC_DEF(p) (p ? UIC_ENET1 : UIC_ENET )
/*-----------------------------------------------------------------------------+
* Global variables. TX and RX descriptors and buffers.
*-----------------------------------------------------------------------------*/
static volatile mal_desc_t *tx;
static volatile mal_desc_t *rx;
static mal_desc_t *alloc_tx_buf = NULL;
static mal_desc_t *alloc_rx_buf = NULL;
/* IER globals */
static unsigned long emac_ier;
static unsigned long mal_ier;
/* Statistic Areas */
#define MAX_ERR_LOG 10
struct emac_stats {
int data_len_err;
int rx_frames;
int rx;
int rx_prot_err;
};
static struct stats { /* Statistic Block */
struct emac_stats emac;
int int_err;
short tx_err_log[MAX_ERR_LOG];
short rx_err_log[MAX_ERR_LOG];
} stats;
static int first_init = 0;
static int tx_err_index = 0; /* Transmit Error Index for tx_err_log */
static int rx_err_index = 0; /* Receive Error Index for rx_err_log */
static int rx_slot = 0; /* MAL Receive Slot */
static int rx_i_index = 0; /* Receive Interrupt Queue Index */
static int rx_u_index = 0; /* Receive User Queue Index */
static int rx_ready[NUM_RX_BUFF]; /* Receive Ready Queue */
static int tx_slot = 0; /* MAL Transmit Slot */
static int tx_i_index = 0; /* Transmit Interrupt Queue Index */
static int tx_u_index = 0; /* Transmit User Queue Index */
static int tx_run[NUM_TX_BUFF]; /* Transmit Running Queue */
#undef INFO_405_ENET
#ifdef INFO_405_ENET
static int packetSent = 0;
static int packetReceived = 0;
static int packetHandled = 0;
#endif
static char emac_hwd_addr[ENET_ADDR_LENGTH];
static bd_t *bis_save = NULL; /* for eth_init upon mal error */
static uint32_t mal_ier;
static int is_receiving = 0; /* sync with eth interrupt */
static int print_speed = 1; /* print speed message upon start */
#if !defined(CONFIG_NET_MULTI)
struct eth_device *emac0_dev;
#endif
/*-----------------------------------------------------------------------------+
* Prototypes and externals.
*-----------------------------------------------------------------------------*/
static void enet_rcv (unsigned long malisr);
static int enetInt(void);
static void mal_err (unsigned long isr, unsigned long uic, unsigned long mal_def,
unsigned long mal_errr);
static void emac_err (unsigned long isr);
static void enet_rcv (struct eth_device *dev, unsigned long malisr);
int enetInt (struct eth_device *dev);
static void mal_err (struct eth_device *dev, unsigned long isr,
unsigned long uic, unsigned long maldef,
unsigned long mal_errr);
static void emac_err (struct eth_device *dev, unsigned long isr);
/*-----------------------------------------------------------------------------+
| ppc_405x_eth_halt
| Disable MAL channel, and EMACn
|
|
+-----------------------------------------------------------------------------*/
static void ppc_4xx_eth_halt (struct eth_device *dev)
{
mtdcr (malier, 0x00000000); /* disable mal interrupts */
out32 (EMAC_IER, 0x00000000); /* disable emac interrupts */
EMAC_405_HW_PST hw_p = dev->priv;
uint32_t failsafe = 10000;
/* 1st reset MAL */
mtdcr (malmcr, MAL_CR_MMSR);
mtdcr (malier, 0x00000000); /* disable mal interrupts */
out32 (EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
/* 1st reset MAL channel */
/* Note: writing a 0 to a channel has no effect */
mtdcr (maltxcarr, (MAL_CR_MMSR >> (hw_p->devnum * 2)));
mtdcr (malrxcarr, (MAL_CR_MMSR >> hw_p->devnum));
/* wait for reset */
while (mfdcr (malmcr) & MAL_CR_MMSR) {
};
while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) {
udelay (1000); /* Delay 1 MS so as not to hammer the register */
failsafe--;
if (failsafe == 0)
break;
}
/* EMAC RESET */
out32 (EMAC_M0, EMAC_M0_SRST);
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
print_speed = 1; /* print speed message again next time */
}
hw_p->print_speed = 1; /* print speed message again next time */
return;
}
static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
{
......@@ -212,63 +184,108 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
unsigned long msr;
unsigned long speed;
unsigned long duplex;
unsigned long failsafe;
unsigned mode_reg;
unsigned short devnum;
unsigned short reg_short;
EMAC_405_HW_PST hw_p = dev->priv;
/* before doing anything, figure out if we have a MAC address */
/* if not, bail */
if (memcmp (dev->enetaddr, "\0\0\0\0\0\0", 6) == 0)
return -1;
msr = mfmsr ();
mtmsr (msr & ~(MSR_EE)); /* disable interrupts */
devnum = hw_p->devnum;
#ifdef INFO_405_ENET
/* AS.HARNOIS
* We should have :
* packetHandled <= packetReceived <= packetHandled+PKTBUFSRX
* In the most cases packetHandled = packetReceived, but it
* hw_p->stats.pkts_handled <= hw_p->stats.pkts_rx <= hw_p->stats.pkts_handled+PKTBUFSRX
* In the most cases hw_p->stats.pkts_handled = hw_p->stats.pkts_rx, but it
* is possible that new packets (without relationship with
* current transfer) have got the time to arrived before
* netloop calls eth_halt
*/
printf ("About preceeding transfer:\n"
printf ("About preceeding transfer (eth%d):\n"
"- Sent packet number %d\n"
"- Received packet number %d\n"
"- Handled packet number %d\n",
packetSent, packetReceived, packetHandled);
packetSent = 0;
packetReceived = 0;
packetHandled = 0;
hw_p->devnum,
hw_p->stats.pkts_tx,
hw_p->stats.pkts_rx, hw_p->stats.pkts_handled);
hw_p->stats.pkts_tx = 0;
hw_p->stats.pkts_rx = 0;
hw_p->stats.pkts_handled = 0;
#endif
/* MAL RESET */
mtdcr (malmcr, MAL_CR_MMSR);
mtdcr (malmcr, MAL_CR_MMSR);
/* wait for reset */
while (mfdcr (malmcr) & MAL_CR_MMSR) {
};
#if defined(CONFIG_440)
/* set RMII mode */
out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
#endif /* CONFIG_440 */
/* MAL Channel RESET */
/* 1st reset MAL channel */
/* Note: writing a 0 to a channel has no effect */
mtdcr (maltxcarr, (MAL_TXRX_CASR >> (hw_p->devnum * 2)));
mtdcr (malrxcarr, (MAL_TXRX_CASR >> hw_p->devnum));
/* wait for reset */
/* TBS: should have udelay and failsafe here */
failsafe = 10000;
/* wait for reset */
while (mfdcr (malmcr) & MAL_CR_MMSR) {
};
while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) {
udelay (1000); /* Delay 1 MS so as not to hammer the register */
failsafe--;
if (failsafe == 0)
break;
tx_err_index = 0; /* Transmit Error Index for tx_err_log */
rx_err_index = 0; /* Receive Error Index for rx_err_log */
}
rx_slot = 0; /* MAL Receive Slot */
rx_i_index = 0; /* Receive Interrupt Queue Index */
rx_u_index = 0; /* Receive User Queue Index */
hw_p->tx_err_index = 0; /* Transmit Error Index for tx_err_log */
hw_p->rx_err_index = 0; /* Receive Error Index for rx_err_log */
tx_slot = 0; /* MAL Transmit Slot */
tx_i_index = 0; /* Transmit Interrupt Queue Index */
tx_u_index = 0; /* Transmit User Queue Index */
hw_p->rx_slot = 0; /* MAL Receive Slot */
hw_p->rx_i_index = 0; /* Receive Interrupt Queue Index */
hw_p->rx_u_index = 0; /* Receive User Queue Index */
#if defined(CONFIG_440)
/* set RMII mode */
out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
#endif /* CONFIG_440 */
hw_p->tx_slot = 0; /* MAL Transmit Slot */
hw_p->tx_i_index = 0; /* Transmit Interrupt Queue Index */
hw_p->tx_u_index = 0; /* Transmit User Queue Index */
/* EMAC RESET */
out32 (EMAC_M0, EMAC_M0_SRST);
__asm__ volatile ("eieio");
/* reset emac so we have access to the phy */
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
__asm__ volatile ("eieio");
failsafe = 1000;
while ((in32 (EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
udelay (1000);
failsafe--;
}
#if defined(CONFIG_NET_MULTI)
reg = hw_p->devnum ? CONFIG_PHY1_ADDR : CONFIG_PHY_ADDR;
#else
reg = CONFIG_PHY_ADDR;
#endif
/* wait for PHY to complete auto negotiation */
reg_short = 0;
#ifndef CONFIG_CS8952_PHY
miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, &reg_short);
miiphy_read (reg, PHY_BMSR, &reg_short);
/*
* Wait if PHY is able of autonegotiation and autonegotiation is not complete
* Wait if PHY is capable of autonegotiation and autonegotiation is not complete
*/
if ((reg_short & PHY_BMSR_AUTN_ABLE)
&& !(reg_short & PHY_BMSR_AUTN_COMP)) {
......@@ -283,36 +300,39 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
break;
}
if ((i++ % 1000) == 0)
if ((i++ % 1000) == 0) {
putc ('.');
}
udelay (1000); /* 1 ms */
miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, &reg_short);
miiphy_read (reg, PHY_BMSR, &reg_short);
}
puts (" done\n");
udelay (500000); /* another 500 ms (results in faster booting) */
}
#endif
speed = miiphy_speed (CONFIG_PHY_ADDR);
duplex = miiphy_duplex (CONFIG_PHY_ADDR);
if (print_speed) {
print_speed = 0;
speed = miiphy_speed (reg);
duplex = miiphy_duplex (reg);
if (hw_p->print_speed) {
hw_p->print_speed = 0;
printf ("ENET Speed is %d Mbps - %s duplex connection\n",
(int) speed, (duplex == HALF) ? "HALF" : "FULL");
}
/* set the Mal configuration reg */
#if defined(CONFIG_440)
/* Errata 1.12: MAL_1 -- Disable MAL bursting */
if( get_pvr() == PVR_440GP_RB )
mtdcr (malmcr, MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
if( get_pvr() == PVR_440GP_RB)
mtdcr (malmcr, MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
else
#else
mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
#endif
/* Free "old" buffers */
if (alloc_tx_buf) free(alloc_tx_buf);
if (alloc_rx_buf) free(alloc_rx_buf);
if (hw_p->alloc_tx_buf)
free (hw_p->alloc_tx_buf);
if (hw_p->alloc_rx_buf)
free (hw_p->alloc_rx_buf);
/*
* Malloc MAL buffer desciptors, make sure they are
......@@ -320,93 +340,108 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
* (401/403/IOP480 = 16, 405 = 32)
* and doesn't cross cache block boundaries.
*/
alloc_tx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_TX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
if (((int)alloc_tx_buf & CACHELINE_MASK) != 0) {
tx = (mal_desc_t *)((int)alloc_tx_buf + CFG_CACHELINE_SIZE -
((int)alloc_tx_buf & CACHELINE_MASK));
hw_p->alloc_tx_buf =
(mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_TX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
if (((int) hw_p->alloc_tx_buf & CACHELINE_MASK) != 0) {
hw_p->tx =
(mal_desc_t *) ((int) hw_p->alloc_tx_buf +
CFG_CACHELINE_SIZE -
((int) hw_p->
alloc_tx_buf & CACHELINE_MASK));
} else {
tx = alloc_tx_buf;
hw_p->tx = hw_p->alloc_tx_buf;
}
alloc_rx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_RX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
if (((int)alloc_rx_buf & CACHELINE_MASK) != 0) {
rx = (mal_desc_t *)((int)alloc_rx_buf + CFG_CACHELINE_SIZE -
((int)alloc_rx_buf & CACHELINE_MASK));
hw_p->alloc_rx_buf =
(mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_RX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
if (((int) hw_p->alloc_rx_buf & CACHELINE_MASK) != 0) {
hw_p->rx =
(mal_desc_t *) ((int) hw_p->alloc_rx_buf +
CFG_CACHELINE_SIZE -
((int) hw_p->
alloc_rx_buf & CACHELINE_MASK));
} else {
rx = alloc_rx_buf;
hw_p->rx = hw_p->alloc_rx_buf;
}
for (i = 0; i < NUM_TX_BUFF; i++) {
tx[i].ctrl = 0;
tx[i].data_len = 0;
if (first_init == 0)
txbuf_ptr = (char *) malloc (ENET_MAX_MTU_ALIGNED);
tx[i].data_ptr = txbuf_ptr;
hw_p->tx[i].ctrl = 0;
hw_p->tx[i].data_len = 0;
if (hw_p->first_init == 0)
hw_p->txbuf_ptr =
(char *) malloc (ENET_MAX_MTU_ALIGNED);
hw_p->tx[i].data_ptr = hw_p->txbuf_ptr;
if ((NUM_TX_BUFF - 1) == i)
tx[i].ctrl |= MAL_TX_CTRL_WRAP;
tx_run[i] = -1;
hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP;
hw_p->tx_run[i] = -1;
#if 0
printf ("TX_BUFF %d @ 0x%08lx\n", i, (ulong) tx[i].data_ptr);
printf ("TX_BUFF %d @ 0x%08lx\n", i,
(ulong) hw_p->tx[i].data_ptr);
#endif
}
for (i = 0; i < NUM_RX_BUFF; i++) {
rx[i].ctrl = 0;
rx[i].data_len = 0;
hw_p->rx[i].ctrl = 0;
hw_p->rx[i].data_len = 0;
/* rx[i].data_ptr = (char *) &rx_buff[i]; */
rx[i].data_ptr = (char *) NetRxPackets[i];
hw_p->rx[i].data_ptr = (char *) NetRxPackets[i];
if ((NUM_RX_BUFF - 1) == i)
rx[i].ctrl |= MAL_RX_CTRL_WRAP;
rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR;
rx_ready[i] = -1;
hw_p->rx[i].ctrl |= MAL_RX_CTRL_WRAP;
hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR;
hw_p->rx_ready[i] = -1;
#if 0
printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) rx[i].data_ptr);
#endif
}
memcpy (emac_hwd_addr, bis->bi_enetaddr, ENET_ADDR_LENGTH);
reg = 0x00000000;
reg |= emac_hwd_addr[0]; /* set high address */
reg |= dev->enetaddr[0]; /* set high address */
reg = reg << 8;
reg |= emac_hwd_addr[1];
reg |= dev->enetaddr[1];
out32 (EMAC_IAH, reg);
out32 (EMAC_IAH + hw_p->hw_addr, reg);
reg = 0x00000000;
reg |= emac_hwd_addr[2]; /* set low address */
reg |= dev->enetaddr[2]; /* set low address */
reg = reg << 8;
reg |= emac_hwd_addr[3];
reg |= dev->enetaddr[3];
reg = reg << 8;
reg |= emac_hwd_addr[4];
reg |= dev->enetaddr[4];
reg = reg << 8;
reg |= emac_hwd_addr[5];
out32 (EMAC_IAL, reg);
/* setup MAL tx & rx channel pointers */
mtdcr (maltxctp0r, tx);
mtdcr (malrxctp0r, rx);
/* Reset transmit and receive channels */
mtdcr (malrxcarr, 0x80000000); /* 2 channels */
mtdcr (maltxcarr, 0x80000000); /* 2 channels */
reg |= dev->enetaddr[5];
out32 (EMAC_IAL + hw_p->hw_addr, reg);
switch (devnum) {
case 1:
/* setup MAL tx & rx channel pointers */
/* For 405EP, the EMAC1 tx channel 0 is MAL tx channel 2 */
mtdcr (maltxctp2r, hw_p->tx);
mtdcr (malrxctp1r, hw_p->rx);
/* set RX buffer size */
mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
break;
case 0:
default:
/* setup MAL tx & rx channel pointers */
mtdcr (maltxctp0r, hw_p->tx);
mtdcr (malrxctp0r, hw_p->rx);
/* set RX buffer size */
mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
break;
}
/* Enable MAL transmit and receive channels */
mtdcr (maltxcasr, 0x80000000); /* 1 channel */
mtdcr (malrxcasr, 0x80000000); /* 1 channel */
/* set RX buffer size */
mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
mtdcr (maltxcasr, (MAL_TXRX_CASR >> (hw_p->devnum * 2)));
mtdcr (malrxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
/* set transmit enable & receive enable */
out32 (EMAC_M0, EMAC_M0_TXE | EMAC_M0_RXE);
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE);
/* set receive fifo to 4k and tx fifo to 2k */
mode_reg = EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;
mode_reg = in32 (EMAC_M1 + hw_p->hw_addr);
mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;
/* set speed */
if (speed == _100BASET)
......@@ -416,7 +451,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
if (duplex == FULL)
mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST;
out32 (EMAC_M1, mode_reg);
out32 (EMAC_M1 + hw_p->hw_addr, mode_reg);
#if defined(CONFIG_440)
/* set speed in the ZMII bridge */
......@@ -427,67 +462,53 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
#endif
/* Enable broadcast and indvidual address */
out32 (EMAC_RXM, EMAC_RMR_BAE | EMAC_RMR_IAE
/*| EMAC_RMR_ARRP| EMAC_RMR_SFCS | EMAC_RMR_SP */ );
/* TBS: enabling runts as some misbehaved nics will send runts */
out32 (EMAC_RXM + hw_p->hw_addr, EMAC_RMR_BAE | EMAC_RMR_IAE);
/* we probably need to set the tx mode1 reg? maybe at tx time */
/* set transmit request threshold register */
out32 (EMAC_TRTR, 0x18000000); /* 256 byte threshold */
out32 (EMAC_TRTR + hw_p->hw_addr, 0x18000000); /* 256 byte threshold */
/* set receive low/high water mark register */
#if defined(CONFIG_440)
/* 440GP has a 64 byte burst length */
out32 (EMAC_RX_HI_LO_WMARK, 0x80009000);
out32 (EMAC_TXM1, 0xf8640000);
#else /* CONFIG_440 */
out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000);
out32 (EMAC_TXM1 + hw_p->hw_addr, 0xf8640000);
#else
/* 405s have a 16 byte burst length */
out32 (EMAC_RX_HI_LO_WMARK, 0x0f002000);
#endif /* CONFIG_440 */
out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000);
#endif
/* Frame gap set */
out32 (EMAC_I_FRAME_GAP_REG, 0x00000008);
out32 (EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008);
/* Set EMAC IER */
hw_p->emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS |
EMAC_ISR_ORE | EMAC_ISR_IRE;
if (speed == _100BASET)
hw_p->emac_ier = hw_p->emac_ier | EMAC_ISR_SYE;
out32 (EMAC_ISR + hw_p->hw_addr, 0xffffffff); /* clear pending interrupts */
out32 (EMAC_IER + hw_p->hw_addr, hw_p->emac_ier);
if (first_init == 0) {
if (hw_p->first_init == 0) {
/*
* Connect interrupt service routines
*/
irq_install_handler (VECNUM_EWU0, (interrupt_handler_t *) enetInt, NULL);
irq_install_handler (VECNUM_MS, (interrupt_handler_t *) enetInt, NULL);
irq_install_handler (VECNUM_MTE, (interrupt_handler_t *) enetInt, NULL);
irq_install_handler (VECNUM_MRE, (interrupt_handler_t *) enetInt, NULL);
irq_install_handler (VECNUM_TXDE, (interrupt_handler_t *) enetInt, NULL);
irq_install_handler (VECNUM_RXDE, (interrupt_handler_t *) enetInt, NULL);
irq_install_handler (VECNUM_ETH0, (interrupt_handler_t *) enetInt, NULL);
#if !defined(CONFIG_405EP)
/* 405EP has one EWU interrupt */
irq_install_handler (VECNUM_EWU0 + (hw_p->devnum * 2),
(interrupt_handler_t *) enetInt, dev);
#endif
irq_install_handler (VECNUM_ETH0 + (hw_p->devnum * 2),
(interrupt_handler_t *) enetInt, dev);
}
/* set up interrupt handler */
/* setup interrupt controler to take interrupts from the MAL &
EMAC */
mtdcr (uicsr, 0xffffffff); /* clear pending interrupts */
mtdcr (uicer, mfdcr (uicer) | MAL_UIC_DEF | EMAC_UIC_DEF);
/* set the MAL IER ??? names may change with new spec ??? */
mal_ier = MAL_IER_DE | MAL_IER_NE | MAL_IER_TE | MAL_IER_OPBE |
MAL_IER_PLBE;
mtdcr (malesr, 0xffffffff); /* clear pending interrupts */
mtdcr (maltxdeir, 0xffffffff); /* clear pending interrupts */
mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */
mtdcr (malier, mal_ier);
/* Set EMAC IER */
emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS |
EMAC_ISR_PTLE | EMAC_ISR_ORE | EMAC_ISR_IRE;
if (speed == _100BASET)
emac_ier = emac_ier | EMAC_ISR_SYE;
out32 (EMAC_ISR, 0xffffffff); /* clear pending interrupts */
out32 (EMAC_IER, emac_ier);
mtmsr (msr); /* enable interrupts again */
mtmsr (msr); /* enable interrupts again */
bis_save = bis;
first_init = 1;
hw_p->bis = bis;
hw_p->first_init = 1;
return (1);
}
......@@ -498,39 +519,43 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, int len
struct enet_frame *ef_ptr;
ulong time_start, time_now;
unsigned long temp_txm0;
EMAC_405_HW_PST hw_p = dev->priv;
ef_ptr = (struct enet_frame *) ptr;
/*-----------------------------------------------------------------------+
* Copy in our address into the frame.
*-----------------------------------------------------------------------*/
(void) memcpy (ef_ptr->source_addr, emac_hwd_addr, ENET_ADDR_LENGTH);
(void) memcpy (ef_ptr->source_addr, dev->enetaddr, ENET_ADDR_LENGTH);
/*-----------------------------------------------------------------------+
* If frame is too long or too short, modify length.
*-----------------------------------------------------------------------*/
/* TBS: where does the fragment go???? */
if (len > ENET_MAX_MTU)
len = ENET_MAX_MTU;
/* memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */
memcpy ((void *) txbuf_ptr, (const void *) ptr, len);
memcpy ((void *) hw_p->txbuf_ptr, (const void *) ptr, len);
/*-----------------------------------------------------------------------+
* set TX Buffer busy, and send it
*-----------------------------------------------------------------------*/
tx[tx_slot].ctrl = (MAL_TX_CTRL_LAST |
EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) &
hw_p->tx[hw_p->tx_slot].ctrl = (MAL_TX_CTRL_LAST |
EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) &
~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA);
if ((NUM_TX_BUFF - 1) == tx_slot)
tx[tx_slot].ctrl |= MAL_TX_CTRL_WRAP;
if ((NUM_TX_BUFF - 1) == hw_p->tx_slot)
hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_WRAP;
hw_p->tx[hw_p->tx_slot].data_len = (short) len;
hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY;
tx[tx_slot].data_len = (short) len;
tx[tx_slot].ctrl |= MAL_TX_CTRL_READY;
__asm__ volatile ("eieio");
__asm__ volatile ("eieio");
out32 (EMAC_TXM0, in32 (EMAC_TXM0) | EMAC_TXM0_GNP0);
out32 (EMAC_TXM0 + hw_p->hw_addr,
in32 (EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
#ifdef INFO_405_ENET
packetSent++;
hw_p->stats.pkts_tx++;
#endif
/*-----------------------------------------------------------------------+
......@@ -538,7 +563,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, int len
*-----------------------------------------------------------------------*/
time_start = get_timer (0);
while (1) {
temp_txm0 = in32 (EMAC_TXM0);
temp_txm0 = in32 (EMAC_TXM0 + hw_p->hw_addr);
/* loop until either TINT turns on or 3 seconds elapse */
if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) {
/* transmit is done, so now check for errors
......@@ -555,15 +580,8 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, int len
}
}
#if defined(CONFIG_440)
/*-----------------------------------------------------------------------------+
| EnetInt.
| EnetInt is the interrupt handler. It will determine the
| cause of the interrupt and call the apporpriate servive
| routine.
+-----------------------------------------------------------------------------*/
int enetInt ()
int enetInt (struct eth_device *dev)
{
int serviced;
int rc = -1; /* default to not us */
......@@ -571,6 +589,18 @@ int enetInt ()
unsigned long emac_isr = 0;
unsigned long mal_rx_eob;
unsigned long my_uic0msr, my_uic1msr;
EMAC_405_HW_PST hw_p;
/*
* Because the mal is generic, we need to get the current
* eth device
*/
#if defined(CONFIG_NET_MULTI)
dev = eth_get_dev();
#else
dev = emac0_dev;
#endif
hw_p = dev->priv;
/* enter loop that stays in interrupt code until nothing to service */
do {
......@@ -593,20 +623,20 @@ int enetInt ()
mal_isr = mfdcr (malesr);
/* look for mal error */
if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) {
mal_err (mal_isr, my_uic0msr, MAL_UIC_DEF, MAL_UIC_ERR);
mal_err (dev, mal_isr, my_uic0msr, MAL_UIC_DEF, MAL_UIC_ERR);
serviced = 1;
rc = 0;
}
}
if (UIC_ETH0 & my_uic1msr) { /* look for EMAC errors */
emac_isr = in32 (EMAC_ISR);
if ((emac_ier & emac_isr) != 0) {
emac_err (emac_isr);
emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
if ((hw_p->emac_ier & emac_isr) != 0) {
emac_err (dev, emac_isr);
serviced = 1;
rc = 0;
}
}
if ((emac_ier & emac_isr)
if ((hw_p->emac_ier & emac_isr)
|| (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
mtdcr (uic0sr, UIC_MRE); /* Clear */
mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
......@@ -617,10 +647,10 @@ int enetInt ()
/* check for EOB on valid channels */
if (my_uic0msr & UIC_MRE) {
mal_rx_eob = mfdcr (malrxeobisr);
if ((mal_rx_eob & 0x80000000) != 0) { /* call emac routine for channel 0 */
if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel 0 */
/* clear EOB
mtdcr(malrxeobisr, mal_rx_eob); */
enet_rcv (emac_isr);
enet_rcv (dev, emac_isr);
/* indicate that we serviced an interrupt */
serviced = 1;
rc = 0;
......@@ -632,187 +662,206 @@ int enetInt ()
return (rc);
}
#else /* CONFIG_440 */
/*-----------------------------------------------------------------------------+
* EnetInt.
* EnetInt is the interrupt handler. It will determine the
* cause of the interrupt and call the apporpriate servive
* routine.
*-----------------------------------------------------------------------------*/
int enetInt ()
int enetInt (struct eth_device *dev)
{
int serviced;
int rc = -1; /* default to not us */
int rc = -1; /* default to not us */
unsigned long mal_isr;
unsigned long emac_isr = 0;
unsigned long mal_rx_eob;
unsigned long my_uicmsr;
EMAC_405_HW_PST hw_p;
/*
* Because the mal is generic, we need to get the current
* eth device
*/
#if defined(CONFIG_NET_MULTI)
dev = eth_get_dev();
#else
dev = emac0_dev;
#endif
hw_p = dev->priv;
/* enter loop that stays in interrupt code until nothing to service */
do {
serviced = 0;
my_uicmsr = mfdcr (uicmsr);
if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) { /* not for us */
return (rc);
}
/* get and clear controller status interrupts */
/* look at Mal and EMAC interrupts */
if ((MAL_UIC_DEF & my_uicmsr) != 0) { /* we have a MAL interrupt */
mal_isr = mfdcr (malesr);
/* look for mal error */
if ((my_uicmsr & MAL_UIC_ERR) != 0) {
mal_err (mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
mal_err (dev, mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
serviced = 1;
rc = 0;
}
}
if ((EMAC_UIC_DEF & my_uicmsr) != 0) { /* look for EMAC errors */
emac_isr = in32 (EMAC_ISR);
if ((emac_ier & emac_isr) != 0) {
emac_err (emac_isr);
/* port by port dispatch of emac interrupts */
if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) { /* look for EMAC errors */
emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
if ((hw_p->emac_ier & emac_isr) != 0) {
emac_err (dev, emac_isr);
serviced = 1;
rc = 0;
}
}
if (((emac_ier & emac_isr) != 0) | ((MAL_UIC_ERR & my_uicmsr) != 0)) {
mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */
if (((hw_p->emac_ier & emac_isr) != 0) || ((MAL_UIC_ERR & my_uicmsr) != 0)) {
mtdcr (uicsr, MAL_UIC_DEF | SEL_UIC_DEF(hw_p->devnum)); /* Clear */
return (rc); /* we had errors so get out */
}
/* handle MAX TX EOB interrupt from a tx */
if (my_uicmsr & UIC_MAL_TXEOB) {
mal_rx_eob = mfdcr (maltxeobisr);
mtdcr (maltxeobisr, mal_rx_eob);
mtdcr (uicsr, UIC_MAL_TXEOB);
}
/* handle MAL RX EOB interupt from a receive */
/* check for EOB on valid channels */
if ((my_uicmsr & UIC_MAL_RXEOB) != 0) {
/* check for EOB on valid channels */
if (my_uicmsr & UIC_MAL_RXEOB)
{
mal_rx_eob = mfdcr (malrxeobisr);
if ((mal_rx_eob & 0x80000000) != 0) { /* call emac routine for channel 0 */
if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
/* clear EOB
mtdcr(malrxeobisr, mal_rx_eob); */
enet_rcv (emac_isr);
mtdcr(malrxeobisr, mal_rx_eob); */
enet_rcv (dev, emac_isr);
/* indicate that we serviced an interrupt */
serviced = 1;
rc = 0;
}
}
mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */
mtdcr (uicsr, MAL_UIC_DEF|EMAC_UIC_DEF|EMAC_UIC_DEF1); /* Clear */
}
while (serviced);
return (rc);
}
#endif /* CONFIG_440 */
#endif
/*-----------------------------------------------------------------------------+
* MAL Error Routine
*-----------------------------------------------------------------------------*/
static void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef,
unsigned long mal_errr)
static void mal_err (struct eth_device *dev, unsigned long isr,
unsigned long uic, unsigned long maldef,
unsigned long mal_errr)
{
mtdcr (malesr, isr); /* clear interrupt */
EMAC_405_HW_PST hw_p = dev->priv;
mtdcr (malesr, isr); /* clear interrupt */
/* clear DE interrupt */
mtdcr (maltxdeir, 0xC0000000);
mtdcr (malrxdeir, 0x80000000);
#ifdef INFO_405_ENET
printf ("\nMAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n",
isr, uic, maldef, mal_errr);
#else
#if 0
/*
* MAL error is RX DE error (out of rx buffers)! This is OK here, upon
* many incoming packets with only 4 rx buffers.
*/
printf ("M"); /* just to see something upon mal error */
#endif
printf ("\nMAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n", isr, uic, maldef, mal_errr);
#endif
eth_init (bis_save); /* start again... */
eth_init (hw_p->bis); /* start again... */
}
/*-----------------------------------------------------------------------------+
* EMAC Error Routine
*-----------------------------------------------------------------------------*/
static void emac_err (unsigned long isr)
static void emac_err (struct eth_device *dev, unsigned long isr)
{
printf ("EMAC error occured.... ISR = %lx\n", isr);
out32 (EMAC_ISR, isr);
EMAC_405_HW_PST hw_p = dev->priv;
printf ("EMAC%d error occured.... ISR = %lx\n", hw_p->devnum, isr);
out32 (EMAC_ISR + hw_p->hw_addr, isr);
}
/*-----------------------------------------------------------------------------+
* enet_rcv() handles the ethernet receive data
*-----------------------------------------------------------------------------*/
static void enet_rcv (unsigned long malisr)
static void enet_rcv (struct eth_device *dev, unsigned long malisr)
{
struct enet_frame *ef_ptr;
unsigned long data_len;
unsigned long rx_eob_isr;
EMAC_405_HW_PST hw_p = dev->priv;
int handled = 0;
int i;
int loop_count = 0;
rx_eob_isr = mfdcr (malrxeobisr);
if ((0x80000000 >> (EMAC_RXCHL - 1)) & rx_eob_isr) {
if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) {
/* clear EOB */
mtdcr (malrxeobisr, rx_eob_isr);
/* EMAC RX done */
while (1) { /* do all */
i = rx_slot;
while (1) { /* do all */
i = hw_p->rx_slot;
if ((MAL_RX_CTRL_EMPTY & rx[i].ctrl)
if ((MAL_RX_CTRL_EMPTY & hw_p->rx[i].ctrl)
|| (loop_count >= NUM_RX_BUFF))
break;
loop_count++;
rx_slot++;
if (NUM_RX_BUFF == rx_slot)
rx_slot = 0;
hw_p->rx_slot++;
if (NUM_RX_BUFF == hw_p->rx_slot)
hw_p->rx_slot = 0;
handled++;
data_len = (unsigned long) rx[i].data_len; /* Get len */
data_len = (unsigned long) hw_p->rx[i].data_len; /* Get len */
if (data_len) {
if (data_len > ENET_MAX_MTU) /* Check len */
data_len = 0;
else {
if (EMAC_RX_ERRORS & rx[i].ctrl) { /* Check Errors */
if (EMAC_RX_ERRORS & hw_p->rx[i].ctrl) { /* Check Errors */
data_len = 0;
stats.rx_err_log[rx_err_index] = rx[i].ctrl;
rx_err_index++;
if (rx_err_index == MAX_ERR_LOG)
rx_err_index = 0;
} /* emac_erros */
} /* data_len < max mtu */
} /* if data_len */
hw_p->stats.rx_err_log[hw_p->
rx_err_index]
= hw_p->rx[i].ctrl;
hw_p->rx_err_index++;
if (hw_p->rx_err_index ==
MAX_ERR_LOG)
hw_p->rx_err_index =
0;
} /* emac_erros */
} /* data_len < max mtu */
} /* if data_len */
if (!data_len) { /* no data */
rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */
hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */
stats.emac.data_len_err++; /* Error at Rx */
hw_p->stats.data_len_err++; /* Error at Rx */
}
/* !data_len */
/* AS.HARNOIS */
/* Check if user has already eaten buffer */
/* if not => ERROR */
else if (rx_ready[rx_i_index] != -1) {
if (is_receiving)
else if (hw_p->rx_ready[hw_p->rx_i_index] != -1) {
if (hw_p->is_receiving)
printf ("ERROR : Receive buffers are full!\n");
break;
} else {
stats.emac.rx_frames++;
stats.emac.rx += data_len;
ef_ptr = (struct enet_frame *) rx[i].data_ptr;
hw_p->stats.rx_frames++;
hw_p->stats.rx += data_len;
ef_ptr = (struct enet_frame *) hw_p->rx[i].
data_ptr;
#ifdef INFO_405_ENET
packetReceived++;
hw_p->stats.pkts_rx++;
#endif
/* AS.HARNOIS
* use ring buffer
*/
rx_ready[rx_i_index] = i;
rx_i_index++;
if (NUM_RX_BUFF == rx_i_index)
rx_i_index = 0;
hw_p->rx_ready[hw_p->rx_i_index] = i;
hw_p->rx_i_index++;
if (NUM_RX_BUFF == hw_p->rx_i_index)
hw_p->rx_i_index = 0;
/* printf("X"); /|* test-only *|/ */
......@@ -820,10 +869,10 @@ static void enet_rcv (unsigned long malisr)
* free receive buffer only when
* buffer has been handled (eth_rx)
rx[i].ctrl |= MAL_RX_CTRL_EMPTY;
*/
} /* if data_len */
} /* while */
} /* if EMACK_RXCHL */
*/
} /* if data_len */
} /* while */
} /* if EMACK_RXCHL */
}
......@@ -832,15 +881,16 @@ static int ppc_4xx_eth_rx (struct eth_device *dev)
int length;
int user_index;
unsigned long msr;
EMAC_405_HW_PST hw_p = dev->priv;
is_receiving = 1; /* tell driver */
hw_p->is_receiving = 1; /* tell driver */
for (;;) {
/* AS.HARNOIS
* use ring buffer and
* get index from rx buffer desciptor queue
*/
user_index = rx_ready[rx_u_index];
user_index = hw_p->rx_ready[hw_p->rx_u_index];
if (user_index == -1) {
length = -1;
break; /* nothing received - leave for() loop */
......@@ -849,72 +899,157 @@ static int ppc_4xx_eth_rx (struct eth_device *dev)
msr = mfmsr ();
mtmsr (msr & ~(MSR_EE));
length = rx[user_index].data_len;
length = hw_p->rx[user_index].data_len;
/* Pass the packet up to the protocol layers. */
/* NetReceive(NetRxPackets[rxIdx], length - 4); */
/* NetReceive(NetRxPackets[i], length); */
NetReceive (NetRxPackets[user_index], length - 4);
/* Free Recv Buffer */
rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
/* Free rx buffer descriptor queue */
rx_ready[rx_u_index] = -1;
rx_u_index++;
if (NUM_RX_BUFF == rx_u_index)
rx_u_index = 0;
hw_p->rx_ready[hw_p->rx_u_index] = -1;
hw_p->rx_u_index++;
if (NUM_RX_BUFF == hw_p->rx_u_index)
hw_p->rx_u_index = 0;
#ifdef INFO_405_ENET
packetHandled++;
hw_p->stats.pkts_handled++;
#endif
mtmsr (msr); /* Enable IRQ's */
mtmsr (msr); /* Enable IRQ's */
}
is_receiving = 0; /* tell driver */
hw_p->is_receiving = 0; /* tell driver */
return length;
}
#if defined(CONFIG_NET_MULTI)
int ppc_4xx_eth_initialize(bd_t *bis)
static int virgin = 0;
int ppc_4xx_eth_initialize (bd_t * bis)
{
struct eth_device *dev;
int eth_num = 0;
int eth_num = 0;
dev = malloc (sizeof *dev);
if (dev == NULL) {
printf(__FUNCTION__ ": Cannot allocate eth_device\n");
return (-1);
}
EMAC_405_HW_PST hw = NULL;
sprintf(dev->name, "ppc_4xx_eth%d", eth_num);
dev->priv = (void *) eth_num;
dev->init = ppc_4xx_eth_init;
dev->halt = ppc_4xx_eth_halt;
dev->send = ppc_4xx_eth_send;
dev->recv = ppc_4xx_eth_rx;
for (eth_num = 0; eth_num < EMAC_NUM_DEV; eth_num++) {
/* Allocate device structure */
dev = (struct eth_device *) malloc (sizeof (*dev));
if (dev == NULL) {
printf ("ppc_405x_eth_initialize: "
"Cannot allocate eth_device %d\n", eth_num);
return (-1);
}
/* Allocate our private use data */
hw = (EMAC_405_HW_PST) malloc (sizeof (*hw));
if (hw == NULL) {
printf ("ppc_405x_eth_initialize: "
"Cannot allocate private hw data for eth_device %d",
eth_num);
free (dev);
return (-1);
}
eth_register (dev);
switch (eth_num) {
case 0:
hw->hw_addr = 0;
memcpy (dev->enetaddr, bis->bi_enetaddr, 6);
break;
#if defined(CONFIG_NET_MULTI)
case 1:
hw->hw_addr = 0x100;
memcpy (dev->enetaddr, bis->bi_enet1addr, 6);
break;
#endif
default:
hw->hw_addr = 0;
memcpy (dev->enetaddr, bis->bi_enetaddr, 6);
break;
}
hw->devnum = eth_num;
hw->print_speed = 1;
sprintf (dev->name, "ppc_405x_eth%d", eth_num);
dev->priv = (void *) hw;
dev->init = ppc_4xx_eth_init;
dev->halt = ppc_4xx_eth_halt;
dev->send = ppc_4xx_eth_send;
dev->recv = ppc_4xx_eth_rx;
if (0 == virgin) {
/* set the MAL IER ??? names may change with new spec ??? */
mal_ier =
MAL_IER_DE | MAL_IER_NE | MAL_IER_TE |
MAL_IER_OPBE | MAL_IER_PLBE;
mtdcr (malesr, 0xffffffff); /* clear pending interrupts */
mtdcr (maltxdeir, 0xffffffff); /* clear pending interrupts */
mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */
mtdcr (malier, mal_ier);
#if defined(CONFIG_405EP)
/* 405EP has one EWU interrupt */
irq_install_handler (VECNUM_EWU0,
(interrupt_handler_t *) enetInt,
dev);
#endif
/* install MAL interrupt handler */
irq_install_handler (VECNUM_MS,
(interrupt_handler_t *) enetInt,
dev);
irq_install_handler (VECNUM_MTE,
(interrupt_handler_t *) enetInt,
dev);
irq_install_handler (VECNUM_MRE,
(interrupt_handler_t *) enetInt,
dev);
irq_install_handler (VECNUM_TXDE,
(interrupt_handler_t *) enetInt,
dev);
irq_install_handler (VECNUM_RXDE,
(interrupt_handler_t *) enetInt,
dev);
virgin = 1;
}
#if defined(CONFIG_NET_MULTI)
eth_register (dev);
#else
emac0_dev = dev;
#endif
} /* end for each supported device */
return (1);
}
#else /* !defined(CONFIG_NET_MULTI) */
void eth_halt (void)
{
ppc_4xx_eth_halt(NULL);
#if !defined(CONFIG_NET_MULTI)
void eth_halt (void) {
if (emac0_dev) {
ppc_4xx_eth_halt(emac0_dev);
free(emac0_dev);
emac0_dev = NULL;
}
}
int eth_init (bd_t *bis)
{
return (ppc_4xx_eth_init(NULL, bis));
ppc_4xx_eth_initialize(bis);
return(ppc_4xx_eth_init(emac0_dev, bis));
}
int eth_send(volatile void *packet, int length)
{
return (ppc_4xx_eth_send(NULL, packet, length));
return (ppc_4xx_eth_send(emac0_dev, packet, length));
}
int eth_rx(void)
{
return (ppc_4xx_eth_rx(NULL));
return (ppc_4xx_eth_rx(emac0_dev));
}
#endif /* !defined(CONFIG_NET_MULTI) */
#endif
#endif /* CONFIG_405GP */
#endif /* CONFIG_405 */
......@@ -48,8 +48,8 @@
#include <405_mal.h>
#include <miiphy.h>
#if (defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_440)) \
&& !defined (CONFIG_NET_MULTI)
#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || \
(defined(CONFIG_440) && !defined(CONFIG_NET_MULTI))
/***********************************************************/
/* Dump out to the screen PHY regs */
......@@ -78,6 +78,12 @@ void miiphy_dump (unsigned char addr)
/***********************************************************/
/* read a phy reg and return the value with a rc */
/* Note: We are referencing to EMAC_STACR register */
/* @(EMAC_BASE + 92) because of: */
/* - 405EP has only STACR for EMAC0 pinned out */
/* - 405GP has onle one EMAC0 */
/* - For 440 this module gets compiled only for */
/* !CONFIG_NET_MULTI, i.e. only EMAC0 is supported. */
/***********************************************************/
int miiphy_read (unsigned char addr, unsigned char reg,
......
......@@ -35,7 +35,8 @@
+----------------------------------------------------------------------------*/
#ifndef _enetemac_h_
#define _enetemac_h_
#include <net.h>
#include <405_mal.h>
/*-----------------------------------------------------------------------------+
| General enternet defines. 802 frames are not supported.
......@@ -235,6 +236,60 @@ struct arp_entry {
/* all the errors we care about */
#define EMAC_RX_ERRORS 0x03FF
#define NUM_RX_BUFF PKTBUFSRX
#define NUM_TX_BUFF 1
#define MAX_ERR_LOG 10
typedef struct emac_stats_st{ /* Statistic Block */
int data_len_err;
int rx_frames;
int rx;
int rx_prot_err;
int int_err;
int pkts_tx;
int pkts_rx;
int pkts_handled;
short tx_err_log[MAX_ERR_LOG];
short rx_err_log[MAX_ERR_LOG];
} EMAC_STATS_ST, *EMAC_STATS_PST;
/* Structure containing variables used by the shared code (440gx_enet.c) */
typedef struct emac_440gx_hw_st {
uint32_t hw_addr; /* EMAC offset */
uint32_t tah_addr; /* TAH offset */
uint32_t phy_id;
uint32_t phy_addr;
uint32_t original_fc;
uint32_t txcw;
uint32_t autoneg_failed;
uint32_t emac_ier;
volatile mal_desc_t *tx;
volatile mal_desc_t *rx;
bd_t *bis; /* for eth_init upon mal error */
mal_desc_t *alloc_tx_buf;
mal_desc_t *alloc_rx_buf;
char *txbuf_ptr;
uint16_t devnum;
int get_link_status;
int tbi_compatibility_en;
int tbi_compatibility_on;
int fc_send_xon;
int report_tx_early;
int first_init;
int tx_err_index;
int rx_err_index;
int rx_slot; /* MAL Receive Slot */
int rx_i_index; /* Receive Interrupt Queue Index */
int rx_u_index; /* Receive User Queue Index */
int tx_slot; /* MAL Transmit Slot */
int tx_i_index; /* Transmit Interrupt Queue Index */
int tx_u_index; /* Transmit User Queue Index */
int rx_ready[NUM_RX_BUFF]; /* Receive Ready Queue */
int tx_run[NUM_TX_BUFF]; /* Transmit Running Queue */
int is_receiving; /* sync with eth interrupt */
int print_speed; /* print speed message upon start */
EMAC_STATS_ST stats;
} EMAC_405_HW_ST, *EMAC_405_HW_PST;
/*-----------------------------------------------------------------------------+
| Function prototypes for device table.
......
......@@ -77,10 +77,12 @@
#undef CONFIG_EXT_PHY
#define CONFIG_NET_MULTI 1
#define CONFIG_MII 1 /* MII PHY management */
#ifndef CONFIG_EXT_PHY
#define CONFIG_PHY_ADDR 1 /* PHY address */
#define CONFIG_PHY_ADDR 0 /* EMAC0 PHY address */
#define CONFIG_PHY1_ADDR 1 /* EMAC1 PHY address */
#else
#define CONFIG_PHY_ADDR 2 /* PHY address */
#endif
......
......@@ -132,9 +132,10 @@
#define UIC_MAL_RXEOB 0x00080000 /* MAL RXEOB */
#define UIC_MAL_TXDE 0x00040000 /* MAL TXDE */
#define UIC_MAL_RXDE 0x00020000 /* MAL RXDE */
#define UIC_ENET 0x00010000 /* Ethernet */
#define UIC_ENET 0x00010000 /* Ethernet0 */
#define UIC_ENET1 0x00004000 /* Ethernet1 on 405EP */
#define UIC_ECC_CE 0x00004000 /* ECC Correctable Error on 405GP */
#define UIC_EXT_PCI_SERR 0x00008000 /* External PCI SERR# */
#define UIC_ECC_CE 0x00004000 /* ECC Correctable Error */
#define UIC_PCI_PM 0x00002000 /* PCI Power Management */
#define UIC_EXT0 0x00000040 /* External interrupt 0 */
#define UIC_EXT1 0x00000020 /* External interrupt 1 */
......@@ -582,8 +583,11 @@
#define malrxdeir (MAL_DCR_BASE+0x13) /* RX Descr. Error Int reg */
#define maltxctp0r (MAL_DCR_BASE+0x20) /* TX 0 Channel table pointer reg */
#define maltxctp1r (MAL_DCR_BASE+0x21) /* TX 1 Channel table pointer reg */
#define maltxctp2r (MAL_DCR_BASE+0x22) /* TX 2 Channel table pointer reg */
#define malrxctp0r (MAL_DCR_BASE+0x40) /* RX 0 Channel table pointer reg */
#define malrxctp1r (MAL_DCR_BASE+0x41) /* RX 1 Channel table pointer reg */
#define malrcbs0 (MAL_DCR_BASE+0x60) /* RX 0 Channel buffer size reg */
#define malrcbs1 (MAL_DCR_BASE+0x61) /* RX 1 Channel buffer size reg */
/*-----------------------------------------------------------------------------
| IIC Register Offsets
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment