diff options
| author | wdenk <wdenk> | 2004-06-06 23:53:59 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2004-06-06 23:53:59 +0000 | 
| commit | cea655a224456d043192156fb2d44a0896194adc (patch) | |
| tree | 4bd5303a7e9b87df12ca56ddda0e42bc674ac4bb | |
| parent | a56bd92289298bde16306bcc754277db45315d2f (diff) | |
| download | olio-uboot-2014.01-cea655a224456d043192156fb2d44a0896194adc.tar.xz olio-uboot-2014.01-cea655a224456d043192156fb2d44a0896194adc.zip | |
Add support for the second Ethernet interface for the 'PPChameleon' board.
| -rw-r--r-- | CHANGELOG | 3 | ||||
| -rw-r--r-- | cpu/ppc4xx/405gp_enet.c | 833 | ||||
| -rw-r--r-- | cpu/ppc4xx/miiphy.c | 10 | ||||
| -rw-r--r-- | include/405gp_enet.h | 57 | ||||
| -rw-r--r-- | include/configs/PPChameleonEVB.h | 4 | ||||
| -rw-r--r-- | include/ppc405.h | 8 | 
6 files changed, 560 insertions, 355 deletions
| @@ -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 diff --git a/cpu/ppc4xx/405gp_enet.c b/cpu/ppc4xx/405gp_enet.c index 65036d1a0..da4555852 100644 --- a/cpu/ppc4xx/405gp_enet.c +++ b/cpu/ppc4xx/405gp_enet.c @@ -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; +static uint32_t 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; +#if !defined(CONFIG_NET_MULTI) +struct eth_device *emac0_dev;  #endif -static char emac_hwd_addr[ENET_ADDR_LENGTH]; - -static bd_t *bis_save = NULL;	/* for eth_init upon mal error */ - -static int is_receiving = 0;	/* sync with eth interrupt */ -static int print_speed = 1;	/* print speed message upon start */ -  /*-----------------------------------------------------------------------------+   * 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, ®_short); +	miiphy_read (reg, PHY_BMSR, ®_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, ®_short); +			miiphy_read (reg, PHY_BMSR, ®_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); +	reg |= dev->enetaddr[5]; -	/* 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 */ +	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; -	if (first_init == 0) { +	out32 (EMAC_ISR + hw_p->hw_addr, 0xffffffff);	/* clear pending interrupts */ +	out32 (EMAC_IER + hw_p->hw_addr, hw_p->emac_ier); + +	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; -	tx[tx_slot].data_len = (short) len; -	tx[tx_slot].ctrl |= MAL_TX_CTRL_READY; +	hw_p->tx[hw_p->tx_slot].data_len = (short) len; +	hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY; -    __asm__ volatile ("eieio"); -	out32 (EMAC_TXM0, in32 (EMAC_TXM0) | EMAC_TXM0_GNP0); +	__asm__ volatile ("eieio"); + +	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; + +	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); +		} + +		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; +		} -	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; +		hw->devnum = eth_num; +		hw->print_speed = 1; -	eth_register (dev); +		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 */ diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index 3d343ee88..cb9dccdc3 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -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, diff --git a/include/405gp_enet.h b/include/405gp_enet.h index 224452106..88ac4add9 100644 --- a/include/405gp_enet.h +++ b/include/405gp_enet.h @@ -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. diff --git a/include/configs/PPChameleonEVB.h b/include/configs/PPChameleonEVB.h index c9e52e2a4..0c9b6dd7e 100644 --- a/include/configs/PPChameleonEVB.h +++ b/include/configs/PPChameleonEVB.h @@ -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 diff --git a/include/ppc405.h b/include/ppc405.h index 29e6ffd0d..64317b0e4 100644 --- a/include/ppc405.h +++ b/include/ppc405.h @@ -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 |