diff options
Diffstat (limited to 'drivers/net/tsec.c')
| -rw-r--r-- | drivers/net/tsec.c | 855 | 
1 files changed, 415 insertions, 440 deletions
| diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index a2705e1ca..a3857b3bb 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -44,31 +44,6 @@ static RTXBD rtx __attribute__ ((aligned(8)));  #error "rtx must be 64-bit aligned"  #endif -static int tsec_send(struct eth_device *dev, -		     volatile void *packet, int length); -static int tsec_recv(struct eth_device *dev); -static int tsec_init(struct eth_device *dev, bd_t * bd); -static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info); -static void tsec_halt(struct eth_device *dev); -static void init_registers(tsec_t *regs); -static void startup_tsec(struct eth_device *dev); -static int init_phy(struct eth_device *dev); -void write_phy_reg(struct tsec_private *priv, uint regnum, uint value); -uint read_phy_reg(struct tsec_private *priv, uint regnum); -static struct phy_info *get_phy_info(struct eth_device *dev); -static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd); -static void adjust_link(struct eth_device *dev); -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ -	&& !defined(BITBANGMII) -static int tsec_miiphy_write(const char *devname, unsigned char addr, -			     unsigned char reg, unsigned short value); -static int tsec_miiphy_read(const char *devname, unsigned char addr, -			    unsigned char reg, unsigned short *value); -#endif -#ifdef CONFIG_MCAST_TFTP -static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set); -#endif -  /* Default initializations for TSEC controllers. */  static struct tsec_info_struct tsec_info[] = { @@ -95,140 +70,6 @@ static struct tsec_info_struct tsec_info[] = {  #endif  }; -/* - * Initialize all the TSEC devices - * - * Returns the number of TSEC devices that were initialized - */ -int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num) -{ -	int i; -	int ret, count = 0; - -	for (i = 0; i < num; i++) { -		ret = tsec_initialize(bis, &tsecs[i]); -		if (ret > 0) -			count += ret; -	} - -	return count; -} - -int tsec_standard_init(bd_t *bis) -{ -	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info)); -} - -/* Initialize device structure. Returns success if PHY - * initialization succeeded (i.e. if it recognizes the PHY) - */ -static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info) -{ -	struct eth_device *dev; -	int i; -	struct tsec_private *priv; - -	dev = (struct eth_device *)malloc(sizeof *dev); - -	if (NULL == dev) -		return 0; - -	memset(dev, 0, sizeof *dev); - -	priv = (struct tsec_private *)malloc(sizeof(*priv)); - -	if (NULL == priv) -		return 0; - -	privlist[num_tsecs++] = priv; -	priv->regs = tsec_info->regs; -	priv->phyregs = tsec_info->miiregs; -	priv->phyregs_sgmii = tsec_info->miiregs_sgmii; - -	priv->phyaddr = tsec_info->phyaddr; -	priv->flags = tsec_info->flags; - -	sprintf(dev->name, tsec_info->devname); -	dev->iobase = 0; -	dev->priv = priv; -	dev->init = tsec_init; -	dev->halt = tsec_halt; -	dev->send = tsec_send; -	dev->recv = tsec_recv; -#ifdef CONFIG_MCAST_TFTP -	dev->mcast = tsec_mcast_addr; -#endif - -	/* Tell u-boot to get the addr from the env */ -	for (i = 0; i < 6; i++) -		dev->enetaddr[i] = 0; - -	eth_register(dev); - -	/* Reset the MAC */ -	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); -	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */ -	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ -	&& !defined(BITBANGMII) -	miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); -#endif - -	/* Try to initialize PHY here, and return */ -	return init_phy(dev); -} - -/* Initializes data structures and registers for the controller, - * and brings the interface up.	 Returns the link status, meaning - * that it returns success if the link is up, failure otherwise. - * This allows u-boot to find the first active controller. - */ -static int tsec_init(struct eth_device *dev, bd_t * bd) -{ -	uint tempval; -	char tmpbuf[MAC_ADDR_LEN]; -	int i; -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	tsec_t *regs = priv->regs; - -	/* Make sure the controller is stopped */ -	tsec_halt(dev); - -	/* Init MACCFG2.  Defaults to GMII */ -	out_be32(®s->maccfg2, MACCFG2_INIT_SETTINGS); - -	/* Init ECNTRL */ -	out_be32(®s->ecntrl, ECNTRL_INIT_SETTINGS); - -	/* Copy the station address into the address registers. -	 * Backwards, because little endian MACS are dumb */ -	for (i = 0; i < MAC_ADDR_LEN; i++) { -		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; -	} -	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | -		  tmpbuf[3]; - -	out_be32(®s->macstnaddr1, tempval); - -	tempval = *((uint *) (tmpbuf + 4)); - -	out_be32(®s->macstnaddr2, tempval); - -	/* reset the indices to zero */ -	rxIdx = 0; -	txIdx = 0; - -	/* Clear out (for the most part) the other registers */ -	init_registers(regs); - -	/* Ready the device for tx/rx */ -	startup_tsec(dev); - -	/* If there's no link, fail */ -	return (priv->link ? 0 : -1); -} -  /* Writes the given phy's reg with value, using the specified MDIO regs */  static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,  		uint reg, uint value) @@ -243,7 +84,6 @@ static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,  		;  } -  /* Provide the default behavior of writing the PHY of this ethernet device */  #define write_phy_reg(priv, regnum, value) \  	tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value) @@ -311,46 +151,6 @@ static void tsec_configure_serdes(struct tsec_private *priv)  			CONFIG_TSEC_TBICR_SETTINGS);  } -/* Discover which PHY is attached to the device, and configure it - * properly.  If the PHY is not recognized, then return 0 - * (failure).  Otherwise, return 1 - */ -static int init_phy(struct eth_device *dev) -{ -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	struct phy_info *curphy; -	tsec_t *regs = priv->regs; - -	/* Assign a Physical address to the TBI */ -	out_be32(®s->tbipa, CONFIG_SYS_TBIPA_VALUE); - -	/* Reset MII (due to new addresses) */ -	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET); -	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE); -	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY) -		; - -	/* Get the cmd structure corresponding to the attached -	 * PHY */ -	curphy = get_phy_info(dev); - -	if (curphy == NULL) { -		priv->phyinfo = NULL; -		printf("%s: No PHY found\n", dev->name); - -		return 0; -	} - -	if (in_be32(®s->ecntrl) & ECNTRL_SGMII_MODE) -		tsec_configure_serdes(priv); - -	priv->phyinfo = curphy; - -	phy_run_commands(priv, priv->phyinfo->config); - -	return 1; -} -  /*   * Returns which value to write to the control register.   * For 10/100, the value is slightly different @@ -866,246 +666,6 @@ static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)  	return mii_data;  } -/* Initialized required registers to appropriate values, zeroing - * those we don't care about (unless zero is bad, in which case, - * choose a more appropriate value) - */ -static void init_registers(tsec_t *regs) -{ -	/* Clear IEVENT */ -	out_be32(®s->ievent, IEVENT_INIT_CLEAR); - -	out_be32(®s->imask, IMASK_INIT_CLEAR); - -	out_be32(®s->hash.iaddr0, 0); -	out_be32(®s->hash.iaddr1, 0); -	out_be32(®s->hash.iaddr2, 0); -	out_be32(®s->hash.iaddr3, 0); -	out_be32(®s->hash.iaddr4, 0); -	out_be32(®s->hash.iaddr5, 0); -	out_be32(®s->hash.iaddr6, 0); -	out_be32(®s->hash.iaddr7, 0); - -	out_be32(®s->hash.gaddr0, 0); -	out_be32(®s->hash.gaddr1, 0); -	out_be32(®s->hash.gaddr2, 0); -	out_be32(®s->hash.gaddr3, 0); -	out_be32(®s->hash.gaddr4, 0); -	out_be32(®s->hash.gaddr5, 0); -	out_be32(®s->hash.gaddr6, 0); -	out_be32(®s->hash.gaddr7, 0); - -	out_be32(®s->rctrl, 0x00000000); - -	/* Init RMON mib registers */ -	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t)); - -	out_be32(®s->rmon.cam1, 0xffffffff); -	out_be32(®s->rmon.cam2, 0xffffffff); - -	out_be32(®s->mrblr, MRBLR_INIT_SETTINGS); - -	out_be32(®s->minflr, MINFLR_INIT_SETTINGS); - -	out_be32(®s->attr, ATTR_INIT_SETTINGS); -	out_be32(®s->attreli, ATTRELI_INIT_SETTINGS); - -} - -/* Configure maccfg2 based on negotiated speed and duplex - * reported by PHY handling code - */ -static void adjust_link(struct eth_device *dev) -{ -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	tsec_t *regs = priv->regs; -	u32 ecntrl, maccfg2; - -	if (!priv->link) { -		printf("%s: No link.\n", dev->name); -		return; -	} - -	/* clear all bits relative with interface mode */ -	ecntrl = in_be32(®s->ecntrl); -	ecntrl &= ~ECNTRL_R100; - -	maccfg2 = in_be32(®s->maccfg2); -	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX); - -	if (priv->duplexity) -		maccfg2 |= MACCFG2_FULL_DUPLEX; - -	switch (priv->speed) { -	case 1000: -		maccfg2 |= MACCFG2_GMII; -		break; -	case 100: -	case 10: -		maccfg2 |= MACCFG2_MII; - -		/* Set R100 bit in all modes although -		 * it is only used in RGMII mode -		 */ -		if (priv->speed == 100) -			ecntrl |= ECNTRL_R100; -		break; -	default: -		printf("%s: Speed was bad\n", dev->name); -		break; -	} - -	out_be32(®s->ecntrl, ecntrl); -	out_be32(®s->maccfg2, maccfg2); - -	printf("Speed: %d, %s duplex%s\n", priv->speed, -			(priv->duplexity) ? "full" : "half", -			(priv->flags & TSEC_FIBER) ? ", fiber mode" : ""); -} - -/* Set up the buffers and their descriptors, and bring up the - * interface - */ -static void startup_tsec(struct eth_device *dev) -{ -	int i; -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	tsec_t *regs = priv->regs; - -	/* Point to the buffer descriptors */ -	out_be32(®s->tbase, (unsigned int)(&rtx.txbd[txIdx])); -	out_be32(®s->rbase, (unsigned int)(&rtx.rxbd[rxIdx])); - -	/* Initialize the Rx Buffer descriptors */ -	for (i = 0; i < PKTBUFSRX; i++) { -		rtx.rxbd[i].status = RXBD_EMPTY; -		rtx.rxbd[i].length = 0; -		rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i]; -	} -	rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP; - -	/* Initialize the TX Buffer Descriptors */ -	for (i = 0; i < TX_BUF_CNT; i++) { -		rtx.txbd[i].status = 0; -		rtx.txbd[i].length = 0; -		rtx.txbd[i].bufPtr = 0; -	} -	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; - -	/* Start up the PHY */ -	if(priv->phyinfo) -		phy_run_commands(priv, priv->phyinfo->startup); - -	adjust_link(dev); - -	/* Enable Transmit and Receive */ -	setbits_be32(®s->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN); - -	/* Tell the DMA it is clear to go */ -	setbits_be32(®s->dmactrl, DMACTRL_INIT_SETTINGS); -	out_be32(®s->tstat, TSTAT_CLEAR_THALT); -	out_be32(®s->rstat, RSTAT_CLEAR_RHALT); -	clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); -} - -/* This returns the status bits of the device.	The return value - * is never checked, and this is what the 8260 driver did, so we - * do the same.	 Presumably, this would be zero if there were no - * errors - */ -static int tsec_send(struct eth_device *dev, volatile void *packet, int length) -{ -	int i; -	int result = 0; -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	tsec_t *regs = priv->regs; - -	/* Find an empty buffer descriptor */ -	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { -		if (i >= TOUT_LOOP) { -			debug("%s: tsec: tx buffers full\n", dev->name); -			return result; -		} -	} - -	rtx.txbd[txIdx].bufPtr = (uint) packet; -	rtx.txbd[txIdx].length = length; -	rtx.txbd[txIdx].status |= -	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT); - -	/* Tell the DMA to go */ -	out_be32(®s->tstat, TSTAT_CLEAR_THALT); - -	/* Wait for buffer to be transmitted */ -	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { -		if (i >= TOUT_LOOP) { -			debug("%s: tsec: tx error\n", dev->name); -			return result; -		} -	} - -	txIdx = (txIdx + 1) % TX_BUF_CNT; -	result = rtx.txbd[txIdx].status & TXBD_STATS; - -	return result; -} - -static int tsec_recv(struct eth_device *dev) -{ -	int length; -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	tsec_t *regs = priv->regs; - -	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { - -		length = rtx.rxbd[rxIdx].length; - -		/* Send the packet up if there were no errors */ -		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) { -			NetReceive(NetRxPackets[rxIdx], length - 4); -		} else { -			printf("Got error %x\n", -			       (rtx.rxbd[rxIdx].status & RXBD_STATS)); -		} - -		rtx.rxbd[rxIdx].length = 0; - -		/* Set the wrap bit if this is the last element in the list */ -		rtx.rxbd[rxIdx].status = -		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); - -		rxIdx = (rxIdx + 1) % PKTBUFSRX; -	} - -	if (in_be32(®s->ievent) & IEVENT_BSY) { -		out_be32(®s->ievent, IEVENT_BSY); -		out_be32(®s->rstat, RSTAT_CLEAR_RHALT); -	} - -	return -1; - -} - -/* Stop the interface */ -static void tsec_halt(struct eth_device *dev) -{ -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	tsec_t *regs = priv->regs; - -	clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); -	setbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); - -	while ((in_be32(®s->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) -			!= (IEVENT_GRSC | IEVENT_GTSC)) -		; - -	clrbits_be32(®s->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN); - -	/* Shut down the PHY, as needed */ -	if(priv->phyinfo) -		phy_run_commands(priv, priv->phyinfo->shutdown); -} -  static struct phy_info phy_info_M88E1149S = {  	0x1410ca,  	"Marvell 88E1149S", @@ -2025,3 +1585,418 @@ tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)  	return 0;  }  #endif /* Multicast TFTP ? */ + +/* Initialized required registers to appropriate values, zeroing + * those we don't care about (unless zero is bad, in which case, + * choose a more appropriate value) + */ +static void init_registers(tsec_t *regs) +{ +	/* Clear IEVENT */ +	out_be32(®s->ievent, IEVENT_INIT_CLEAR); + +	out_be32(®s->imask, IMASK_INIT_CLEAR); + +	out_be32(®s->hash.iaddr0, 0); +	out_be32(®s->hash.iaddr1, 0); +	out_be32(®s->hash.iaddr2, 0); +	out_be32(®s->hash.iaddr3, 0); +	out_be32(®s->hash.iaddr4, 0); +	out_be32(®s->hash.iaddr5, 0); +	out_be32(®s->hash.iaddr6, 0); +	out_be32(®s->hash.iaddr7, 0); + +	out_be32(®s->hash.gaddr0, 0); +	out_be32(®s->hash.gaddr1, 0); +	out_be32(®s->hash.gaddr2, 0); +	out_be32(®s->hash.gaddr3, 0); +	out_be32(®s->hash.gaddr4, 0); +	out_be32(®s->hash.gaddr5, 0); +	out_be32(®s->hash.gaddr6, 0); +	out_be32(®s->hash.gaddr7, 0); + +	out_be32(®s->rctrl, 0x00000000); + +	/* Init RMON mib registers */ +	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t)); + +	out_be32(®s->rmon.cam1, 0xffffffff); +	out_be32(®s->rmon.cam2, 0xffffffff); + +	out_be32(®s->mrblr, MRBLR_INIT_SETTINGS); + +	out_be32(®s->minflr, MINFLR_INIT_SETTINGS); + +	out_be32(®s->attr, ATTR_INIT_SETTINGS); +	out_be32(®s->attreli, ATTRELI_INIT_SETTINGS); + +} + +/* Configure maccfg2 based on negotiated speed and duplex + * reported by PHY handling code + */ +static void adjust_link(struct eth_device *dev) +{ +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	tsec_t *regs = priv->regs; +	u32 ecntrl, maccfg2; + +	if (!priv->link) { +		printf("%s: No link.\n", dev->name); +		return; +	} + +	/* clear all bits relative with interface mode */ +	ecntrl = in_be32(®s->ecntrl); +	ecntrl &= ~ECNTRL_R100; + +	maccfg2 = in_be32(®s->maccfg2); +	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX); + +	if (priv->duplexity) +		maccfg2 |= MACCFG2_FULL_DUPLEX; + +	switch (priv->speed) { +	case 1000: +		maccfg2 |= MACCFG2_GMII; +		break; +	case 100: +	case 10: +		maccfg2 |= MACCFG2_MII; + +		/* Set R100 bit in all modes although +		 * it is only used in RGMII mode +		 */ +		if (priv->speed == 100) +			ecntrl |= ECNTRL_R100; +		break; +	default: +		printf("%s: Speed was bad\n", dev->name); +		break; +	} + +	out_be32(®s->ecntrl, ecntrl); +	out_be32(®s->maccfg2, maccfg2); + +	printf("Speed: %d, %s duplex%s\n", priv->speed, +			(priv->duplexity) ? "full" : "half", +			(priv->flags & TSEC_FIBER) ? ", fiber mode" : ""); +} + +/* Set up the buffers and their descriptors, and bring up the + * interface + */ +static void startup_tsec(struct eth_device *dev) +{ +	int i; +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	tsec_t *regs = priv->regs; + +	/* Point to the buffer descriptors */ +	out_be32(®s->tbase, (unsigned int)(&rtx.txbd[txIdx])); +	out_be32(®s->rbase, (unsigned int)(&rtx.rxbd[rxIdx])); + +	/* Initialize the Rx Buffer descriptors */ +	for (i = 0; i < PKTBUFSRX; i++) { +		rtx.rxbd[i].status = RXBD_EMPTY; +		rtx.rxbd[i].length = 0; +		rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i]; +	} +	rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP; + +	/* Initialize the TX Buffer Descriptors */ +	for (i = 0; i < TX_BUF_CNT; i++) { +		rtx.txbd[i].status = 0; +		rtx.txbd[i].length = 0; +		rtx.txbd[i].bufPtr = 0; +	} +	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; + +	/* Start up the PHY */ +	if (priv->phyinfo) +		phy_run_commands(priv, priv->phyinfo->startup); + +	adjust_link(dev); + +	/* Enable Transmit and Receive */ +	setbits_be32(®s->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN); + +	/* Tell the DMA it is clear to go */ +	setbits_be32(®s->dmactrl, DMACTRL_INIT_SETTINGS); +	out_be32(®s->tstat, TSTAT_CLEAR_THALT); +	out_be32(®s->rstat, RSTAT_CLEAR_RHALT); +	clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); +} + +/* This returns the status bits of the device.	The return value + * is never checked, and this is what the 8260 driver did, so we + * do the same.	 Presumably, this would be zero if there were no + * errors + */ +static int tsec_send(struct eth_device *dev, volatile void *packet, int length) +{ +	int i; +	int result = 0; +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	tsec_t *regs = priv->regs; + +	/* Find an empty buffer descriptor */ +	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { +		if (i >= TOUT_LOOP) { +			debug("%s: tsec: tx buffers full\n", dev->name); +			return result; +		} +	} + +	rtx.txbd[txIdx].bufPtr = (uint) packet; +	rtx.txbd[txIdx].length = length; +	rtx.txbd[txIdx].status |= +	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT); + +	/* Tell the DMA to go */ +	out_be32(®s->tstat, TSTAT_CLEAR_THALT); + +	/* Wait for buffer to be transmitted */ +	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { +		if (i >= TOUT_LOOP) { +			debug("%s: tsec: tx error\n", dev->name); +			return result; +		} +	} + +	txIdx = (txIdx + 1) % TX_BUF_CNT; +	result = rtx.txbd[txIdx].status & TXBD_STATS; + +	return result; +} + +static int tsec_recv(struct eth_device *dev) +{ +	int length; +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	tsec_t *regs = priv->regs; + +	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { + +		length = rtx.rxbd[rxIdx].length; + +		/* Send the packet up if there were no errors */ +		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) { +			NetReceive(NetRxPackets[rxIdx], length - 4); +		} else { +			printf("Got error %x\n", +			       (rtx.rxbd[rxIdx].status & RXBD_STATS)); +		} + +		rtx.rxbd[rxIdx].length = 0; + +		/* Set the wrap bit if this is the last element in the list */ +		rtx.rxbd[rxIdx].status = +		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); + +		rxIdx = (rxIdx + 1) % PKTBUFSRX; +	} + +	if (in_be32(®s->ievent) & IEVENT_BSY) { +		out_be32(®s->ievent, IEVENT_BSY); +		out_be32(®s->rstat, RSTAT_CLEAR_RHALT); +	} + +	return -1; + +} + +/* Stop the interface */ +static void tsec_halt(struct eth_device *dev) +{ +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	tsec_t *regs = priv->regs; + +	clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); +	setbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); + +	while ((in_be32(®s->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) +			!= (IEVENT_GRSC | IEVENT_GTSC)) +		; + +	clrbits_be32(®s->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN); + +	/* Shut down the PHY, as needed */ +	if (priv->phyinfo) +		phy_run_commands(priv, priv->phyinfo->shutdown); +} + +/* Initializes data structures and registers for the controller, + * and brings the interface up.	 Returns the link status, meaning + * that it returns success if the link is up, failure otherwise. + * This allows u-boot to find the first active controller. + */ +static int tsec_init(struct eth_device *dev, bd_t * bd) +{ +	uint tempval; +	char tmpbuf[MAC_ADDR_LEN]; +	int i; +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	tsec_t *regs = priv->regs; + +	/* Make sure the controller is stopped */ +	tsec_halt(dev); + +	/* Init MACCFG2.  Defaults to GMII */ +	out_be32(®s->maccfg2, MACCFG2_INIT_SETTINGS); + +	/* Init ECNTRL */ +	out_be32(®s->ecntrl, ECNTRL_INIT_SETTINGS); + +	/* Copy the station address into the address registers. +	 * Backwards, because little endian MACS are dumb */ +	for (i = 0; i < MAC_ADDR_LEN; i++) +		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; + +	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | +		  tmpbuf[3]; + +	out_be32(®s->macstnaddr1, tempval); + +	tempval = *((uint *) (tmpbuf + 4)); + +	out_be32(®s->macstnaddr2, tempval); + +	/* reset the indices to zero */ +	rxIdx = 0; +	txIdx = 0; + +	/* Clear out (for the most part) the other registers */ +	init_registers(regs); + +	/* Ready the device for tx/rx */ +	startup_tsec(dev); + +	/* If there's no link, fail */ +	return priv->link ? 0 : -1; +} + +/* Discover which PHY is attached to the device, and configure it + * properly.  If the PHY is not recognized, then return 0 + * (failure).  Otherwise, return 1 + */ +static int init_phy(struct eth_device *dev) +{ +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	struct phy_info *curphy; +	tsec_t *regs = priv->regs; + +	/* Assign a Physical address to the TBI */ +	out_be32(®s->tbipa, CONFIG_SYS_TBIPA_VALUE); + +	/* Reset MII (due to new addresses) */ +	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET); +	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE); +	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY) +		; + +	/* Get the cmd structure corresponding to the attached +	 * PHY */ +	curphy = get_phy_info(dev); + +	if (curphy == NULL) { +		priv->phyinfo = NULL; +		printf("%s: No PHY found\n", dev->name); + +		return 0; +	} + +	if (in_be32(®s->ecntrl) & ECNTRL_SGMII_MODE) +		tsec_configure_serdes(priv); + +	priv->phyinfo = curphy; + +	phy_run_commands(priv, priv->phyinfo->config); + +	return 1; +} + +/* Initialize device structure. Returns success if PHY + * initialization succeeded (i.e. if it recognizes the PHY) + */ +static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info) +{ +	struct eth_device *dev; +	int i; +	struct tsec_private *priv; + +	dev = (struct eth_device *)malloc(sizeof *dev); + +	if (NULL == dev) +		return 0; + +	memset(dev, 0, sizeof *dev); + +	priv = (struct tsec_private *)malloc(sizeof(*priv)); + +	if (NULL == priv) +		return 0; + +	privlist[num_tsecs++] = priv; +	priv->regs = tsec_info->regs; +	priv->phyregs = tsec_info->miiregs; +	priv->phyregs_sgmii = tsec_info->miiregs_sgmii; + +	priv->phyaddr = tsec_info->phyaddr; +	priv->flags = tsec_info->flags; + +	sprintf(dev->name, tsec_info->devname); +	dev->iobase = 0; +	dev->priv = priv; +	dev->init = tsec_init; +	dev->halt = tsec_halt; +	dev->send = tsec_send; +	dev->recv = tsec_recv; +#ifdef CONFIG_MCAST_TFTP +	dev->mcast = tsec_mcast_addr; +#endif + +	/* Tell u-boot to get the addr from the env */ +	for (i = 0; i < 6; i++) +		dev->enetaddr[i] = 0; + +	eth_register(dev); + +	/* Reset the MAC */ +	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); +	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */ +	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ +	&& !defined(BITBANGMII) +	miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); +#endif + +	/* Try to initialize PHY here, and return */ +	return init_phy(dev); +} + +/* + * Initialize all the TSEC devices + * + * Returns the number of TSEC devices that were initialized + */ +int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num) +{ +	int i; +	int ret, count = 0; + +	for (i = 0; i < num; i++) { +		ret = tsec_initialize(bis, &tsecs[i]); +		if (ret > 0) +			count += ret; +	} + +	return count; +} + +int tsec_standard_init(bd_t *bis) +{ +	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info)); +} + |