blob: 5d12e4b7755857960d4909d1c5d53f53c4a7326f [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
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900557static int tsec_init(struct eth_device *dev, struct bd_info *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 */
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900704static int tsec_initialize(struct bd_info *bis,
705 struct tsec_info_struct *tsec_info)
Mingkai Hu90751912011-01-27 12:52:46 +0800706{
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300707 struct tsec_private *priv;
Mingkai Hu90751912011-01-27 12:52:46 +0800708 struct eth_device *dev;
709 int i;
Mingkai Hu90751912011-01-27 12:52:46 +0800710
Mario Sixd38de332018-01-15 11:08:21 +0100711 dev = (struct eth_device *)malloc(sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800712
Mario Sixd38de332018-01-15 11:08:21 +0100713 if (!dev)
Mingkai Hu90751912011-01-27 12:52:46 +0800714 return 0;
715
Mario Sixd38de332018-01-15 11:08:21 +0100716 memset(dev, 0, sizeof(*dev));
Mingkai Hu90751912011-01-27 12:52:46 +0800717
718 priv = (struct tsec_private *)malloc(sizeof(*priv));
719
Mario Six5775f002018-01-15 11:08:22 +0100720 if (!priv) {
721 free(dev);
Mingkai Hu90751912011-01-27 12:52:46 +0800722 return 0;
Mario Six5775f002018-01-15 11:08:22 +0100723 }
Mingkai Hu90751912011-01-27 12:52:46 +0800724
Mingkai Hu90751912011-01-27 12:52:46 +0800725 priv->regs = tsec_info->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800726 priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
727
728 priv->phyaddr = tsec_info->phyaddr;
Bin Menga1c76c12016-01-11 22:41:25 -0800729 priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Mingkai Hu90751912011-01-27 12:52:46 +0800730 priv->flags = tsec_info->flags;
731
Ben Whitten192bc692015-12-30 13:05:58 +0000732 strcpy(dev->name, tsec_info->devname);
Andy Fleming063c1262011-04-08 02:10:54 -0500733 priv->interface = tsec_info->interface;
734 priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
Bin Meng56a27a12016-01-11 22:41:22 -0800735 priv->dev = dev;
Mingkai Hu90751912011-01-27 12:52:46 +0800736 dev->iobase = 0;
737 dev->priv = priv;
738 dev->init = tsec_init;
739 dev->halt = tsec_halt;
740 dev->send = tsec_send;
741 dev->recv = tsec_recv;
Mingkai Hu90751912011-01-27 12:52:46 +0800742 dev->mcast = tsec_mcast_addr;
Mingkai Hu90751912011-01-27 12:52:46 +0800743
Bin Meng9872b732016-01-11 22:41:18 -0800744 /* Tell U-Boot to get the addr from the env */
Mingkai Hu90751912011-01-27 12:52:46 +0800745 for (i = 0; i < 6; i++)
746 dev->enetaddr[i] = 0;
747
748 eth_register(dev);
749
750 /* Reset the MAC */
751 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
752 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
753 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
754
Mingkai Hu90751912011-01-27 12:52:46 +0800755 /* Try to initialize PHY here, and return */
Bin Meng56a27a12016-01-11 22:41:22 -0800756 return init_phy(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800757}
758
759/*
760 * Initialize all the TSEC devices
761 *
762 * Returns the number of TSEC devices that were initialized
763 */
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900764int tsec_eth_init(struct bd_info *bis, struct tsec_info_struct *tsecs,
765 int num)
Mingkai Hu90751912011-01-27 12:52:46 +0800766{
767 int i;
Mario Sixd38de332018-01-15 11:08:21 +0100768 int count = 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800769
770 for (i = 0; i < num; i++) {
Mario Sixd38de332018-01-15 11:08:21 +0100771 int ret = tsec_initialize(bis, &tsecs[i]);
772
Mingkai Hu90751912011-01-27 12:52:46 +0800773 if (ret > 0)
774 count += ret;
775 }
776
777 return count;
778}
779
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900780int tsec_standard_init(struct bd_info *bis)
Mingkai Hu90751912011-01-27 12:52:46 +0800781{
Andy Fleming063c1262011-04-08 02:10:54 -0500782 struct fsl_pq_mdio_info info;
783
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300784 info.regs = TSEC_GET_MDIO_REGS_BASE(1);
Andy Fleming063c1262011-04-08 02:10:54 -0500785 info.name = DEFAULT_MII_NAME;
786
787 fsl_pq_mdio_init(bis, &info);
788
Mingkai Hu90751912011-01-27 12:52:46 +0800789 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
790}
Bin Meng9a1d6af2016-01-11 22:41:24 -0800791#else /* CONFIG_DM_ETH */
792int tsec_probe(struct udevice *dev)
793{
Bin Meng9a1d6af2016-01-11 22:41:24 -0800794 struct eth_pdata *pdata = dev_get_platdata(dev);
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300795 struct tsec_private *priv = dev_get_priv(dev);
Hou Zhiqianga0f47e02020-05-03 22:48:43 +0800796 struct tsec_mii_mng __iomem *ext_phyregs_mii;
Mario Six1313aaf2018-01-15 11:08:23 +0100797 struct ofnode_phandle_args phandle_args;
Vladimir Oltean29db3102019-07-19 00:29:53 +0300798 u32 tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300799 struct fsl_pq_mdio_info mdio_info;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800800 const char *phy_mode;
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300801 fdt_addr_t reg;
Vladimir Oltean07bd39f2019-07-19 00:29:55 +0300802 ofnode parent;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800803 int ret;
804
Mario Six1313aaf2018-01-15 11:08:23 +0100805 pdata->iobase = (phys_addr_t)dev_read_addr(dev);
Hou Zhiqiangbf67eb32020-05-03 22:48:42 +0800806 priv->regs = dev_remap_addr(dev);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800807
Mario Six1313aaf2018-01-15 11:08:23 +0100808 if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
809 &phandle_args)) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300810 printf("phy-handle does not exist under tsec %s\n", dev->name);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800811 return -ENOENT;
Mario Six1313aaf2018-01-15 11:08:23 +0100812 } else {
813 int reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
814
815 priv->phyaddr = reg;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800816 }
817
Mario Six1313aaf2018-01-15 11:08:23 +0100818 parent = ofnode_get_parent(phandle_args.node);
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300819 if (!ofnode_valid(parent)) {
820 printf("No parent node for PHY?\n");
Bin Meng9a1d6af2016-01-11 22:41:24 -0800821 return -ENOENT;
822 }
823
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300824 reg = ofnode_get_addr_index(parent, 0);
Hou Zhiqiangbf67eb32020-05-03 22:48:42 +0800825 if (reg == FDT_ADDR_T_NONE) {
826 printf("No 'reg' property of MII for external PHY\n");
827 return -ENOENT;
828 }
829
Hou Zhiqianga0f47e02020-05-03 22:48:43 +0800830 ext_phyregs_mii = map_physmem(reg + TSEC_MDIO_REGS_OFFSET, 0,
831 MAP_NOCACHE);
Vladimir Olteanbca686a2019-07-19 00:29:54 +0300832
Vladimir Oltean29db3102019-07-19 00:29:53 +0300833 ret = dev_read_phandle_with_args(dev, "tbi-handle", NULL, 0, 0,
834 &phandle_args);
Hou Zhiqianga0f47e02020-05-03 22:48:43 +0800835 if (ret == 0) {
Vladimir Oltean29db3102019-07-19 00:29:53 +0300836 ofnode_read_u32(phandle_args.node, "reg", &tbiaddr);
837
Hou Zhiqianga0f47e02020-05-03 22:48:43 +0800838 parent = ofnode_get_parent(phandle_args.node);
839 if (!ofnode_valid(parent)) {
840 printf("No parent node for TBI PHY?\n");
841 return -ENOENT;
842 }
843
844 reg = ofnode_get_addr_index(parent, 0);
845 if (reg == FDT_ADDR_T_NONE) {
846 printf("No 'reg' property of MII for TBI PHY\n");
847 return -ENOENT;
848 }
849
850 priv->phyregs_sgmii = map_physmem(reg + TSEC_MDIO_REGS_OFFSET,
851 0, MAP_NOCACHE);
852 }
853
Vladimir Oltean29db3102019-07-19 00:29:53 +0300854 priv->tbiaddr = tbiaddr;
Bin Menga1c76c12016-01-11 22:41:25 -0800855
Mario Six1313aaf2018-01-15 11:08:23 +0100856 phy_mode = dev_read_prop(dev, "phy-connection-type", NULL);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800857 if (phy_mode)
858 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
859 if (pdata->phy_interface == -1) {
Vladimir Olteanb7be7762019-07-19 00:29:56 +0300860 printf("Invalid PHY interface '%s'\n", phy_mode);
Bin Meng9a1d6af2016-01-11 22:41:24 -0800861 return -EINVAL;
862 }
863 priv->interface = pdata->phy_interface;
864
865 /* Initialize flags */
866 priv->flags = TSEC_GIGABIT;
867 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
868 priv->flags |= TSEC_SGMII;
869
Hou Zhiqianga0f47e02020-05-03 22:48:43 +0800870 mdio_info.regs = ext_phyregs_mii;
Bin Meng9a1d6af2016-01-11 22:41:24 -0800871 mdio_info.name = (char *)dev->name;
872 ret = fsl_pq_mdio_init(NULL, &mdio_info);
873 if (ret)
874 return ret;
875
876 /* Reset the MAC */
877 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
878 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
879 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
880
881 priv->dev = dev;
882 priv->bus = miiphy_get_dev_by_name(dev->name);
883
884 /* Try to initialize PHY here, and return */
885 return !init_phy(priv);
886}
887
888int tsec_remove(struct udevice *dev)
889{
890 struct tsec_private *priv = dev->priv;
891
892 free(priv->phydev);
893 mdio_unregister(priv->bus);
894 mdio_free(priv->bus);
895
896 return 0;
897}
898
899static const struct eth_ops tsec_ops = {
900 .start = tsec_init,
901 .send = tsec_send,
902 .recv = tsec_recv,
903 .free_pkt = tsec_free_pkt,
904 .stop = tsec_halt,
Bin Meng9a1d6af2016-01-11 22:41:24 -0800905 .mcast = tsec_mcast_addr,
Bin Meng9a1d6af2016-01-11 22:41:24 -0800906};
907
908static const struct udevice_id tsec_ids[] = {
Vladimir Oltean1c8ad082019-07-19 00:29:58 +0300909 { .compatible = "fsl,etsec2" },
Bin Meng9a1d6af2016-01-11 22:41:24 -0800910 { }
911};
912
913U_BOOT_DRIVER(eth_tsec) = {
914 .name = "tsec",
915 .id = UCLASS_ETH,
916 .of_match = tsec_ids,
917 .probe = tsec_probe,
918 .remove = tsec_remove,
919 .ops = &tsec_ops,
920 .priv_auto_alloc_size = sizeof(struct tsec_private),
921 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
922 .flags = DM_FLAG_ALLOC_PRIV_DMA,
923};
924#endif /* CONFIG_DM_ETH */