blob: 9a4fab85e928361fa51ee2c4f75f97eef9695add [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>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090018#include <linux/errno.h>
chenhui zhaoaada81d2011-10-03 08:38:50 -050019#include <asm/processor.h>
Alison Wang52d00a82014-09-05 13:52:38 +080020#include <asm/io.h>
wdenk42d1f032003-10-15 23:53:47 +000021
Bin Meng9a1d6af2016-01-11 22:41:24 -080022#ifndef CONFIG_DM_ETH
Andy Fleming75b9d4a2008-08-31 16:33:26 -050023/* Default initializations for TSEC controllers. */
24
25static struct tsec_info_struct tsec_info[] = {
26#ifdef CONFIG_TSEC1
27 STD_TSEC_INFO(1), /* TSEC1 */
28#endif
29#ifdef CONFIG_TSEC2
30 STD_TSEC_INFO(2), /* TSEC2 */
31#endif
32#ifdef CONFIG_MPC85XX_FEC
33 {
Claudiu Manoilaec84bf2013-09-30 12:44:42 +030034 .regs = TSEC_GET_REGS(2, 0x2000),
Andy Fleming75b9d4a2008-08-31 16:33:26 -050035 .devname = CONFIG_MPC85XX_FEC_NAME,
36 .phyaddr = FEC_PHY_ADDR,
Andy Fleming063c1262011-04-08 02:10:54 -050037 .flags = FEC_FLAGS,
38 .mii_devname = DEFAULT_MII_NAME
Andy Fleming75b9d4a2008-08-31 16:33:26 -050039 }, /* FEC */
40#endif
41#ifdef CONFIG_TSEC3
42 STD_TSEC_INFO(3), /* TSEC3 */
43#endif
44#ifdef CONFIG_TSEC4
45 STD_TSEC_INFO(4), /* TSEC4 */
46#endif
47};
Bin Meng9a1d6af2016-01-11 22:41:24 -080048#endif /* CONFIG_DM_ETH */
Andy Fleming75b9d4a2008-08-31 16:33:26 -050049
Andy Fleming2abe3612008-08-31 16:33:27 -050050#define TBIANA_SETTINGS ( \
51 TBIANA_ASYMMETRIC_PAUSE \
52 | TBIANA_SYMMETRIC_PAUSE \
53 | TBIANA_FULL_DUPLEX \
54 )
55
Felix Radensky90b5bf22010-06-28 01:57:39 +030056/* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
57#ifndef CONFIG_TSEC_TBICR_SETTINGS
Kumar Gala72c96a62010-12-01 22:55:54 -060058#define CONFIG_TSEC_TBICR_SETTINGS ( \
Andy Fleming2abe3612008-08-31 16:33:27 -050059 TBICR_PHY_RESET \
Kumar Gala72c96a62010-12-01 22:55:54 -060060 | TBICR_ANEG_ENABLE \
Andy Fleming2abe3612008-08-31 16:33:27 -050061 | TBICR_FULL_DUPLEX \
62 | TBICR_SPEED1_SET \
63 )
Felix Radensky90b5bf22010-06-28 01:57:39 +030064#endif /* CONFIG_TSEC_TBICR_SETTINGS */
Peter Tyser46e91672009-11-03 17:52:07 -060065
Andy Fleming2abe3612008-08-31 16:33:27 -050066/* Configure the TBI for SGMII operation */
67static void tsec_configure_serdes(struct tsec_private *priv)
68{
Bin Meng9872b732016-01-11 22:41:18 -080069 /*
70 * Access TBI PHY registers at given TSEC register offset as opposed
71 * to the register offset used for external PHY accesses
72 */
Andy Fleming063c1262011-04-08 02:10:54 -050073 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixd38de332018-01-15 11:08:21 +010074 0, TBI_ANA, TBIANA_SETTINGS);
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_TBICON, TBICON_CLK_SELECT);
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_CR, CONFIG_TSEC_TBICR_SETTINGS);
Andy Fleming2abe3612008-08-31 16:33:27 -050079}
michael.firth@bt.com55fe7c52008-01-16 11:40:51 +000080
David Updegraff53a5c422007-06-11 10:41:07 -050081#ifdef CONFIG_MCAST_TFTP
82
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
Bin Meng9872b732016-01-11 22:41:18 -0800127static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set)
Bin Meng9a1d6af2016-01-11 22:41:24 -0800128#else
129static int tsec_mcast_addr(struct udevice *dev, const u8 *mcast_mac, int set)
130#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
Claudiu Manoil876d4512013-09-30 12:44:40 +0300143 if (set)
144 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}
150#endif /* Multicast TFTP ? */
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;
Mario Sixd38de332018-01-15 11:08:21 +0100264 u16 status;
Bin Meng8ba50172016-01-11 22:41:21 -0800265 int result = 0;
266 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) {
273 debug("%s: tsec: tx buffers full\n", dev->name);
274 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) {
292 debug("%s: tsec: tx error\n", dev->name);
293 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);
565#endif
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300566 struct tsec __iomem *regs = priv->regs;
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300567 u32 tempval;
Timur Tabi11af8d62012-07-09 08:52:43 +0000568 int ret;
Mingkai Hu90751912011-01-27 12:52:46 +0800569
570 /* Make sure the controller is stopped */
571 tsec_halt(dev);
572
573 /* Init MACCFG2. Defaults to GMII */
574 out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
575
576 /* Init ECNTRL */
577 out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
578
Bin Meng9872b732016-01-11 22:41:18 -0800579 /*
580 * Copy the station address into the address registers.
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300581 * For a station address of 0x12345678ABCD in transmission
582 * order (BE), MACnADDR1 is set to 0xCDAB7856 and
583 * MACnADDR2 is set to 0x34120000.
584 */
Bin Meng9a1d6af2016-01-11 22:41:24 -0800585#ifndef CONFIG_DM_ETH
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300586 tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) |
587 (dev->enetaddr[3] << 8) | dev->enetaddr[2];
Bin Meng9a1d6af2016-01-11 22:41:24 -0800588#else
589 tempval = (pdata->enetaddr[5] << 24) | (pdata->enetaddr[4] << 16) |
590 (pdata->enetaddr[3] << 8) | pdata->enetaddr[2];
591#endif
Mingkai Hu90751912011-01-27 12:52:46 +0800592
593 out_be32(&regs->macstnaddr1, tempval);
594
Bin Meng9a1d6af2016-01-11 22:41:24 -0800595#ifndef CONFIG_DM_ETH
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300596 tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800597#else
598 tempval = (pdata->enetaddr[1] << 24) | (pdata->enetaddr[0] << 16);
599#endif
Mingkai Hu90751912011-01-27 12:52:46 +0800600
601 out_be32(&regs->macstnaddr2, tempval);
602
Mingkai Hu90751912011-01-27 12:52:46 +0800603 /* Clear out (for the most part) the other registers */
604 init_registers(regs);
605
606 /* Ready the device for tx/rx */
Bin Meng56a27a12016-01-11 22:41:22 -0800607 startup_tsec(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800608
Andy Fleming063c1262011-04-08 02:10:54 -0500609 /* Start up the PHY */
Timur Tabi11af8d62012-07-09 08:52:43 +0000610 ret = phy_startup(priv->phydev);
611 if (ret) {
612 printf("Could not initialize PHY %s\n",
613 priv->phydev->dev->name);
614 return ret;
615 }
Andy Fleming063c1262011-04-08 02:10:54 -0500616
617 adjust_link(priv, priv->phydev);
618
Mingkai Hu90751912011-01-27 12:52:46 +0800619 /* If there's no link, fail */
Andy Fleming063c1262011-04-08 02:10:54 -0500620 return priv->phydev->link ? 0 : -1;
Mingkai Hu90751912011-01-27 12:52:46 +0800621}
622
Andy Fleming063c1262011-04-08 02:10:54 -0500623static phy_interface_t tsec_get_interface(struct tsec_private *priv)
624{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300625 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500626 u32 ecntrl;
627
628 ecntrl = in_be32(&regs->ecntrl);
629
630 if (ecntrl & ECNTRL_SGMII_MODE)
631 return PHY_INTERFACE_MODE_SGMII;
632
633 if (ecntrl & ECNTRL_TBI_MODE) {
634 if (ecntrl & ECNTRL_REDUCED_MODE)
635 return PHY_INTERFACE_MODE_RTBI;
636 else
637 return PHY_INTERFACE_MODE_TBI;
638 }
639
640 if (ecntrl & ECNTRL_REDUCED_MODE) {
Mario Sixd38de332018-01-15 11:08:21 +0100641 phy_interface_t interface;
642
Andy Fleming063c1262011-04-08 02:10:54 -0500643 if (ecntrl & ECNTRL_REDUCED_MII_MODE)
644 return PHY_INTERFACE_MODE_RMII;
Andy Fleming063c1262011-04-08 02:10:54 -0500645
Mario Sixd38de332018-01-15 11:08:21 +0100646 interface = priv->interface;
Andy Fleming063c1262011-04-08 02:10:54 -0500647
Mario Sixd38de332018-01-15 11:08:21 +0100648 /*
649 * This isn't autodetected, so it must
650 * be set by the platform code.
651 */
652 if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
653 interface == PHY_INTERFACE_MODE_RGMII_TXID ||
654 interface == PHY_INTERFACE_MODE_RGMII_RXID)
655 return interface;
656
657 return PHY_INTERFACE_MODE_RGMII;
Andy Fleming063c1262011-04-08 02:10:54 -0500658 }
659
660 if (priv->flags & TSEC_GIGABIT)
661 return PHY_INTERFACE_MODE_GMII;
662
663 return PHY_INTERFACE_MODE_MII;
664}
665
Bin Meng9872b732016-01-11 22:41:18 -0800666/*
667 * Discover which PHY is attached to the device, and configure it
Mingkai Hu90751912011-01-27 12:52:46 +0800668 * properly. If the PHY is not recognized, then return 0
669 * (failure). Otherwise, return 1
670 */
Bin Meng56a27a12016-01-11 22:41:22 -0800671static int init_phy(struct tsec_private *priv)
Mingkai Hu90751912011-01-27 12:52:46 +0800672{
Andy Fleming063c1262011-04-08 02:10:54 -0500673 struct phy_device *phydev;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300674 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500675 u32 supported = (SUPPORTED_10baseT_Half |
676 SUPPORTED_10baseT_Full |
677 SUPPORTED_100baseT_Half |
678 SUPPORTED_100baseT_Full);
679
680 if (priv->flags & TSEC_GIGABIT)
681 supported |= SUPPORTED_1000baseT_Full;
Mingkai Hu90751912011-01-27 12:52:46 +0800682
683 /* Assign a Physical address to the TBI */
Bin Menga1c76c12016-01-11 22:41:25 -0800684 out_be32(&regs->tbipa, priv->tbiaddr);
Mingkai Hu90751912011-01-27 12:52:46 +0800685
Andy Fleming063c1262011-04-08 02:10:54 -0500686 priv->interface = tsec_get_interface(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800687
Andy Fleming063c1262011-04-08 02:10:54 -0500688 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
Mingkai Hu90751912011-01-27 12:52:46 +0800689 tsec_configure_serdes(priv);
690
Bin Meng56a27a12016-01-11 22:41:22 -0800691 phydev = phy_connect(priv->bus, priv->phyaddr, priv->dev,
692 priv->interface);
Claudiu Manoil7f233c02013-12-10 15:21:04 +0200693 if (!phydev)
694 return 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800695
Andy Fleming063c1262011-04-08 02:10:54 -0500696 phydev->supported &= supported;
697 phydev->advertising = phydev->supported;
698
699 priv->phydev = phydev;
700
701 phy_config(phydev);
Mingkai Hu90751912011-01-27 12:52:46 +0800702
703 return 1;
704}
705
Bin Meng9a1d6af2016-01-11 22:41:24 -0800706#ifndef CONFIG_DM_ETH
Bin Meng9872b732016-01-11 22:41:18 -0800707/*
708 * Initialize device structure. Returns success if PHY
Mingkai Hu90751912011-01-27 12:52:46 +0800709 * initialization succeeded (i.e. if it recognizes the PHY)
710 */
711static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
712{
713 struct eth_device *dev;
714 int i;
715 struct tsec_private *priv;
716
Mario Sixd38de332018-01-15 11:08:21 +0100717 dev = (struct eth_device *)malloc(sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800718
Mario Sixd38de332018-01-15 11:08:21 +0100719 if (!dev)
Mingkai Hu90751912011-01-27 12:52:46 +0800720 return 0;
721
Mario Sixd38de332018-01-15 11:08:21 +0100722 memset(dev, 0, sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800723
724 priv = (struct tsec_private *)malloc(sizeof(*priv));
725
Mario Six5775f002018-01-15 11:08:22 +0100726 if (!priv) {
727 free(dev);
Mingkai Hu90751912011-01-27 12:52:46 +0800728 return 0;
Mario Six5775f002018-01-15 11:08:22 +0100729 }
Mingkai Hu90751912011-01-27 12:52:46 +0800730
Mingkai Hu90751912011-01-27 12:52:46 +0800731 priv->regs = tsec_info->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800732 priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
733
734 priv->phyaddr = tsec_info->phyaddr;
Bin Menga1c76c12016-01-11 22:41:25 -0800735 priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Mingkai Hu90751912011-01-27 12:52:46 +0800736 priv->flags = tsec_info->flags;
737
Ben Whitten192bc692015-12-30 13:05:58 +0000738 strcpy(dev->name, tsec_info->devname);
Andy Fleming063c1262011-04-08 02:10:54 -0500739 priv->interface = tsec_info->interface;
740 priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
Bin Meng56a27a12016-01-11 22:41:22 -0800741 priv->dev = dev;
Mingkai Hu90751912011-01-27 12:52:46 +0800742 dev->iobase = 0;
743 dev->priv = priv;
744 dev->init = tsec_init;
745 dev->halt = tsec_halt;
746 dev->send = tsec_send;
747 dev->recv = tsec_recv;
748#ifdef CONFIG_MCAST_TFTP
749 dev->mcast = tsec_mcast_addr;
750#endif
751
Bin Meng9872b732016-01-11 22:41:18 -0800752 /* Tell U-Boot to get the addr from the env */
Mingkai Hu90751912011-01-27 12:52:46 +0800753 for (i = 0; i < 6; i++)
754 dev->enetaddr[i] = 0;
755
756 eth_register(dev);
757
758 /* Reset the MAC */
759 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
760 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
761 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
762
Mingkai Hu90751912011-01-27 12:52:46 +0800763 /* Try to initialize PHY here, and return */
Bin Meng56a27a12016-01-11 22:41:22 -0800764 return init_phy(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800765}
766
767/*
768 * Initialize all the TSEC devices
769 *
770 * Returns the number of TSEC devices that were initialized
771 */
772int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
773{
774 int i;
Mario Sixd38de332018-01-15 11:08:21 +0100775 int count = 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800776
777 for (i = 0; i < num; i++) {
Mario Sixd38de332018-01-15 11:08:21 +0100778 int ret = tsec_initialize(bis, &tsecs[i]);
779
Mingkai Hu90751912011-01-27 12:52:46 +0800780 if (ret > 0)
781 count += ret;
782 }
783
784 return count;
785}
786
787int tsec_standard_init(bd_t *bis)
788{
Andy Fleming063c1262011-04-08 02:10:54 -0500789 struct fsl_pq_mdio_info info;
790
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300791 info.regs = TSEC_GET_MDIO_REGS_BASE(1);
Andy Fleming063c1262011-04-08 02:10:54 -0500792 info.name = DEFAULT_MII_NAME;
793
794 fsl_pq_mdio_init(bis, &info);
795
Mingkai Hu90751912011-01-27 12:52:46 +0800796 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
797}
Bin Meng9a1d6af2016-01-11 22:41:24 -0800798#else /* CONFIG_DM_ETH */
799int tsec_probe(struct udevice *dev)
800{
801 struct tsec_private *priv = dev_get_priv(dev);
802 struct eth_pdata *pdata = dev_get_platdata(dev);
803 struct fsl_pq_mdio_info mdio_info;
Mario Six1313aaf2018-01-15 11:08:23 +0100804 struct ofnode_phandle_args phandle_args;
805 ofnode parent;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800806 const char *phy_mode;
807 int ret;
808
Mario Six1313aaf2018-01-15 11:08:23 +0100809 pdata->iobase = (phys_addr_t)dev_read_addr(dev);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800810 priv->regs = (struct tsec *)pdata->iobase;
811
Mario Six1313aaf2018-01-15 11:08:23 +0100812 if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
813 &phandle_args)) {
Bin Meng9a1d6af2016-01-11 22:41:24 -0800814 debug("phy-handle does not exist under tsec %s\n", dev->name);
815 return -ENOENT;
Mario Six1313aaf2018-01-15 11:08:23 +0100816 } else {
817 int reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
818
819 priv->phyaddr = reg;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800820 }
821
Mario Six1313aaf2018-01-15 11:08:23 +0100822 parent = ofnode_get_parent(phandle_args.node);
823 if (ofnode_valid(parent)) {
Mario Six5e9d9ab2018-04-27 14:52:57 +0200824 int reg = ofnode_get_addr_index(parent, 0);
825
826 priv->phyregs_sgmii = (struct tsec_mii_mng *)reg;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800827 } else {
828 debug("No parent node for PHY?\n");
829 return -ENOENT;
830 }
831
Mario Six1313aaf2018-01-15 11:08:23 +0100832 if (dev_read_phandle_with_args(dev, "tbi-handle", NULL, 0, 0,
833 &phandle_args)) {
Bin Menga1c76c12016-01-11 22:41:25 -0800834 priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Mario Six1313aaf2018-01-15 11:08:23 +0100835 } else {
836 int reg = ofnode_read_u32_default(phandle_args.node, "reg",
837 CONFIG_SYS_TBIPA_VALUE);
838 priv->tbiaddr = reg;
Bin Menga1c76c12016-01-11 22:41:25 -0800839 }
840
Mario Six1313aaf2018-01-15 11:08:23 +0100841 phy_mode = dev_read_prop(dev, "phy-connection-type", NULL);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800842 if (phy_mode)
843 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
844 if (pdata->phy_interface == -1) {
845 debug("Invalid PHY interface '%s'\n", phy_mode);
846 return -EINVAL;
847 }
848 priv->interface = pdata->phy_interface;
849
850 /* Initialize flags */
851 priv->flags = TSEC_GIGABIT;
852 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
853 priv->flags |= TSEC_SGMII;
854
855 mdio_info.regs = priv->phyregs_sgmii;
856 mdio_info.name = (char *)dev->name;
857 ret = fsl_pq_mdio_init(NULL, &mdio_info);
858 if (ret)
859 return ret;
860
861 /* Reset the MAC */
862 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
863 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
864 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
865
866 priv->dev = dev;
867 priv->bus = miiphy_get_dev_by_name(dev->name);
868
869 /* Try to initialize PHY here, and return */
870 return !init_phy(priv);
871}
872
873int tsec_remove(struct udevice *dev)
874{
875 struct tsec_private *priv = dev->priv;
876
877 free(priv->phydev);
878 mdio_unregister(priv->bus);
879 mdio_free(priv->bus);
880
881 return 0;
882}
883
884static const struct eth_ops tsec_ops = {
885 .start = tsec_init,
886 .send = tsec_send,
887 .recv = tsec_recv,
888 .free_pkt = tsec_free_pkt,
889 .stop = tsec_halt,
890#ifdef CONFIG_MCAST_TFTP
891 .mcast = tsec_mcast_addr,
892#endif
893};
894
895static const struct udevice_id tsec_ids[] = {
896 { .compatible = "fsl,tsec" },
897 { }
898};
899
900U_BOOT_DRIVER(eth_tsec) = {
901 .name = "tsec",
902 .id = UCLASS_ETH,
903 .of_match = tsec_ids,
904 .probe = tsec_probe,
905 .remove = tsec_remove,
906 .ops = &tsec_ops,
907 .priv_auto_alloc_size = sizeof(struct tsec_private),
908 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
909 .flags = DM_FLAG_ALLOC_PRIV_DMA,
910};
911#endif /* CONFIG_DM_ETH */