diff options
Diffstat (limited to 'cpu/mpc8xx/fec.c')
| -rw-r--r-- | cpu/mpc8xx/fec.c | 686 | 
1 files changed, 458 insertions, 228 deletions
| diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c index 811ac7971..b7603da45 100644 --- a/cpu/mpc8xx/fec.c +++ b/cpu/mpc8xx/fec.c @@ -29,13 +29,71 @@  #undef	ET_DEBUG -#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET) +#if (CONFIG_COMMANDS & CFG_CMD_NET) && \ +	(defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FEC1) || defined(CONFIG_ETHER_ON_FEC2)) -#ifdef CFG_DISCOVER_PHY +/* compatibility test, if only FEC_ENET defined assume ETHER on FEC1 */ +#if defined(FEC_ENET) && !defined(CONFIG_ETHER_ON_FEC1) && !defined(CONFIG_ETHER_ON_FEC2) +#define CONFIG_ETHER_ON_FEC1 1 +#endif + +/* define WANT_MII when MII support is required */ +#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY) +#define WANT_MII +#else +#undef WANT_MII +#endif + +#if defined(WANT_MII)  #include <miiphy.h> -static void mii_discover_phy(void);  #endif +#if defined(CONFIG_RMII) && !defined(WANT_MII) +#error RMII support is unusable without a working PHY. +#endif + +#ifdef CFG_DISCOVER_PHY +static int mii_discover_phy(struct eth_device *dev); +#endif + +static struct ether_fcc_info_s +{ +	int ether_index; +	int fecp_offset; +	int bd_offset; +	int phy_addr; +	int actual_phy_addr; +} +	ether_fcc_info[] = { +#if defined(CONFIG_ETHER_ON_FEC1) +	{ +		0, +		offsetof(immap_t, im_cpm.cp_fec1), +		CPM_FEC_BASE, +#if defined(CONFIG_FEC1_PHY) +		CONFIG_FEC1_PHY, +#else +		-1,	/* discover */ +#endif +		-1, + +	}, +#endif +#if defined(CONFIG_ETHER_ON_FEC2) +	{ +		1, +		offsetof(immap_t, im_cpm.cp_fec2), +		CPM_FEC_BASE + 0x50, +#if defined(CONFIG_FEC2_PHY) +		CONFIG_FEC2_PHY, +#else +		-1, +#endif +		-1, +	}, +#endif +}; +  /* Ethernet Transmit and Receive Buffers */  #define DBUF_LENGTH  1520 @@ -47,8 +105,11 @@ static void mii_discover_phy(void);  #define PKT_MINBUF_SIZE		64  #define PKT_MAXBLR_SIZE		1520 - -static char txbuf[DBUF_LENGTH]; +#ifdef __GNUC__ +static char txbuf[DBUF_LENGTH] __attribute__ ((aligned(8))); +#else +#error txbuf must be aligned. +#endif  static uint rxIdx;	/* index of the current RX buffer */  static uint txIdx;	/* index of the current TX buffer */ @@ -74,28 +135,49 @@ static void fec_halt(struct eth_device* dev);  int fec_initialize(bd_t *bis)  {  	struct eth_device* dev; +	struct ether_fcc_info_s *efis; +	int             i; -	dev = (struct eth_device*) malloc(sizeof *dev); -	memset(dev, 0, sizeof *dev); +	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) { -	sprintf(dev->name, "FEC ETHERNET"); -	dev->iobase = 0; -	dev->priv   = 0; -	dev->init   = fec_init; -	dev->halt   = fec_halt; -	dev->send   = fec_send; -	dev->recv   = fec_recv; +		dev = malloc(sizeof(*dev)); +		if (dev == NULL) +			hang(); + +		memset(dev, 0, sizeof(*dev)); + +		/* for FEC1 make sure that the name of the interface is the same +		   as the old one for compatibility reasons */ +		if (i == 0) { +			sprintf (dev->name, "FEC ETHERNET"); +		} else { +			sprintf (dev->name, "FEC%d ETHERNET", +				ether_fcc_info[i].ether_index + 1); +		} -	eth_register(dev); +		efis = ðer_fcc_info[i]; +		/* +		 * reset actual phy addr +		 */ +		efis->actual_phy_addr = -1; + +		dev->priv = efis; +		dev->init = fec_init; +		dev->halt = fec_halt; +		dev->send = fec_send; +		dev->recv = fec_recv; + +		eth_register(dev); +	}  	return 1;  }  static int fec_send(struct eth_device* dev, volatile void *packet, int length)  {  	int j, rc; -	volatile immap_t *immr = (immap_t *) CFG_IMMR; -	volatile fec_t *fecp = &(immr->im_cpm.cp_fec); +	struct ether_fcc_info_s *efis = dev->priv; +	volatile fec_t *fecp = (volatile fec_t *)(CFG_IMMR + efis->fecp_offset);  	/* section 16.9.23.3  	 * Wait for ready @@ -142,50 +224,66 @@ static int fec_send(struct eth_device* dev, volatile void *packet, int length)  	return rc;  } -static int fec_recv(struct eth_device* dev) +static int fec_recv (struct eth_device *dev)  { +	struct ether_fcc_info_s *efis = dev->priv; +	volatile fec_t *fecp = +		(volatile fec_t *) (CFG_IMMR + efis->fecp_offset);  	int length; -	volatile immap_t *immr = (immap_t *) CFG_IMMR; -	volatile fec_t *fecp = &(immr->im_cpm.cp_fec); -   for (;;) { -	/* section 16.9.23.2 */ -	if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { -		length = -1; -		break;     /* nothing received - leave for() loop */ -	} +	for (;;) { +		/* section 16.9.23.2 */ +		if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { +			length = -1; +			break;	/* nothing received - leave for() loop */ +		} -	length = rtx->rxbd[rxIdx].cbd_datlen; +		length = rtx->rxbd[rxIdx].cbd_datlen; -	if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) { +		if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {  #ifdef ET_DEBUG -		printf("%s[%d] err: %x\n", -		__FUNCTION__,__LINE__,rtx->rxbd[rxIdx].cbd_sc); +			printf ("%s[%d] err: %x\n", +				__FUNCTION__, __LINE__, +				rtx->rxbd[rxIdx].cbd_sc);  #endif -	} else { -		/* Pass the packet up to the protocol layers. */ -		NetReceive(NetRxPackets[rxIdx], length - 4); -	} +		} else { +			volatile uchar *rx = NetRxPackets[rxIdx]; -	/* Give the buffer back to the FEC. */ -	rtx->rxbd[rxIdx].cbd_datlen = 0; +			length -= 4; -	/* wrap around buffer index when necessary */ -	if ((rxIdx + 1) >= PKTBUFSRX) { -		rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); -		rxIdx = 0; -	} else { -		rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; -		rxIdx++; -	} +#if (CONFIG_COMMANDS & CFG_CMD_CDP) +			if ((rx[0] & 1) != 0 +			    && memcmp ((uchar *) rx, NetBcastAddr, 6) != 0 +			    && memcmp ((uchar *) rx, NetCDPAddr, 6) != 0) +				rx = NULL; +#endif +			/* +			 * Pass the packet up to the protocol layers. +			 */ +			if (rx != NULL) +				NetReceive (rx, length); +		} -	__asm__ ("eieio"); +		/* Give the buffer back to the FEC. */ +		rtx->rxbd[rxIdx].cbd_datlen = 0; + +		/* wrap around buffer index when necessary */ +		if ((rxIdx + 1) >= PKTBUFSRX) { +			rtx->rxbd[PKTBUFSRX - 1].cbd_sc = +				(BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); +			rxIdx = 0; +		} else { +			rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; +			rxIdx++; +		} -	/* Try to fill Buffer Descriptors */ -	fecp->fec_r_des_active = 0x01000000;	/* Descriptor polling active	*/ -   } +		__asm__ ("eieio"); -   return length; +		/* Try to fill Buffer Descriptors */ +		fecp->fec_r_des_active = 0x01000000;	/* Descriptor polling active    */ +	} + +	return length;  }  /************************************************************** @@ -210,34 +308,250 @@ static int fec_recv(struct eth_device* dev)  #define	FEC_RESET_DELAY		50 -static int fec_init(struct eth_device* dev, bd_t * bd) +#if defined(CONFIG_RMII) + +static inline void fec_10Mbps(struct eth_device *dev)  { +	struct ether_fcc_info_s *efis = dev->priv; +	int fecidx = efis->ether_index; +	uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; -	int i; +	if ((unsigned int)fecidx >= 2) +		hang(); + +	((volatile immap_t *)CFG_IMMR)->im_cpm.cp_cptr |=  mask; +} + +static inline void fec_100Mbps(struct eth_device *dev) +{ +	struct ether_fcc_info_s *efis = dev->priv; +	int fecidx = efis->ether_index; +	uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; + +	if ((unsigned int)fecidx >= 2) +		hang(); + +	((volatile immap_t *)CFG_IMMR)->im_cpm.cp_cptr &= ~mask; +} + +#endif + +static inline void fec_full_duplex(struct eth_device *dev) +{ +	struct ether_fcc_info_s *efis = dev->priv; +	volatile fec_t *fecp = (volatile fec_t *)(CFG_IMMR + efis->fecp_offset); + +	fecp->fec_r_cntrl &= ~FEC_RCNTRL_DRT; +	fecp->fec_x_cntrl |=  FEC_TCNTRL_FDEN;	/* FD enable */ +} + +static inline void fec_half_duplex(struct eth_device *dev) +{ +	struct ether_fcc_info_s *efis = dev->priv; +	volatile fec_t *fecp = (volatile fec_t *)(CFG_IMMR + efis->fecp_offset); + +	fecp->fec_r_cntrl |=  FEC_RCNTRL_DRT; +	fecp->fec_x_cntrl &= ~FEC_TCNTRL_FDEN;	/* FD disable */ +} + +static void fec_pin_init(int fecidx) +{ +	DECLARE_GLOBAL_DATA_PTR; +	bd_t           *bd = gd->bd;  	volatile immap_t *immr = (immap_t *) CFG_IMMR; -	volatile fec_t *fecp = &(immr->im_cpm.cp_fec); +	volatile fec_t *fecp; -#if defined(CONFIG_FADS) /* FADS family uses FPGA (BCSR) to control PHYs */ -#if defined(CONFIG_DUET_ADS) -	*(vu_char *)BCSR5 &= ~(BCSR5_MII1_EN | BCSR5_MII1_RST); -#else -	/* configure FADS for fast (FEC) ethernet, half-duplex */ -	/* The LXT970 needs about 50ms to recover from reset, so -	 * wait for it by discovering the PHY before leaving eth_init(). +	/* +	 * only two FECs please  	 */ -	{ -		volatile uint *bcsr4 = (volatile uint *) BCSR4; -		*bcsr4 = (*bcsr4 & ~(BCSR4_FETH_EN | BCSR4_FETHCFG1)) -			| (BCSR4_FETHCFG0 | BCSR4_FETHFDE | BCSR4_FETHRST); +	if ((unsigned int)fecidx >= 2) +		hang(); + +	if (fecidx == 0) +		fecp = &immr->im_cpm.cp_fec1; +	else +		fecp = &immr->im_cpm.cp_fec2; + +	/* +	 * Set MII speed to 2.5 MHz or slightly below. +	 * * According to the MPC860T (Rev. D) Fast ethernet controller user +	 * * manual (6.2.14), +	 * * the MII management interface clock must be less than or equal +	 * * to 2.5 MHz. +	 * * This MDC frequency is equal to system clock / (2 * MII_SPEED). +	 * * Then MII_SPEED = system_clock / 2 * 2,5 Mhz. +	 */ +	fecp->fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1; + +#if defined(CONFIG_DUET) && defined(WANT_MII) +	/* use MDC for MII */ +	immr->im_ioport.iop_pdpar |=  0x0080; +	immr->im_ioport.iop_pddir &= ~0x0080; +#endif + +	if (fecidx == 0) { +#if defined(CONFIG_ETHER_ON_FEC1) + +#if defined(CONFIG_DUET)	/* MPC87x/88x have got 2 FECs and different pinout */ + +#if !defined(CONFIG_RMII) + +		immr->im_ioport.iop_papar |=  0xf830; +		immr->im_ioport.iop_padir |=  0x0830; +		immr->im_ioport.iop_padir &= ~0xf000; + +		immr->im_cpm.cp_pbpar     |=  0x00001001; +		immr->im_cpm.cp_pbdir     &= ~0x00001001; + +		immr->im_ioport.iop_pcpar |=  0x000c; +		immr->im_ioport.iop_pcdir &= ~0x000c; + +		immr->im_cpm.cp_pepar     |=  0x00000003; +		immr->im_cpm.cp_pedir     |=  0x00000003; +		immr->im_cpm.cp_peso      &= ~0x00000003; + +		immr->im_cpm.cp_cptr      &= ~0x00000100; + +#else + +#if !defined(CONFIG_FEC1_PHY_NORXERR) +		immr->im_ioport.iop_papar |=  0x1000; +		immr->im_ioport.iop_padir &= ~0x1000; +#endif +		immr->im_ioport.iop_papar |=  0xe810; +		immr->im_ioport.iop_padir |=  0x0810; +		immr->im_ioport.iop_padir &= ~0xe000; + +		immr->im_cpm.cp_pbpar     |=  0x00000001; +		immr->im_cpm.cp_pbdir     &= ~0x00000001; + +		immr->im_cpm.cp_cptr      |=  0x00000100; +		immr->im_cpm.cp_cptr      &= ~0x00000050; + +#endif /* !CONFIG_RMII */ + +#elif !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) +		/* +		 * Configure all of port D for MII. +		 */ +		immr->im_ioport.iop_pdpar = 0x1fff; + +		/* +		 * Bits moved from Rev. D onward +		 */ +		if ((get_immr(0) & 0xffff) < 0x0501) +			immr->im_ioport.iop_pddir = 0x1c58;	/* Pre rev. D */ +		else +			immr->im_ioport.iop_pddir = 0x1fff;	/* Rev. D and later */ +#else +		/* +		 * Configure port A for MII. +		 */ + +#if defined(CONFIG_ICU862) && defined(CFG_DISCOVER_PHY) + +		/* +		 * On the ICU862 board the MII-MDC pin is routed to PD8 pin +		 * * of CPU, so for this board we need to configure Utopia and +		 * * enable PD8 to MII-MDC function +		 */ +		immr->im_ioport.iop_pdpar |= 0x4080; +#endif + +		/* +		 * Has Utopia been configured? +		 */ +		if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) { +			/* +			 * YES - Use MUXED mode for UTOPIA bus. +			 * This frees Port A for use by MII (see 862UM table 41-6). +			 */ +			immr->im_ioport.utmode &= ~0x80; +		} else { +			/* +			 * NO - set SPLIT mode for UTOPIA bus. +			 * +			 * This doesn't really effect UTOPIA (which isn't +			 * enabled anyway) but just tells the 862 +			 * to use port A for MII (see 862UM table 41-6). +			 */ +			immr->im_ioport.utmode |= 0x80; +		} +#endif				/* !defined(CONFIG_ICU862) */ + +#endif	/* CONFIG_ETHER_ON_FEC1 */ +	} else if (fecidx == 1) { + +#if defined(CONFIG_ETHER_ON_FEC2) + +#if defined(CONFIG_DUET)	/* MPC87x/88x have got 2 FECs and different pinout */ + +#if !defined(CONFIG_RMII) + +#warning this configuration is not tested; please report if it works +		immr->im_cpm.cp_pepar     |=  0x0003fffc; +		immr->im_cpm.cp_pedir     |=  0x0003fffc; +		immr->im_cpm.cp_peso      &= ~0x000087fc; +		immr->im_cpm.cp_peso      |=  0x00037800; + +		immr->im_cpm.cp_cptr      &= ~0x00000080; +#else + +#if !defined(CONFIG_FEC2_PHY_NORXERR) +		immr->im_cpm.cp_pepar     |=  0x00000010; +		immr->im_cpm.cp_pedir     |=  0x00000010; +		immr->im_cpm.cp_peso      &= ~0x00000010; +#endif +		immr->im_cpm.cp_pepar     |=  0x00039620; +		immr->im_cpm.cp_pedir     |=  0x00039620; +		immr->im_cpm.cp_peso      |=  0x00031000; +		immr->im_cpm.cp_peso      &= ~0x00008620; + +		immr->im_cpm.cp_cptr      |=  0x00000080; +		immr->im_cpm.cp_cptr      &= ~0x00000028; +#endif /* CONFIG_RMII */ + +#endif /* CONFIG_DUET */ + +#endif /* CONFIG_ETHER_ON_FEC2 */ -		/* reset the LXT970 PHY */ -		*bcsr4 &= ~BCSR4_FETHRST; -		udelay (10); -		*bcsr4 |= BCSR4_FETHRST; -		udelay (10);  	} +} + +static int fec_init (struct eth_device *dev, bd_t * bd) +{ +	struct ether_fcc_info_s *efis = dev->priv; +	volatile immap_t *immr = (immap_t *) CFG_IMMR; +	volatile fec_t *fecp = +		(volatile fec_t *) (CFG_IMMR + efis->fecp_offset); +	int i; + +	if (efis->ether_index == 0) { +#if defined(CONFIG_FADS)	/* FADS family uses FPGA (BCSR) to control PHYs */ +#if defined(CONFIG_DUET_ADS) +		*(vu_char *) BCSR5 &= ~(BCSR5_MII1_EN | BCSR5_MII1_RST); +#else +		/* configure FADS for fast (FEC) ethernet, half-duplex */ +		/* The LXT970 needs about 50ms to recover from reset, so +		 * wait for it by discovering the PHY before leaving eth_init(). +		 */ +		{ +			volatile uint *bcsr4 = (volatile uint *) BCSR4; + +			*bcsr4 = (*bcsr4 & ~(BCSR4_FETH_EN | BCSR4_FETHCFG1)) +				| (BCSR4_FETHCFG0 | BCSR4_FETHFDE | +				   BCSR4_FETHRST); + +			/* reset the LXT970 PHY */ +			*bcsr4 &= ~BCSR4_FETHRST; +			udelay (10); +			*bcsr4 |= BCSR4_FETHRST; +			udelay (10); +		}  #endif /* CONFIG_DUET_ADS */  #endif /* CONFIG_FADS */ +	} +  	/* Whack a reset.  	 * A delay is required between a reset of the FEC block and  	 * initialization of other FEC registers because the reset takes @@ -269,15 +583,22 @@ static int fec_init(struct eth_device* dev, bd_t * bd)  	/* Set station address  	 */  #define ea eth_get_dev()->enetaddr -	fecp->fec_addr_low   =	(ea[0] << 24) | (ea[1] << 16) | -				(ea[2] <<  8) | (ea[3]      ) ; -	fecp->fec_addr_high  =	(ea[4] <<  8) | (ea[5]	    ) ; +	fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); +	fecp->fec_addr_high = (ea[4] << 8) | (ea[5]);  #undef ea +#if (CONFIG_COMMANDS & CFG_CMD_CDP) +	/* +	 * Turn on multicast address hash table +	 */ +	fecp->fec_hash_table_high = 0xffffffff; +	fecp->fec_hash_table_low = 0xffffffff; +#else  	/* Clear multicast address hash table  	 */  	fecp->fec_hash_table_high = 0; -	fecp->fec_hash_table_low  = 0; +	fecp->fec_hash_table_low = 0; +#endif  	/* Set maximum receive buffer size.  	 */ @@ -295,9 +616,10 @@ static int fec_init(struct eth_device* dev, bd_t * bd)  	if (!rtx) {  #ifdef CFG_ALLOC_DPRAM -	    rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + dpram_alloc_align(sizeof(RTXBD),8)); +		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + +				 dpram_alloc_align (sizeof (RTXBD), 8));  #else -	    rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE); +		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);  #endif  	}  	/* @@ -306,8 +628,8 @@ static int fec_init(struct eth_device* dev, bd_t * bd)  	 *     Empty, Wrap  	 */  	for (i = 0; i < PKTBUFSRX; i++) { -		rtx->rxbd[i].cbd_sc      = BD_ENET_RX_EMPTY; -		rtx->rxbd[i].cbd_datlen  = 0;	/* Reset */ +		rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; +		rtx->rxbd[i].cbd_datlen = 0;	/* Reset */  		rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];  	}  	rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; @@ -318,8 +640,8 @@ static int fec_init(struct eth_device* dev, bd_t * bd)  	 *    Last, Tx CRC  	 */  	for (i = 0; i < TX_BUF_CNT; i++) { -		rtx->txbd[i].cbd_sc      = BD_ENET_TX_LAST | BD_ENET_TX_TC; -		rtx->txbd[i].cbd_datlen  = 0;	/* Reset */ +		rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; +		rtx->txbd[i].cbd_datlen = 0;	/* Reset */  		rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);  	}  	rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; @@ -331,10 +653,10 @@ static int fec_init(struct eth_device* dev, bd_t * bd)  	/* Enable MII mode  	 */ -#if 0	/* Full duplex mode */ +#if 0				/* Full duplex mode */  	fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE;  	fecp->fec_x_cntrl = FEC_TCNTRL_FDEN; -#else	/* Half duplex mode */ +#else  /* Half duplex mode */  	fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;  	fecp->fec_x_cntrl = 0;  #endif @@ -343,86 +665,59 @@ static int fec_init(struct eth_device* dev, bd_t * bd)  	 */  	fecp->fec_fun_code = 0x78000000; -	/* Set MII speed to 2.5 MHz or slightly below. -	 * According to the MPC860T (Rev. D) Fast ethernet controller user -	 * manual (6.2.14), -	 * the MII management interface clock must be less than or equal -	 * to 2.5 MHz. -	 * This MDC frequency is equal to system clock / (2 * MII_SPEED). -	 * Then MII_SPEED = system_clock / 2 * 2,5 Mhz. -	 */ -	fecp->fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1; - -#if defined(CONFIG_DUET) /* MPC87x/88x have got 2 FECs and different pinout */ -	immr->im_ioport.iop_papar |=  0xf830; -	immr->im_ioport.iop_padir |=  0x0830; -	immr->im_ioport.iop_padir &= ~0xf000; -	immr->im_cpm.cp_pbpar     |=  0x00001001; -	immr->im_cpm.cp_pbdir     &= ~0x00001001; -	immr->im_ioport.iop_pcpar |=  0x000c; -	immr->im_ioport.iop_pcdir &= ~0x000c; -	immr->im_ioport.iop_pdpar |=  0x0080; -	immr->im_ioport.iop_pddir &= ~0x0080; -	immr->im_cpm.cp_pepar     |=  0x00000003; -	immr->im_cpm.cp_pedir     |=  0x00000003; -	immr->im_cpm.cp_peso      &= ~0x00000003; -#elif !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) -	/* Configure all of port D for MII. +	/* +	 * Setup the pin configuration of the FEC  	 */ -	immr->im_ioport.iop_pdpar = 0x1fff; - -	/* Bits moved from Rev. D onward */ -	if ((get_immr (0) & 0xffff) < 0x0501) { -		immr->im_ioport.iop_pddir = 0x1c58;	/* Pre rev. D */ -	} else { -		immr->im_ioport.iop_pddir = 0x1fff;	/* Rev. D and later */ -	} -#else -	/* Configure port A for MII. -	*/ +	fec_pin_init (efis->ether_index); -#if defined(CONFIG_ICU862) && defined(CFG_DISCOVER_PHY) +	rxIdx = 0; +	txIdx = 0; -	/* On the ICU862 board the MII-MDC pin is routed to PD8 pin -	 * of CPU, so for this board we need to configure Utopia and -	 * enable PD8 to MII-MDC function */ -	immr->im_ioport.iop_pdpar |= 0x4080; -#endif +	/* +	 * Now enable the transmit and receive processing +	 */ +	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; -	/* Has Utopia been configured? */ -	if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) { +	if (efis->phy_addr == -1) { +#ifdef CFG_DISCOVER_PHY  		/* -		 * YES - Use MUXED mode for UTOPIA bus. -		 * This frees Port A for use by MII (see 862UM table 41-6). +		 * wait for the PHY to wake up after reset  		 */ -		immr->im_ioport.utmode &= ~0x80; +		efis->actual_phy_addr = mii_discover_phy (dev); +#else +		efis->actual_phy_addr = -1; +#endif +		if (efis->actual_phy_addr == -1) { +			printf ("Unable to discover phy!\n"); +			return 0; +		}  	} else { -		/* -		 * NO - set SPLIT mode for UTOPIA bus. -		 * -		 * This doesn't really effect UTOPIA (which isn't -		 * enabled anyway) but just tells the 862 -		 * to use port A for MII (see 862UM table 41-6). -		 */ -		immr->im_ioport.utmode |= 0x80; +		efis->actual_phy_addr = efis->phy_addr;  	} -#endif	/* !defined(CONFIG_ICU862) */ - -	rxIdx = 0; -	txIdx = 0; - -	/* Now enable the transmit and receive processing +#if defined(CONFIG_MII) && defined(CONFIG_RMII) +	/* +	 * adapt the RMII speed to the speed of the phy  	 */ -	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; +	if (miiphy_speed (efis->actual_phy_addr) == _100BASET) { +		fec_100Mbps (dev); +	} else { +		fec_10Mbps (dev); +	} +#endif -#ifdef CFG_DISCOVER_PHY -	/* wait for the PHY to wake up after reset +#if defined(CONFIG_MII) +	/* +	 * adapt to the half/full speed settings  	 */ -	mii_discover_phy(); +	if (miiphy_duplex (efis->actual_phy_addr) == FULL) { +		fec_full_duplex (dev); +	} else { +		fec_half_duplex (dev); +	}  #endif  	/* And last, try to fill Rx Buffer Descriptors */ -	fecp->fec_r_des_active = 0x01000000;	/* Descriptor polling active	*/ +	fecp->fec_r_des_active = 0x01000000;	/* Descriptor polling active    */  	return 1;  } @@ -431,23 +726,20 @@ static int fec_init(struct eth_device* dev, bd_t * bd)  static void fec_halt(struct eth_device* dev)  {  #if 0 -    volatile immap_t *immr = (immap_t *)CFG_IMMR; -    immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); +	volatile immap_t *immr = (immap_t *)CFG_IMMR; +	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);  #endif  }  #if 0  void restart(void)  { -   volatile immap_t *immr = (immap_t *)CFG_IMMR; -   immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); +	volatile immap_t *immr = (immap_t *)CFG_IMMR; +	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);  }  #endif -#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII) - -static	int	phyaddr = -1;	/* didn't find a PHY yet */ -static	uint	phytype; +#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)  /* Make MII read/write commands for the FEC.  */ @@ -508,12 +800,13 @@ mii_send(uint mii_cmd)  #endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */  #if defined(CFG_DISCOVER_PHY) -static void -mii_discover_phy(void) +static int mii_discover_phy(struct eth_device *dev)  {  #define MAX_PHY_PASSES 11  	uint phyno;  	int  pass; +	uint phytype; +	int phyaddr;  	phyaddr = -1;	/* didn't find a PHY yet */  	for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) { @@ -571,10 +864,11 @@ mii_discover_phy(void)  	if (phyaddr < 0) {  		printf("No PHY device found.\n");  	} +	return phyaddr;  }  #endif	/* CFG_DISCOVER_PHY */ -#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) +#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) && !defined(CONFIG_BITBANGMII)  static int mii_init_done = 0; @@ -585,17 +879,16 @@ static int mii_init_done = 0;   */  void mii_init (void)  { -	DECLARE_GLOBAL_DATA_PTR; -	bd_t *bd = gd->bd; -  	volatile immap_t *immr = (immap_t *) CFG_IMMR;  	volatile fec_t *fecp = &(immr->im_cpm.cp_fec); -	int i; +	int i, j;  	if (mii_init_done != 0) {  		return;  	} +	for (j = 0; j < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); j++) { +  	/* Whack a reset.  	 * A delay is required between a reset of the FEC block and  	 * initialization of other FEC registers because the reset takes @@ -623,76 +916,18 @@ void mii_init (void)  	 */  	fecp->fec_ievent = 0xffc0; -	/* Set MII speed to 2.5 MHz or slightly below. -	 * According to the MPC860T (Rev. D) Fast ethernet controller user -	 * manual (6.2.14), -	 * the MII management interface clock must be less than or equal -	 * to 2.5 MHz. -	 * This MDC frequency is equal to system clock / (2 * MII_SPEED). -	 * Then MII_SPEED = system_clock / 2 * 2,5 Mhz. -	 */ -	fecp->fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1; - -#if defined(CONFIG_DUET) /* MPC87x/88x have got 2 FECs and different pinout */ -	immr->im_ioport.iop_papar |=  0xf830; -	immr->im_ioport.iop_padir |=  0x0830; -	immr->im_ioport.iop_padir &= ~0xf000; -	immr->im_cpm.cp_pbpar     |=  0x00001001; -	immr->im_cpm.cp_pbdir     &= ~0x00001001; -	immr->im_ioport.iop_pcpar |=  0x000c; -	immr->im_ioport.iop_pcdir &= ~0x000c; -	immr->im_ioport.iop_pdpar |=  0x0080; -	immr->im_ioport.iop_pddir &= ~0x0080; -	immr->im_cpm.cp_pepar     |=  0x00000003; -	immr->im_cpm.cp_pedir     |=  0x00000003; -	immr->im_cpm.cp_peso      &= ~0x00000003; -#elif !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) -	/* Configure all of port D for MII. -	 */ -	immr->im_ioport.iop_pdpar = 0x1fff; - -	/* Bits moved from Rev. D onward */ -	if ((get_immr (0) & 0xffff) < 0x0501) { -		immr->im_ioport.iop_pddir = 0x1c58;	/* Pre rev. D */ -	} else { -		immr->im_ioport.iop_pddir = 0x1fff;	/* Rev. D and later */ -	} -#else -	/* Configure port A for MII. +		/* Setup the pin configuration of the FEC(s)  	*/ +		fec_pin_init(ether_fcc_info[i].ether_index); -#if defined(CONFIG_ICU862) - -	/* On the ICU862 board the MII-MDC pin is routed to PD8 pin -	 * of CPU, so for this board we need to configure Utopia and -	 * enable PD8 to MII-MDC function */ -	immr->im_ioport.iop_pdpar |= 0x4080; -#endif - -	/* Has Utopia been configured? */ -	if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) { -		/* -		 * YES - Use MUXED mode for UTOPIA bus. -		 * This frees Port A for use by MII (see 862UM table 41-6). -		 */ -		immr->im_ioport.utmode &= ~0x80; -	} else { -		/* -		 * NO - set SPLIT mode for UTOPIA bus. -		 * -		 * This doesn't really effect UTOPIA (which isn't -		 * enabled anyway) but just tells the 862 -		 * to use port A for MII (see 862UM table 41-6). -		 */ -		immr->im_ioport.utmode |= 0x80; -	} -#endif	/* !defined(CONFIG_ICU862) */  	/* Now enable the transmit and receive processing  	 */  	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; +	}  	mii_init_done = 1;  } +  /*****************************************************************************   * Read and write a MII PHY register, routines used by MII Utilities   * @@ -714,28 +949,23 @@ int miiphy_read(unsigned char addr, unsigned char  reg, unsigned short *value)  	rdreg = mii_send(mk_mii_read(addr, reg));  	*value = rdreg; -  #ifdef MII_DEBUG  	printf ("0x%04x\n", *value);  #endif -  	return 0;  }  int miiphy_write(unsigned char  addr, unsigned char  reg, unsigned short value)  {  	short rdreg;    /* register working value */ -  #ifdef MII_DEBUG  	printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);  #endif -  	rdreg = mii_send(mk_mii_write(addr, reg, value));  #ifdef MII_DEBUG  	printf ("0x%04x\n", value);  #endif -  	return 0;  }  #endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)*/ |