blob: 611cb040dc534d84f3cf29b28c41387ff0a8bc4c [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 Glasscd93d622020-05-10 11:40:13 -060018#include <linux/bitops.h>
Simon Glassc05ed002020-05-10 11:40:11 -060019#include <linux/delay.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090020#include <linux/errno.h>
chenhui zhaoaada81d2011-10-03 08:38:50 -050021#include <asm/processor.h>
Alison Wang52d00a82014-09-05 13:52:38 +080022#include <asm/io.h>
wdenk42d1f032003-10-15 23:53:47 +000023
Bin Meng9a1d6af2016-01-11 22:41:24 -080024#ifndef CONFIG_DM_ETH
Andy Fleming75b9d4a2008-08-31 16:33:26 -050025/* Default initializations for TSEC controllers. */
26
27static struct tsec_info_struct tsec_info[] = {
28#ifdef CONFIG_TSEC1
29 STD_TSEC_INFO(1), /* TSEC1 */
30#endif
31#ifdef CONFIG_TSEC2
32 STD_TSEC_INFO(2), /* TSEC2 */
33#endif
34#ifdef CONFIG_MPC85XX_FEC
35 {
Claudiu Manoilaec84bf2013-09-30 12:44:42 +030036 .regs = TSEC_GET_REGS(2, 0x2000),
Andy Fleming75b9d4a2008-08-31 16:33:26 -050037 .devname = CONFIG_MPC85XX_FEC_NAME,
38 .phyaddr = FEC_PHY_ADDR,
Andy Fleming063c1262011-04-08 02:10:54 -050039 .flags = FEC_FLAGS,
40 .mii_devname = DEFAULT_MII_NAME
Andy Fleming75b9d4a2008-08-31 16:33:26 -050041 }, /* FEC */
42#endif
43#ifdef CONFIG_TSEC3
44 STD_TSEC_INFO(3), /* TSEC3 */
45#endif
46#ifdef CONFIG_TSEC4
47 STD_TSEC_INFO(4), /* TSEC4 */
48#endif
49};
Bin Meng9a1d6af2016-01-11 22:41:24 -080050#endif /* CONFIG_DM_ETH */
Andy Fleming75b9d4a2008-08-31 16:33:26 -050051
Andy Fleming2abe3612008-08-31 16:33:27 -050052#define TBIANA_SETTINGS ( \
53 TBIANA_ASYMMETRIC_PAUSE \
54 | TBIANA_SYMMETRIC_PAUSE \
55 | TBIANA_FULL_DUPLEX \
56 )
57
Felix Radensky90b5bf22010-06-28 01:57:39 +030058/* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
59#ifndef CONFIG_TSEC_TBICR_SETTINGS
Kumar Gala72c96a62010-12-01 22:55:54 -060060#define CONFIG_TSEC_TBICR_SETTINGS ( \
Andy Fleming2abe3612008-08-31 16:33:27 -050061 TBICR_PHY_RESET \
Kumar Gala72c96a62010-12-01 22:55:54 -060062 | TBICR_ANEG_ENABLE \
Andy Fleming2abe3612008-08-31 16:33:27 -050063 | TBICR_FULL_DUPLEX \
64 | TBICR_SPEED1_SET \
65 )
Felix Radensky90b5bf22010-06-28 01:57:39 +030066#endif /* CONFIG_TSEC_TBICR_SETTINGS */
Peter Tyser46e91672009-11-03 17:52:07 -060067
Andy Fleming2abe3612008-08-31 16:33:27 -050068/* Configure the TBI for SGMII operation */
69static void tsec_configure_serdes(struct tsec_private *priv)
70{
Bin Meng9872b732016-01-11 22:41:18 -080071 /*
72 * Access TBI PHY registers at given TSEC register offset as opposed
73 * to the register offset used for external PHY accesses
74 */
Andy Fleming063c1262011-04-08 02:10:54 -050075 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixd38de332018-01-15 11:08:21 +010076 0, TBI_ANA, TBIANA_SETTINGS);
Andy Fleming063c1262011-04-08 02:10:54 -050077 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixd38de332018-01-15 11:08:21 +010078 0, TBI_TBICON, TBICON_CLK_SELECT);
Andy Fleming063c1262011-04-08 02:10:54 -050079 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixd38de332018-01-15 11:08:21 +010080 0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
Andy Fleming2abe3612008-08-31 16:33:27 -050081}
michael.firth@bt.com55fe7c52008-01-16 11:40:51 +000082
Chris Packham1a4af5c2018-11-26 21:00:28 +130083/* the 'way' for ethernet-CRC-32. Spliced in from Linux lib/crc32.c
84 * and this is the ethernet-crc method needed for TSEC -- and perhaps
85 * some other adapter -- hash tables
86 */
87#define CRCPOLY_LE 0xedb88320
88static u32 ether_crc(size_t len, unsigned char const *p)
89{
90 int i;
91 u32 crc;
92
93 crc = ~0;
94 while (len--) {
95 crc ^= *p++;
96 for (i = 0; i < 8; i++)
97 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
98 }
99 /* an reverse the bits, cuz of way they arrive -- last-first */
100 crc = (crc >> 16) | (crc << 16);
101 crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
102 crc = (crc >> 4 & 0x0f0f0f0f) | (crc << 4 & 0xf0f0f0f0);
103 crc = (crc >> 2 & 0x33333333) | (crc << 2 & 0xcccccccc);
104 crc = (crc >> 1 & 0x55555555) | (crc << 1 & 0xaaaaaaaa);
105 return crc;
106}
107
David Updegraff53a5c422007-06-11 10:41:07 -0500108/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
109
110/* Set the appropriate hash bit for the given addr */
111
Bin Meng9872b732016-01-11 22:41:18 -0800112/*
113 * The algorithm works like so:
David Updegraff53a5c422007-06-11 10:41:07 -0500114 * 1) Take the Destination Address (ie the multicast address), and
115 * do a CRC on it (little endian), and reverse the bits of the
116 * result.
117 * 2) Use the 8 most significant bits as a hash into a 256-entry
118 * table. The table is controlled through 8 32-bit registers:
Claudiu Manoil876d4512013-09-30 12:44:40 +0300119 * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is entry
120 * 255. This means that the 3 most significant bits in the
David Updegraff53a5c422007-06-11 10:41:07 -0500121 * hash index which gaddr register to use, and the 5 other bits
122 * indicate which bit (assuming an IBM numbering scheme, which
Claudiu Manoil876d4512013-09-30 12:44:40 +0300123 * for PowerPC (tm) is usually the case) in the register holds
Bin Meng9872b732016-01-11 22:41:18 -0800124 * the entry.
125 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800126#ifndef CONFIG_DM_ETH
Chris Packham67bb9842018-11-26 21:00:29 +1300127static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac,
128 int join)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800129#else
Chris Packham67bb9842018-11-26 21:00:29 +1300130static int tsec_mcast_addr(struct udevice *dev, const u8 *mcast_mac, int join)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800131#endif
David Updegraff53a5c422007-06-11 10:41:07 -0500132{
Claudiu Manoilb2002042013-09-30 12:44:41 +0300133 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoil876d4512013-09-30 12:44:40 +0300134 struct tsec __iomem *regs = priv->regs;
135 u32 result, value;
136 u8 whichbit, whichreg;
David Updegraff53a5c422007-06-11 10:41:07 -0500137
Claudiu Manoil876d4512013-09-30 12:44:40 +0300138 result = ether_crc(MAC_ADDR_LEN, mcast_mac);
139 whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */
140 whichreg = result >> 29; /* the 3 MSB = which reg to set it in */
David Updegraff53a5c422007-06-11 10:41:07 -0500141
Mario Sixd38de332018-01-15 11:08:21 +0100142 value = BIT(31 - whichbit);
David Updegraff53a5c422007-06-11 10:41:07 -0500143
Chris Packham67bb9842018-11-26 21:00:29 +1300144 if (join)
Claudiu Manoil876d4512013-09-30 12:44:40 +0300145 setbits_be32(&regs->hash.gaddr0 + whichreg, value);
146 else
147 clrbits_be32(&regs->hash.gaddr0 + whichreg, value);
148
David Updegraff53a5c422007-06-11 10:41:07 -0500149 return 0;
150}
Mingkai Hu90751912011-01-27 12:52:46 +0800151
Bin Meng9872b732016-01-11 22:41:18 -0800152/*
153 * Initialized required registers to appropriate values, zeroing
Mingkai Hu90751912011-01-27 12:52:46 +0800154 * those we don't care about (unless zero is bad, in which case,
155 * choose a more appropriate value)
156 */
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300157static void init_registers(struct tsec __iomem *regs)
Mingkai Hu90751912011-01-27 12:52:46 +0800158{
159 /* Clear IEVENT */
160 out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
161
162 out_be32(&regs->imask, IMASK_INIT_CLEAR);
163
164 out_be32(&regs->hash.iaddr0, 0);
165 out_be32(&regs->hash.iaddr1, 0);
166 out_be32(&regs->hash.iaddr2, 0);
167 out_be32(&regs->hash.iaddr3, 0);
168 out_be32(&regs->hash.iaddr4, 0);
169 out_be32(&regs->hash.iaddr5, 0);
170 out_be32(&regs->hash.iaddr6, 0);
171 out_be32(&regs->hash.iaddr7, 0);
172
173 out_be32(&regs->hash.gaddr0, 0);
174 out_be32(&regs->hash.gaddr1, 0);
175 out_be32(&regs->hash.gaddr2, 0);
176 out_be32(&regs->hash.gaddr3, 0);
177 out_be32(&regs->hash.gaddr4, 0);
178 out_be32(&regs->hash.gaddr5, 0);
179 out_be32(&regs->hash.gaddr6, 0);
180 out_be32(&regs->hash.gaddr7, 0);
181
182 out_be32(&regs->rctrl, 0x00000000);
183
184 /* Init RMON mib registers */
Claudiu Manoil82ef75c2013-09-30 12:44:46 +0300185 memset((void *)&regs->rmon, 0, sizeof(regs->rmon));
Mingkai Hu90751912011-01-27 12:52:46 +0800186
187 out_be32(&regs->rmon.cam1, 0xffffffff);
188 out_be32(&regs->rmon.cam2, 0xffffffff);
189
190 out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
191
192 out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
193
194 out_be32(&regs->attr, ATTR_INIT_SETTINGS);
195 out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
Mingkai Hu90751912011-01-27 12:52:46 +0800196}
197
Bin Meng9872b732016-01-11 22:41:18 -0800198/*
199 * Configure maccfg2 based on negotiated speed and duplex
Mingkai Hu90751912011-01-27 12:52:46 +0800200 * reported by PHY handling code
201 */
Andy Fleming063c1262011-04-08 02:10:54 -0500202static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
Mingkai Hu90751912011-01-27 12:52:46 +0800203{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300204 struct tsec __iomem *regs = priv->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800205 u32 ecntrl, maccfg2;
206
Andy Fleming063c1262011-04-08 02:10:54 -0500207 if (!phydev->link) {
208 printf("%s: No link.\n", phydev->dev->name);
Mingkai Hu90751912011-01-27 12:52:46 +0800209 return;
210 }
211
212 /* clear all bits relative with interface mode */
213 ecntrl = in_be32(&regs->ecntrl);
214 ecntrl &= ~ECNTRL_R100;
215
216 maccfg2 = in_be32(&regs->maccfg2);
217 maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
218
Andy Fleming063c1262011-04-08 02:10:54 -0500219 if (phydev->duplex)
Mingkai Hu90751912011-01-27 12:52:46 +0800220 maccfg2 |= MACCFG2_FULL_DUPLEX;
221
Andy Fleming063c1262011-04-08 02:10:54 -0500222 switch (phydev->speed) {
Mingkai Hu90751912011-01-27 12:52:46 +0800223 case 1000:
224 maccfg2 |= MACCFG2_GMII;
225 break;
226 case 100:
227 case 10:
228 maccfg2 |= MACCFG2_MII;
229
Bin Meng9872b732016-01-11 22:41:18 -0800230 /*
231 * Set R100 bit in all modes although
Mingkai Hu90751912011-01-27 12:52:46 +0800232 * it is only used in RGMII mode
233 */
Andy Fleming063c1262011-04-08 02:10:54 -0500234 if (phydev->speed == 100)
Mingkai Hu90751912011-01-27 12:52:46 +0800235 ecntrl |= ECNTRL_R100;
236 break;
237 default:
Andy Fleming063c1262011-04-08 02:10:54 -0500238 printf("%s: Speed was bad\n", phydev->dev->name);
Mingkai Hu90751912011-01-27 12:52:46 +0800239 break;
240 }
241
242 out_be32(&regs->ecntrl, ecntrl);
243 out_be32(&regs->maccfg2, maccfg2);
244
Andy Fleming063c1262011-04-08 02:10:54 -0500245 printf("Speed: %d, %s duplex%s\n", phydev->speed,
Mario Sixd38de332018-01-15 11:08:21 +0100246 (phydev->duplex) ? "full" : "half",
247 (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
Mingkai Hu90751912011-01-27 12:52:46 +0800248}
249
Bin Meng8ba50172016-01-11 22:41:21 -0800250/*
251 * This returns the status bits of the device. The return value
252 * is never checked, and this is what the 8260 driver did, so we
253 * do the same. Presumably, this would be zero if there were no
254 * errors
255 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800256#ifndef CONFIG_DM_ETH
Bin Meng8ba50172016-01-11 22:41:21 -0800257static int tsec_send(struct eth_device *dev, void *packet, int length)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800258#else
259static int tsec_send(struct udevice *dev, void *packet, int length)
260#endif
Bin Meng8ba50172016-01-11 22:41:21 -0800261{
262 struct tsec_private *priv = (struct tsec_private *)dev->priv;
263 struct tsec __iomem *regs = priv->regs;
Bin Meng8ba50172016-01-11 22:41:21 -0800264 int result = 0;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300265 u16 status;
Bin Meng8ba50172016-01-11 22:41:21 -0800266 int i;
267
268 /* Find an empty buffer descriptor */
269 for (i = 0;
270 in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY;
271 i++) {
272 if (i >= TOUT_LOOP) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300273 printf("%s: tsec: tx buffers full\n", dev->name);
Bin Meng8ba50172016-01-11 22:41:21 -0800274 return result;
275 }
276 }
277
278 out_be32(&priv->txbd[priv->tx_idx].bufptr, (u32)packet);
279 out_be16(&priv->txbd[priv->tx_idx].length, length);
280 status = in_be16(&priv->txbd[priv->tx_idx].status);
281 out_be16(&priv->txbd[priv->tx_idx].status, status |
282 (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
283
284 /* Tell the DMA to go */
285 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
286
287 /* Wait for buffer to be transmitted */
288 for (i = 0;
289 in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY;
290 i++) {
291 if (i >= TOUT_LOOP) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300292 printf("%s: tsec: tx error\n", dev->name);
Bin Meng8ba50172016-01-11 22:41:21 -0800293 return result;
294 }
295 }
296
297 priv->tx_idx = (priv->tx_idx + 1) % TX_BUF_CNT;
298 result = in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_STATS;
299
300 return result;
301}
302
Bin Meng9a1d6af2016-01-11 22:41:24 -0800303#ifndef CONFIG_DM_ETH
Bin Meng8ba50172016-01-11 22:41:21 -0800304static int tsec_recv(struct eth_device *dev)
305{
306 struct tsec_private *priv = (struct tsec_private *)dev->priv;
307 struct tsec __iomem *regs = priv->regs;
308
309 while (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) {
310 int length = in_be16(&priv->rxbd[priv->rx_idx].length);
Mario Sixd38de332018-01-15 11:08:21 +0100311 u16 status = in_be16(&priv->rxbd[priv->rx_idx].status);
Bin Meng8ba50172016-01-11 22:41:21 -0800312 uchar *packet = net_rx_packets[priv->rx_idx];
313
314 /* Send the packet up if there were no errors */
315 if (!(status & RXBD_STATS))
316 net_process_received_packet(packet, length - 4);
317 else
318 printf("Got error %x\n", (status & RXBD_STATS));
319
320 out_be16(&priv->rxbd[priv->rx_idx].length, 0);
321
322 status = RXBD_EMPTY;
323 /* Set the wrap bit if this is the last element in the list */
324 if ((priv->rx_idx + 1) == PKTBUFSRX)
325 status |= RXBD_WRAP;
326 out_be16(&priv->rxbd[priv->rx_idx].status, status);
327
328 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
329 }
330
331 if (in_be32(&regs->ievent) & IEVENT_BSY) {
332 out_be32(&regs->ievent, IEVENT_BSY);
333 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
334 }
335
336 return -1;
337}
Bin Meng9a1d6af2016-01-11 22:41:24 -0800338#else
339static int tsec_recv(struct udevice *dev, int flags, uchar **packetp)
340{
341 struct tsec_private *priv = (struct tsec_private *)dev->priv;
342 struct tsec __iomem *regs = priv->regs;
343 int ret = -1;
344
345 if (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) {
346 int length = in_be16(&priv->rxbd[priv->rx_idx].length);
Mario Sixd38de332018-01-15 11:08:21 +0100347 u16 status = in_be16(&priv->rxbd[priv->rx_idx].status);
348 u32 buf;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800349
350 /* Send the packet up if there were no errors */
351 if (!(status & RXBD_STATS)) {
352 buf = in_be32(&priv->rxbd[priv->rx_idx].bufptr);
353 *packetp = (uchar *)buf;
354 ret = length - 4;
355 } else {
356 printf("Got error %x\n", (status & RXBD_STATS));
357 }
358 }
359
360 if (in_be32(&regs->ievent) & IEVENT_BSY) {
361 out_be32(&regs->ievent, IEVENT_BSY);
362 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
363 }
364
365 return ret;
366}
367
368static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length)
369{
370 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Mario Sixd38de332018-01-15 11:08:21 +0100371 u16 status;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800372
373 out_be16(&priv->rxbd[priv->rx_idx].length, 0);
374
375 status = RXBD_EMPTY;
376 /* Set the wrap bit if this is the last element in the list */
377 if ((priv->rx_idx + 1) == PKTBUFSRX)
378 status |= RXBD_WRAP;
379 out_be16(&priv->rxbd[priv->rx_idx].status, status);
380
381 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
382
383 return 0;
384}
385#endif
Bin Meng8ba50172016-01-11 22:41:21 -0800386
387/* Stop the interface */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800388#ifndef CONFIG_DM_ETH
Bin Meng8ba50172016-01-11 22:41:21 -0800389static void tsec_halt(struct eth_device *dev)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800390#else
391static void tsec_halt(struct udevice *dev)
392#endif
Bin Meng8ba50172016-01-11 22:41:21 -0800393{
394 struct tsec_private *priv = (struct tsec_private *)dev->priv;
395 struct tsec __iomem *regs = priv->regs;
396
397 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
398 setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
399
400 while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
401 != (IEVENT_GRSC | IEVENT_GTSC))
402 ;
403
404 clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
405
406 /* Shut down the PHY, as needed */
407 phy_shutdown(priv->phydev);
408}
409
chenhui zhaoaada81d2011-10-03 08:38:50 -0500410#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
411/*
412 * When MACCFG1[Rx_EN] is enabled during system boot as part
413 * of the eTSEC port initialization sequence,
414 * the eTSEC Rx logic may not be properly initialized.
415 */
Bin Meng56a27a12016-01-11 22:41:22 -0800416void redundant_init(struct tsec_private *priv)
chenhui zhaoaada81d2011-10-03 08:38:50 -0500417{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300418 struct tsec __iomem *regs = priv->regs;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500419 uint t, count = 0;
420 int fail = 1;
421 static const u8 pkt[] = {
422 0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25,
423 0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00,
424 0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01,
425 0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1,
426 0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00,
427 0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
428 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
429 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
430 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
431 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
432 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
433 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
434 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
435 0x71, 0x72};
436
437 /* Enable promiscuous mode */
438 setbits_be32(&regs->rctrl, 0x8);
439 /* Enable loopback mode */
440 setbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
441 /* Enable transmit and receive */
442 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
443
444 /* Tell the DMA it is clear to go */
445 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
446 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
447 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
448 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
449
450 do {
Mario Sixd38de332018-01-15 11:08:21 +0100451 u16 status;
452
Bin Meng56a27a12016-01-11 22:41:22 -0800453 tsec_send(priv->dev, (void *)pkt, sizeof(pkt));
chenhui zhaoaada81d2011-10-03 08:38:50 -0500454
455 /* Wait for buffer to be received */
Bin Menge677da92016-01-11 22:41:20 -0800456 for (t = 0;
457 in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY;
Bin Meng362b1232016-01-11 22:41:19 -0800458 t++) {
chenhui zhaoaada81d2011-10-03 08:38:50 -0500459 if (t >= 10 * TOUT_LOOP) {
Bin Meng56a27a12016-01-11 22:41:22 -0800460 printf("%s: tsec: rx error\n", priv->dev->name);
chenhui zhaoaada81d2011-10-03 08:38:50 -0500461 break;
462 }
463 }
464
Bin Meng362b1232016-01-11 22:41:19 -0800465 if (!memcmp(pkt, net_rx_packets[priv->rx_idx], sizeof(pkt)))
chenhui zhaoaada81d2011-10-03 08:38:50 -0500466 fail = 0;
467
Bin Menge677da92016-01-11 22:41:20 -0800468 out_be16(&priv->rxbd[priv->rx_idx].length, 0);
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300469 status = RXBD_EMPTY;
Bin Meng362b1232016-01-11 22:41:19 -0800470 if ((priv->rx_idx + 1) == PKTBUFSRX)
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300471 status |= RXBD_WRAP;
Bin Menge677da92016-01-11 22:41:20 -0800472 out_be16(&priv->rxbd[priv->rx_idx].status, status);
Bin Meng362b1232016-01-11 22:41:19 -0800473 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500474
475 if (in_be32(&regs->ievent) & IEVENT_BSY) {
476 out_be32(&regs->ievent, IEVENT_BSY);
477 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
478 }
479 if (fail) {
480 printf("loopback recv packet error!\n");
481 clrbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
482 udelay(1000);
483 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
484 }
485 } while ((count++ < 4) && (fail == 1));
486
487 if (fail)
488 panic("eTSEC init fail!\n");
489 /* Disable promiscuous mode */
490 clrbits_be32(&regs->rctrl, 0x8);
491 /* Disable loopback mode */
492 clrbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
493}
494#endif
495
Bin Meng9872b732016-01-11 22:41:18 -0800496/*
497 * Set up the buffers and their descriptors, and bring up the
Mingkai Hu90751912011-01-27 12:52:46 +0800498 * interface
499 */
Bin Meng56a27a12016-01-11 22:41:22 -0800500static void startup_tsec(struct tsec_private *priv)
Mingkai Hu90751912011-01-27 12:52:46 +0800501{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300502 struct tsec __iomem *regs = priv->regs;
Mario Sixd38de332018-01-15 11:08:21 +0100503 u16 status;
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300504 int i;
Mingkai Hu90751912011-01-27 12:52:46 +0800505
Andy Fleming063c1262011-04-08 02:10:54 -0500506 /* reset the indices to zero */
Bin Meng362b1232016-01-11 22:41:19 -0800507 priv->rx_idx = 0;
508 priv->tx_idx = 0;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500509#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
510 uint svr;
511#endif
Andy Fleming063c1262011-04-08 02:10:54 -0500512
Mingkai Hu90751912011-01-27 12:52:46 +0800513 /* Point to the buffer descriptors */
Bin Menge677da92016-01-11 22:41:20 -0800514 out_be32(&regs->tbase, (u32)&priv->txbd[0]);
515 out_be32(&regs->rbase, (u32)&priv->rxbd[0]);
Mingkai Hu90751912011-01-27 12:52:46 +0800516
517 /* Initialize the Rx Buffer descriptors */
518 for (i = 0; i < PKTBUFSRX; i++) {
Bin Menge677da92016-01-11 22:41:20 -0800519 out_be16(&priv->rxbd[i].status, RXBD_EMPTY);
520 out_be16(&priv->rxbd[i].length, 0);
521 out_be32(&priv->rxbd[i].bufptr, (u32)net_rx_packets[i]);
Mingkai Hu90751912011-01-27 12:52:46 +0800522 }
Bin Menge677da92016-01-11 22:41:20 -0800523 status = in_be16(&priv->rxbd[PKTBUFSRX - 1].status);
524 out_be16(&priv->rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
Mingkai Hu90751912011-01-27 12:52:46 +0800525
526 /* Initialize the TX Buffer Descriptors */
527 for (i = 0; i < TX_BUF_CNT; i++) {
Bin Menge677da92016-01-11 22:41:20 -0800528 out_be16(&priv->txbd[i].status, 0);
529 out_be16(&priv->txbd[i].length, 0);
530 out_be32(&priv->txbd[i].bufptr, 0);
Mingkai Hu90751912011-01-27 12:52:46 +0800531 }
Bin Menge677da92016-01-11 22:41:20 -0800532 status = in_be16(&priv->txbd[TX_BUF_CNT - 1].status);
533 out_be16(&priv->txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
Mingkai Hu90751912011-01-27 12:52:46 +0800534
chenhui zhaoaada81d2011-10-03 08:38:50 -0500535#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
536 svr = get_svr();
537 if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
Bin Meng56a27a12016-01-11 22:41:22 -0800538 redundant_init(priv);
chenhui zhaoaada81d2011-10-03 08:38:50 -0500539#endif
Mingkai Hu90751912011-01-27 12:52:46 +0800540 /* Enable Transmit and Receive */
541 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
542
543 /* Tell the DMA it is clear to go */
544 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
545 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
546 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
547 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
548}
549
Bin Meng9872b732016-01-11 22:41:18 -0800550/*
Bin Meng9872b732016-01-11 22:41:18 -0800551 * Initializes data structures and registers for the controller,
552 * and brings the interface up. Returns the link status, meaning
Mingkai Hu90751912011-01-27 12:52:46 +0800553 * that it returns success if the link is up, failure otherwise.
Bin Meng9872b732016-01-11 22:41:18 -0800554 * This allows U-Boot to find the first active controller.
Mingkai Hu90751912011-01-27 12:52:46 +0800555 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800556#ifndef CONFIG_DM_ETH
Mario Sixd38de332018-01-15 11:08:21 +0100557static int tsec_init(struct eth_device *dev, bd_t *bd)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800558#else
559static int tsec_init(struct udevice *dev)
560#endif
Mingkai Hu90751912011-01-27 12:52:46 +0800561{
Mingkai Hu90751912011-01-27 12:52:46 +0800562 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800563#ifdef CONFIG_DM_ETH
564 struct eth_pdata *pdata = dev_get_platdata(dev);
Vladimir Olteanf6297c02019-07-19 00:29:57 +0300565#else
566 struct eth_device *pdata = dev;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800567#endif
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300568 struct tsec __iomem *regs = priv->regs;
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300569 u32 tempval;
Timur Tabi11af8d62012-07-09 08:52:43 +0000570 int ret;
Mingkai Hu90751912011-01-27 12:52:46 +0800571
572 /* Make sure the controller is stopped */
573 tsec_halt(dev);
574
575 /* Init MACCFG2. Defaults to GMII */
576 out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
577
578 /* Init ECNTRL */
579 out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
580
Bin Meng9872b732016-01-11 22:41:18 -0800581 /*
582 * Copy the station address into the address registers.
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300583 * For a station address of 0x12345678ABCD in transmission
584 * order (BE), MACnADDR1 is set to 0xCDAB7856 and
585 * MACnADDR2 is set to 0x34120000.
586 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800587 tempval = (pdata->enetaddr[5] << 24) | (pdata->enetaddr[4] << 16) |
588 (pdata->enetaddr[3] << 8) | pdata->enetaddr[2];
Mingkai Hu90751912011-01-27 12:52:46 +0800589
590 out_be32(&regs->macstnaddr1, tempval);
591
Bin Meng9a1d6af2016-01-11 22:41:24 -0800592 tempval = (pdata->enetaddr[1] << 24) | (pdata->enetaddr[0] << 16);
Mingkai Hu90751912011-01-27 12:52:46 +0800593
594 out_be32(&regs->macstnaddr2, tempval);
595
Mingkai Hu90751912011-01-27 12:52:46 +0800596 /* Clear out (for the most part) the other registers */
597 init_registers(regs);
598
599 /* Ready the device for tx/rx */
Bin Meng56a27a12016-01-11 22:41:22 -0800600 startup_tsec(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800601
Andy Fleming063c1262011-04-08 02:10:54 -0500602 /* Start up the PHY */
Timur Tabi11af8d62012-07-09 08:52:43 +0000603 ret = phy_startup(priv->phydev);
604 if (ret) {
605 printf("Could not initialize PHY %s\n",
606 priv->phydev->dev->name);
607 return ret;
608 }
Andy Fleming063c1262011-04-08 02:10:54 -0500609
610 adjust_link(priv, priv->phydev);
611
Mingkai Hu90751912011-01-27 12:52:46 +0800612 /* If there's no link, fail */
Andy Fleming063c1262011-04-08 02:10:54 -0500613 return priv->phydev->link ? 0 : -1;
Mingkai Hu90751912011-01-27 12:52:46 +0800614}
615
Andy Fleming063c1262011-04-08 02:10:54 -0500616static phy_interface_t tsec_get_interface(struct tsec_private *priv)
617{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300618 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500619 u32 ecntrl;
620
621 ecntrl = in_be32(&regs->ecntrl);
622
623 if (ecntrl & ECNTRL_SGMII_MODE)
624 return PHY_INTERFACE_MODE_SGMII;
625
626 if (ecntrl & ECNTRL_TBI_MODE) {
627 if (ecntrl & ECNTRL_REDUCED_MODE)
628 return PHY_INTERFACE_MODE_RTBI;
629 else
630 return PHY_INTERFACE_MODE_TBI;
631 }
632
633 if (ecntrl & ECNTRL_REDUCED_MODE) {
Mario Sixd38de332018-01-15 11:08:21 +0100634 phy_interface_t interface;
635
Andy Fleming063c1262011-04-08 02:10:54 -0500636 if (ecntrl & ECNTRL_REDUCED_MII_MODE)
637 return PHY_INTERFACE_MODE_RMII;
Andy Fleming063c1262011-04-08 02:10:54 -0500638
Mario Sixd38de332018-01-15 11:08:21 +0100639 interface = priv->interface;
Andy Fleming063c1262011-04-08 02:10:54 -0500640
Mario Sixd38de332018-01-15 11:08:21 +0100641 /*
642 * This isn't autodetected, so it must
643 * be set by the platform code.
644 */
645 if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
646 interface == PHY_INTERFACE_MODE_RGMII_TXID ||
647 interface == PHY_INTERFACE_MODE_RGMII_RXID)
648 return interface;
649
650 return PHY_INTERFACE_MODE_RGMII;
Andy Fleming063c1262011-04-08 02:10:54 -0500651 }
652
653 if (priv->flags & TSEC_GIGABIT)
654 return PHY_INTERFACE_MODE_GMII;
655
656 return PHY_INTERFACE_MODE_MII;
657}
658
Bin Meng9872b732016-01-11 22:41:18 -0800659/*
660 * Discover which PHY is attached to the device, and configure it
Mingkai Hu90751912011-01-27 12:52:46 +0800661 * properly. If the PHY is not recognized, then return 0
662 * (failure). Otherwise, return 1
663 */
Bin Meng56a27a12016-01-11 22:41:22 -0800664static int init_phy(struct tsec_private *priv)
Mingkai Hu90751912011-01-27 12:52:46 +0800665{
Andy Fleming063c1262011-04-08 02:10:54 -0500666 struct phy_device *phydev;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300667 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500668 u32 supported = (SUPPORTED_10baseT_Half |
669 SUPPORTED_10baseT_Full |
670 SUPPORTED_100baseT_Half |
671 SUPPORTED_100baseT_Full);
672
673 if (priv->flags & TSEC_GIGABIT)
674 supported |= SUPPORTED_1000baseT_Full;
Mingkai Hu90751912011-01-27 12:52:46 +0800675
676 /* Assign a Physical address to the TBI */
Bin Menga1c76c12016-01-11 22:41:25 -0800677 out_be32(&regs->tbipa, priv->tbiaddr);
Mingkai Hu90751912011-01-27 12:52:46 +0800678
Andy Fleming063c1262011-04-08 02:10:54 -0500679 priv->interface = tsec_get_interface(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800680
Andy Fleming063c1262011-04-08 02:10:54 -0500681 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
Mingkai Hu90751912011-01-27 12:52:46 +0800682 tsec_configure_serdes(priv);
683
Bin Meng56a27a12016-01-11 22:41:22 -0800684 phydev = phy_connect(priv->bus, priv->phyaddr, priv->dev,
685 priv->interface);
Claudiu Manoil7f233c02013-12-10 15:21:04 +0200686 if (!phydev)
687 return 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800688
Andy Fleming063c1262011-04-08 02:10:54 -0500689 phydev->supported &= supported;
690 phydev->advertising = phydev->supported;
691
692 priv->phydev = phydev;
693
694 phy_config(phydev);
Mingkai Hu90751912011-01-27 12:52:46 +0800695
696 return 1;
697}
698
Bin Meng9a1d6af2016-01-11 22:41:24 -0800699#ifndef CONFIG_DM_ETH
Bin Meng9872b732016-01-11 22:41:18 -0800700/*
701 * Initialize device structure. Returns success if PHY
Mingkai Hu90751912011-01-27 12:52:46 +0800702 * initialization succeeded (i.e. if it recognizes the PHY)
703 */
704static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
705{
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300706 struct tsec_private *priv;
Mingkai Hu90751912011-01-27 12:52:46 +0800707 struct eth_device *dev;
708 int i;
Mingkai Hu90751912011-01-27 12:52:46 +0800709
Mario Sixd38de332018-01-15 11:08:21 +0100710 dev = (struct eth_device *)malloc(sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800711
Mario Sixd38de332018-01-15 11:08:21 +0100712 if (!dev)
Mingkai Hu90751912011-01-27 12:52:46 +0800713 return 0;
714
Mario Sixd38de332018-01-15 11:08:21 +0100715 memset(dev, 0, sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800716
717 priv = (struct tsec_private *)malloc(sizeof(*priv));
718
Mario Six5775f002018-01-15 11:08:22 +0100719 if (!priv) {
720 free(dev);
Mingkai Hu90751912011-01-27 12:52:46 +0800721 return 0;
Mario Six5775f002018-01-15 11:08:22 +0100722 }
Mingkai Hu90751912011-01-27 12:52:46 +0800723
Mingkai Hu90751912011-01-27 12:52:46 +0800724 priv->regs = tsec_info->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800725 priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
726
727 priv->phyaddr = tsec_info->phyaddr;
Bin Menga1c76c12016-01-11 22:41:25 -0800728 priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Mingkai Hu90751912011-01-27 12:52:46 +0800729 priv->flags = tsec_info->flags;
730
Ben Whitten192bc692015-12-30 13:05:58 +0000731 strcpy(dev->name, tsec_info->devname);
Andy Fleming063c1262011-04-08 02:10:54 -0500732 priv->interface = tsec_info->interface;
733 priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
Bin Meng56a27a12016-01-11 22:41:22 -0800734 priv->dev = dev;
Mingkai Hu90751912011-01-27 12:52:46 +0800735 dev->iobase = 0;
736 dev->priv = priv;
737 dev->init = tsec_init;
738 dev->halt = tsec_halt;
739 dev->send = tsec_send;
740 dev->recv = tsec_recv;
Mingkai Hu90751912011-01-27 12:52:46 +0800741 dev->mcast = tsec_mcast_addr;
Mingkai Hu90751912011-01-27 12:52:46 +0800742
Bin Meng9872b732016-01-11 22:41:18 -0800743 /* Tell U-Boot to get the addr from the env */
Mingkai Hu90751912011-01-27 12:52:46 +0800744 for (i = 0; i < 6; i++)
745 dev->enetaddr[i] = 0;
746
747 eth_register(dev);
748
749 /* Reset the MAC */
750 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
751 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
752 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
753
Mingkai Hu90751912011-01-27 12:52:46 +0800754 /* Try to initialize PHY here, and return */
Bin Meng56a27a12016-01-11 22:41:22 -0800755 return init_phy(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800756}
757
758/*
759 * Initialize all the TSEC devices
760 *
761 * Returns the number of TSEC devices that were initialized
762 */
763int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
764{
765 int i;
Mario Sixd38de332018-01-15 11:08:21 +0100766 int count = 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800767
768 for (i = 0; i < num; i++) {
Mario Sixd38de332018-01-15 11:08:21 +0100769 int ret = tsec_initialize(bis, &tsecs[i]);
770
Mingkai Hu90751912011-01-27 12:52:46 +0800771 if (ret > 0)
772 count += ret;
773 }
774
775 return count;
776}
777
778int tsec_standard_init(bd_t *bis)
779{
Andy Fleming063c1262011-04-08 02:10:54 -0500780 struct fsl_pq_mdio_info info;
781
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300782 info.regs = TSEC_GET_MDIO_REGS_BASE(1);
Andy Fleming063c1262011-04-08 02:10:54 -0500783 info.name = DEFAULT_MII_NAME;
784
785 fsl_pq_mdio_init(bis, &info);
786
Mingkai Hu90751912011-01-27 12:52:46 +0800787 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
788}
Bin Meng9a1d6af2016-01-11 22:41:24 -0800789#else /* CONFIG_DM_ETH */
790int tsec_probe(struct udevice *dev)
791{
Bin Meng9a1d6af2016-01-11 22:41:24 -0800792 struct eth_pdata *pdata = dev_get_platdata(dev);
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300793 struct tsec_private *priv = dev_get_priv(dev);
Mario Six1313aaf2018-01-15 11:08:23 +0100794 struct ofnode_phandle_args phandle_args;
Vladimir Oltean29db3102019-07-19 00:29:53 +0300795 u32 tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300796 struct fsl_pq_mdio_info mdio_info;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800797 const char *phy_mode;
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300798 fdt_addr_t reg;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300799 ofnode parent;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800800 int ret;
801
Mario Six1313aaf2018-01-15 11:08:23 +0100802 pdata->iobase = (phys_addr_t)dev_read_addr(dev);
Hou Zhiqiangbf67eb32020-05-03 22:48:42 +0800803 priv->regs = dev_remap_addr(dev);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800804
Mario Six1313aaf2018-01-15 11:08:23 +0100805 if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
806 &phandle_args)) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300807 printf("phy-handle does not exist under tsec %s\n", dev->name);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800808 return -ENOENT;
Mario Six1313aaf2018-01-15 11:08:23 +0100809 } else {
810 int reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
811
812 priv->phyaddr = reg;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800813 }
814
Mario Six1313aaf2018-01-15 11:08:23 +0100815 parent = ofnode_get_parent(phandle_args.node);
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300816 if (!ofnode_valid(parent)) {
817 printf("No parent node for PHY?\n");
Bin Meng9a1d6af2016-01-11 22:41:24 -0800818 return -ENOENT;
819 }
820
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300821 reg = ofnode_get_addr_index(parent, 0);
Hou Zhiqiangbf67eb32020-05-03 22:48:42 +0800822 if (reg == FDT_ADDR_T_NONE) {
823 printf("No 'reg' property of MII for external PHY\n");
824 return -ENOENT;
825 }
826
827 priv->phyregs_sgmii = map_physmem(reg + TSEC_MDIO_REGS_OFFSET, 0,
828 MAP_NOCACHE);
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300829
Vladimir Oltean29db3102019-07-19 00:29:53 +0300830 ret = dev_read_phandle_with_args(dev, "tbi-handle", NULL, 0, 0,
831 &phandle_args);
832 if (ret == 0)
833 ofnode_read_u32(phandle_args.node, "reg", &tbiaddr);
834
835 priv->tbiaddr = tbiaddr;
Bin Menga1c76c12016-01-11 22:41:25 -0800836
Mario Six1313aaf2018-01-15 11:08:23 +0100837 phy_mode = dev_read_prop(dev, "phy-connection-type", NULL);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800838 if (phy_mode)
839 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
840 if (pdata->phy_interface == -1) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300841 printf("Invalid PHY interface '%s'\n", phy_mode);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800842 return -EINVAL;
843 }
844 priv->interface = pdata->phy_interface;
845
846 /* Initialize flags */
847 priv->flags = TSEC_GIGABIT;
848 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
849 priv->flags |= TSEC_SGMII;
850
851 mdio_info.regs = priv->phyregs_sgmii;
852 mdio_info.name = (char *)dev->name;
853 ret = fsl_pq_mdio_init(NULL, &mdio_info);
854 if (ret)
855 return ret;
856
857 /* Reset the MAC */
858 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
859 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
860 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
861
862 priv->dev = dev;
863 priv->bus = miiphy_get_dev_by_name(dev->name);
864
865 /* Try to initialize PHY here, and return */
866 return !init_phy(priv);
867}
868
869int tsec_remove(struct udevice *dev)
870{
871 struct tsec_private *priv = dev->priv;
872
873 free(priv->phydev);
874 mdio_unregister(priv->bus);
875 mdio_free(priv->bus);
876
877 return 0;
878}
879
880static const struct eth_ops tsec_ops = {
881 .start = tsec_init,
882 .send = tsec_send,
883 .recv = tsec_recv,
884 .free_pkt = tsec_free_pkt,
885 .stop = tsec_halt,
Bin Meng9a1d6af2016-01-11 22:41:24 -0800886 .mcast = tsec_mcast_addr,
Bin Meng9a1d6af2016-01-11 22:41:24 -0800887};
888
889static const struct udevice_id tsec_ids[] = {
Vladimir Oltean1c8ad082019-07-19 00:29:58 +0300890 { .compatible = "fsl,etsec2" },
Bin Meng9a1d6af2016-01-11 22:41:24 -0800891 { }
892};
893
894U_BOOT_DRIVER(eth_tsec) = {
895 .name = "tsec",
896 .id = UCLASS_ETH,
897 .of_match = tsec_ids,
898 .probe = tsec_probe,
899 .remove = tsec_remove,
900 .ops = &tsec_ops,
901 .priv_auto_alloc_size = sizeof(struct tsec_private),
902 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
903 .flags = DM_FLAG_ALLOC_PRIV_DMA,
904};
905#endif /* CONFIG_DM_ETH */