xref: /rk3399_rockchip-uboot/drivers/net/tsec.c (revision 11af8d65274df736deeb651d12e0763eec527ea5)
12439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
22439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Freescale Three Speed Ethernet Controller driver
32439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
42439e4bfSJean-Christophe PLAGNIOL-VILLARD  * This software may be used and distributed according to the
52439e4bfSJean-Christophe PLAGNIOL-VILLARD  * terms of the GNU Public License, Version 2, incorporated
62439e4bfSJean-Christophe PLAGNIOL-VILLARD  * herein by reference.
72439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
8a32a6be2SMingkai Hu  * Copyright 2004-2011 Freescale Semiconductor, Inc.
92439e4bfSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2003, Motorola, Inc.
102439e4bfSJean-Christophe PLAGNIOL-VILLARD  * author Andy Fleming
112439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
122439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
132439e4bfSJean-Christophe PLAGNIOL-VILLARD 
142439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <config.h>
152439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
162439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h>
172439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
182439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h>
19dd3d1f56SAndy Fleming #include <tsec.h>
20063c1263SAndy Fleming #include <fsl_mdio.h>
210d071cddSKim Phillips #include <asm/errno.h>
22aada81deSchenhui zhao #include <asm/processor.h>
232439e4bfSJean-Christophe PLAGNIOL-VILLARD 
242439e4bfSJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR;
252439e4bfSJean-Christophe PLAGNIOL-VILLARD 
262439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_BUF_CNT		2
272439e4bfSJean-Christophe PLAGNIOL-VILLARD 
282439e4bfSJean-Christophe PLAGNIOL-VILLARD static uint rxIdx;		/* index of the current RX buffer */
292439e4bfSJean-Christophe PLAGNIOL-VILLARD static uint txIdx;		/* index of the current TX buffer */
302439e4bfSJean-Christophe PLAGNIOL-VILLARD 
312439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef volatile struct rtxbd {
322439e4bfSJean-Christophe PLAGNIOL-VILLARD 	txbd8_t txbd[TX_BUF_CNT];
332439e4bfSJean-Christophe PLAGNIOL-VILLARD 	rxbd8_t rxbd[PKTBUFSRX];
342439e4bfSJean-Christophe PLAGNIOL-VILLARD } RTXBD;
352439e4bfSJean-Christophe PLAGNIOL-VILLARD 
3675b9d4aeSAndy Fleming #define MAXCONTROLLERS	(8)
372439e4bfSJean-Christophe PLAGNIOL-VILLARD 
382439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct tsec_private *privlist[MAXCONTROLLERS];
3975b9d4aeSAndy Fleming static int num_tsecs = 0;
402439e4bfSJean-Christophe PLAGNIOL-VILLARD 
412439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef __GNUC__
422439e4bfSJean-Christophe PLAGNIOL-VILLARD static RTXBD rtx __attribute__ ((aligned(8)));
432439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
442439e4bfSJean-Christophe PLAGNIOL-VILLARD #error "rtx must be 64-bit aligned"
452439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
462439e4bfSJean-Christophe PLAGNIOL-VILLARD 
47c8a60b53SJoe Hershberger static int tsec_send(struct eth_device *dev, void *packet, int length);
48aada81deSchenhui zhao 
4975b9d4aeSAndy Fleming /* Default initializations for TSEC controllers. */
5075b9d4aeSAndy Fleming 
5175b9d4aeSAndy Fleming static struct tsec_info_struct tsec_info[] = {
5275b9d4aeSAndy Fleming #ifdef CONFIG_TSEC1
5375b9d4aeSAndy Fleming 	STD_TSEC_INFO(1),	/* TSEC1 */
5475b9d4aeSAndy Fleming #endif
5575b9d4aeSAndy Fleming #ifdef CONFIG_TSEC2
5675b9d4aeSAndy Fleming 	STD_TSEC_INFO(2),	/* TSEC2 */
5775b9d4aeSAndy Fleming #endif
5875b9d4aeSAndy Fleming #ifdef CONFIG_MPC85XX_FEC
5975b9d4aeSAndy Fleming 	{
6075b9d4aeSAndy Fleming 		.regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000),
6175b9d4aeSAndy Fleming 		.devname = CONFIG_MPC85XX_FEC_NAME,
6275b9d4aeSAndy Fleming 		.phyaddr = FEC_PHY_ADDR,
63063c1263SAndy Fleming 		.flags = FEC_FLAGS,
64063c1263SAndy Fleming 		.mii_devname = DEFAULT_MII_NAME
6575b9d4aeSAndy Fleming 	},			/* FEC */
6675b9d4aeSAndy Fleming #endif
6775b9d4aeSAndy Fleming #ifdef CONFIG_TSEC3
6875b9d4aeSAndy Fleming 	STD_TSEC_INFO(3),	/* TSEC3 */
6975b9d4aeSAndy Fleming #endif
7075b9d4aeSAndy Fleming #ifdef CONFIG_TSEC4
7175b9d4aeSAndy Fleming 	STD_TSEC_INFO(4),	/* TSEC4 */
7275b9d4aeSAndy Fleming #endif
7375b9d4aeSAndy Fleming };
7475b9d4aeSAndy Fleming 
752abe361cSAndy Fleming #define TBIANA_SETTINGS ( \
762abe361cSAndy Fleming 		TBIANA_ASYMMETRIC_PAUSE \
772abe361cSAndy Fleming 		| TBIANA_SYMMETRIC_PAUSE \
782abe361cSAndy Fleming 		| TBIANA_FULL_DUPLEX \
792abe361cSAndy Fleming 		)
802abe361cSAndy Fleming 
8190b5bf21SFelix Radensky /* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
8290b5bf21SFelix Radensky #ifndef CONFIG_TSEC_TBICR_SETTINGS
8372c96a68SKumar Gala #define CONFIG_TSEC_TBICR_SETTINGS ( \
842abe361cSAndy Fleming 		TBICR_PHY_RESET \
8572c96a68SKumar Gala 		| TBICR_ANEG_ENABLE \
862abe361cSAndy Fleming 		| TBICR_FULL_DUPLEX \
872abe361cSAndy Fleming 		| TBICR_SPEED1_SET \
882abe361cSAndy Fleming 		)
8990b5bf21SFelix Radensky #endif /* CONFIG_TSEC_TBICR_SETTINGS */
9046e91674SPeter Tyser 
912abe361cSAndy Fleming /* Configure the TBI for SGMII operation */
922abe361cSAndy Fleming static void tsec_configure_serdes(struct tsec_private *priv)
932abe361cSAndy Fleming {
94c6dbdfdaSPeter Tyser 	/* Access TBI PHY registers at given TSEC register offset as opposed
95c6dbdfdaSPeter Tyser 	 * to the register offset used for external PHY accesses */
96063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
97063c1263SAndy Fleming 			0, TBI_ANA, TBIANA_SETTINGS);
98063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
99063c1263SAndy Fleming 			0, TBI_TBICON, TBICON_CLK_SELECT);
100063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
101063c1263SAndy Fleming 			0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
1022439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1032439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1042439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MCAST_TFTP
1052439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1062439e4bfSJean-Christophe PLAGNIOL-VILLARD /* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
1072439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1082439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the appropriate hash bit for the given addr */
1092439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1102439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The algorithm works like so:
1112439e4bfSJean-Christophe PLAGNIOL-VILLARD  * 1) Take the Destination Address (ie the multicast address), and
1122439e4bfSJean-Christophe PLAGNIOL-VILLARD  * do a CRC on it (little endian), and reverse the bits of the
1132439e4bfSJean-Christophe PLAGNIOL-VILLARD  * result.
1142439e4bfSJean-Christophe PLAGNIOL-VILLARD  * 2) Use the 8 most significant bits as a hash into a 256-entry
1152439e4bfSJean-Christophe PLAGNIOL-VILLARD  * table.  The table is controlled through 8 32-bit registers:
1162439e4bfSJean-Christophe PLAGNIOL-VILLARD  * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is
1172439e4bfSJean-Christophe PLAGNIOL-VILLARD  * gaddr7.  This means that the 3 most significant bits in the
1182439e4bfSJean-Christophe PLAGNIOL-VILLARD  * hash index which gaddr register to use, and the 5 other bits
1192439e4bfSJean-Christophe PLAGNIOL-VILLARD  * indicate which bit (assuming an IBM numbering scheme, which
1202439e4bfSJean-Christophe PLAGNIOL-VILLARD  * for PowerPC (tm) is usually the case) in the tregister holds
1212439e4bfSJean-Christophe PLAGNIOL-VILLARD  * the entry. */
1222439e4bfSJean-Christophe PLAGNIOL-VILLARD static int
1232439e4bfSJean-Christophe PLAGNIOL-VILLARD tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
1242439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1252439e4bfSJean-Christophe PLAGNIOL-VILLARD 	struct tsec_private *priv = privlist[1];
1262439e4bfSJean-Christophe PLAGNIOL-VILLARD 	volatile tsec_t *regs = priv->regs;
1272439e4bfSJean-Christophe PLAGNIOL-VILLARD 	volatile u32  *reg_array, value;
1282439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u8 result, whichbit, whichreg;
1292439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1302439e4bfSJean-Christophe PLAGNIOL-VILLARD 	result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff);
1312439e4bfSJean-Christophe PLAGNIOL-VILLARD 	whichbit = result & 0x1f;	/* the 5 LSB = which bit to set */
1322439e4bfSJean-Christophe PLAGNIOL-VILLARD 	whichreg = result >> 5;		/* the 3 MSB = which reg to set it in */
1332439e4bfSJean-Christophe PLAGNIOL-VILLARD 	value = (1 << (31-whichbit));
1342439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1352439e4bfSJean-Christophe PLAGNIOL-VILLARD 	reg_array = &(regs->hash.gaddr0);
1362439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1372439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (set) {
1382439e4bfSJean-Christophe PLAGNIOL-VILLARD 		reg_array[whichreg] |= value;
1392439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {
1402439e4bfSJean-Christophe PLAGNIOL-VILLARD 		reg_array[whichreg] &= ~value;
1412439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1422439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
1432439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1442439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* Multicast TFTP ? */
14590751910SMingkai Hu 
14690751910SMingkai Hu /* Initialized required registers to appropriate values, zeroing
14790751910SMingkai Hu  * those we don't care about (unless zero is bad, in which case,
14890751910SMingkai Hu  * choose a more appropriate value)
14990751910SMingkai Hu  */
15090751910SMingkai Hu static void init_registers(tsec_t *regs)
15190751910SMingkai Hu {
15290751910SMingkai Hu 	/* Clear IEVENT */
15390751910SMingkai Hu 	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
15490751910SMingkai Hu 
15590751910SMingkai Hu 	out_be32(&regs->imask, IMASK_INIT_CLEAR);
15690751910SMingkai Hu 
15790751910SMingkai Hu 	out_be32(&regs->hash.iaddr0, 0);
15890751910SMingkai Hu 	out_be32(&regs->hash.iaddr1, 0);
15990751910SMingkai Hu 	out_be32(&regs->hash.iaddr2, 0);
16090751910SMingkai Hu 	out_be32(&regs->hash.iaddr3, 0);
16190751910SMingkai Hu 	out_be32(&regs->hash.iaddr4, 0);
16290751910SMingkai Hu 	out_be32(&regs->hash.iaddr5, 0);
16390751910SMingkai Hu 	out_be32(&regs->hash.iaddr6, 0);
16490751910SMingkai Hu 	out_be32(&regs->hash.iaddr7, 0);
16590751910SMingkai Hu 
16690751910SMingkai Hu 	out_be32(&regs->hash.gaddr0, 0);
16790751910SMingkai Hu 	out_be32(&regs->hash.gaddr1, 0);
16890751910SMingkai Hu 	out_be32(&regs->hash.gaddr2, 0);
16990751910SMingkai Hu 	out_be32(&regs->hash.gaddr3, 0);
17090751910SMingkai Hu 	out_be32(&regs->hash.gaddr4, 0);
17190751910SMingkai Hu 	out_be32(&regs->hash.gaddr5, 0);
17290751910SMingkai Hu 	out_be32(&regs->hash.gaddr6, 0);
17390751910SMingkai Hu 	out_be32(&regs->hash.gaddr7, 0);
17490751910SMingkai Hu 
17590751910SMingkai Hu 	out_be32(&regs->rctrl, 0x00000000);
17690751910SMingkai Hu 
17790751910SMingkai Hu 	/* Init RMON mib registers */
17890751910SMingkai Hu 	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
17990751910SMingkai Hu 
18090751910SMingkai Hu 	out_be32(&regs->rmon.cam1, 0xffffffff);
18190751910SMingkai Hu 	out_be32(&regs->rmon.cam2, 0xffffffff);
18290751910SMingkai Hu 
18390751910SMingkai Hu 	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
18490751910SMingkai Hu 
18590751910SMingkai Hu 	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
18690751910SMingkai Hu 
18790751910SMingkai Hu 	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
18890751910SMingkai Hu 	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
18990751910SMingkai Hu 
19090751910SMingkai Hu }
19190751910SMingkai Hu 
19290751910SMingkai Hu /* Configure maccfg2 based on negotiated speed and duplex
19390751910SMingkai Hu  * reported by PHY handling code
19490751910SMingkai Hu  */
195063c1263SAndy Fleming static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
19690751910SMingkai Hu {
19790751910SMingkai Hu 	tsec_t *regs = priv->regs;
19890751910SMingkai Hu 	u32 ecntrl, maccfg2;
19990751910SMingkai Hu 
200063c1263SAndy Fleming 	if (!phydev->link) {
201063c1263SAndy Fleming 		printf("%s: No link.\n", phydev->dev->name);
20290751910SMingkai Hu 		return;
20390751910SMingkai Hu 	}
20490751910SMingkai Hu 
20590751910SMingkai Hu 	/* clear all bits relative with interface mode */
20690751910SMingkai Hu 	ecntrl = in_be32(&regs->ecntrl);
20790751910SMingkai Hu 	ecntrl &= ~ECNTRL_R100;
20890751910SMingkai Hu 
20990751910SMingkai Hu 	maccfg2 = in_be32(&regs->maccfg2);
21090751910SMingkai Hu 	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
21190751910SMingkai Hu 
212063c1263SAndy Fleming 	if (phydev->duplex)
21390751910SMingkai Hu 		maccfg2 |= MACCFG2_FULL_DUPLEX;
21490751910SMingkai Hu 
215063c1263SAndy Fleming 	switch (phydev->speed) {
21690751910SMingkai Hu 	case 1000:
21790751910SMingkai Hu 		maccfg2 |= MACCFG2_GMII;
21890751910SMingkai Hu 		break;
21990751910SMingkai Hu 	case 100:
22090751910SMingkai Hu 	case 10:
22190751910SMingkai Hu 		maccfg2 |= MACCFG2_MII;
22290751910SMingkai Hu 
22390751910SMingkai Hu 		/* Set R100 bit in all modes although
22490751910SMingkai Hu 		 * it is only used in RGMII mode
22590751910SMingkai Hu 		 */
226063c1263SAndy Fleming 		if (phydev->speed == 100)
22790751910SMingkai Hu 			ecntrl |= ECNTRL_R100;
22890751910SMingkai Hu 		break;
22990751910SMingkai Hu 	default:
230063c1263SAndy Fleming 		printf("%s: Speed was bad\n", phydev->dev->name);
23190751910SMingkai Hu 		break;
23290751910SMingkai Hu 	}
23390751910SMingkai Hu 
23490751910SMingkai Hu 	out_be32(&regs->ecntrl, ecntrl);
23590751910SMingkai Hu 	out_be32(&regs->maccfg2, maccfg2);
23690751910SMingkai Hu 
237063c1263SAndy Fleming 	printf("Speed: %d, %s duplex%s\n", phydev->speed,
238063c1263SAndy Fleming 			(phydev->duplex) ? "full" : "half",
239063c1263SAndy Fleming 			(phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
24090751910SMingkai Hu }
24190751910SMingkai Hu 
242aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
243aada81deSchenhui zhao /*
244aada81deSchenhui zhao  * When MACCFG1[Rx_EN] is enabled during system boot as part
245aada81deSchenhui zhao  * of the eTSEC port initialization sequence,
246aada81deSchenhui zhao  * the eTSEC Rx logic may not be properly initialized.
247aada81deSchenhui zhao  */
248aada81deSchenhui zhao void redundant_init(struct eth_device *dev)
249aada81deSchenhui zhao {
250aada81deSchenhui zhao 	struct tsec_private *priv = dev->priv;
251aada81deSchenhui zhao 	tsec_t *regs = priv->regs;
252aada81deSchenhui zhao 	uint t, count = 0;
253aada81deSchenhui zhao 	int fail = 1;
254aada81deSchenhui zhao 	static const u8 pkt[] = {
255aada81deSchenhui zhao 		0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25,
256aada81deSchenhui zhao 		0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00,
257aada81deSchenhui zhao 		0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01,
258aada81deSchenhui zhao 		0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1,
259aada81deSchenhui zhao 		0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00,
260aada81deSchenhui zhao 		0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
261aada81deSchenhui zhao 		0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
262aada81deSchenhui zhao 		0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
263aada81deSchenhui zhao 		0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
264aada81deSchenhui zhao 		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
265aada81deSchenhui zhao 		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
266aada81deSchenhui zhao 		0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
267aada81deSchenhui zhao 		0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
268aada81deSchenhui zhao 		0x71, 0x72};
269aada81deSchenhui zhao 
270aada81deSchenhui zhao 	/* Enable promiscuous mode */
271aada81deSchenhui zhao 	setbits_be32(&regs->rctrl, 0x8);
272aada81deSchenhui zhao 	/* Enable loopback mode */
273aada81deSchenhui zhao 	setbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
274aada81deSchenhui zhao 	/* Enable transmit and receive */
275aada81deSchenhui zhao 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
276aada81deSchenhui zhao 
277aada81deSchenhui zhao 	/* Tell the DMA it is clear to go */
278aada81deSchenhui zhao 	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
279aada81deSchenhui zhao 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
280aada81deSchenhui zhao 	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
281aada81deSchenhui zhao 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
282aada81deSchenhui zhao 
283aada81deSchenhui zhao 	do {
284aada81deSchenhui zhao 		tsec_send(dev, (void *)pkt, sizeof(pkt));
285aada81deSchenhui zhao 
286aada81deSchenhui zhao 		/* Wait for buffer to be received */
287aada81deSchenhui zhao 		for (t = 0; rtx.rxbd[rxIdx].status & RXBD_EMPTY; t++) {
288aada81deSchenhui zhao 			if (t >= 10 * TOUT_LOOP) {
289aada81deSchenhui zhao 				printf("%s: tsec: rx error\n", dev->name);
290aada81deSchenhui zhao 				break;
291aada81deSchenhui zhao 			}
292aada81deSchenhui zhao 		}
293aada81deSchenhui zhao 
294aada81deSchenhui zhao 		if (!memcmp(pkt, (void *)NetRxPackets[rxIdx], sizeof(pkt)))
295aada81deSchenhui zhao 			fail = 0;
296aada81deSchenhui zhao 
297aada81deSchenhui zhao 		rtx.rxbd[rxIdx].length = 0;
298aada81deSchenhui zhao 		rtx.rxbd[rxIdx].status =
299aada81deSchenhui zhao 		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
300aada81deSchenhui zhao 		rxIdx = (rxIdx + 1) % PKTBUFSRX;
301aada81deSchenhui zhao 
302aada81deSchenhui zhao 		if (in_be32(&regs->ievent) & IEVENT_BSY) {
303aada81deSchenhui zhao 			out_be32(&regs->ievent, IEVENT_BSY);
304aada81deSchenhui zhao 			out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
305aada81deSchenhui zhao 		}
306aada81deSchenhui zhao 		if (fail) {
307aada81deSchenhui zhao 			printf("loopback recv packet error!\n");
308aada81deSchenhui zhao 			clrbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
309aada81deSchenhui zhao 			udelay(1000);
310aada81deSchenhui zhao 			setbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
311aada81deSchenhui zhao 		}
312aada81deSchenhui zhao 	} while ((count++ < 4) && (fail == 1));
313aada81deSchenhui zhao 
314aada81deSchenhui zhao 	if (fail)
315aada81deSchenhui zhao 		panic("eTSEC init fail!\n");
316aada81deSchenhui zhao 	/* Disable promiscuous mode */
317aada81deSchenhui zhao 	clrbits_be32(&regs->rctrl, 0x8);
318aada81deSchenhui zhao 	/* Disable loopback mode */
319aada81deSchenhui zhao 	clrbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
320aada81deSchenhui zhao }
321aada81deSchenhui zhao #endif
322aada81deSchenhui zhao 
32390751910SMingkai Hu /* Set up the buffers and their descriptors, and bring up the
32490751910SMingkai Hu  * interface
32590751910SMingkai Hu  */
32690751910SMingkai Hu static void startup_tsec(struct eth_device *dev)
32790751910SMingkai Hu {
32890751910SMingkai Hu 	int i;
32990751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
33090751910SMingkai Hu 	tsec_t *regs = priv->regs;
33190751910SMingkai Hu 
332063c1263SAndy Fleming 	/* reset the indices to zero */
333063c1263SAndy Fleming 	rxIdx = 0;
334063c1263SAndy Fleming 	txIdx = 0;
335aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
336aada81deSchenhui zhao 	uint svr;
337aada81deSchenhui zhao #endif
338063c1263SAndy Fleming 
33990751910SMingkai Hu 	/* Point to the buffer descriptors */
34090751910SMingkai Hu 	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
34190751910SMingkai Hu 	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
34290751910SMingkai Hu 
34390751910SMingkai Hu 	/* Initialize the Rx Buffer descriptors */
34490751910SMingkai Hu 	for (i = 0; i < PKTBUFSRX; i++) {
34590751910SMingkai Hu 		rtx.rxbd[i].status = RXBD_EMPTY;
34690751910SMingkai Hu 		rtx.rxbd[i].length = 0;
34790751910SMingkai Hu 		rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i];
34890751910SMingkai Hu 	}
34990751910SMingkai Hu 	rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
35090751910SMingkai Hu 
35190751910SMingkai Hu 	/* Initialize the TX Buffer Descriptors */
35290751910SMingkai Hu 	for (i = 0; i < TX_BUF_CNT; i++) {
35390751910SMingkai Hu 		rtx.txbd[i].status = 0;
35490751910SMingkai Hu 		rtx.txbd[i].length = 0;
35590751910SMingkai Hu 		rtx.txbd[i].bufPtr = 0;
35690751910SMingkai Hu 	}
35790751910SMingkai Hu 	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
35890751910SMingkai Hu 
359aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
360aada81deSchenhui zhao 	svr = get_svr();
361aada81deSchenhui zhao 	if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
362aada81deSchenhui zhao 		redundant_init(dev);
363aada81deSchenhui zhao #endif
36490751910SMingkai Hu 	/* Enable Transmit and Receive */
36590751910SMingkai Hu 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
36690751910SMingkai Hu 
36790751910SMingkai Hu 	/* Tell the DMA it is clear to go */
36890751910SMingkai Hu 	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
36990751910SMingkai Hu 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
37090751910SMingkai Hu 	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
37190751910SMingkai Hu 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
37290751910SMingkai Hu }
37390751910SMingkai Hu 
37490751910SMingkai Hu /* This returns the status bits of the device.	The return value
37590751910SMingkai Hu  * is never checked, and this is what the 8260 driver did, so we
37690751910SMingkai Hu  * do the same.	 Presumably, this would be zero if there were no
37790751910SMingkai Hu  * errors
37890751910SMingkai Hu  */
379c8a60b53SJoe Hershberger static int tsec_send(struct eth_device *dev, void *packet, int length)
38090751910SMingkai Hu {
38190751910SMingkai Hu 	int i;
38290751910SMingkai Hu 	int result = 0;
38390751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
38490751910SMingkai Hu 	tsec_t *regs = priv->regs;
38590751910SMingkai Hu 
38690751910SMingkai Hu 	/* Find an empty buffer descriptor */
38790751910SMingkai Hu 	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
38890751910SMingkai Hu 		if (i >= TOUT_LOOP) {
38990751910SMingkai Hu 			debug("%s: tsec: tx buffers full\n", dev->name);
39090751910SMingkai Hu 			return result;
39190751910SMingkai Hu 		}
39290751910SMingkai Hu 	}
39390751910SMingkai Hu 
39490751910SMingkai Hu 	rtx.txbd[txIdx].bufPtr = (uint) packet;
39590751910SMingkai Hu 	rtx.txbd[txIdx].length = length;
39690751910SMingkai Hu 	rtx.txbd[txIdx].status |=
39790751910SMingkai Hu 	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
39890751910SMingkai Hu 
39990751910SMingkai Hu 	/* Tell the DMA to go */
40090751910SMingkai Hu 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
40190751910SMingkai Hu 
40290751910SMingkai Hu 	/* Wait for buffer to be transmitted */
40390751910SMingkai Hu 	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
40490751910SMingkai Hu 		if (i >= TOUT_LOOP) {
40590751910SMingkai Hu 			debug("%s: tsec: tx error\n", dev->name);
40690751910SMingkai Hu 			return result;
40790751910SMingkai Hu 		}
40890751910SMingkai Hu 	}
40990751910SMingkai Hu 
41090751910SMingkai Hu 	txIdx = (txIdx + 1) % TX_BUF_CNT;
41190751910SMingkai Hu 	result = rtx.txbd[txIdx].status & TXBD_STATS;
41290751910SMingkai Hu 
41390751910SMingkai Hu 	return result;
41490751910SMingkai Hu }
41590751910SMingkai Hu 
41690751910SMingkai Hu static int tsec_recv(struct eth_device *dev)
41790751910SMingkai Hu {
41890751910SMingkai Hu 	int length;
41990751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
42090751910SMingkai Hu 	tsec_t *regs = priv->regs;
42190751910SMingkai Hu 
42290751910SMingkai Hu 	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
42390751910SMingkai Hu 
42490751910SMingkai Hu 		length = rtx.rxbd[rxIdx].length;
42590751910SMingkai Hu 
42690751910SMingkai Hu 		/* Send the packet up if there were no errors */
42790751910SMingkai Hu 		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
42890751910SMingkai Hu 			NetReceive(NetRxPackets[rxIdx], length - 4);
42990751910SMingkai Hu 		} else {
43090751910SMingkai Hu 			printf("Got error %x\n",
43190751910SMingkai Hu 			       (rtx.rxbd[rxIdx].status & RXBD_STATS));
43290751910SMingkai Hu 		}
43390751910SMingkai Hu 
43490751910SMingkai Hu 		rtx.rxbd[rxIdx].length = 0;
43590751910SMingkai Hu 
43690751910SMingkai Hu 		/* Set the wrap bit if this is the last element in the list */
43790751910SMingkai Hu 		rtx.rxbd[rxIdx].status =
43890751910SMingkai Hu 		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
43990751910SMingkai Hu 
44090751910SMingkai Hu 		rxIdx = (rxIdx + 1) % PKTBUFSRX;
44190751910SMingkai Hu 	}
44290751910SMingkai Hu 
44390751910SMingkai Hu 	if (in_be32(&regs->ievent) & IEVENT_BSY) {
44490751910SMingkai Hu 		out_be32(&regs->ievent, IEVENT_BSY);
44590751910SMingkai Hu 		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
44690751910SMingkai Hu 	}
44790751910SMingkai Hu 
44890751910SMingkai Hu 	return -1;
44990751910SMingkai Hu 
45090751910SMingkai Hu }
45190751910SMingkai Hu 
45290751910SMingkai Hu /* Stop the interface */
45390751910SMingkai Hu static void tsec_halt(struct eth_device *dev)
45490751910SMingkai Hu {
45590751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
45690751910SMingkai Hu 	tsec_t *regs = priv->regs;
45790751910SMingkai Hu 
45890751910SMingkai Hu 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
45990751910SMingkai Hu 	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
46090751910SMingkai Hu 
46190751910SMingkai Hu 	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
46290751910SMingkai Hu 			!= (IEVENT_GRSC | IEVENT_GTSC))
46390751910SMingkai Hu 		;
46490751910SMingkai Hu 
46590751910SMingkai Hu 	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
46690751910SMingkai Hu 
46790751910SMingkai Hu 	/* Shut down the PHY, as needed */
468063c1263SAndy Fleming 	phy_shutdown(priv->phydev);
46990751910SMingkai Hu }
47090751910SMingkai Hu 
47190751910SMingkai Hu /* Initializes data structures and registers for the controller,
47290751910SMingkai Hu  * and brings the interface up.	 Returns the link status, meaning
47390751910SMingkai Hu  * that it returns success if the link is up, failure otherwise.
47490751910SMingkai Hu  * This allows u-boot to find the first active controller.
47590751910SMingkai Hu  */
47690751910SMingkai Hu static int tsec_init(struct eth_device *dev, bd_t * bd)
47790751910SMingkai Hu {
47890751910SMingkai Hu 	uint tempval;
47990751910SMingkai Hu 	char tmpbuf[MAC_ADDR_LEN];
48090751910SMingkai Hu 	int i;
48190751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
48290751910SMingkai Hu 	tsec_t *regs = priv->regs;
483*11af8d65STimur Tabi 	int ret;
48490751910SMingkai Hu 
48590751910SMingkai Hu 	/* Make sure the controller is stopped */
48690751910SMingkai Hu 	tsec_halt(dev);
48790751910SMingkai Hu 
48890751910SMingkai Hu 	/* Init MACCFG2.  Defaults to GMII */
48990751910SMingkai Hu 	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
49090751910SMingkai Hu 
49190751910SMingkai Hu 	/* Init ECNTRL */
49290751910SMingkai Hu 	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
49390751910SMingkai Hu 
49490751910SMingkai Hu 	/* Copy the station address into the address registers.
49590751910SMingkai Hu 	 * Backwards, because little endian MACS are dumb */
49690751910SMingkai Hu 	for (i = 0; i < MAC_ADDR_LEN; i++)
49790751910SMingkai Hu 		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
49890751910SMingkai Hu 
49990751910SMingkai Hu 	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
50090751910SMingkai Hu 		  tmpbuf[3];
50190751910SMingkai Hu 
50290751910SMingkai Hu 	out_be32(&regs->macstnaddr1, tempval);
50390751910SMingkai Hu 
50490751910SMingkai Hu 	tempval = *((uint *) (tmpbuf + 4));
50590751910SMingkai Hu 
50690751910SMingkai Hu 	out_be32(&regs->macstnaddr2, tempval);
50790751910SMingkai Hu 
50890751910SMingkai Hu 	/* Clear out (for the most part) the other registers */
50990751910SMingkai Hu 	init_registers(regs);
51090751910SMingkai Hu 
51190751910SMingkai Hu 	/* Ready the device for tx/rx */
51290751910SMingkai Hu 	startup_tsec(dev);
51390751910SMingkai Hu 
514063c1263SAndy Fleming 	/* Start up the PHY */
515*11af8d65STimur Tabi 	ret = phy_startup(priv->phydev);
516*11af8d65STimur Tabi 	if (ret) {
517*11af8d65STimur Tabi 		printf("Could not initialize PHY %s\n",
518*11af8d65STimur Tabi 		       priv->phydev->dev->name);
519*11af8d65STimur Tabi 		return ret;
520*11af8d65STimur Tabi 	}
521063c1263SAndy Fleming 
522063c1263SAndy Fleming 	adjust_link(priv, priv->phydev);
523063c1263SAndy Fleming 
52490751910SMingkai Hu 	/* If there's no link, fail */
525063c1263SAndy Fleming 	return priv->phydev->link ? 0 : -1;
52690751910SMingkai Hu }
52790751910SMingkai Hu 
528063c1263SAndy Fleming static phy_interface_t tsec_get_interface(struct tsec_private *priv)
529063c1263SAndy Fleming {
530063c1263SAndy Fleming 	tsec_t *regs = priv->regs;
531063c1263SAndy Fleming 	u32 ecntrl;
532063c1263SAndy Fleming 
533063c1263SAndy Fleming 	ecntrl = in_be32(&regs->ecntrl);
534063c1263SAndy Fleming 
535063c1263SAndy Fleming 	if (ecntrl & ECNTRL_SGMII_MODE)
536063c1263SAndy Fleming 		return PHY_INTERFACE_MODE_SGMII;
537063c1263SAndy Fleming 
538063c1263SAndy Fleming 	if (ecntrl & ECNTRL_TBI_MODE) {
539063c1263SAndy Fleming 		if (ecntrl & ECNTRL_REDUCED_MODE)
540063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RTBI;
541063c1263SAndy Fleming 		else
542063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_TBI;
543063c1263SAndy Fleming 	}
544063c1263SAndy Fleming 
545063c1263SAndy Fleming 	if (ecntrl & ECNTRL_REDUCED_MODE) {
546063c1263SAndy Fleming 		if (ecntrl & ECNTRL_REDUCED_MII_MODE)
547063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RMII;
548063c1263SAndy Fleming 		else {
549063c1263SAndy Fleming 			phy_interface_t interface = priv->interface;
550063c1263SAndy Fleming 
551063c1263SAndy Fleming 			/*
552063c1263SAndy Fleming 			 * This isn't autodetected, so it must
553063c1263SAndy Fleming 			 * be set by the platform code.
554063c1263SAndy Fleming 			 */
555063c1263SAndy Fleming 			if ((interface == PHY_INTERFACE_MODE_RGMII_ID) ||
556063c1263SAndy Fleming 				 (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
557063c1263SAndy Fleming 				 (interface == PHY_INTERFACE_MODE_RGMII_RXID))
558063c1263SAndy Fleming 				return interface;
559063c1263SAndy Fleming 
560063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RGMII;
561063c1263SAndy Fleming 		}
562063c1263SAndy Fleming 	}
563063c1263SAndy Fleming 
564063c1263SAndy Fleming 	if (priv->flags & TSEC_GIGABIT)
565063c1263SAndy Fleming 		return PHY_INTERFACE_MODE_GMII;
566063c1263SAndy Fleming 
567063c1263SAndy Fleming 	return PHY_INTERFACE_MODE_MII;
568063c1263SAndy Fleming }
569063c1263SAndy Fleming 
570063c1263SAndy Fleming 
57190751910SMingkai Hu /* Discover which PHY is attached to the device, and configure it
57290751910SMingkai Hu  * properly.  If the PHY is not recognized, then return 0
57390751910SMingkai Hu  * (failure).  Otherwise, return 1
57490751910SMingkai Hu  */
57590751910SMingkai Hu static int init_phy(struct eth_device *dev)
57690751910SMingkai Hu {
57790751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
578063c1263SAndy Fleming 	struct phy_device *phydev;
57990751910SMingkai Hu 	tsec_t *regs = priv->regs;
580063c1263SAndy Fleming 	u32 supported = (SUPPORTED_10baseT_Half |
581063c1263SAndy Fleming 			SUPPORTED_10baseT_Full |
582063c1263SAndy Fleming 			SUPPORTED_100baseT_Half |
583063c1263SAndy Fleming 			SUPPORTED_100baseT_Full);
584063c1263SAndy Fleming 
585063c1263SAndy Fleming 	if (priv->flags & TSEC_GIGABIT)
586063c1263SAndy Fleming 		supported |= SUPPORTED_1000baseT_Full;
58790751910SMingkai Hu 
58890751910SMingkai Hu 	/* Assign a Physical address to the TBI */
58990751910SMingkai Hu 	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
59090751910SMingkai Hu 
591063c1263SAndy Fleming 	priv->interface = tsec_get_interface(priv);
59290751910SMingkai Hu 
593063c1263SAndy Fleming 	if (priv->interface == PHY_INTERFACE_MODE_SGMII)
59490751910SMingkai Hu 		tsec_configure_serdes(priv);
59590751910SMingkai Hu 
596063c1263SAndy Fleming 	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
59790751910SMingkai Hu 
598063c1263SAndy Fleming 	phydev->supported &= supported;
599063c1263SAndy Fleming 	phydev->advertising = phydev->supported;
600063c1263SAndy Fleming 
601063c1263SAndy Fleming 	priv->phydev = phydev;
602063c1263SAndy Fleming 
603063c1263SAndy Fleming 	phy_config(phydev);
60490751910SMingkai Hu 
60590751910SMingkai Hu 	return 1;
60690751910SMingkai Hu }
60790751910SMingkai Hu 
60890751910SMingkai Hu /* Initialize device structure. Returns success if PHY
60990751910SMingkai Hu  * initialization succeeded (i.e. if it recognizes the PHY)
61090751910SMingkai Hu  */
61190751910SMingkai Hu static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
61290751910SMingkai Hu {
61390751910SMingkai Hu 	struct eth_device *dev;
61490751910SMingkai Hu 	int i;
61590751910SMingkai Hu 	struct tsec_private *priv;
61690751910SMingkai Hu 
61790751910SMingkai Hu 	dev = (struct eth_device *)malloc(sizeof *dev);
61890751910SMingkai Hu 
61990751910SMingkai Hu 	if (NULL == dev)
62090751910SMingkai Hu 		return 0;
62190751910SMingkai Hu 
62290751910SMingkai Hu 	memset(dev, 0, sizeof *dev);
62390751910SMingkai Hu 
62490751910SMingkai Hu 	priv = (struct tsec_private *)malloc(sizeof(*priv));
62590751910SMingkai Hu 
62690751910SMingkai Hu 	if (NULL == priv)
62790751910SMingkai Hu 		return 0;
62890751910SMingkai Hu 
62990751910SMingkai Hu 	privlist[num_tsecs++] = priv;
63090751910SMingkai Hu 	priv->regs = tsec_info->regs;
63190751910SMingkai Hu 	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
63290751910SMingkai Hu 
63390751910SMingkai Hu 	priv->phyaddr = tsec_info->phyaddr;
63490751910SMingkai Hu 	priv->flags = tsec_info->flags;
63590751910SMingkai Hu 
63690751910SMingkai Hu 	sprintf(dev->name, tsec_info->devname);
637063c1263SAndy Fleming 	priv->interface = tsec_info->interface;
638063c1263SAndy Fleming 	priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
63990751910SMingkai Hu 	dev->iobase = 0;
64090751910SMingkai Hu 	dev->priv = priv;
64190751910SMingkai Hu 	dev->init = tsec_init;
64290751910SMingkai Hu 	dev->halt = tsec_halt;
64390751910SMingkai Hu 	dev->send = tsec_send;
64490751910SMingkai Hu 	dev->recv = tsec_recv;
64590751910SMingkai Hu #ifdef CONFIG_MCAST_TFTP
64690751910SMingkai Hu 	dev->mcast = tsec_mcast_addr;
64790751910SMingkai Hu #endif
64890751910SMingkai Hu 
64990751910SMingkai Hu 	/* Tell u-boot to get the addr from the env */
65090751910SMingkai Hu 	for (i = 0; i < 6; i++)
65190751910SMingkai Hu 		dev->enetaddr[i] = 0;
65290751910SMingkai Hu 
65390751910SMingkai Hu 	eth_register(dev);
65490751910SMingkai Hu 
65590751910SMingkai Hu 	/* Reset the MAC */
65690751910SMingkai Hu 	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
65790751910SMingkai Hu 	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
65890751910SMingkai Hu 	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
65990751910SMingkai Hu 
66090751910SMingkai Hu 	/* Try to initialize PHY here, and return */
66190751910SMingkai Hu 	return init_phy(dev);
66290751910SMingkai Hu }
66390751910SMingkai Hu 
66490751910SMingkai Hu /*
66590751910SMingkai Hu  * Initialize all the TSEC devices
66690751910SMingkai Hu  *
66790751910SMingkai Hu  * Returns the number of TSEC devices that were initialized
66890751910SMingkai Hu  */
66990751910SMingkai Hu int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
67090751910SMingkai Hu {
67190751910SMingkai Hu 	int i;
67290751910SMingkai Hu 	int ret, count = 0;
67390751910SMingkai Hu 
67490751910SMingkai Hu 	for (i = 0; i < num; i++) {
67590751910SMingkai Hu 		ret = tsec_initialize(bis, &tsecs[i]);
67690751910SMingkai Hu 		if (ret > 0)
67790751910SMingkai Hu 			count += ret;
67890751910SMingkai Hu 	}
67990751910SMingkai Hu 
68090751910SMingkai Hu 	return count;
68190751910SMingkai Hu }
68290751910SMingkai Hu 
68390751910SMingkai Hu int tsec_standard_init(bd_t *bis)
68490751910SMingkai Hu {
685063c1263SAndy Fleming 	struct fsl_pq_mdio_info info;
686063c1263SAndy Fleming 
687063c1263SAndy Fleming 	info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
688063c1263SAndy Fleming 	info.name = DEFAULT_MII_NAME;
689063c1263SAndy Fleming 
690063c1263SAndy Fleming 	fsl_pq_mdio_init(bis, &info);
691063c1263SAndy Fleming 
69290751910SMingkai Hu 	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
69390751910SMingkai Hu }
694