xref: /rk3399_rockchip-uboot/drivers/net/tsec.c (revision 192bc6948b02ff4168cab16162fffb507946dc2b)
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  *
8aec84bf6SClaudiu Manoil  * Copyright 2004-2011, 2013 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>
2352d00a81SAlison Wang #include <asm/io.h>
242439e4bfSJean-Christophe PLAGNIOL-VILLARD 
252439e4bfSJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR;
262439e4bfSJean-Christophe PLAGNIOL-VILLARD 
272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_BUF_CNT		2
282439e4bfSJean-Christophe PLAGNIOL-VILLARD 
2918b338fbSClaudiu Manoil static uint rx_idx;		/* index of the current RX buffer */
3018b338fbSClaudiu Manoil static uint tx_idx;		/* index of the current TX buffer */
312439e4bfSJean-Christophe PLAGNIOL-VILLARD 
322439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef __GNUC__
339c9141fdSClaudiu Manoil static struct txbd8 __iomem txbd[TX_BUF_CNT] __aligned(8);
349c9141fdSClaudiu Manoil static struct rxbd8 __iomem rxbd[PKTBUFSRX] __aligned(8);
359c9141fdSClaudiu Manoil 
362439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
372439e4bfSJean-Christophe PLAGNIOL-VILLARD #error "rtx must be 64-bit aligned"
382439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
392439e4bfSJean-Christophe PLAGNIOL-VILLARD 
40c8a60b53SJoe Hershberger static int tsec_send(struct eth_device *dev, void *packet, int length);
41aada81deSchenhui zhao 
4275b9d4aeSAndy Fleming /* Default initializations for TSEC controllers. */
4375b9d4aeSAndy Fleming 
4475b9d4aeSAndy Fleming static struct tsec_info_struct tsec_info[] = {
4575b9d4aeSAndy Fleming #ifdef CONFIG_TSEC1
4675b9d4aeSAndy Fleming 	STD_TSEC_INFO(1),	/* TSEC1 */
4775b9d4aeSAndy Fleming #endif
4875b9d4aeSAndy Fleming #ifdef CONFIG_TSEC2
4975b9d4aeSAndy Fleming 	STD_TSEC_INFO(2),	/* TSEC2 */
5075b9d4aeSAndy Fleming #endif
5175b9d4aeSAndy Fleming #ifdef CONFIG_MPC85XX_FEC
5275b9d4aeSAndy Fleming 	{
53aec84bf6SClaudiu Manoil 		.regs = TSEC_GET_REGS(2, 0x2000),
5475b9d4aeSAndy Fleming 		.devname = CONFIG_MPC85XX_FEC_NAME,
5575b9d4aeSAndy Fleming 		.phyaddr = FEC_PHY_ADDR,
56063c1263SAndy Fleming 		.flags = FEC_FLAGS,
57063c1263SAndy Fleming 		.mii_devname = DEFAULT_MII_NAME
5875b9d4aeSAndy Fleming 	},			/* FEC */
5975b9d4aeSAndy Fleming #endif
6075b9d4aeSAndy Fleming #ifdef CONFIG_TSEC3
6175b9d4aeSAndy Fleming 	STD_TSEC_INFO(3),	/* TSEC3 */
6275b9d4aeSAndy Fleming #endif
6375b9d4aeSAndy Fleming #ifdef CONFIG_TSEC4
6475b9d4aeSAndy Fleming 	STD_TSEC_INFO(4),	/* TSEC4 */
6575b9d4aeSAndy Fleming #endif
6675b9d4aeSAndy Fleming };
6775b9d4aeSAndy Fleming 
682abe361cSAndy Fleming #define TBIANA_SETTINGS ( \
692abe361cSAndy Fleming 		TBIANA_ASYMMETRIC_PAUSE \
702abe361cSAndy Fleming 		| TBIANA_SYMMETRIC_PAUSE \
712abe361cSAndy Fleming 		| TBIANA_FULL_DUPLEX \
722abe361cSAndy Fleming 		)
732abe361cSAndy Fleming 
7490b5bf21SFelix Radensky /* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
7590b5bf21SFelix Radensky #ifndef CONFIG_TSEC_TBICR_SETTINGS
7672c96a68SKumar Gala #define CONFIG_TSEC_TBICR_SETTINGS ( \
772abe361cSAndy Fleming 		TBICR_PHY_RESET \
7872c96a68SKumar Gala 		| TBICR_ANEG_ENABLE \
792abe361cSAndy Fleming 		| TBICR_FULL_DUPLEX \
802abe361cSAndy Fleming 		| TBICR_SPEED1_SET \
812abe361cSAndy Fleming 		)
8290b5bf21SFelix Radensky #endif /* CONFIG_TSEC_TBICR_SETTINGS */
8346e91674SPeter Tyser 
842abe361cSAndy Fleming /* Configure the TBI for SGMII operation */
852abe361cSAndy Fleming static void tsec_configure_serdes(struct tsec_private *priv)
862abe361cSAndy Fleming {
87c6dbdfdaSPeter Tyser 	/* Access TBI PHY registers at given TSEC register offset as opposed
88c6dbdfdaSPeter Tyser 	 * to the register offset used for external PHY accesses */
89063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
90063c1263SAndy Fleming 			0, TBI_ANA, TBIANA_SETTINGS);
91063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
92063c1263SAndy Fleming 			0, TBI_TBICON, TBICON_CLK_SELECT);
93063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
94063c1263SAndy Fleming 			0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
952439e4bfSJean-Christophe PLAGNIOL-VILLARD }
962439e4bfSJean-Christophe PLAGNIOL-VILLARD 
972439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MCAST_TFTP
982439e4bfSJean-Christophe PLAGNIOL-VILLARD 
992439e4bfSJean-Christophe PLAGNIOL-VILLARD /* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
1002439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1012439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the appropriate hash bit for the given addr */
1022439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1032439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The algorithm works like so:
1042439e4bfSJean-Christophe PLAGNIOL-VILLARD  * 1) Take the Destination Address (ie the multicast address), and
1052439e4bfSJean-Christophe PLAGNIOL-VILLARD  * do a CRC on it (little endian), and reverse the bits of the
1062439e4bfSJean-Christophe PLAGNIOL-VILLARD  * result.
1072439e4bfSJean-Christophe PLAGNIOL-VILLARD  * 2) Use the 8 most significant bits as a hash into a 256-entry
1082439e4bfSJean-Christophe PLAGNIOL-VILLARD  * table.  The table is controlled through 8 32-bit registers:
109876d4515SClaudiu Manoil  * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is entry
110876d4515SClaudiu Manoil  * 255.  This means that the 3 most significant bits in the
1112439e4bfSJean-Christophe PLAGNIOL-VILLARD  * hash index which gaddr register to use, and the 5 other bits
1122439e4bfSJean-Christophe PLAGNIOL-VILLARD  * indicate which bit (assuming an IBM numbering scheme, which
113876d4515SClaudiu Manoil  * for PowerPC (tm) is usually the case) in the register holds
1142439e4bfSJean-Christophe PLAGNIOL-VILLARD  * the entry. */
1152439e4bfSJean-Christophe PLAGNIOL-VILLARD static int
1169c4cffacSClaudiu Manoil tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set)
1172439e4bfSJean-Christophe PLAGNIOL-VILLARD {
118b200204eSClaudiu Manoil 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
119876d4515SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
120876d4515SClaudiu Manoil 	u32 result, value;
121876d4515SClaudiu Manoil 	u8 whichbit, whichreg;
1222439e4bfSJean-Christophe PLAGNIOL-VILLARD 
123876d4515SClaudiu Manoil 	result = ether_crc(MAC_ADDR_LEN, mcast_mac);
124876d4515SClaudiu Manoil 	whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */
125876d4515SClaudiu Manoil 	whichreg = result >> 29; /* the 3 MSB = which reg to set it in */
1262439e4bfSJean-Christophe PLAGNIOL-VILLARD 
127876d4515SClaudiu Manoil 	value = 1 << (31-whichbit);
1282439e4bfSJean-Christophe PLAGNIOL-VILLARD 
129876d4515SClaudiu Manoil 	if (set)
130876d4515SClaudiu Manoil 		setbits_be32(&regs->hash.gaddr0 + whichreg, value);
131876d4515SClaudiu Manoil 	else
132876d4515SClaudiu Manoil 		clrbits_be32(&regs->hash.gaddr0 + whichreg, value);
133876d4515SClaudiu Manoil 
1342439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
1352439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1362439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* Multicast TFTP ? */
13790751910SMingkai Hu 
13890751910SMingkai Hu /* Initialized required registers to appropriate values, zeroing
13990751910SMingkai Hu  * those we don't care about (unless zero is bad, in which case,
14090751910SMingkai Hu  * choose a more appropriate value)
14190751910SMingkai Hu  */
142aec84bf6SClaudiu Manoil static void init_registers(struct tsec __iomem *regs)
14390751910SMingkai Hu {
14490751910SMingkai Hu 	/* Clear IEVENT */
14590751910SMingkai Hu 	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
14690751910SMingkai Hu 
14790751910SMingkai Hu 	out_be32(&regs->imask, IMASK_INIT_CLEAR);
14890751910SMingkai Hu 
14990751910SMingkai Hu 	out_be32(&regs->hash.iaddr0, 0);
15090751910SMingkai Hu 	out_be32(&regs->hash.iaddr1, 0);
15190751910SMingkai Hu 	out_be32(&regs->hash.iaddr2, 0);
15290751910SMingkai Hu 	out_be32(&regs->hash.iaddr3, 0);
15390751910SMingkai Hu 	out_be32(&regs->hash.iaddr4, 0);
15490751910SMingkai Hu 	out_be32(&regs->hash.iaddr5, 0);
15590751910SMingkai Hu 	out_be32(&regs->hash.iaddr6, 0);
15690751910SMingkai Hu 	out_be32(&regs->hash.iaddr7, 0);
15790751910SMingkai Hu 
15890751910SMingkai Hu 	out_be32(&regs->hash.gaddr0, 0);
15990751910SMingkai Hu 	out_be32(&regs->hash.gaddr1, 0);
16090751910SMingkai Hu 	out_be32(&regs->hash.gaddr2, 0);
16190751910SMingkai Hu 	out_be32(&regs->hash.gaddr3, 0);
16290751910SMingkai Hu 	out_be32(&regs->hash.gaddr4, 0);
16390751910SMingkai Hu 	out_be32(&regs->hash.gaddr5, 0);
16490751910SMingkai Hu 	out_be32(&regs->hash.gaddr6, 0);
16590751910SMingkai Hu 	out_be32(&regs->hash.gaddr7, 0);
16690751910SMingkai Hu 
16790751910SMingkai Hu 	out_be32(&regs->rctrl, 0x00000000);
16890751910SMingkai Hu 
16990751910SMingkai Hu 	/* Init RMON mib registers */
17082ef75caSClaudiu Manoil 	memset((void *)&regs->rmon, 0, sizeof(regs->rmon));
17190751910SMingkai Hu 
17290751910SMingkai Hu 	out_be32(&regs->rmon.cam1, 0xffffffff);
17390751910SMingkai Hu 	out_be32(&regs->rmon.cam2, 0xffffffff);
17490751910SMingkai Hu 
17590751910SMingkai Hu 	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
17690751910SMingkai Hu 
17790751910SMingkai Hu 	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
17890751910SMingkai Hu 
17990751910SMingkai Hu 	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
18090751910SMingkai Hu 	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
18190751910SMingkai Hu 
18290751910SMingkai Hu }
18390751910SMingkai Hu 
18490751910SMingkai Hu /* Configure maccfg2 based on negotiated speed and duplex
18590751910SMingkai Hu  * reported by PHY handling code
18690751910SMingkai Hu  */
187063c1263SAndy Fleming static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
18890751910SMingkai Hu {
189aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
19090751910SMingkai Hu 	u32 ecntrl, maccfg2;
19190751910SMingkai Hu 
192063c1263SAndy Fleming 	if (!phydev->link) {
193063c1263SAndy Fleming 		printf("%s: No link.\n", phydev->dev->name);
19490751910SMingkai Hu 		return;
19590751910SMingkai Hu 	}
19690751910SMingkai Hu 
19790751910SMingkai Hu 	/* clear all bits relative with interface mode */
19890751910SMingkai Hu 	ecntrl = in_be32(&regs->ecntrl);
19990751910SMingkai Hu 	ecntrl &= ~ECNTRL_R100;
20090751910SMingkai Hu 
20190751910SMingkai Hu 	maccfg2 = in_be32(&regs->maccfg2);
20290751910SMingkai Hu 	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
20390751910SMingkai Hu 
204063c1263SAndy Fleming 	if (phydev->duplex)
20590751910SMingkai Hu 		maccfg2 |= MACCFG2_FULL_DUPLEX;
20690751910SMingkai Hu 
207063c1263SAndy Fleming 	switch (phydev->speed) {
20890751910SMingkai Hu 	case 1000:
20990751910SMingkai Hu 		maccfg2 |= MACCFG2_GMII;
21090751910SMingkai Hu 		break;
21190751910SMingkai Hu 	case 100:
21290751910SMingkai Hu 	case 10:
21390751910SMingkai Hu 		maccfg2 |= MACCFG2_MII;
21490751910SMingkai Hu 
21590751910SMingkai Hu 		/* Set R100 bit in all modes although
21690751910SMingkai Hu 		 * it is only used in RGMII mode
21790751910SMingkai Hu 		 */
218063c1263SAndy Fleming 		if (phydev->speed == 100)
21990751910SMingkai Hu 			ecntrl |= ECNTRL_R100;
22090751910SMingkai Hu 		break;
22190751910SMingkai Hu 	default:
222063c1263SAndy Fleming 		printf("%s: Speed was bad\n", phydev->dev->name);
22390751910SMingkai Hu 		break;
22490751910SMingkai Hu 	}
22590751910SMingkai Hu 
22690751910SMingkai Hu 	out_be32(&regs->ecntrl, ecntrl);
22790751910SMingkai Hu 	out_be32(&regs->maccfg2, maccfg2);
22890751910SMingkai Hu 
229063c1263SAndy Fleming 	printf("Speed: %d, %s duplex%s\n", phydev->speed,
230063c1263SAndy Fleming 			(phydev->duplex) ? "full" : "half",
231063c1263SAndy Fleming 			(phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
23290751910SMingkai Hu }
23390751910SMingkai Hu 
234aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
235aada81deSchenhui zhao /*
236aada81deSchenhui zhao  * When MACCFG1[Rx_EN] is enabled during system boot as part
237aada81deSchenhui zhao  * of the eTSEC port initialization sequence,
238aada81deSchenhui zhao  * the eTSEC Rx logic may not be properly initialized.
239aada81deSchenhui zhao  */
240aada81deSchenhui zhao void redundant_init(struct eth_device *dev)
241aada81deSchenhui zhao {
242aada81deSchenhui zhao 	struct tsec_private *priv = dev->priv;
243aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
244aada81deSchenhui zhao 	uint t, count = 0;
245aada81deSchenhui zhao 	int fail = 1;
246aada81deSchenhui zhao 	static const u8 pkt[] = {
247aada81deSchenhui zhao 		0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25,
248aada81deSchenhui zhao 		0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00,
249aada81deSchenhui zhao 		0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01,
250aada81deSchenhui zhao 		0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1,
251aada81deSchenhui zhao 		0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00,
252aada81deSchenhui zhao 		0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
253aada81deSchenhui zhao 		0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
254aada81deSchenhui zhao 		0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
255aada81deSchenhui zhao 		0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
256aada81deSchenhui zhao 		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
257aada81deSchenhui zhao 		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
258aada81deSchenhui zhao 		0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
259aada81deSchenhui zhao 		0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
260aada81deSchenhui zhao 		0x71, 0x72};
261aada81deSchenhui zhao 
262aada81deSchenhui zhao 	/* Enable promiscuous mode */
263aada81deSchenhui zhao 	setbits_be32(&regs->rctrl, 0x8);
264aada81deSchenhui zhao 	/* Enable loopback mode */
265aada81deSchenhui zhao 	setbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
266aada81deSchenhui zhao 	/* Enable transmit and receive */
267aada81deSchenhui zhao 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
268aada81deSchenhui zhao 
269aada81deSchenhui zhao 	/* Tell the DMA it is clear to go */
270aada81deSchenhui zhao 	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
271aada81deSchenhui zhao 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
272aada81deSchenhui zhao 	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
273aada81deSchenhui zhao 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
274aada81deSchenhui zhao 
275aada81deSchenhui zhao 	do {
2769c9141fdSClaudiu Manoil 		uint16_t status;
277aada81deSchenhui zhao 		tsec_send(dev, (void *)pkt, sizeof(pkt));
278aada81deSchenhui zhao 
279aada81deSchenhui zhao 		/* Wait for buffer to be received */
2809c9141fdSClaudiu Manoil 		for (t = 0; in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY; t++) {
281aada81deSchenhui zhao 			if (t >= 10 * TOUT_LOOP) {
282aada81deSchenhui zhao 				printf("%s: tsec: rx error\n", dev->name);
283aada81deSchenhui zhao 				break;
284aada81deSchenhui zhao 			}
285aada81deSchenhui zhao 		}
286aada81deSchenhui zhao 
2871fd92db8SJoe Hershberger 		if (!memcmp(pkt, (void *)net_rx_packets[rx_idx], sizeof(pkt)))
288aada81deSchenhui zhao 			fail = 0;
289aada81deSchenhui zhao 
2909c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].length, 0);
2919c9141fdSClaudiu Manoil 		status = RXBD_EMPTY;
2929c9141fdSClaudiu Manoil 		if ((rx_idx + 1) == PKTBUFSRX)
2939c9141fdSClaudiu Manoil 			status |= RXBD_WRAP;
2949c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].status, status);
29518b338fbSClaudiu Manoil 		rx_idx = (rx_idx + 1) % PKTBUFSRX;
296aada81deSchenhui zhao 
297aada81deSchenhui zhao 		if (in_be32(&regs->ievent) & IEVENT_BSY) {
298aada81deSchenhui zhao 			out_be32(&regs->ievent, IEVENT_BSY);
299aada81deSchenhui zhao 			out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
300aada81deSchenhui zhao 		}
301aada81deSchenhui zhao 		if (fail) {
302aada81deSchenhui zhao 			printf("loopback recv packet error!\n");
303aada81deSchenhui zhao 			clrbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
304aada81deSchenhui zhao 			udelay(1000);
305aada81deSchenhui zhao 			setbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
306aada81deSchenhui zhao 		}
307aada81deSchenhui zhao 	} while ((count++ < 4) && (fail == 1));
308aada81deSchenhui zhao 
309aada81deSchenhui zhao 	if (fail)
310aada81deSchenhui zhao 		panic("eTSEC init fail!\n");
311aada81deSchenhui zhao 	/* Disable promiscuous mode */
312aada81deSchenhui zhao 	clrbits_be32(&regs->rctrl, 0x8);
313aada81deSchenhui zhao 	/* Disable loopback mode */
314aada81deSchenhui zhao 	clrbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
315aada81deSchenhui zhao }
316aada81deSchenhui zhao #endif
317aada81deSchenhui zhao 
31890751910SMingkai Hu /* Set up the buffers and their descriptors, and bring up the
31990751910SMingkai Hu  * interface
32090751910SMingkai Hu  */
32190751910SMingkai Hu static void startup_tsec(struct eth_device *dev)
32290751910SMingkai Hu {
32390751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
324aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
3259c9141fdSClaudiu Manoil 	uint16_t status;
3269c9141fdSClaudiu Manoil 	int i;
32790751910SMingkai Hu 
328063c1263SAndy Fleming 	/* reset the indices to zero */
32918b338fbSClaudiu Manoil 	rx_idx = 0;
33018b338fbSClaudiu Manoil 	tx_idx = 0;
331aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
332aada81deSchenhui zhao 	uint svr;
333aada81deSchenhui zhao #endif
334063c1263SAndy Fleming 
33590751910SMingkai Hu 	/* Point to the buffer descriptors */
3369c9141fdSClaudiu Manoil 	out_be32(&regs->tbase, (u32)&txbd[0]);
3379c9141fdSClaudiu Manoil 	out_be32(&regs->rbase, (u32)&rxbd[0]);
33890751910SMingkai Hu 
33990751910SMingkai Hu 	/* Initialize the Rx Buffer descriptors */
34090751910SMingkai Hu 	for (i = 0; i < PKTBUFSRX; i++) {
3419c9141fdSClaudiu Manoil 		out_be16(&rxbd[i].status, RXBD_EMPTY);
3429c9141fdSClaudiu Manoil 		out_be16(&rxbd[i].length, 0);
3431fd92db8SJoe Hershberger 		out_be32(&rxbd[i].bufptr, (u32)net_rx_packets[i]);
34490751910SMingkai Hu 	}
3459c9141fdSClaudiu Manoil 	status = in_be16(&rxbd[PKTBUFSRX - 1].status);
3469c9141fdSClaudiu Manoil 	out_be16(&rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
34790751910SMingkai Hu 
34890751910SMingkai Hu 	/* Initialize the TX Buffer Descriptors */
34990751910SMingkai Hu 	for (i = 0; i < TX_BUF_CNT; i++) {
3509c9141fdSClaudiu Manoil 		out_be16(&txbd[i].status, 0);
3519c9141fdSClaudiu Manoil 		out_be16(&txbd[i].length, 0);
3529c9141fdSClaudiu Manoil 		out_be32(&txbd[i].bufptr, 0);
35390751910SMingkai Hu 	}
3549c9141fdSClaudiu Manoil 	status = in_be16(&txbd[TX_BUF_CNT - 1].status);
3559c9141fdSClaudiu Manoil 	out_be16(&txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
35690751910SMingkai Hu 
357aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
358aada81deSchenhui zhao 	svr = get_svr();
359aada81deSchenhui zhao 	if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
360aada81deSchenhui zhao 		redundant_init(dev);
361aada81deSchenhui zhao #endif
36290751910SMingkai Hu 	/* Enable Transmit and Receive */
36390751910SMingkai Hu 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
36490751910SMingkai Hu 
36590751910SMingkai Hu 	/* Tell the DMA it is clear to go */
36690751910SMingkai Hu 	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
36790751910SMingkai Hu 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
36890751910SMingkai Hu 	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
36990751910SMingkai Hu 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
37090751910SMingkai Hu }
37190751910SMingkai Hu 
37290751910SMingkai Hu /* This returns the status bits of the device.	The return value
37390751910SMingkai Hu  * is never checked, and this is what the 8260 driver did, so we
37490751910SMingkai Hu  * do the same.	 Presumably, this would be zero if there were no
37590751910SMingkai Hu  * errors
37690751910SMingkai Hu  */
377c8a60b53SJoe Hershberger static int tsec_send(struct eth_device *dev, void *packet, int length)
37890751910SMingkai Hu {
37990751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
380aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
3819c9141fdSClaudiu Manoil 	uint16_t status;
3829c9141fdSClaudiu Manoil 	int result = 0;
3839c9141fdSClaudiu Manoil 	int i;
38490751910SMingkai Hu 
38590751910SMingkai Hu 	/* Find an empty buffer descriptor */
3869c9141fdSClaudiu Manoil 	for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) {
38790751910SMingkai Hu 		if (i >= TOUT_LOOP) {
38890751910SMingkai Hu 			debug("%s: tsec: tx buffers full\n", dev->name);
38990751910SMingkai Hu 			return result;
39090751910SMingkai Hu 		}
39190751910SMingkai Hu 	}
39290751910SMingkai Hu 
3939c9141fdSClaudiu Manoil 	out_be32(&txbd[tx_idx].bufptr, (u32)packet);
3949c9141fdSClaudiu Manoil 	out_be16(&txbd[tx_idx].length, length);
3959c9141fdSClaudiu Manoil 	status = in_be16(&txbd[tx_idx].status);
3969c9141fdSClaudiu Manoil 	out_be16(&txbd[tx_idx].status, status |
3979c9141fdSClaudiu Manoil 		(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 */
4039c9141fdSClaudiu Manoil 	for (i = 0; in_be16(&txbd[tx_idx].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 
41018b338fbSClaudiu Manoil 	tx_idx = (tx_idx + 1) % TX_BUF_CNT;
4119c9141fdSClaudiu Manoil 	result = in_be16(&txbd[tx_idx].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 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
419aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
42090751910SMingkai Hu 
4219c9141fdSClaudiu Manoil 	while (!(in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY)) {
4229c9141fdSClaudiu Manoil 		int length = in_be16(&rxbd[rx_idx].length);
4239c9141fdSClaudiu Manoil 		uint16_t status = in_be16(&rxbd[rx_idx].status);
42490751910SMingkai Hu 
42590751910SMingkai Hu 		/* Send the packet up if there were no errors */
4269c9141fdSClaudiu Manoil 		if (!(status & RXBD_STATS))
4271fd92db8SJoe Hershberger 			net_process_received_packet(net_rx_packets[rx_idx],
4281fd92db8SJoe Hershberger 						    length - 4);
4299c9141fdSClaudiu Manoil 		else
4309c9141fdSClaudiu Manoil 			printf("Got error %x\n", (status & RXBD_STATS));
43190751910SMingkai Hu 
4329c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].length, 0);
43390751910SMingkai Hu 
4349c9141fdSClaudiu Manoil 		status = RXBD_EMPTY;
43590751910SMingkai Hu 		/* Set the wrap bit if this is the last element in the list */
4369c9141fdSClaudiu Manoil 		if ((rx_idx + 1) == PKTBUFSRX)
4379c9141fdSClaudiu Manoil 			status |= RXBD_WRAP;
4389c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].status, status);
43990751910SMingkai Hu 
44018b338fbSClaudiu Manoil 		rx_idx = (rx_idx + 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;
456aec84bf6SClaudiu Manoil 	struct tsec __iomem *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 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
479aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
480b1690bc3SClaudiu Manoil 	u32 tempval;
48111af8d65STimur Tabi 	int ret;
48290751910SMingkai Hu 
48390751910SMingkai Hu 	/* Make sure the controller is stopped */
48490751910SMingkai Hu 	tsec_halt(dev);
48590751910SMingkai Hu 
48690751910SMingkai Hu 	/* Init MACCFG2.  Defaults to GMII */
48790751910SMingkai Hu 	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
48890751910SMingkai Hu 
48990751910SMingkai Hu 	/* Init ECNTRL */
49090751910SMingkai Hu 	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
49190751910SMingkai Hu 
49290751910SMingkai Hu 	/* Copy the station address into the address registers.
493b1690bc3SClaudiu Manoil 	 * For a station address of 0x12345678ABCD in transmission
494b1690bc3SClaudiu Manoil 	 * order (BE), MACnADDR1 is set to 0xCDAB7856 and
495b1690bc3SClaudiu Manoil 	 * MACnADDR2 is set to 0x34120000.
496b1690bc3SClaudiu Manoil 	 */
497b1690bc3SClaudiu Manoil 	tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) |
498b1690bc3SClaudiu Manoil 		  (dev->enetaddr[3] << 8)  |  dev->enetaddr[2];
49990751910SMingkai Hu 
50090751910SMingkai Hu 	out_be32(&regs->macstnaddr1, tempval);
50190751910SMingkai Hu 
502b1690bc3SClaudiu Manoil 	tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16);
50390751910SMingkai Hu 
50490751910SMingkai Hu 	out_be32(&regs->macstnaddr2, tempval);
50590751910SMingkai Hu 
50690751910SMingkai Hu 	/* Clear out (for the most part) the other registers */
50790751910SMingkai Hu 	init_registers(regs);
50890751910SMingkai Hu 
50990751910SMingkai Hu 	/* Ready the device for tx/rx */
51090751910SMingkai Hu 	startup_tsec(dev);
51190751910SMingkai Hu 
512063c1263SAndy Fleming 	/* Start up the PHY */
51311af8d65STimur Tabi 	ret = phy_startup(priv->phydev);
51411af8d65STimur Tabi 	if (ret) {
51511af8d65STimur Tabi 		printf("Could not initialize PHY %s\n",
51611af8d65STimur Tabi 		       priv->phydev->dev->name);
51711af8d65STimur Tabi 		return ret;
51811af8d65STimur Tabi 	}
519063c1263SAndy Fleming 
520063c1263SAndy Fleming 	adjust_link(priv, priv->phydev);
521063c1263SAndy Fleming 
52290751910SMingkai Hu 	/* If there's no link, fail */
523063c1263SAndy Fleming 	return priv->phydev->link ? 0 : -1;
52490751910SMingkai Hu }
52590751910SMingkai Hu 
526063c1263SAndy Fleming static phy_interface_t tsec_get_interface(struct tsec_private *priv)
527063c1263SAndy Fleming {
528aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
529063c1263SAndy Fleming 	u32 ecntrl;
530063c1263SAndy Fleming 
531063c1263SAndy Fleming 	ecntrl = in_be32(&regs->ecntrl);
532063c1263SAndy Fleming 
533063c1263SAndy Fleming 	if (ecntrl & ECNTRL_SGMII_MODE)
534063c1263SAndy Fleming 		return PHY_INTERFACE_MODE_SGMII;
535063c1263SAndy Fleming 
536063c1263SAndy Fleming 	if (ecntrl & ECNTRL_TBI_MODE) {
537063c1263SAndy Fleming 		if (ecntrl & ECNTRL_REDUCED_MODE)
538063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RTBI;
539063c1263SAndy Fleming 		else
540063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_TBI;
541063c1263SAndy Fleming 	}
542063c1263SAndy Fleming 
543063c1263SAndy Fleming 	if (ecntrl & ECNTRL_REDUCED_MODE) {
544063c1263SAndy Fleming 		if (ecntrl & ECNTRL_REDUCED_MII_MODE)
545063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RMII;
546063c1263SAndy Fleming 		else {
547063c1263SAndy Fleming 			phy_interface_t interface = priv->interface;
548063c1263SAndy Fleming 
549063c1263SAndy Fleming 			/*
550063c1263SAndy Fleming 			 * This isn't autodetected, so it must
551063c1263SAndy Fleming 			 * be set by the platform code.
552063c1263SAndy Fleming 			 */
553063c1263SAndy Fleming 			if ((interface == PHY_INTERFACE_MODE_RGMII_ID) ||
554063c1263SAndy Fleming 				 (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
555063c1263SAndy Fleming 				 (interface == PHY_INTERFACE_MODE_RGMII_RXID))
556063c1263SAndy Fleming 				return interface;
557063c1263SAndy Fleming 
558063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RGMII;
559063c1263SAndy Fleming 		}
560063c1263SAndy Fleming 	}
561063c1263SAndy Fleming 
562063c1263SAndy Fleming 	if (priv->flags & TSEC_GIGABIT)
563063c1263SAndy Fleming 		return PHY_INTERFACE_MODE_GMII;
564063c1263SAndy Fleming 
565063c1263SAndy Fleming 	return PHY_INTERFACE_MODE_MII;
566063c1263SAndy Fleming }
567063c1263SAndy Fleming 
568063c1263SAndy Fleming 
56990751910SMingkai Hu /* Discover which PHY is attached to the device, and configure it
57090751910SMingkai Hu  * properly.  If the PHY is not recognized, then return 0
57190751910SMingkai Hu  * (failure).  Otherwise, return 1
57290751910SMingkai Hu  */
57390751910SMingkai Hu static int init_phy(struct eth_device *dev)
57490751910SMingkai Hu {
57590751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
576063c1263SAndy Fleming 	struct phy_device *phydev;
577aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
578063c1263SAndy Fleming 	u32 supported = (SUPPORTED_10baseT_Half |
579063c1263SAndy Fleming 			SUPPORTED_10baseT_Full |
580063c1263SAndy Fleming 			SUPPORTED_100baseT_Half |
581063c1263SAndy Fleming 			SUPPORTED_100baseT_Full);
582063c1263SAndy Fleming 
583063c1263SAndy Fleming 	if (priv->flags & TSEC_GIGABIT)
584063c1263SAndy Fleming 		supported |= SUPPORTED_1000baseT_Full;
58590751910SMingkai Hu 
58690751910SMingkai Hu 	/* Assign a Physical address to the TBI */
58790751910SMingkai Hu 	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
58890751910SMingkai Hu 
589063c1263SAndy Fleming 	priv->interface = tsec_get_interface(priv);
59090751910SMingkai Hu 
591063c1263SAndy Fleming 	if (priv->interface == PHY_INTERFACE_MODE_SGMII)
59290751910SMingkai Hu 		tsec_configure_serdes(priv);
59390751910SMingkai Hu 
594063c1263SAndy Fleming 	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
5957f233c05SClaudiu Manoil 	if (!phydev)
5967f233c05SClaudiu Manoil 		return 0;
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 	priv->regs = tsec_info->regs;
63090751910SMingkai Hu 	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
63190751910SMingkai Hu 
63290751910SMingkai Hu 	priv->phyaddr = tsec_info->phyaddr;
63390751910SMingkai Hu 	priv->flags = tsec_info->flags;
63490751910SMingkai Hu 
635*192bc694SBen Whitten 	strcpy(dev->name, tsec_info->devname);
636063c1263SAndy Fleming 	priv->interface = tsec_info->interface;
637063c1263SAndy Fleming 	priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
63890751910SMingkai Hu 	dev->iobase = 0;
63990751910SMingkai Hu 	dev->priv = priv;
64090751910SMingkai Hu 	dev->init = tsec_init;
64190751910SMingkai Hu 	dev->halt = tsec_halt;
64290751910SMingkai Hu 	dev->send = tsec_send;
64390751910SMingkai Hu 	dev->recv = tsec_recv;
64490751910SMingkai Hu #ifdef CONFIG_MCAST_TFTP
64590751910SMingkai Hu 	dev->mcast = tsec_mcast_addr;
64690751910SMingkai Hu #endif
64790751910SMingkai Hu 
64890751910SMingkai Hu 	/* Tell u-boot to get the addr from the env */
64990751910SMingkai Hu 	for (i = 0; i < 6; i++)
65090751910SMingkai Hu 		dev->enetaddr[i] = 0;
65190751910SMingkai Hu 
65290751910SMingkai Hu 	eth_register(dev);
65390751910SMingkai Hu 
65490751910SMingkai Hu 	/* Reset the MAC */
65590751910SMingkai Hu 	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
65690751910SMingkai Hu 	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
65790751910SMingkai Hu 	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
65890751910SMingkai Hu 
65990751910SMingkai Hu 	/* Try to initialize PHY here, and return */
66090751910SMingkai Hu 	return init_phy(dev);
66190751910SMingkai Hu }
66290751910SMingkai Hu 
66390751910SMingkai Hu /*
66490751910SMingkai Hu  * Initialize all the TSEC devices
66590751910SMingkai Hu  *
66690751910SMingkai Hu  * Returns the number of TSEC devices that were initialized
66790751910SMingkai Hu  */
66890751910SMingkai Hu int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
66990751910SMingkai Hu {
67090751910SMingkai Hu 	int i;
67190751910SMingkai Hu 	int ret, count = 0;
67290751910SMingkai Hu 
67390751910SMingkai Hu 	for (i = 0; i < num; i++) {
67490751910SMingkai Hu 		ret = tsec_initialize(bis, &tsecs[i]);
67590751910SMingkai Hu 		if (ret > 0)
67690751910SMingkai Hu 			count += ret;
67790751910SMingkai Hu 	}
67890751910SMingkai Hu 
67990751910SMingkai Hu 	return count;
68090751910SMingkai Hu }
68190751910SMingkai Hu 
68290751910SMingkai Hu int tsec_standard_init(bd_t *bis)
68390751910SMingkai Hu {
684063c1263SAndy Fleming 	struct fsl_pq_mdio_info info;
685063c1263SAndy Fleming 
686aec84bf6SClaudiu Manoil 	info.regs = TSEC_GET_MDIO_REGS_BASE(1);
687063c1263SAndy Fleming 	info.name = DEFAULT_MII_NAME;
688063c1263SAndy Fleming 
689063c1263SAndy Fleming 	fsl_pq_mdio_init(bis, &info);
690063c1263SAndy Fleming 
69190751910SMingkai Hu 	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
69290751910SMingkai Hu }
693