⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fec.c.svn-base

📁 PowerPC850系列的產品開機程式uboot是linuxOS BASED的程式碼
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
#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_MPC885_FAMILY */#endif /* CONFIG_ETHER_ON_FEC2 */	}}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_MPC885ADS)		*(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_MPC885ADS */#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	 * some time to complete. If you don't delay, subsequent writes	 * to FEC registers might get killed by the reset routine which is	 * still in progress.	 */	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;	for (i = 0;	     (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);	     ++i) {		udelay (1);	}	if (i == FEC_RESET_DELAY) {		printf ("FEC_RESET_DELAY timeout\n");		return 0;	}	/* We use strictly polling mode only	 */	fecp->fec_imask = 0;	/* Clear any pending interrupt	 */	fecp->fec_ievent = 0xffc0;	/* No need to set the IVEC register */	/* 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]);#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;#endif	/* Set maximum receive buffer size.	 */	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;	/* Set maximum frame length	 */	fecp->fec_r_hash = PKT_MAXBUF_SIZE;	/*	 * Setup Buffers and Buffer Desriptors	 */	rxIdx = 0;	txIdx = 0;	if (!rtx) {#ifdef CFG_ALLOC_DPRAM		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +				 dpram_alloc_align (sizeof (RTXBD), 8));#else		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);#endif	}	/*	 * Setup Receiver Buffer Descriptors (13.14.24.18)	 * Settings:	 *     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_bufaddr = (uint) NetRxPackets[i];	}	rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;	/*	 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)	 * Settings:	 *    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_bufaddr = (uint) (&txbuf[0]);	}	rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;	/* Set receive and transmit descriptor base	 */	fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);	fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);	/* Enable MII 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 */	fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;	fecp->fec_x_cntrl = 0;#endif	/* Enable big endian and don't care about SDMA FC.	 */	fecp->fec_fun_code = 0x78000000;	/*	 * Setup the pin configuration of the FEC	 */	fec_pin_init (efis->ether_index);	rxIdx = 0;	txIdx = 0;	/*	 * Now enable the transmit and receive processing	 */	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;	if (efis->phy_addr == -1) {#ifdef CFG_DISCOVER_PHY		/*		 * wait for the PHY to wake up after reset		 */		efis->actual_phy_addr = mii_discover_phy (dev);		if (efis->actual_phy_addr == -1) {			printf ("Unable to discover phy!\n");			return 0;		}#else		efis->actual_phy_addr = -1;#endif	} else {		efis->actual_phy_addr = efis->phy_addr;	}#if defined(CONFIG_MII) && defined(CONFIG_RMII)	/* the MII interface is connected to FEC1	 * so for the miiphy_xxx function to work we must	 * call mii_init since fec_halt messes the thing up	 */	if (efis->ether_index != 0)		mii_init();	/*	 * adapt the RMII speed to the speed of the phy	 */	if (miiphy_speed (dev->name, efis->actual_phy_addr) == _100BASET) {		fec_100Mbps (dev);	} else {		fec_10Mbps (dev);	}#endif#if defined(CONFIG_MII)	/*	 * adapt to the half/full speed settings	 */	if (miiphy_duplex (dev->name, 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    */	efis->initialized = 1;	return 1;}static void fec_halt(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 i;	/* avoid halt if initialized; mii gets stuck otherwise */	if (!efis->initialized)		return;	/* Whack a reset.	 * A delay is required between a reset of the FEC block and	 * initialization of other FEC registers because the reset takes	 * some time to complete. If you don't delay, subsequent writes	 * to FEC registers might get killed by the reset routine which is	 * still in progress.	 */	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;	for (i = 0;	     (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);	     ++i) {		udelay (1);	}	if (i == FEC_RESET_DELAY) {		printf ("FEC_RESET_DELAY timeout\n");		return;	}	efis->initialized = 0;}#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)/* Make MII read/write commands for the FEC.*/#define mk_mii_read(ADDR, REG)	(0x60020000 | ((ADDR << 23) | \						(REG & 0x1f) << 18))#define mk_mii_write(ADDR, REG, VAL)	(0x50020000 | ((ADDR << 23) | \						(REG & 0x1f) << 18) | \						(VAL & 0xffff))/* Interrupt events/masks.*/#define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */#define FEC_ENET_BABR	((uint)0x40000000)	/* Babbling receiver */#define FEC_ENET_BABT	((uint)0x20000000)	/* Babbling transmitter */#define FEC_ENET_GRA	((uint)0x10000000)	/* Graceful stop complete */#define FEC_ENET_TXF	((uint)0x08000000)	/* Full frame transmitted */#define FEC_ENET_TXB	((uint)0x04000000)	/* A buffer was transmitted */#define FEC_ENET_RXF	((uint)0x02000000)	/* Full frame received */#define FEC_ENET_RXB	((uint)0x01000000)	/* A buffer was received */#define FEC_ENET_MII	((uint)0x00800000)	/* MII interrupt */#define FEC_ENET_EBERR	((uint)0x00400000)	/* SDMA bus error *//* PHY identification */#define PHY_ID_LXT970		0x78100000	/* LXT970 */#define PHY_ID_LXT971		0x001378e0	/* LXT971 and 972 */#define PHY_ID_82555		0x02a80150	/* Intel 82555 */#define PHY_ID_QS6612		0x01814400	/* QS6612 */#define PHY_ID_AMD79C784	0x00225610	/* AMD 79C784 */#define PHY_ID_LSI80225		0x0016f870	/* LSI 80225 */#define PHY_ID_LSI80225B	0x0016f880	/* LSI 80225/B */#define PHY_ID_DM9161		0x0181B880	/* Davicom DM9161 *//* send command to phy using mii, wait for result */static uintmii_send(uint mii_cmd){	uint mii_reply;	volatile fec_t	*ep;	int cnt;	ep = &(((immap_t *)CFG_IMMR)->im_cpm.cp_fec);	ep->fec_mii_data = mii_cmd;	/* command to phy */	/* wait for mii complete */	cnt = 0;	while (!(ep->fec_ievent & FEC_ENET_MII)) {		if (++cnt > 1000) {			printf("mii_send STUCK!\n");			break;		}	}	mii_reply = ep->fec_mii_data;		/* result from phy */	ep->fec_ievent = FEC_ENET_MII;		/* clear MII complete */#if 0	printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",		__FILE__,__LINE__,__FUNCTION__,mii_cmd,mii_reply);#endif	return (mii_reply & 0xffff);		/* data read from phy */}#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */#if defined(CFG_DISCOVER_PHY)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) {		if (pass > 1) {			/* PHY may need more time to recover from reset.			 * The LXT970 needs 50ms typical, no maximum is			 * specified, so wait 10ms before try again.			 * With 11 passes this gives it 100ms to wake up.			 */			udelay(10000);	/* wait 10ms */		}		for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {			phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR1));#ifdef ET_DEBUG			printf("PHY type 0x%x pass %d type ", phytype, pass);#endif			if (phytype != 0xffff) {				phyaddr = phyno;				phytype <<= 16;				phytype |= mii_send(mk_mii_read(phyno,								PHY_PHYIDR2));#ifdef ET_DEBUG				printf("PHY @ 0x%x pass %d type ",phyno,pass);				switch (phytype & 0xfffffff0) {				case PHY_ID_LXT970:					printf("LXT970\n");					break;				case PHY_ID_LXT971:					printf("LXT971\n");					break;				case PHY_ID_82555:					printf("82555\n");					break;				case PHY_ID_QS6612:					printf("QS6612\n");					break;				case PHY_ID_AMD79C784:					printf("AMD79C784\n");					break;				case PHY_ID_LSI80225B:					printf("LSI L80225/B\n");					break;				case PHY_ID_DM9161:					printf("Davicom DM9161\n");					break;				default:					printf("0x%08x\n", phytype);					break;				}#endif			}		}	}	if (phyaddr < 0) {		printf("No PHY device found.\n");	}	return phyaddr;}#endif	/* CFG_DISCOVER_PHY */#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) && !defined(CONFIG_BITBANGMII)/**************************************************************************** * mii_init -- Initialize the MII for MII command without ethernet * This function is a subset of eth_init **************************************************************************** */void mii_init (void){	volatile immap_t *immr = (immap_t *) CFG_IMMR;	volatile fec_t *fecp = &(immr->im_cpm.cp_fec);	int i, j;	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	 * some time to complete. If you don't delay, subsequent writes	 * to FEC registers might get killed by the reset routine which is	 * still in progress.	 */	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;	for (i = 0;	     (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);	     ++i) {		udelay (1);	}	if (i == FEC_RESET_DELAY) {		printf ("FEC_RESET_DELAY timeout\n");		return;	}	/* We use strictly polling mode only	 */	fecp->fec_imask = 0;	/* Clear any pending interrupt	 */	fecp->fec_ievent = 0xffc0;	/* Setup the pin configuration of the FEC(s)	*/		fec_pin_init(ether_fcc_info[i].ether_index);	/* Now enable the transmit and receive processing	 */	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;	}}/***************************************************************************** * Read and write a MII PHY register, routines used by MII Utilities * * FIXME: These routines are expected to return 0 on success, but mii_send *	  does _not_ return an error code. Maybe 0xFFFF means error, i.e. *	  no PHY connected... *	  For now always return 0. * FIXME: These routines only work after calling eth_init() at least once! *	  Otherwise they hang in mii_send() !!! Sorry! *****************************************************************************/int fec8xx_miiphy_read(char *devname, unsigned char addr,		unsigned char  reg, unsigned short *value){	short rdreg;    /* register working value */#ifdef MII_DEBUG	printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr);#endif	rdreg = mii_send(mk_mii_read(addr, reg));	*value = rdreg;#ifdef MII_DEBUG	printf ("0x%04x\n", *value);#endif	return 0;}int fec8xx_miiphy_write(char *devname, 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)*/#endif	/* CFG_CMD_NET, FEC_ENET */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -