blob: 15701ee1474fdebddfdf11d555a783783b04df84 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk42d1f032003-10-15 23:53:47 +00002/*
wdenk97d80fc2004-06-09 00:34:46 +00003 * Freescale Three Speed Ethernet Controller driver
wdenk42d1f032003-10-15 23:53:47 +00004 *
Claudiu Manoilaec84bf2013-09-30 12:44:42 +03005 * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc.
wdenk42d1f032003-10-15 23:53:47 +00006 * (C) Copyright 2003, Motorola, Inc.
wdenk42d1f032003-10-15 23:53:47 +00007 * author Andy Fleming
wdenk42d1f032003-10-15 23:53:47 +00008 */
9
10#include <config.h>
wdenk42d1f032003-10-15 23:53:47 +000011#include <common.h>
Bin Meng9a1d6af2016-01-11 22:41:24 -080012#include <dm.h>
wdenk42d1f032003-10-15 23:53:47 +000013#include <malloc.h>
14#include <net.h>
15#include <command.h>
Andy Flemingdd3d1f52008-08-31 16:33:25 -050016#include <tsec.h>
Andy Fleming063c1262011-04-08 02:10:54 -050017#include <fsl_mdio.h>
Simon Glassc05ed002020-05-10 11:40:11 -060018#include <linux/delay.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090019#include <linux/errno.h>
chenhui zhaoaada81d2011-10-03 08:38:50 -050020#include <asm/processor.h>
Alison Wang52d00a82014-09-05 13:52:38 +080021#include <asm/io.h>
wdenk42d1f032003-10-15 23:53:47 +000022
Bin Meng9a1d6af2016-01-11 22:41:24 -080023#ifndef CONFIG_DM_ETH
Andy Fleming75b9d4a2008-08-31 16:33:26 -050024/* Default initializations for TSEC controllers. */
25
26static struct tsec_info_struct tsec_info[] = {
27#ifdef CONFIG_TSEC1
28 STD_TSEC_INFO(1), /* TSEC1 */
29#endif
30#ifdef CONFIG_TSEC2
31 STD_TSEC_INFO(2), /* TSEC2 */
32#endif
33#ifdef CONFIG_MPC85XX_FEC
34 {
Claudiu Manoilaec84bf2013-09-30 12:44:42 +030035 .regs = TSEC_GET_REGS(2, 0x2000),
Andy Fleming75b9d4a2008-08-31 16:33:26 -050036 .devname = CONFIG_MPC85XX_FEC_NAME,
37 .phyaddr = FEC_PHY_ADDR,
Andy Fleming063c1262011-04-08 02:10:54 -050038 .flags = FEC_FLAGS,
39 .mii_devname = DEFAULT_MII_NAME
Andy Fleming75b9d4a2008-08-31 16:33:26 -050040 }, /* FEC */
41#endif
42#ifdef CONFIG_TSEC3
43 STD_TSEC_INFO(3), /* TSEC3 */
44#endif
45#ifdef CONFIG_TSEC4
46 STD_TSEC_INFO(4), /* TSEC4 */
47#endif
48};
Bin Meng9a1d6af2016-01-11 22:41:24 -080049#endif /* CONFIG_DM_ETH */
Andy Fleming75b9d4a2008-08-31 16:33:26 -050050
Andy Fleming2abe3612008-08-31 16:33:27 -050051#define TBIANA_SETTINGS ( \
52 TBIANA_ASYMMETRIC_PAUSE \
53 | TBIANA_SYMMETRIC_PAUSE \
54 | TBIANA_FULL_DUPLEX \
55 )
56
Felix Radensky90b5bf22010-06-28 01:57:39 +030057/* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
58#ifndef CONFIG_TSEC_TBICR_SETTINGS
Kumar Gala72c96a62010-12-01 22:55:54 -060059#define CONFIG_TSEC_TBICR_SETTINGS ( \
Andy Fleming2abe3612008-08-31 16:33:27 -050060 TBICR_PHY_RESET \
Kumar Gala72c96a62010-12-01 22:55:54 -060061 | TBICR_ANEG_ENABLE \
Andy Fleming2abe3612008-08-31 16:33:27 -050062 | TBICR_FULL_DUPLEX \
63 | TBICR_SPEED1_SET \
64 )
Felix Radensky90b5bf22010-06-28 01:57:39 +030065#endif /* CONFIG_TSEC_TBICR_SETTINGS */
Peter Tyser46e91672009-11-03 17:52:07 -060066
Andy Fleming2abe3612008-08-31 16:33:27 -050067/* Configure the TBI for SGMII operation */
68static void tsec_configure_serdes(struct tsec_private *priv)
69{
Bin Meng9872b732016-01-11 22:41:18 -080070 /*
71 * Access TBI PHY registers at given TSEC register offset as opposed
72 * to the register offset used for external PHY accesses
73 */
Andy Fleming063c1262011-04-08 02:10:54 -050074 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixd38de332018-01-15 11:08:21 +010075 0, TBI_ANA, TBIANA_SETTINGS);
Andy Fleming063c1262011-04-08 02:10:54 -050076 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixd38de332018-01-15 11:08:21 +010077 0, TBI_TBICON, TBICON_CLK_SELECT);
Andy Fleming063c1262011-04-08 02:10:54 -050078 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixd38de332018-01-15 11:08:21 +010079 0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
Andy Fleming2abe3612008-08-31 16:33:27 -050080}
michael.firth@bt.com55fe7c52008-01-16 11:40:51 +000081
Chris Packham1a4af5c2018-11-26 21:00:28 +130082/* the 'way' for ethernet-CRC-32. Spliced in from Linux lib/crc32.c
83 * and this is the ethernet-crc method needed for TSEC -- and perhaps
84 * some other adapter -- hash tables
85 */
86#define CRCPOLY_LE 0xedb88320
87static u32 ether_crc(size_t len, unsigned char const *p)
88{
89 int i;
90 u32 crc;
91
92 crc = ~0;
93 while (len--) {
94 crc ^= *p++;
95 for (i = 0; i < 8; i++)
96 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
97 }
98 /* an reverse the bits, cuz of way they arrive -- last-first */
99 crc = (crc >> 16) | (crc << 16);
100 crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
101 crc = (crc >> 4 & 0x0f0f0f0f) | (crc << 4 & 0xf0f0f0f0);
102 crc = (crc >> 2 & 0x33333333) | (crc << 2 & 0xcccccccc);
103 crc = (crc >> 1 & 0x55555555) | (crc << 1 & 0xaaaaaaaa);
104 return crc;
105}
106
David Updegraff53a5c422007-06-11 10:41:07 -0500107/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
108
109/* Set the appropriate hash bit for the given addr */
110
Bin Meng9872b732016-01-11 22:41:18 -0800111/*
112 * The algorithm works like so:
David Updegraff53a5c422007-06-11 10:41:07 -0500113 * 1) Take the Destination Address (ie the multicast address), and
114 * do a CRC on it (little endian), and reverse the bits of the
115 * result.
116 * 2) Use the 8 most significant bits as a hash into a 256-entry
117 * table. The table is controlled through 8 32-bit registers:
Claudiu Manoil876d4512013-09-30 12:44:40 +0300118 * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is entry
119 * 255. This means that the 3 most significant bits in the
David Updegraff53a5c422007-06-11 10:41:07 -0500120 * hash index which gaddr register to use, and the 5 other bits
121 * indicate which bit (assuming an IBM numbering scheme, which
Claudiu Manoil876d4512013-09-30 12:44:40 +0300122 * for PowerPC (tm) is usually the case) in the register holds
Bin Meng9872b732016-01-11 22:41:18 -0800123 * the entry.
124 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800125#ifndef CONFIG_DM_ETH
Chris Packham67bb9842018-11-26 21:00:29 +1300126static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac,
127 int join)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800128#else
Chris Packham67bb9842018-11-26 21:00:29 +1300129static int tsec_mcast_addr(struct udevice *dev, const u8 *mcast_mac, int join)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800130#endif
David Updegraff53a5c422007-06-11 10:41:07 -0500131{
Claudiu Manoilb2002042013-09-30 12:44:41 +0300132 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoil876d4512013-09-30 12:44:40 +0300133 struct tsec __iomem *regs = priv->regs;
134 u32 result, value;
135 u8 whichbit, whichreg;
David Updegraff53a5c422007-06-11 10:41:07 -0500136
Claudiu Manoil876d4512013-09-30 12:44:40 +0300137 result = ether_crc(MAC_ADDR_LEN, mcast_mac);
138 whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */
139 whichreg = result >> 29; /* the 3 MSB = which reg to set it in */
David Updegraff53a5c422007-06-11 10:41:07 -0500140
Mario Sixd38de332018-01-15 11:08:21 +0100141 value = BIT(31 - whichbit);
David Updegraff53a5c422007-06-11 10:41:07 -0500142
Chris Packham67bb9842018-11-26 21:00:29 +1300143 if (join)
Claudiu Manoil876d4512013-09-30 12:44:40 +0300144 setbits_be32(&regs->hash.gaddr0 + whichreg, value);
145 else
146 clrbits_be32(&regs->hash.gaddr0 + whichreg, value);
147
David Updegraff53a5c422007-06-11 10:41:07 -0500148 return 0;
149}
Mingkai Hu90751912011-01-27 12:52:46 +0800150
Bin Meng9872b732016-01-11 22:41:18 -0800151/*
152 * Initialized required registers to appropriate values, zeroing
Mingkai Hu90751912011-01-27 12:52:46 +0800153 * those we don't care about (unless zero is bad, in which case,
154 * choose a more appropriate value)
155 */
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300156static void init_registers(struct tsec __iomem *regs)
Mingkai Hu90751912011-01-27 12:52:46 +0800157{
158 /* Clear IEVENT */
159 out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
160
161 out_be32(&regs->imask, IMASK_INIT_CLEAR);
162
163 out_be32(&regs->hash.iaddr0, 0);
164 out_be32(&regs->hash.iaddr1, 0);
165 out_be32(&regs->hash.iaddr2, 0);
166 out_be32(&regs->hash.iaddr3, 0);
167 out_be32(&regs->hash.iaddr4, 0);
168 out_be32(&regs->hash.iaddr5, 0);
169 out_be32(&regs->hash.iaddr6, 0);
170 out_be32(&regs->hash.iaddr7, 0);
171
172 out_be32(&regs->hash.gaddr0, 0);
173 out_be32(&regs->hash.gaddr1, 0);
174 out_be32(&regs->hash.gaddr2, 0);
175 out_be32(&regs->hash.gaddr3, 0);
176 out_be32(&regs->hash.gaddr4, 0);
177 out_be32(&regs->hash.gaddr5, 0);
178 out_be32(&regs->hash.gaddr6, 0);
179 out_be32(&regs->hash.gaddr7, 0);
180
181 out_be32(&regs->rctrl, 0x00000000);
182
183 /* Init RMON mib registers */
Claudiu Manoil82ef75c2013-09-30 12:44:46 +0300184 memset((void *)&regs->rmon, 0, sizeof(regs->rmon));
Mingkai Hu90751912011-01-27 12:52:46 +0800185
186 out_be32(&regs->rmon.cam1, 0xffffffff);
187 out_be32(&regs->rmon.cam2, 0xffffffff);
188
189 out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
190
191 out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
192
193 out_be32(&regs->attr, ATTR_INIT_SETTINGS);
194 out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
Mingkai Hu90751912011-01-27 12:52:46 +0800195}
196
Bin Meng9872b732016-01-11 22:41:18 -0800197/*
198 * Configure maccfg2 based on negotiated speed and duplex
Mingkai Hu90751912011-01-27 12:52:46 +0800199 * reported by PHY handling code
200 */
Andy Fleming063c1262011-04-08 02:10:54 -0500201static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
Mingkai Hu90751912011-01-27 12:52:46 +0800202{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300203 struct tsec __iomem *regs = priv->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800204 u32 ecntrl, maccfg2;
205
Andy Fleming063c1262011-04-08 02:10:54 -0500206 if (!phydev->link) {
207 printf("%s: No link.\n", phydev->dev->name);
Mingkai Hu90751912011-01-27 12:52:46 +0800208 return;
209 }
210
211 /* clear all bits relative with interface mode */
212 ecntrl = in_be32(&regs->ecntrl);
213 ecntrl &= ~ECNTRL_R100;
214
215 maccfg2 = in_be32(&regs->maccfg2);
216 maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
217
Andy Fleming063c1262011-04-08 02:10:54 -0500218 if (phydev->duplex)
Mingkai Hu90751912011-01-27 12:52:46 +0800219 maccfg2 |= MACCFG2_FULL_DUPLEX;
220
Andy Fleming063c1262011-04-08 02:10:54 -0500221 switch (phydev->speed) {
Mingkai Hu90751912011-01-27 12:52:46 +0800222 case 1000:
223 maccfg2 |= MACCFG2_GMII;
224 break;
225 case 100:
226 case 10:
227 maccfg2 |= MACCFG2_MII;
228
Bin Meng9872b732016-01-11 22:41:18 -0800229 /*
230 * Set R100 bit in all modes although
Mingkai Hu90751912011-01-27 12:52:46 +0800231 * it is only used in RGMII mode
232 */
Andy Fleming063c1262011-04-08 02:10:54 -0500233 if (phydev->speed == 100)
Mingkai Hu90751912011-01-27 12:52:46 +0800234 ecntrl |= ECNTRL_R100;
235 break;
236 default:
Andy Fleming063c1262011-04-08 02:10:54 -0500237 printf("%s: Speed was bad\n", phydev->dev->name);
Mingkai Hu90751912011-01-27 12:52:46 +0800238 break;
239 }
240
241 out_be32(&regs->ecntrl, ecntrl);
242 out_be32(&regs->maccfg2, maccfg2);
243
Andy Fleming063c1262011-04-08 02:10:54 -0500244 printf("Speed: %d, %s duplex%s\n", phydev->speed,
Mario Sixd38de332018-01-15 11:08:21 +0100245 (phydev->duplex) ? "full" : "half",
246 (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
Mingkai Hu90751912011-01-27 12:52:46 +0800247}
248
Bin Meng8ba50172016-01-11 22:41:21 -0800249/*
250 * This returns the status bits of the device. The return value
251 * is never checked, and this is what the 8260 driver did, so we
252 * do the same. Presumably, this would be zero if there were no
253 * errors
254 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800255#ifndef CONFIG_DM_ETH
Bin Meng8ba50172016-01-11 22:41:21 -0800256static int tsec_send(struct eth_device *dev, void *packet, int length)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800257#else
258static int tsec_send(struct udevice *dev, void *packet, int length)
259#endif
Bin Meng8ba50172016-01-11 22:41:21 -0800260{
261 struct tsec_private *priv = (struct tsec_private *)dev->priv;
262 struct tsec __iomem *regs = priv->regs;
Bin Meng8ba50172016-01-11 22:41:21 -0800263 int result = 0;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300264 u16 status;
Bin Meng8ba50172016-01-11 22:41:21 -0800265 int i;
266
267 /* Find an empty buffer descriptor */
268 for (i = 0;
269 in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY;
270 i++) {
271 if (i >= TOUT_LOOP) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300272 printf("%s: tsec: tx buffers full\n", dev->name);
Bin Meng8ba50172016-01-11 22:41:21 -0800273 return result;
274 }
275 }
276
277 out_be32(&priv->txbd[priv->tx_idx].bufptr, (u32)packet);
278 out_be16(&priv->txbd[priv->tx_idx].length, length);
279 status = in_be16(&priv->txbd[priv->tx_idx].status);
280 out_be16(&priv->txbd[priv->tx_idx].status, status |
281 (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
282
283 /* Tell the DMA to go */
284 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
285
286 /* Wait for buffer to be transmitted */
287 for (i = 0;
288 in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY;
289 i++) {
290 if (i >= TOUT_LOOP) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300291 printf("%s: tsec: tx error\n", dev->name);
Bin Meng8ba50172016-01-11 22:41:21 -0800292 return result;
293 }
294 }
295
296 priv->tx_idx = (priv->tx_idx + 1) % TX_BUF_CNT;
297 result = in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_STATS;
298
299 return result;
300}
301
Bin Meng9a1d6af2016-01-11 22:41:24 -0800302#ifndef CONFIG_DM_ETH
Bin Meng8ba50172016-01-11 22:41:21 -0800303static int tsec_recv(struct eth_device *dev)
304{
305 struct tsec_private *priv = (struct tsec_private *)dev->priv;
306 struct tsec __iomem *regs = priv->regs;
307
308 while (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) {
309 int length = in_be16(&priv->rxbd[priv->rx_idx].length);
Mario Sixd38de332018-01-15 11:08:21 +0100310 u16 status = in_be16(&priv->rxbd[priv->rx_idx].status);
Bin Meng8ba50172016-01-11 22:41:21 -0800311 uchar *packet = net_rx_packets[priv->rx_idx];
312
313 /* Send the packet up if there were no errors */
314 if (!(status & RXBD_STATS))
315 net_process_received_packet(packet, length - 4);
316 else
317 printf("Got error %x\n", (status & RXBD_STATS));
318
319 out_be16(&priv->rxbd[priv->rx_idx].length, 0);
320
321 status = RXBD_EMPTY;
322 /* Set the wrap bit if this is the last element in the list */
323 if ((priv->rx_idx + 1) == PKTBUFSRX)
324 status |= RXBD_WRAP;
325 out_be16(&priv->rxbd[priv->rx_idx].status, status);
326
327 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
328 }
329
330 if (in_be32(&regs->ievent) & IEVENT_BSY) {
331 out_be32(&regs->ievent, IEVENT_BSY);
332 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
333 }
334
335 return -1;
336}
Bin Meng9a1d6af2016-01-11 22:41:24 -0800337#else
338static int tsec_recv(struct udevice *dev, int flags, uchar **packetp)
339{
340 struct tsec_private *priv = (struct tsec_private *)dev->priv;
341 struct tsec __iomem *regs = priv->regs;
342 int ret = -1;
343
344 if (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) {
345 int length = in_be16(&priv->rxbd[priv->rx_idx].length);
Mario Sixd38de332018-01-15 11:08:21 +0100346 u16 status = in_be16(&priv->rxbd[priv->rx_idx].status);
347 u32 buf;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800348
349 /* Send the packet up if there were no errors */
350 if (!(status & RXBD_STATS)) {
351 buf = in_be32(&priv->rxbd[priv->rx_idx].bufptr);
352 *packetp = (uchar *)buf;
353 ret = length - 4;
354 } else {
355 printf("Got error %x\n", (status & RXBD_STATS));
356 }
357 }
358
359 if (in_be32(&regs->ievent) & IEVENT_BSY) {
360 out_be32(&regs->ievent, IEVENT_BSY);
361 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
362 }
363
364 return ret;
365}
366
367static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length)
368{
369 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Mario Sixd38de332018-01-15 11:08:21 +0100370 u16 status;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800371
372 out_be16(&priv->rxbd[priv->rx_idx].length, 0);
373
374 status = RXBD_EMPTY;
375 /* Set the wrap bit if this is the last element in the list */
376 if ((priv->rx_idx + 1) == PKTBUFSRX)
377 status |= RXBD_WRAP;
378 out_be16(&priv->rxbd[priv->rx_idx].status, status);
379
380 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
381
382 return 0;
383}
384#endif
Bin Meng8ba50172016-01-11 22:41:21 -0800385
386/* Stop the interface */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800387#ifndef CONFIG_DM_ETH
Bin Meng8ba50172016-01-11 22:41:21 -0800388static void tsec_halt(struct eth_device *dev)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800389#else
390static void tsec_halt(struct udevice *dev)
391#endif
Bin Meng8ba50172016-01-11 22:41:21 -0800392{
393 struct tsec_private *priv = (struct tsec_private *)dev->priv;
394 struct tsec __iomem *regs = priv->regs;
395
396 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
397 setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
398
399 while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
400 != (IEVENT_GRSC | IEVENT_GTSC))
401 ;
402
403 clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
404
405 /* Shut down the PHY, as needed */
406 phy_shutdown(priv->phydev);
407}
408
chenhui zhaoaada81d2011-10-03 08:38:50 -0500409#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
410/*
411 * When MACCFG1[Rx_EN] is enabled during system boot as part
412 * of the eTSEC port initialization sequence,
413 * the eTSEC Rx logic may not be properly initialized.
414 */
Bin Meng56a27a12016-01-11 22:41:22 -0800415void redundant_init(struct tsec_private *priv)
chenhui zhaoaada81d2011-10-03 08:38:50 -0500416{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300417 struct tsec __iomem *regs = priv->regs;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500418 uint t, count = 0;
419 int fail = 1;
420 static const u8 pkt[] = {
421 0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25,
422 0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00,
423 0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01,
424 0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1,
425 0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00,
426 0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
427 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
428 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
429 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
430 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
431 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
432 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
433 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
434 0x71, 0x72};
435
436 /* Enable promiscuous mode */
437 setbits_be32(&regs->rctrl, 0x8);
438 /* Enable loopback mode */
439 setbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
440 /* Enable transmit and receive */
441 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
442
443 /* Tell the DMA it is clear to go */
444 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
445 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
446 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
447 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
448
449 do {
Mario Sixd38de332018-01-15 11:08:21 +0100450 u16 status;
451
Bin Meng56a27a12016-01-11 22:41:22 -0800452 tsec_send(priv->dev, (void *)pkt, sizeof(pkt));
chenhui zhaoaada81d2011-10-03 08:38:50 -0500453
454 /* Wait for buffer to be received */
Bin Menge677da92016-01-11 22:41:20 -0800455 for (t = 0;
456 in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY;
Bin Meng362b1232016-01-11 22:41:19 -0800457 t++) {
chenhui zhaoaada81d2011-10-03 08:38:50 -0500458 if (t >= 10 * TOUT_LOOP) {
Bin Meng56a27a12016-01-11 22:41:22 -0800459 printf("%s: tsec: rx error\n", priv->dev->name);
chenhui zhaoaada81d2011-10-03 08:38:50 -0500460 break;
461 }
462 }
463
Bin Meng362b1232016-01-11 22:41:19 -0800464 if (!memcmp(pkt, net_rx_packets[priv->rx_idx], sizeof(pkt)))
chenhui zhaoaada81d2011-10-03 08:38:50 -0500465 fail = 0;
466
Bin Menge677da92016-01-11 22:41:20 -0800467 out_be16(&priv->rxbd[priv->rx_idx].length, 0);
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300468 status = RXBD_EMPTY;
Bin Meng362b1232016-01-11 22:41:19 -0800469 if ((priv->rx_idx + 1) == PKTBUFSRX)
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300470 status |= RXBD_WRAP;
Bin Menge677da92016-01-11 22:41:20 -0800471 out_be16(&priv->rxbd[priv->rx_idx].status, status);
Bin Meng362b1232016-01-11 22:41:19 -0800472 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500473
474 if (in_be32(&regs->ievent) & IEVENT_BSY) {
475 out_be32(&regs->ievent, IEVENT_BSY);
476 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
477 }
478 if (fail) {
479 printf("loopback recv packet error!\n");
480 clrbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
481 udelay(1000);
482 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
483 }
484 } while ((count++ < 4) && (fail == 1));
485
486 if (fail)
487 panic("eTSEC init fail!\n");
488 /* Disable promiscuous mode */
489 clrbits_be32(&regs->rctrl, 0x8);
490 /* Disable loopback mode */
491 clrbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
492}
493#endif
494
Bin Meng9872b732016-01-11 22:41:18 -0800495/*
496 * Set up the buffers and their descriptors, and bring up the
Mingkai Hu90751912011-01-27 12:52:46 +0800497 * interface
498 */
Bin Meng56a27a12016-01-11 22:41:22 -0800499static void startup_tsec(struct tsec_private *priv)
Mingkai Hu90751912011-01-27 12:52:46 +0800500{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300501 struct tsec __iomem *regs = priv->regs;
Mario Sixd38de332018-01-15 11:08:21 +0100502 u16 status;
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300503 int i;
Mingkai Hu90751912011-01-27 12:52:46 +0800504
Andy Fleming063c1262011-04-08 02:10:54 -0500505 /* reset the indices to zero */
Bin Meng362b1232016-01-11 22:41:19 -0800506 priv->rx_idx = 0;
507 priv->tx_idx = 0;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500508#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
509 uint svr;
510#endif
Andy Fleming063c1262011-04-08 02:10:54 -0500511
Mingkai Hu90751912011-01-27 12:52:46 +0800512 /* Point to the buffer descriptors */
Bin Menge677da92016-01-11 22:41:20 -0800513 out_be32(&regs->tbase, (u32)&priv->txbd[0]);
514 out_be32(&regs->rbase, (u32)&priv->rxbd[0]);
Mingkai Hu90751912011-01-27 12:52:46 +0800515
516 /* Initialize the Rx Buffer descriptors */
517 for (i = 0; i < PKTBUFSRX; i++) {
Bin Menge677da92016-01-11 22:41:20 -0800518 out_be16(&priv->rxbd[i].status, RXBD_EMPTY);
519 out_be16(&priv->rxbd[i].length, 0);
520 out_be32(&priv->rxbd[i].bufptr, (u32)net_rx_packets[i]);
Mingkai Hu90751912011-01-27 12:52:46 +0800521 }
Bin Menge677da92016-01-11 22:41:20 -0800522 status = in_be16(&priv->rxbd[PKTBUFSRX - 1].status);
523 out_be16(&priv->rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
Mingkai Hu90751912011-01-27 12:52:46 +0800524
525 /* Initialize the TX Buffer Descriptors */
526 for (i = 0; i < TX_BUF_CNT; i++) {
Bin Menge677da92016-01-11 22:41:20 -0800527 out_be16(&priv->txbd[i].status, 0);
528 out_be16(&priv->txbd[i].length, 0);
529 out_be32(&priv->txbd[i].bufptr, 0);
Mingkai Hu90751912011-01-27 12:52:46 +0800530 }
Bin Menge677da92016-01-11 22:41:20 -0800531 status = in_be16(&priv->txbd[TX_BUF_CNT - 1].status);
532 out_be16(&priv->txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
Mingkai Hu90751912011-01-27 12:52:46 +0800533
chenhui zhaoaada81d2011-10-03 08:38:50 -0500534#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
535 svr = get_svr();
536 if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
Bin Meng56a27a12016-01-11 22:41:22 -0800537 redundant_init(priv);
chenhui zhaoaada81d2011-10-03 08:38:50 -0500538#endif
Mingkai Hu90751912011-01-27 12:52:46 +0800539 /* Enable Transmit and Receive */
540 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
541
542 /* Tell the DMA it is clear to go */
543 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
544 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
545 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
546 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
547}
548
Bin Meng9872b732016-01-11 22:41:18 -0800549/*
Bin Meng9872b732016-01-11 22:41:18 -0800550 * Initializes data structures and registers for the controller,
551 * and brings the interface up. Returns the link status, meaning
Mingkai Hu90751912011-01-27 12:52:46 +0800552 * that it returns success if the link is up, failure otherwise.
Bin Meng9872b732016-01-11 22:41:18 -0800553 * This allows U-Boot to find the first active controller.
Mingkai Hu90751912011-01-27 12:52:46 +0800554 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800555#ifndef CONFIG_DM_ETH
Mario Sixd38de332018-01-15 11:08:21 +0100556static int tsec_init(struct eth_device *dev, bd_t *bd)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800557#else
558static int tsec_init(struct udevice *dev)
559#endif
Mingkai Hu90751912011-01-27 12:52:46 +0800560{
Mingkai Hu90751912011-01-27 12:52:46 +0800561 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800562#ifdef CONFIG_DM_ETH
563 struct eth_pdata *pdata = dev_get_platdata(dev);
Vladimir Olteanf6297c02019-07-19 00:29:57 +0300564#else
565 struct eth_device *pdata = dev;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800566#endif
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300567 struct tsec __iomem *regs = priv->regs;
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300568 u32 tempval;
Timur Tabi11af8d62012-07-09 08:52:43 +0000569 int ret;
Mingkai Hu90751912011-01-27 12:52:46 +0800570
571 /* Make sure the controller is stopped */
572 tsec_halt(dev);
573
574 /* Init MACCFG2. Defaults to GMII */
575 out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
576
577 /* Init ECNTRL */
578 out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
579
Bin Meng9872b732016-01-11 22:41:18 -0800580 /*
581 * Copy the station address into the address registers.
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300582 * For a station address of 0x12345678ABCD in transmission
583 * order (BE), MACnADDR1 is set to 0xCDAB7856 and
584 * MACnADDR2 is set to 0x34120000.
585 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800586 tempval = (pdata->enetaddr[5] << 24) | (pdata->enetaddr[4] << 16) |
587 (pdata->enetaddr[3] << 8) | pdata->enetaddr[2];
Mingkai Hu90751912011-01-27 12:52:46 +0800588
589 out_be32(&regs->macstnaddr1, tempval);
590
Bin Meng9a1d6af2016-01-11 22:41:24 -0800591 tempval = (pdata->enetaddr[1] << 24) | (pdata->enetaddr[0] << 16);
Mingkai Hu90751912011-01-27 12:52:46 +0800592
593 out_be32(&regs->macstnaddr2, tempval);
594
Mingkai Hu90751912011-01-27 12:52:46 +0800595 /* Clear out (for the most part) the other registers */
596 init_registers(regs);
597
598 /* Ready the device for tx/rx */
Bin Meng56a27a12016-01-11 22:41:22 -0800599 startup_tsec(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800600
Andy Fleming063c1262011-04-08 02:10:54 -0500601 /* Start up the PHY */
Timur Tabi11af8d62012-07-09 08:52:43 +0000602 ret = phy_startup(priv->phydev);
603 if (ret) {
604 printf("Could not initialize PHY %s\n",
605 priv->phydev->dev->name);
606 return ret;
607 }
Andy Fleming063c1262011-04-08 02:10:54 -0500608
609 adjust_link(priv, priv->phydev);
610
Mingkai Hu90751912011-01-27 12:52:46 +0800611 /* If there's no link, fail */
Andy Fleming063c1262011-04-08 02:10:54 -0500612 return priv->phydev->link ? 0 : -1;
Mingkai Hu90751912011-01-27 12:52:46 +0800613}
614
Andy Fleming063c1262011-04-08 02:10:54 -0500615static phy_interface_t tsec_get_interface(struct tsec_private *priv)
616{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300617 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500618 u32 ecntrl;
619
620 ecntrl = in_be32(&regs->ecntrl);
621
622 if (ecntrl & ECNTRL_SGMII_MODE)
623 return PHY_INTERFACE_MODE_SGMII;
624
625 if (ecntrl & ECNTRL_TBI_MODE) {
626 if (ecntrl & ECNTRL_REDUCED_MODE)
627 return PHY_INTERFACE_MODE_RTBI;
628 else
629 return PHY_INTERFACE_MODE_TBI;
630 }
631
632 if (ecntrl & ECNTRL_REDUCED_MODE) {
Mario Sixd38de332018-01-15 11:08:21 +0100633 phy_interface_t interface;
634
Andy Fleming063c1262011-04-08 02:10:54 -0500635 if (ecntrl & ECNTRL_REDUCED_MII_MODE)
636 return PHY_INTERFACE_MODE_RMII;
Andy Fleming063c1262011-04-08 02:10:54 -0500637
Mario Sixd38de332018-01-15 11:08:21 +0100638 interface = priv->interface;
Andy Fleming063c1262011-04-08 02:10:54 -0500639
Mario Sixd38de332018-01-15 11:08:21 +0100640 /*
641 * This isn't autodetected, so it must
642 * be set by the platform code.
643 */
644 if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
645 interface == PHY_INTERFACE_MODE_RGMII_TXID ||
646 interface == PHY_INTERFACE_MODE_RGMII_RXID)
647 return interface;
648
649 return PHY_INTERFACE_MODE_RGMII;
Andy Fleming063c1262011-04-08 02:10:54 -0500650 }
651
652 if (priv->flags & TSEC_GIGABIT)
653 return PHY_INTERFACE_MODE_GMII;
654
655 return PHY_INTERFACE_MODE_MII;
656}
657
Bin Meng9872b732016-01-11 22:41:18 -0800658/*
659 * Discover which PHY is attached to the device, and configure it
Mingkai Hu90751912011-01-27 12:52:46 +0800660 * properly. If the PHY is not recognized, then return 0
661 * (failure). Otherwise, return 1
662 */
Bin Meng56a27a12016-01-11 22:41:22 -0800663static int init_phy(struct tsec_private *priv)
Mingkai Hu90751912011-01-27 12:52:46 +0800664{
Andy Fleming063c1262011-04-08 02:10:54 -0500665 struct phy_device *phydev;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300666 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500667 u32 supported = (SUPPORTED_10baseT_Half |
668 SUPPORTED_10baseT_Full |
669 SUPPORTED_100baseT_Half |
670 SUPPORTED_100baseT_Full);
671
672 if (priv->flags & TSEC_GIGABIT)
673 supported |= SUPPORTED_1000baseT_Full;
Mingkai Hu90751912011-01-27 12:52:46 +0800674
675 /* Assign a Physical address to the TBI */
Bin Menga1c76c12016-01-11 22:41:25 -0800676 out_be32(&regs->tbipa, priv->tbiaddr);
Mingkai Hu90751912011-01-27 12:52:46 +0800677
Andy Fleming063c1262011-04-08 02:10:54 -0500678 priv->interface = tsec_get_interface(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800679
Andy Fleming063c1262011-04-08 02:10:54 -0500680 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
Mingkai Hu90751912011-01-27 12:52:46 +0800681 tsec_configure_serdes(priv);
682
Bin Meng56a27a12016-01-11 22:41:22 -0800683 phydev = phy_connect(priv->bus, priv->phyaddr, priv->dev,
684 priv->interface);
Claudiu Manoil7f233c02013-12-10 15:21:04 +0200685 if (!phydev)
686 return 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800687
Andy Fleming063c1262011-04-08 02:10:54 -0500688 phydev->supported &= supported;
689 phydev->advertising = phydev->supported;
690
691 priv->phydev = phydev;
692
693 phy_config(phydev);
Mingkai Hu90751912011-01-27 12:52:46 +0800694
695 return 1;
696}
697
Bin Meng9a1d6af2016-01-11 22:41:24 -0800698#ifndef CONFIG_DM_ETH
Bin Meng9872b732016-01-11 22:41:18 -0800699/*
700 * Initialize device structure. Returns success if PHY
Mingkai Hu90751912011-01-27 12:52:46 +0800701 * initialization succeeded (i.e. if it recognizes the PHY)
702 */
703static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
704{
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300705 struct tsec_private *priv;
Mingkai Hu90751912011-01-27 12:52:46 +0800706 struct eth_device *dev;
707 int i;
Mingkai Hu90751912011-01-27 12:52:46 +0800708
Mario Sixd38de332018-01-15 11:08:21 +0100709 dev = (struct eth_device *)malloc(sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800710
Mario Sixd38de332018-01-15 11:08:21 +0100711 if (!dev)
Mingkai Hu90751912011-01-27 12:52:46 +0800712 return 0;
713
Mario Sixd38de332018-01-15 11:08:21 +0100714 memset(dev, 0, sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800715
716 priv = (struct tsec_private *)malloc(sizeof(*priv));
717
Mario Six5775f002018-01-15 11:08:22 +0100718 if (!priv) {
719 free(dev);
Mingkai Hu90751912011-01-27 12:52:46 +0800720 return 0;
Mario Six5775f002018-01-15 11:08:22 +0100721 }
Mingkai Hu90751912011-01-27 12:52:46 +0800722
Mingkai Hu90751912011-01-27 12:52:46 +0800723 priv->regs = tsec_info->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800724 priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
725
726 priv->phyaddr = tsec_info->phyaddr;
Bin Menga1c76c12016-01-11 22:41:25 -0800727 priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Mingkai Hu90751912011-01-27 12:52:46 +0800728 priv->flags = tsec_info->flags;
729
Ben Whitten192bc692015-12-30 13:05:58 +0000730 strcpy(dev->name, tsec_info->devname);
Andy Fleming063c1262011-04-08 02:10:54 -0500731 priv->interface = tsec_info->interface;
732 priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
Bin Meng56a27a12016-01-11 22:41:22 -0800733 priv->dev = dev;
Mingkai Hu90751912011-01-27 12:52:46 +0800734 dev->iobase = 0;
735 dev->priv = priv;
736 dev->init = tsec_init;
737 dev->halt = tsec_halt;
738 dev->send = tsec_send;
739 dev->recv = tsec_recv;
Mingkai Hu90751912011-01-27 12:52:46 +0800740 dev->mcast = tsec_mcast_addr;
Mingkai Hu90751912011-01-27 12:52:46 +0800741
Bin Meng9872b732016-01-11 22:41:18 -0800742 /* Tell U-Boot to get the addr from the env */
Mingkai Hu90751912011-01-27 12:52:46 +0800743 for (i = 0; i < 6; i++)
744 dev->enetaddr[i] = 0;
745
746 eth_register(dev);
747
748 /* Reset the MAC */
749 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
750 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
751 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
752
Mingkai Hu90751912011-01-27 12:52:46 +0800753 /* Try to initialize PHY here, and return */
Bin Meng56a27a12016-01-11 22:41:22 -0800754 return init_phy(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800755}
756
757/*
758 * Initialize all the TSEC devices
759 *
760 * Returns the number of TSEC devices that were initialized
761 */
762int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
763{
764 int i;
Mario Sixd38de332018-01-15 11:08:21 +0100765 int count = 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800766
767 for (i = 0; i < num; i++) {
Mario Sixd38de332018-01-15 11:08:21 +0100768 int ret = tsec_initialize(bis, &tsecs[i]);
769
Mingkai Hu90751912011-01-27 12:52:46 +0800770 if (ret > 0)
771 count += ret;
772 }
773
774 return count;
775}
776
777int tsec_standard_init(bd_t *bis)
778{
Andy Fleming063c1262011-04-08 02:10:54 -0500779 struct fsl_pq_mdio_info info;
780
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300781 info.regs = TSEC_GET_MDIO_REGS_BASE(1);
Andy Fleming063c1262011-04-08 02:10:54 -0500782 info.name = DEFAULT_MII_NAME;
783
784 fsl_pq_mdio_init(bis, &info);
785
Mingkai Hu90751912011-01-27 12:52:46 +0800786 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
787}
Bin Meng9a1d6af2016-01-11 22:41:24 -0800788#else /* CONFIG_DM_ETH */
789int tsec_probe(struct udevice *dev)
790{
Bin Meng9a1d6af2016-01-11 22:41:24 -0800791 struct eth_pdata *pdata = dev_get_platdata(dev);
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300792 struct tsec_private *priv = dev_get_priv(dev);
Mario Six1313aaf2018-01-15 11:08:23 +0100793 struct ofnode_phandle_args phandle_args;
Vladimir Oltean29db3102019-07-19 00:29:53 +0300794 u32 tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300795 struct fsl_pq_mdio_info mdio_info;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800796 const char *phy_mode;
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300797 fdt_addr_t reg;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300798 ofnode parent;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800799 int ret;
800
Mario Six1313aaf2018-01-15 11:08:23 +0100801 pdata->iobase = (phys_addr_t)dev_read_addr(dev);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800802 priv->regs = (struct tsec *)pdata->iobase;
803
Mario Six1313aaf2018-01-15 11:08:23 +0100804 if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
805 &phandle_args)) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300806 printf("phy-handle does not exist under tsec %s\n", dev->name);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800807 return -ENOENT;
Mario Six1313aaf2018-01-15 11:08:23 +0100808 } else {
809 int reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
810
811 priv->phyaddr = reg;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800812 }
813
Mario Six1313aaf2018-01-15 11:08:23 +0100814 parent = ofnode_get_parent(phandle_args.node);
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300815 if (!ofnode_valid(parent)) {
816 printf("No parent node for PHY?\n");
Bin Meng9a1d6af2016-01-11 22:41:24 -0800817 return -ENOENT;
818 }
819
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300820 reg = ofnode_get_addr_index(parent, 0);
821 priv->phyregs_sgmii = (struct tsec_mii_mng *)
822 (reg + TSEC_MDIO_REGS_OFFSET);
823
Vladimir Oltean29db3102019-07-19 00:29:53 +0300824 ret = dev_read_phandle_with_args(dev, "tbi-handle", NULL, 0, 0,
825 &phandle_args);
826 if (ret == 0)
827 ofnode_read_u32(phandle_args.node, "reg", &tbiaddr);
828
829 priv->tbiaddr = tbiaddr;
Bin Menga1c76c12016-01-11 22:41:25 -0800830
Mario Six1313aaf2018-01-15 11:08:23 +0100831 phy_mode = dev_read_prop(dev, "phy-connection-type", NULL);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800832 if (phy_mode)
833 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
834 if (pdata->phy_interface == -1) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300835 printf("Invalid PHY interface '%s'\n", phy_mode);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800836 return -EINVAL;
837 }
838 priv->interface = pdata->phy_interface;
839
840 /* Initialize flags */
841 priv->flags = TSEC_GIGABIT;
842 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
843 priv->flags |= TSEC_SGMII;
844
845 mdio_info.regs = priv->phyregs_sgmii;
846 mdio_info.name = (char *)dev->name;
847 ret = fsl_pq_mdio_init(NULL, &mdio_info);
848 if (ret)
849 return ret;
850
851 /* Reset the MAC */
852 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
853 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
854 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
855
856 priv->dev = dev;
857 priv->bus = miiphy_get_dev_by_name(dev->name);
858
859 /* Try to initialize PHY here, and return */
860 return !init_phy(priv);
861}
862
863int tsec_remove(struct udevice *dev)
864{
865 struct tsec_private *priv = dev->priv;
866
867 free(priv->phydev);
868 mdio_unregister(priv->bus);
869 mdio_free(priv->bus);
870
871 return 0;
872}
873
874static const struct eth_ops tsec_ops = {
875 .start = tsec_init,
876 .send = tsec_send,
877 .recv = tsec_recv,
878 .free_pkt = tsec_free_pkt,
879 .stop = tsec_halt,
Bin Meng9a1d6af2016-01-11 22:41:24 -0800880 .mcast = tsec_mcast_addr,
Bin Meng9a1d6af2016-01-11 22:41:24 -0800881};
882
883static const struct udevice_id tsec_ids[] = {
Vladimir Oltean1c8ad082019-07-19 00:29:58 +0300884 { .compatible = "fsl,etsec2" },
Bin Meng9a1d6af2016-01-11 22:41:24 -0800885 { }
886};
887
888U_BOOT_DRIVER(eth_tsec) = {
889 .name = "tsec",
890 .id = UCLASS_ETH,
891 .of_match = tsec_ids,
892 .probe = tsec_probe,
893 .remove = tsec_remove,
894 .ops = &tsec_ops,
895 .priv_auto_alloc_size = sizeof(struct tsec_private),
896 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
897 .flags = DM_FLAG_ALLOC_PRIV_DMA,
898};
899#endif /* CONFIG_DM_ETH */