xref: /rk3399_rockchip-uboot/drivers/net/tsec.c (revision 9872b736f957585c6494e727634fe6ed837bcd86)
12439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
22439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Freescale Three Speed Ethernet Controller driver
32439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
4aec84bf6SClaudiu Manoil  * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc.
52439e4bfSJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2003, Motorola, Inc.
62439e4bfSJean-Christophe PLAGNIOL-VILLARD  * author Andy Fleming
72439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
8*9872b736SBin Meng  * SPDX-License-Identifier:	GPL-2.0+
92439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
102439e4bfSJean-Christophe PLAGNIOL-VILLARD 
112439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <config.h>
122439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
132439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h>
142439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
152439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h>
16dd3d1f56SAndy Fleming #include <tsec.h>
17063c1263SAndy Fleming #include <fsl_mdio.h>
180d071cddSKim Phillips #include <asm/errno.h>
19aada81deSchenhui zhao #include <asm/processor.h>
2052d00a81SAlison Wang #include <asm/io.h>
212439e4bfSJean-Christophe PLAGNIOL-VILLARD 
222439e4bfSJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR;
232439e4bfSJean-Christophe PLAGNIOL-VILLARD 
242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_BUF_CNT		2
252439e4bfSJean-Christophe PLAGNIOL-VILLARD 
2618b338fbSClaudiu Manoil static uint rx_idx;		/* index of the current RX buffer */
2718b338fbSClaudiu Manoil static uint tx_idx;		/* index of the current TX buffer */
282439e4bfSJean-Christophe PLAGNIOL-VILLARD 
292439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef __GNUC__
309c9141fdSClaudiu Manoil static struct txbd8 __iomem txbd[TX_BUF_CNT] __aligned(8);
319c9141fdSClaudiu Manoil static struct rxbd8 __iomem rxbd[PKTBUFSRX] __aligned(8);
329c9141fdSClaudiu Manoil 
332439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
342439e4bfSJean-Christophe PLAGNIOL-VILLARD #error "rtx must be 64-bit aligned"
352439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
362439e4bfSJean-Christophe PLAGNIOL-VILLARD 
37c8a60b53SJoe Hershberger static int tsec_send(struct eth_device *dev, void *packet, int length);
38aada81deSchenhui zhao 
3975b9d4aeSAndy Fleming /* Default initializations for TSEC controllers. */
4075b9d4aeSAndy Fleming 
4175b9d4aeSAndy Fleming static struct tsec_info_struct tsec_info[] = {
4275b9d4aeSAndy Fleming #ifdef CONFIG_TSEC1
4375b9d4aeSAndy Fleming 	STD_TSEC_INFO(1),	/* TSEC1 */
4475b9d4aeSAndy Fleming #endif
4575b9d4aeSAndy Fleming #ifdef CONFIG_TSEC2
4675b9d4aeSAndy Fleming 	STD_TSEC_INFO(2),	/* TSEC2 */
4775b9d4aeSAndy Fleming #endif
4875b9d4aeSAndy Fleming #ifdef CONFIG_MPC85XX_FEC
4975b9d4aeSAndy Fleming 	{
50aec84bf6SClaudiu Manoil 		.regs = TSEC_GET_REGS(2, 0x2000),
5175b9d4aeSAndy Fleming 		.devname = CONFIG_MPC85XX_FEC_NAME,
5275b9d4aeSAndy Fleming 		.phyaddr = FEC_PHY_ADDR,
53063c1263SAndy Fleming 		.flags = FEC_FLAGS,
54063c1263SAndy Fleming 		.mii_devname = DEFAULT_MII_NAME
5575b9d4aeSAndy Fleming 	},			/* FEC */
5675b9d4aeSAndy Fleming #endif
5775b9d4aeSAndy Fleming #ifdef CONFIG_TSEC3
5875b9d4aeSAndy Fleming 	STD_TSEC_INFO(3),	/* TSEC3 */
5975b9d4aeSAndy Fleming #endif
6075b9d4aeSAndy Fleming #ifdef CONFIG_TSEC4
6175b9d4aeSAndy Fleming 	STD_TSEC_INFO(4),	/* TSEC4 */
6275b9d4aeSAndy Fleming #endif
6375b9d4aeSAndy Fleming };
6475b9d4aeSAndy Fleming 
652abe361cSAndy Fleming #define TBIANA_SETTINGS ( \
662abe361cSAndy Fleming 		TBIANA_ASYMMETRIC_PAUSE \
672abe361cSAndy Fleming 		| TBIANA_SYMMETRIC_PAUSE \
682abe361cSAndy Fleming 		| TBIANA_FULL_DUPLEX \
692abe361cSAndy Fleming 		)
702abe361cSAndy Fleming 
7190b5bf21SFelix Radensky /* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
7290b5bf21SFelix Radensky #ifndef CONFIG_TSEC_TBICR_SETTINGS
7372c96a68SKumar Gala #define CONFIG_TSEC_TBICR_SETTINGS ( \
742abe361cSAndy Fleming 		TBICR_PHY_RESET \
7572c96a68SKumar Gala 		| TBICR_ANEG_ENABLE \
762abe361cSAndy Fleming 		| TBICR_FULL_DUPLEX \
772abe361cSAndy Fleming 		| TBICR_SPEED1_SET \
782abe361cSAndy Fleming 		)
7990b5bf21SFelix Radensky #endif /* CONFIG_TSEC_TBICR_SETTINGS */
8046e91674SPeter Tyser 
812abe361cSAndy Fleming /* Configure the TBI for SGMII operation */
822abe361cSAndy Fleming static void tsec_configure_serdes(struct tsec_private *priv)
832abe361cSAndy Fleming {
84*9872b736SBin Meng 	/*
85*9872b736SBin Meng 	 * Access TBI PHY registers at given TSEC register offset as opposed
86*9872b736SBin Meng 	 * to the register offset used for external PHY accesses
87*9872b736SBin Meng 	 */
88063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
89063c1263SAndy Fleming 			0, TBI_ANA, TBIANA_SETTINGS);
90063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
91063c1263SAndy Fleming 			0, TBI_TBICON, TBICON_CLK_SELECT);
92063c1263SAndy Fleming 	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
93063c1263SAndy Fleming 			0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
942439e4bfSJean-Christophe PLAGNIOL-VILLARD }
952439e4bfSJean-Christophe PLAGNIOL-VILLARD 
962439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MCAST_TFTP
972439e4bfSJean-Christophe PLAGNIOL-VILLARD 
982439e4bfSJean-Christophe PLAGNIOL-VILLARD /* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
992439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1002439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the appropriate hash bit for the given addr */
1012439e4bfSJean-Christophe PLAGNIOL-VILLARD 
102*9872b736SBin Meng /*
103*9872b736SBin Meng  * 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
114*9872b736SBin Meng  * the entry.
115*9872b736SBin Meng  */
116*9872b736SBin Meng static int 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 
138*9872b736SBin Meng /*
139*9872b736SBin Meng  * Initialized required registers to appropriate values, zeroing
14090751910SMingkai Hu  * those we don't care about (unless zero is bad, in which case,
14190751910SMingkai Hu  * choose a more appropriate value)
14290751910SMingkai Hu  */
143aec84bf6SClaudiu Manoil static void init_registers(struct tsec __iomem *regs)
14490751910SMingkai Hu {
14590751910SMingkai Hu 	/* Clear IEVENT */
14690751910SMingkai Hu 	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
14790751910SMingkai Hu 
14890751910SMingkai Hu 	out_be32(&regs->imask, IMASK_INIT_CLEAR);
14990751910SMingkai Hu 
15090751910SMingkai Hu 	out_be32(&regs->hash.iaddr0, 0);
15190751910SMingkai Hu 	out_be32(&regs->hash.iaddr1, 0);
15290751910SMingkai Hu 	out_be32(&regs->hash.iaddr2, 0);
15390751910SMingkai Hu 	out_be32(&regs->hash.iaddr3, 0);
15490751910SMingkai Hu 	out_be32(&regs->hash.iaddr4, 0);
15590751910SMingkai Hu 	out_be32(&regs->hash.iaddr5, 0);
15690751910SMingkai Hu 	out_be32(&regs->hash.iaddr6, 0);
15790751910SMingkai Hu 	out_be32(&regs->hash.iaddr7, 0);
15890751910SMingkai Hu 
15990751910SMingkai Hu 	out_be32(&regs->hash.gaddr0, 0);
16090751910SMingkai Hu 	out_be32(&regs->hash.gaddr1, 0);
16190751910SMingkai Hu 	out_be32(&regs->hash.gaddr2, 0);
16290751910SMingkai Hu 	out_be32(&regs->hash.gaddr3, 0);
16390751910SMingkai Hu 	out_be32(&regs->hash.gaddr4, 0);
16490751910SMingkai Hu 	out_be32(&regs->hash.gaddr5, 0);
16590751910SMingkai Hu 	out_be32(&regs->hash.gaddr6, 0);
16690751910SMingkai Hu 	out_be32(&regs->hash.gaddr7, 0);
16790751910SMingkai Hu 
16890751910SMingkai Hu 	out_be32(&regs->rctrl, 0x00000000);
16990751910SMingkai Hu 
17090751910SMingkai Hu 	/* Init RMON mib registers */
17182ef75caSClaudiu Manoil 	memset((void *)&regs->rmon, 0, sizeof(regs->rmon));
17290751910SMingkai Hu 
17390751910SMingkai Hu 	out_be32(&regs->rmon.cam1, 0xffffffff);
17490751910SMingkai Hu 	out_be32(&regs->rmon.cam2, 0xffffffff);
17590751910SMingkai Hu 
17690751910SMingkai Hu 	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
17790751910SMingkai Hu 
17890751910SMingkai Hu 	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
17990751910SMingkai Hu 
18090751910SMingkai Hu 	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
18190751910SMingkai Hu 	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
18290751910SMingkai Hu 
18390751910SMingkai Hu }
18490751910SMingkai Hu 
185*9872b736SBin Meng /*
186*9872b736SBin Meng  * Configure maccfg2 based on negotiated speed and duplex
18790751910SMingkai Hu  * reported by PHY handling code
18890751910SMingkai Hu  */
189063c1263SAndy Fleming static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
19090751910SMingkai Hu {
191aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
19290751910SMingkai Hu 	u32 ecntrl, maccfg2;
19390751910SMingkai Hu 
194063c1263SAndy Fleming 	if (!phydev->link) {
195063c1263SAndy Fleming 		printf("%s: No link.\n", phydev->dev->name);
19690751910SMingkai Hu 		return;
19790751910SMingkai Hu 	}
19890751910SMingkai Hu 
19990751910SMingkai Hu 	/* clear all bits relative with interface mode */
20090751910SMingkai Hu 	ecntrl = in_be32(&regs->ecntrl);
20190751910SMingkai Hu 	ecntrl &= ~ECNTRL_R100;
20290751910SMingkai Hu 
20390751910SMingkai Hu 	maccfg2 = in_be32(&regs->maccfg2);
20490751910SMingkai Hu 	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
20590751910SMingkai Hu 
206063c1263SAndy Fleming 	if (phydev->duplex)
20790751910SMingkai Hu 		maccfg2 |= MACCFG2_FULL_DUPLEX;
20890751910SMingkai Hu 
209063c1263SAndy Fleming 	switch (phydev->speed) {
21090751910SMingkai Hu 	case 1000:
21190751910SMingkai Hu 		maccfg2 |= MACCFG2_GMII;
21290751910SMingkai Hu 		break;
21390751910SMingkai Hu 	case 100:
21490751910SMingkai Hu 	case 10:
21590751910SMingkai Hu 		maccfg2 |= MACCFG2_MII;
21690751910SMingkai Hu 
217*9872b736SBin Meng 		/*
218*9872b736SBin Meng 		 * Set R100 bit in all modes although
21990751910SMingkai Hu 		 * it is only used in RGMII mode
22090751910SMingkai Hu 		 */
221063c1263SAndy Fleming 		if (phydev->speed == 100)
22290751910SMingkai Hu 			ecntrl |= ECNTRL_R100;
22390751910SMingkai Hu 		break;
22490751910SMingkai Hu 	default:
225063c1263SAndy Fleming 		printf("%s: Speed was bad\n", phydev->dev->name);
22690751910SMingkai Hu 		break;
22790751910SMingkai Hu 	}
22890751910SMingkai Hu 
22990751910SMingkai Hu 	out_be32(&regs->ecntrl, ecntrl);
23090751910SMingkai Hu 	out_be32(&regs->maccfg2, maccfg2);
23190751910SMingkai Hu 
232063c1263SAndy Fleming 	printf("Speed: %d, %s duplex%s\n", phydev->speed,
233063c1263SAndy Fleming 			(phydev->duplex) ? "full" : "half",
234063c1263SAndy Fleming 			(phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
23590751910SMingkai Hu }
23690751910SMingkai Hu 
237aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
238aada81deSchenhui zhao /*
239aada81deSchenhui zhao  * When MACCFG1[Rx_EN] is enabled during system boot as part
240aada81deSchenhui zhao  * of the eTSEC port initialization sequence,
241aada81deSchenhui zhao  * the eTSEC Rx logic may not be properly initialized.
242aada81deSchenhui zhao  */
243aada81deSchenhui zhao void redundant_init(struct eth_device *dev)
244aada81deSchenhui zhao {
245aada81deSchenhui zhao 	struct tsec_private *priv = dev->priv;
246aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
247aada81deSchenhui zhao 	uint t, count = 0;
248aada81deSchenhui zhao 	int fail = 1;
249aada81deSchenhui zhao 	static const u8 pkt[] = {
250aada81deSchenhui zhao 		0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25,
251aada81deSchenhui zhao 		0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00,
252aada81deSchenhui zhao 		0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01,
253aada81deSchenhui zhao 		0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1,
254aada81deSchenhui zhao 		0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00,
255aada81deSchenhui zhao 		0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
256aada81deSchenhui zhao 		0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
257aada81deSchenhui zhao 		0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
258aada81deSchenhui zhao 		0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
259aada81deSchenhui zhao 		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
260aada81deSchenhui zhao 		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
261aada81deSchenhui zhao 		0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
262aada81deSchenhui zhao 		0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
263aada81deSchenhui zhao 		0x71, 0x72};
264aada81deSchenhui zhao 
265aada81deSchenhui zhao 	/* Enable promiscuous mode */
266aada81deSchenhui zhao 	setbits_be32(&regs->rctrl, 0x8);
267aada81deSchenhui zhao 	/* Enable loopback mode */
268aada81deSchenhui zhao 	setbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
269aada81deSchenhui zhao 	/* Enable transmit and receive */
270aada81deSchenhui zhao 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
271aada81deSchenhui zhao 
272aada81deSchenhui zhao 	/* Tell the DMA it is clear to go */
273aada81deSchenhui zhao 	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
274aada81deSchenhui zhao 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
275aada81deSchenhui zhao 	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
276aada81deSchenhui zhao 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
277aada81deSchenhui zhao 
278aada81deSchenhui zhao 	do {
2799c9141fdSClaudiu Manoil 		uint16_t status;
280aada81deSchenhui zhao 		tsec_send(dev, (void *)pkt, sizeof(pkt));
281aada81deSchenhui zhao 
282aada81deSchenhui zhao 		/* Wait for buffer to be received */
2839c9141fdSClaudiu Manoil 		for (t = 0; in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY; t++) {
284aada81deSchenhui zhao 			if (t >= 10 * TOUT_LOOP) {
285aada81deSchenhui zhao 				printf("%s: tsec: rx error\n", dev->name);
286aada81deSchenhui zhao 				break;
287aada81deSchenhui zhao 			}
288aada81deSchenhui zhao 		}
289aada81deSchenhui zhao 
2901fd92db8SJoe Hershberger 		if (!memcmp(pkt, (void *)net_rx_packets[rx_idx], sizeof(pkt)))
291aada81deSchenhui zhao 			fail = 0;
292aada81deSchenhui zhao 
2939c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].length, 0);
2949c9141fdSClaudiu Manoil 		status = RXBD_EMPTY;
2959c9141fdSClaudiu Manoil 		if ((rx_idx + 1) == PKTBUFSRX)
2969c9141fdSClaudiu Manoil 			status |= RXBD_WRAP;
2979c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].status, status);
29818b338fbSClaudiu Manoil 		rx_idx = (rx_idx + 1) % PKTBUFSRX;
299aada81deSchenhui zhao 
300aada81deSchenhui zhao 		if (in_be32(&regs->ievent) & IEVENT_BSY) {
301aada81deSchenhui zhao 			out_be32(&regs->ievent, IEVENT_BSY);
302aada81deSchenhui zhao 			out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
303aada81deSchenhui zhao 		}
304aada81deSchenhui zhao 		if (fail) {
305aada81deSchenhui zhao 			printf("loopback recv packet error!\n");
306aada81deSchenhui zhao 			clrbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
307aada81deSchenhui zhao 			udelay(1000);
308aada81deSchenhui zhao 			setbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
309aada81deSchenhui zhao 		}
310aada81deSchenhui zhao 	} while ((count++ < 4) && (fail == 1));
311aada81deSchenhui zhao 
312aada81deSchenhui zhao 	if (fail)
313aada81deSchenhui zhao 		panic("eTSEC init fail!\n");
314aada81deSchenhui zhao 	/* Disable promiscuous mode */
315aada81deSchenhui zhao 	clrbits_be32(&regs->rctrl, 0x8);
316aada81deSchenhui zhao 	/* Disable loopback mode */
317aada81deSchenhui zhao 	clrbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
318aada81deSchenhui zhao }
319aada81deSchenhui zhao #endif
320aada81deSchenhui zhao 
321*9872b736SBin Meng /*
322*9872b736SBin Meng  * Set up the buffers and their descriptors, and bring up the
32390751910SMingkai Hu  * interface
32490751910SMingkai Hu  */
32590751910SMingkai Hu static void startup_tsec(struct eth_device *dev)
32690751910SMingkai Hu {
32790751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
328aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
3299c9141fdSClaudiu Manoil 	uint16_t status;
3309c9141fdSClaudiu Manoil 	int i;
33190751910SMingkai Hu 
332063c1263SAndy Fleming 	/* reset the indices to zero */
33318b338fbSClaudiu Manoil 	rx_idx = 0;
33418b338fbSClaudiu Manoil 	tx_idx = 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 */
3409c9141fdSClaudiu Manoil 	out_be32(&regs->tbase, (u32)&txbd[0]);
3419c9141fdSClaudiu Manoil 	out_be32(&regs->rbase, (u32)&rxbd[0]);
34290751910SMingkai Hu 
34390751910SMingkai Hu 	/* Initialize the Rx Buffer descriptors */
34490751910SMingkai Hu 	for (i = 0; i < PKTBUFSRX; i++) {
3459c9141fdSClaudiu Manoil 		out_be16(&rxbd[i].status, RXBD_EMPTY);
3469c9141fdSClaudiu Manoil 		out_be16(&rxbd[i].length, 0);
3471fd92db8SJoe Hershberger 		out_be32(&rxbd[i].bufptr, (u32)net_rx_packets[i]);
34890751910SMingkai Hu 	}
3499c9141fdSClaudiu Manoil 	status = in_be16(&rxbd[PKTBUFSRX - 1].status);
3509c9141fdSClaudiu Manoil 	out_be16(&rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
35190751910SMingkai Hu 
35290751910SMingkai Hu 	/* Initialize the TX Buffer Descriptors */
35390751910SMingkai Hu 	for (i = 0; i < TX_BUF_CNT; i++) {
3549c9141fdSClaudiu Manoil 		out_be16(&txbd[i].status, 0);
3559c9141fdSClaudiu Manoil 		out_be16(&txbd[i].length, 0);
3569c9141fdSClaudiu Manoil 		out_be32(&txbd[i].bufptr, 0);
35790751910SMingkai Hu 	}
3589c9141fdSClaudiu Manoil 	status = in_be16(&txbd[TX_BUF_CNT - 1].status);
3599c9141fdSClaudiu Manoil 	out_be16(&txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
36090751910SMingkai Hu 
361aada81deSchenhui zhao #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
362aada81deSchenhui zhao 	svr = get_svr();
363aada81deSchenhui zhao 	if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
364aada81deSchenhui zhao 		redundant_init(dev);
365aada81deSchenhui zhao #endif
36690751910SMingkai Hu 	/* Enable Transmit and Receive */
36790751910SMingkai Hu 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
36890751910SMingkai Hu 
36990751910SMingkai Hu 	/* Tell the DMA it is clear to go */
37090751910SMingkai Hu 	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
37190751910SMingkai Hu 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
37290751910SMingkai Hu 	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
37390751910SMingkai Hu 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
37490751910SMingkai Hu }
37590751910SMingkai Hu 
376*9872b736SBin Meng /*
377*9872b736SBin Meng  * This returns the status bits of the device. The return value
37890751910SMingkai Hu  * is never checked, and this is what the 8260 driver did, so we
37990751910SMingkai Hu  * do the same. Presumably, this would be zero if there were no
38090751910SMingkai Hu  * errors
38190751910SMingkai Hu  */
382c8a60b53SJoe Hershberger static int tsec_send(struct eth_device *dev, void *packet, int length)
38390751910SMingkai Hu {
38490751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
385aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
3869c9141fdSClaudiu Manoil 	uint16_t status;
3879c9141fdSClaudiu Manoil 	int result = 0;
3889c9141fdSClaudiu Manoil 	int i;
38990751910SMingkai Hu 
39090751910SMingkai Hu 	/* Find an empty buffer descriptor */
3919c9141fdSClaudiu Manoil 	for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) {
39290751910SMingkai Hu 		if (i >= TOUT_LOOP) {
39390751910SMingkai Hu 			debug("%s: tsec: tx buffers full\n", dev->name);
39490751910SMingkai Hu 			return result;
39590751910SMingkai Hu 		}
39690751910SMingkai Hu 	}
39790751910SMingkai Hu 
3989c9141fdSClaudiu Manoil 	out_be32(&txbd[tx_idx].bufptr, (u32)packet);
3999c9141fdSClaudiu Manoil 	out_be16(&txbd[tx_idx].length, length);
4009c9141fdSClaudiu Manoil 	status = in_be16(&txbd[tx_idx].status);
4019c9141fdSClaudiu Manoil 	out_be16(&txbd[tx_idx].status, status |
4029c9141fdSClaudiu Manoil 		(TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
40390751910SMingkai Hu 
40490751910SMingkai Hu 	/* Tell the DMA to go */
40590751910SMingkai Hu 	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
40690751910SMingkai Hu 
40790751910SMingkai Hu 	/* Wait for buffer to be transmitted */
4089c9141fdSClaudiu Manoil 	for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) {
40990751910SMingkai Hu 		if (i >= TOUT_LOOP) {
41090751910SMingkai Hu 			debug("%s: tsec: tx error\n", dev->name);
41190751910SMingkai Hu 			return result;
41290751910SMingkai Hu 		}
41390751910SMingkai Hu 	}
41490751910SMingkai Hu 
41518b338fbSClaudiu Manoil 	tx_idx = (tx_idx + 1) % TX_BUF_CNT;
4169c9141fdSClaudiu Manoil 	result = in_be16(&txbd[tx_idx].status) & TXBD_STATS;
41790751910SMingkai Hu 
41890751910SMingkai Hu 	return result;
41990751910SMingkai Hu }
42090751910SMingkai Hu 
42190751910SMingkai Hu static int tsec_recv(struct eth_device *dev)
42290751910SMingkai Hu {
42390751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
424aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
42590751910SMingkai Hu 
4269c9141fdSClaudiu Manoil 	while (!(in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY)) {
4279c9141fdSClaudiu Manoil 		int length = in_be16(&rxbd[rx_idx].length);
4289c9141fdSClaudiu Manoil 		uint16_t status = in_be16(&rxbd[rx_idx].status);
42990751910SMingkai Hu 
43090751910SMingkai Hu 		/* Send the packet up if there were no errors */
4319c9141fdSClaudiu Manoil 		if (!(status & RXBD_STATS))
4321fd92db8SJoe Hershberger 			net_process_received_packet(net_rx_packets[rx_idx],
4331fd92db8SJoe Hershberger 						    length - 4);
4349c9141fdSClaudiu Manoil 		else
4359c9141fdSClaudiu Manoil 			printf("Got error %x\n", (status & RXBD_STATS));
43690751910SMingkai Hu 
4379c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].length, 0);
43890751910SMingkai Hu 
4399c9141fdSClaudiu Manoil 		status = RXBD_EMPTY;
44090751910SMingkai Hu 		/* Set the wrap bit if this is the last element in the list */
4419c9141fdSClaudiu Manoil 		if ((rx_idx + 1) == PKTBUFSRX)
4429c9141fdSClaudiu Manoil 			status |= RXBD_WRAP;
4439c9141fdSClaudiu Manoil 		out_be16(&rxbd[rx_idx].status, status);
44490751910SMingkai Hu 
44518b338fbSClaudiu Manoil 		rx_idx = (rx_idx + 1) % PKTBUFSRX;
44690751910SMingkai Hu 	}
44790751910SMingkai Hu 
44890751910SMingkai Hu 	if (in_be32(&regs->ievent) & IEVENT_BSY) {
44990751910SMingkai Hu 		out_be32(&regs->ievent, IEVENT_BSY);
45090751910SMingkai Hu 		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
45190751910SMingkai Hu 	}
45290751910SMingkai Hu 
45390751910SMingkai Hu 	return -1;
45490751910SMingkai Hu }
45590751910SMingkai Hu 
45690751910SMingkai Hu /* Stop the interface */
45790751910SMingkai Hu static void tsec_halt(struct eth_device *dev)
45890751910SMingkai Hu {
45990751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
460aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
46190751910SMingkai Hu 
46290751910SMingkai Hu 	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
46390751910SMingkai Hu 	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
46490751910SMingkai Hu 
46590751910SMingkai Hu 	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
46690751910SMingkai Hu 			!= (IEVENT_GRSC | IEVENT_GTSC))
46790751910SMingkai Hu 		;
46890751910SMingkai Hu 
46990751910SMingkai Hu 	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
47090751910SMingkai Hu 
47190751910SMingkai Hu 	/* Shut down the PHY, as needed */
472063c1263SAndy Fleming 	phy_shutdown(priv->phydev);
47390751910SMingkai Hu }
47490751910SMingkai Hu 
475*9872b736SBin Meng /*
476*9872b736SBin Meng  * Initializes data structures and registers for the controller,
47790751910SMingkai Hu  * and brings the interface up. Returns the link status, meaning
47890751910SMingkai Hu  * that it returns success if the link is up, failure otherwise.
479*9872b736SBin Meng  * This allows U-Boot to find the first active controller.
48090751910SMingkai Hu  */
48190751910SMingkai Hu static int tsec_init(struct eth_device *dev, bd_t * bd)
48290751910SMingkai Hu {
48390751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
484aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
485b1690bc3SClaudiu Manoil 	u32 tempval;
48611af8d65STimur Tabi 	int ret;
48790751910SMingkai Hu 
48890751910SMingkai Hu 	/* Make sure the controller is stopped */
48990751910SMingkai Hu 	tsec_halt(dev);
49090751910SMingkai Hu 
49190751910SMingkai Hu 	/* Init MACCFG2.  Defaults to GMII */
49290751910SMingkai Hu 	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
49390751910SMingkai Hu 
49490751910SMingkai Hu 	/* Init ECNTRL */
49590751910SMingkai Hu 	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
49690751910SMingkai Hu 
497*9872b736SBin Meng 	/*
498*9872b736SBin Meng 	 * Copy the station address into the address registers.
499b1690bc3SClaudiu Manoil 	 * For a station address of 0x12345678ABCD in transmission
500b1690bc3SClaudiu Manoil 	 * order (BE), MACnADDR1 is set to 0xCDAB7856 and
501b1690bc3SClaudiu Manoil 	 * MACnADDR2 is set to 0x34120000.
502b1690bc3SClaudiu Manoil 	 */
503b1690bc3SClaudiu Manoil 	tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) |
504b1690bc3SClaudiu Manoil 		  (dev->enetaddr[3] << 8)  |  dev->enetaddr[2];
50590751910SMingkai Hu 
50690751910SMingkai Hu 	out_be32(&regs->macstnaddr1, tempval);
50790751910SMingkai Hu 
508b1690bc3SClaudiu Manoil 	tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16);
50990751910SMingkai Hu 
51090751910SMingkai Hu 	out_be32(&regs->macstnaddr2, tempval);
51190751910SMingkai Hu 
51290751910SMingkai Hu 	/* Clear out (for the most part) the other registers */
51390751910SMingkai Hu 	init_registers(regs);
51490751910SMingkai Hu 
51590751910SMingkai Hu 	/* Ready the device for tx/rx */
51690751910SMingkai Hu 	startup_tsec(dev);
51790751910SMingkai Hu 
518063c1263SAndy Fleming 	/* Start up the PHY */
51911af8d65STimur Tabi 	ret = phy_startup(priv->phydev);
52011af8d65STimur Tabi 	if (ret) {
52111af8d65STimur Tabi 		printf("Could not initialize PHY %s\n",
52211af8d65STimur Tabi 		       priv->phydev->dev->name);
52311af8d65STimur Tabi 		return ret;
52411af8d65STimur Tabi 	}
525063c1263SAndy Fleming 
526063c1263SAndy Fleming 	adjust_link(priv, priv->phydev);
527063c1263SAndy Fleming 
52890751910SMingkai Hu 	/* If there's no link, fail */
529063c1263SAndy Fleming 	return priv->phydev->link ? 0 : -1;
53090751910SMingkai Hu }
53190751910SMingkai Hu 
532063c1263SAndy Fleming static phy_interface_t tsec_get_interface(struct tsec_private *priv)
533063c1263SAndy Fleming {
534aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
535063c1263SAndy Fleming 	u32 ecntrl;
536063c1263SAndy Fleming 
537063c1263SAndy Fleming 	ecntrl = in_be32(&regs->ecntrl);
538063c1263SAndy Fleming 
539063c1263SAndy Fleming 	if (ecntrl & ECNTRL_SGMII_MODE)
540063c1263SAndy Fleming 		return PHY_INTERFACE_MODE_SGMII;
541063c1263SAndy Fleming 
542063c1263SAndy Fleming 	if (ecntrl & ECNTRL_TBI_MODE) {
543063c1263SAndy Fleming 		if (ecntrl & ECNTRL_REDUCED_MODE)
544063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RTBI;
545063c1263SAndy Fleming 		else
546063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_TBI;
547063c1263SAndy Fleming 	}
548063c1263SAndy Fleming 
549063c1263SAndy Fleming 	if (ecntrl & ECNTRL_REDUCED_MODE) {
550063c1263SAndy Fleming 		if (ecntrl & ECNTRL_REDUCED_MII_MODE)
551063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RMII;
552063c1263SAndy Fleming 		else {
553063c1263SAndy Fleming 			phy_interface_t interface = priv->interface;
554063c1263SAndy Fleming 
555063c1263SAndy Fleming 			/*
556063c1263SAndy Fleming 			 * This isn't autodetected, so it must
557063c1263SAndy Fleming 			 * be set by the platform code.
558063c1263SAndy Fleming 			 */
559063c1263SAndy Fleming 			if ((interface == PHY_INTERFACE_MODE_RGMII_ID) ||
560063c1263SAndy Fleming 			    (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
561063c1263SAndy Fleming 			    (interface == PHY_INTERFACE_MODE_RGMII_RXID))
562063c1263SAndy Fleming 				return interface;
563063c1263SAndy Fleming 
564063c1263SAndy Fleming 			return PHY_INTERFACE_MODE_RGMII;
565063c1263SAndy Fleming 		}
566063c1263SAndy Fleming 	}
567063c1263SAndy Fleming 
568063c1263SAndy Fleming 	if (priv->flags & TSEC_GIGABIT)
569063c1263SAndy Fleming 		return PHY_INTERFACE_MODE_GMII;
570063c1263SAndy Fleming 
571063c1263SAndy Fleming 	return PHY_INTERFACE_MODE_MII;
572063c1263SAndy Fleming }
573063c1263SAndy Fleming 
574*9872b736SBin Meng /*
575*9872b736SBin Meng  * Discover which PHY is attached to the device, and configure it
57690751910SMingkai Hu  * properly.  If the PHY is not recognized, then return 0
57790751910SMingkai Hu  * (failure).  Otherwise, return 1
57890751910SMingkai Hu  */
57990751910SMingkai Hu static int init_phy(struct eth_device *dev)
58090751910SMingkai Hu {
58190751910SMingkai Hu 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
582063c1263SAndy Fleming 	struct phy_device *phydev;
583aec84bf6SClaudiu Manoil 	struct tsec __iomem *regs = priv->regs;
584063c1263SAndy Fleming 	u32 supported = (SUPPORTED_10baseT_Half |
585063c1263SAndy Fleming 			SUPPORTED_10baseT_Full |
586063c1263SAndy Fleming 			SUPPORTED_100baseT_Half |
587063c1263SAndy Fleming 			SUPPORTED_100baseT_Full);
588063c1263SAndy Fleming 
589063c1263SAndy Fleming 	if (priv->flags & TSEC_GIGABIT)
590063c1263SAndy Fleming 		supported |= SUPPORTED_1000baseT_Full;
59190751910SMingkai Hu 
59290751910SMingkai Hu 	/* Assign a Physical address to the TBI */
59390751910SMingkai Hu 	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
59490751910SMingkai Hu 
595063c1263SAndy Fleming 	priv->interface = tsec_get_interface(priv);
59690751910SMingkai Hu 
597063c1263SAndy Fleming 	if (priv->interface == PHY_INTERFACE_MODE_SGMII)
59890751910SMingkai Hu 		tsec_configure_serdes(priv);
59990751910SMingkai Hu 
600063c1263SAndy Fleming 	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
6017f233c05SClaudiu Manoil 	if (!phydev)
6027f233c05SClaudiu Manoil 		return 0;
60390751910SMingkai Hu 
604063c1263SAndy Fleming 	phydev->supported &= supported;
605063c1263SAndy Fleming 	phydev->advertising = phydev->supported;
606063c1263SAndy Fleming 
607063c1263SAndy Fleming 	priv->phydev = phydev;
608063c1263SAndy Fleming 
609063c1263SAndy Fleming 	phy_config(phydev);
61090751910SMingkai Hu 
61190751910SMingkai Hu 	return 1;
61290751910SMingkai Hu }
61390751910SMingkai Hu 
614*9872b736SBin Meng /*
615*9872b736SBin Meng  * Initialize device structure. Returns success if PHY
61690751910SMingkai Hu  * initialization succeeded (i.e. if it recognizes the PHY)
61790751910SMingkai Hu  */
61890751910SMingkai Hu static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
61990751910SMingkai Hu {
62090751910SMingkai Hu 	struct eth_device *dev;
62190751910SMingkai Hu 	int i;
62290751910SMingkai Hu 	struct tsec_private *priv;
62390751910SMingkai Hu 
62490751910SMingkai Hu 	dev = (struct eth_device *)malloc(sizeof *dev);
62590751910SMingkai Hu 
62690751910SMingkai Hu 	if (NULL == dev)
62790751910SMingkai Hu 		return 0;
62890751910SMingkai Hu 
62990751910SMingkai Hu 	memset(dev, 0, sizeof *dev);
63090751910SMingkai Hu 
63190751910SMingkai Hu 	priv = (struct tsec_private *)malloc(sizeof(*priv));
63290751910SMingkai Hu 
63390751910SMingkai Hu 	if (NULL == priv)
63490751910SMingkai Hu 		return 0;
63590751910SMingkai Hu 
63690751910SMingkai Hu 	priv->regs = tsec_info->regs;
63790751910SMingkai Hu 	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
63890751910SMingkai Hu 
63990751910SMingkai Hu 	priv->phyaddr = tsec_info->phyaddr;
64090751910SMingkai Hu 	priv->flags = tsec_info->flags;
64190751910SMingkai Hu 
64290751910SMingkai Hu 	sprintf(dev->name, tsec_info->devname);
643063c1263SAndy Fleming 	priv->interface = tsec_info->interface;
644063c1263SAndy Fleming 	priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
64590751910SMingkai Hu 	dev->iobase = 0;
64690751910SMingkai Hu 	dev->priv = priv;
64790751910SMingkai Hu 	dev->init = tsec_init;
64890751910SMingkai Hu 	dev->halt = tsec_halt;
64990751910SMingkai Hu 	dev->send = tsec_send;
65090751910SMingkai Hu 	dev->recv = tsec_recv;
65190751910SMingkai Hu #ifdef CONFIG_MCAST_TFTP
65290751910SMingkai Hu 	dev->mcast = tsec_mcast_addr;
65390751910SMingkai Hu #endif
65490751910SMingkai Hu 
655*9872b736SBin Meng 	/* Tell U-Boot to get the addr from the env */
65690751910SMingkai Hu 	for (i = 0; i < 6; i++)
65790751910SMingkai Hu 		dev->enetaddr[i] = 0;
65890751910SMingkai Hu 
65990751910SMingkai Hu 	eth_register(dev);
66090751910SMingkai Hu 
66190751910SMingkai Hu 	/* Reset the MAC */
66290751910SMingkai Hu 	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
66390751910SMingkai Hu 	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
66490751910SMingkai Hu 	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
66590751910SMingkai Hu 
66690751910SMingkai Hu 	/* Try to initialize PHY here, and return */
66790751910SMingkai Hu 	return init_phy(dev);
66890751910SMingkai Hu }
66990751910SMingkai Hu 
67090751910SMingkai Hu /*
67190751910SMingkai Hu  * Initialize all the TSEC devices
67290751910SMingkai Hu  *
67390751910SMingkai Hu  * Returns the number of TSEC devices that were initialized
67490751910SMingkai Hu  */
67590751910SMingkai Hu int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
67690751910SMingkai Hu {
67790751910SMingkai Hu 	int i;
67890751910SMingkai Hu 	int ret, count = 0;
67990751910SMingkai Hu 
68090751910SMingkai Hu 	for (i = 0; i < num; i++) {
68190751910SMingkai Hu 		ret = tsec_initialize(bis, &tsecs[i]);
68290751910SMingkai Hu 		if (ret > 0)
68390751910SMingkai Hu 			count += ret;
68490751910SMingkai Hu 	}
68590751910SMingkai Hu 
68690751910SMingkai Hu 	return count;
68790751910SMingkai Hu }
68890751910SMingkai Hu 
68990751910SMingkai Hu int tsec_standard_init(bd_t *bis)
69090751910SMingkai Hu {
691063c1263SAndy Fleming 	struct fsl_pq_mdio_info info;
692063c1263SAndy Fleming 
693aec84bf6SClaudiu Manoil 	info.regs = TSEC_GET_MDIO_REGS_BASE(1);
694063c1263SAndy Fleming 	info.name = DEFAULT_MII_NAME;
695063c1263SAndy Fleming 
696063c1263SAndy Fleming 	fsl_pq_mdio_init(bis, &info);
697063c1263SAndy Fleming 
69890751910SMingkai Hu 	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
69990751910SMingkai Hu }
700