blob: 3d75acb6b4ee6138fe091ac4ef0267d7d7af5b7c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk9c53f402003-10-15 23:53:47 +00002/*
wdenka445ddf2004-06-09 00:34:46 +00003 * Freescale Three Speed Ethernet Controller driver
wdenk9c53f402003-10-15 23:53:47 +00004 *
Claudiu Manoilcd0c4122013-09-30 12:44:42 +03005 * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc.
wdenk9c53f402003-10-15 23:53:47 +00006 * (C) Copyright 2003, Motorola, Inc.
wdenk9c53f402003-10-15 23:53:47 +00007 * author Andy Fleming
wdenk9c53f402003-10-15 23:53:47 +00008 */
9
10#include <config.h>
wdenk9c53f402003-10-15 23:53:47 +000011#include <common.h>
Bin Meng1048f612016-01-11 22:41:24 -080012#include <dm.h>
wdenk9c53f402003-10-15 23:53:47 +000013#include <malloc.h>
14#include <net.h>
15#include <command.h>
Andy Flemingc067fc12008-08-31 16:33:25 -050016#include <tsec.h>
Andy Fleming422effd2011-04-08 02:10:54 -050017#include <fsl_mdio.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060019#include <linux/delay.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090020#include <linux/errno.h>
chenhui zhaoc8caa8a2011-10-03 08:38:50 -050021#include <asm/processor.h>
Alison Wang32cc5912014-09-05 13:52:38 +080022#include <asm/io.h>
wdenk9c53f402003-10-15 23:53:47 +000023
Bin Meng1048f612016-01-11 22:41:24 -080024#ifndef CONFIG_DM_ETH
Andy Flemingfecff2b2008-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 Manoilcd0c4122013-09-30 12:44:42 +030036 .regs = TSEC_GET_REGS(2, 0x2000),
Andy Flemingfecff2b2008-08-31 16:33:26 -050037 .devname = CONFIG_MPC85XX_FEC_NAME,
38 .phyaddr = FEC_PHY_ADDR,
Andy Fleming422effd2011-04-08 02:10:54 -050039 .flags = FEC_FLAGS,
40 .mii_devname = DEFAULT_MII_NAME
Andy Flemingfecff2b2008-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 Meng1048f612016-01-11 22:41:24 -080050#endif /* CONFIG_DM_ETH */
Andy Flemingfecff2b2008-08-31 16:33:26 -050051
Andy Flemingac65e072008-08-31 16:33:27 -050052#define TBIANA_SETTINGS ( \
53 TBIANA_ASYMMETRIC_PAUSE \
54 | TBIANA_SYMMETRIC_PAUSE \
55 | TBIANA_FULL_DUPLEX \
56 )
57
Felix Radensky27f98e02010-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 Galac1457f92010-12-01 22:55:54 -060060#define CONFIG_TSEC_TBICR_SETTINGS ( \
Andy Flemingac65e072008-08-31 16:33:27 -050061 TBICR_PHY_RESET \
Kumar Galac1457f92010-12-01 22:55:54 -060062 | TBICR_ANEG_ENABLE \
Andy Flemingac65e072008-08-31 16:33:27 -050063 | TBICR_FULL_DUPLEX \
64 | TBICR_SPEED1_SET \
65 )
Felix Radensky27f98e02010-06-28 01:57:39 +030066#endif /* CONFIG_TSEC_TBICR_SETTINGS */
Peter Tyser583c1f42009-11-03 17:52:07 -060067
Andy Flemingac65e072008-08-31 16:33:27 -050068/* Configure the TBI for SGMII operation */
69static void tsec_configure_serdes(struct tsec_private *priv)
70{
Bin Meng79cd33a2016-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 Fleming422effd2011-04-08 02:10:54 -050075 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixc29fcc72018-01-15 11:08:21 +010076 0, TBI_ANA, TBIANA_SETTINGS);
Andy Fleming422effd2011-04-08 02:10:54 -050077 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixc29fcc72018-01-15 11:08:21 +010078 0, TBI_TBICON, TBICON_CLK_SELECT);
Andy Fleming422effd2011-04-08 02:10:54 -050079 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
Mario Sixc29fcc72018-01-15 11:08:21 +010080 0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
David Updegraff0451b012007-04-20 14:34:48 -050081}
82
Chris Packhambbe18572018-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
Mingkai Hue0653bf2011-01-27 12:52:46 +0800108/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
109
110/* Set the appropriate hash bit for the given addr */
111
Bin Meng79cd33a2016-01-11 22:41:18 -0800112/*
113 * The algorithm works like so:
Mingkai Hue0653bf2011-01-27 12:52:46 +0800114 * 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 Manoil461511b2013-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
Mingkai Hue0653bf2011-01-27 12:52:46 +0800121 * hash index which gaddr register to use, and the 5 other bits
122 * indicate which bit (assuming an IBM numbering scheme, which
Claudiu Manoil461511b2013-09-30 12:44:40 +0300123 * for PowerPC (tm) is usually the case) in the register holds
Bin Meng79cd33a2016-01-11 22:41:18 -0800124 * the entry.
125 */
Bin Meng1048f612016-01-11 22:41:24 -0800126#ifndef CONFIG_DM_ETH
Chris Packhama55ef7f2018-11-26 21:00:29 +1300127static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac,
128 int join)
Bin Meng1048f612016-01-11 22:41:24 -0800129#else
Chris Packhama55ef7f2018-11-26 21:00:29 +1300130static int tsec_mcast_addr(struct udevice *dev, const u8 *mcast_mac, int join)
Bin Meng1048f612016-01-11 22:41:24 -0800131#endif
Mingkai Hue0653bf2011-01-27 12:52:46 +0800132{
Claudiu Manoil766c8942013-09-30 12:44:41 +0300133 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoil461511b2013-09-30 12:44:40 +0300134 struct tsec __iomem *regs = priv->regs;
135 u32 result, value;
136 u8 whichbit, whichreg;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800137
Claudiu Manoil461511b2013-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 */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800141
Mario Sixc29fcc72018-01-15 11:08:21 +0100142 value = BIT(31 - whichbit);
Claudiu Manoil461511b2013-09-30 12:44:40 +0300143
Chris Packhama55ef7f2018-11-26 21:00:29 +1300144 if (join)
Claudiu Manoil461511b2013-09-30 12:44:40 +0300145 setbits_be32(&regs->hash.gaddr0 + whichreg, value);
146 else
147 clrbits_be32(&regs->hash.gaddr0 + whichreg, value);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800148
Mingkai Hue0653bf2011-01-27 12:52:46 +0800149 return 0;
150}
Mingkai Hue0653bf2011-01-27 12:52:46 +0800151
Bin Meng79cd33a2016-01-11 22:41:18 -0800152/*
153 * Initialized required registers to appropriate values, zeroing
Mingkai Hue0653bf2011-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 Manoilcd0c4122013-09-30 12:44:42 +0300157static void init_registers(struct tsec __iomem *regs)
Mingkai Hue0653bf2011-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 Manoila18ab902013-09-30 12:44:46 +0300185 memset((void *)&regs->rmon, 0, sizeof(regs->rmon));
Mingkai Hue0653bf2011-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 Hue0653bf2011-01-27 12:52:46 +0800196}
197
Bin Meng79cd33a2016-01-11 22:41:18 -0800198/*
199 * Configure maccfg2 based on negotiated speed and duplex
Mingkai Hue0653bf2011-01-27 12:52:46 +0800200 * reported by PHY handling code
201 */
Andy Fleming422effd2011-04-08 02:10:54 -0500202static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800203{
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300204 struct tsec __iomem *regs = priv->regs;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800205 u32 ecntrl, maccfg2;
206
Andy Fleming422effd2011-04-08 02:10:54 -0500207 if (!phydev->link) {
208 printf("%s: No link.\n", phydev->dev->name);
Mingkai Hue0653bf2011-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 Fleming422effd2011-04-08 02:10:54 -0500219 if (phydev->duplex)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800220 maccfg2 |= MACCFG2_FULL_DUPLEX;
221
Andy Fleming422effd2011-04-08 02:10:54 -0500222 switch (phydev->speed) {
Mingkai Hue0653bf2011-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 Meng79cd33a2016-01-11 22:41:18 -0800230 /*
231 * Set R100 bit in all modes although
Mingkai Hue0653bf2011-01-27 12:52:46 +0800232 * it is only used in RGMII mode
233 */
Andy Fleming422effd2011-04-08 02:10:54 -0500234 if (phydev->speed == 100)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800235 ecntrl |= ECNTRL_R100;
236 break;
237 default:
Andy Fleming422effd2011-04-08 02:10:54 -0500238 printf("%s: Speed was bad\n", phydev->dev->name);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800239 break;
240 }
241
242 out_be32(&regs->ecntrl, ecntrl);
243 out_be32(&regs->maccfg2, maccfg2);
wdenkf41ff3b2005-04-04 23:43:44 +0000244
Andy Fleming422effd2011-04-08 02:10:54 -0500245 printf("Speed: %d, %s duplex%s\n", phydev->speed,
Mario Sixc29fcc72018-01-15 11:08:21 +0100246 (phydev->duplex) ? "full" : "half",
247 (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
Mingkai Hue0653bf2011-01-27 12:52:46 +0800248}
wdenkbfad55d2005-03-14 23:56:42 +0000249
Bin Meng80b1a1c2016-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 Meng1048f612016-01-11 22:41:24 -0800256#ifndef CONFIG_DM_ETH
Bin Meng80b1a1c2016-01-11 22:41:21 -0800257static int tsec_send(struct eth_device *dev, void *packet, int length)
Bin Meng1048f612016-01-11 22:41:24 -0800258#else
259static int tsec_send(struct udevice *dev, void *packet, int length)
260#endif
Bin Meng80b1a1c2016-01-11 22:41:21 -0800261{
262 struct tsec_private *priv = (struct tsec_private *)dev->priv;
263 struct tsec __iomem *regs = priv->regs;
Bin Meng80b1a1c2016-01-11 22:41:21 -0800264 int result = 0;
Vladimir Olteana11c89d2019-07-19 00:29:55 +0300265 u16 status;
Bin Meng80b1a1c2016-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 Oltean8ec8eaa2019-07-19 00:29:56 +0300273 printf("%s: tsec: tx buffers full\n", dev->name);
Bin Meng80b1a1c2016-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 Oltean8ec8eaa2019-07-19 00:29:56 +0300292 printf("%s: tsec: tx error\n", dev->name);
Bin Meng80b1a1c2016-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 Meng1048f612016-01-11 22:41:24 -0800303#ifndef CONFIG_DM_ETH
Bin Meng80b1a1c2016-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 Sixc29fcc72018-01-15 11:08:21 +0100311 u16 status = in_be16(&priv->rxbd[priv->rx_idx].status);
Bin Meng80b1a1c2016-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 Meng1048f612016-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 Sixc29fcc72018-01-15 11:08:21 +0100347 u16 status = in_be16(&priv->rxbd[priv->rx_idx].status);
348 u32 buf;
Bin Meng1048f612016-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 Sixc29fcc72018-01-15 11:08:21 +0100371 u16 status;
Bin Meng1048f612016-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 Meng80b1a1c2016-01-11 22:41:21 -0800386
387/* Stop the interface */
Bin Meng1048f612016-01-11 22:41:24 -0800388#ifndef CONFIG_DM_ETH
Bin Meng80b1a1c2016-01-11 22:41:21 -0800389static void tsec_halt(struct eth_device *dev)
Bin Meng1048f612016-01-11 22:41:24 -0800390#else
391static void tsec_halt(struct udevice *dev)
392#endif
Bin Meng80b1a1c2016-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 zhaoc8caa8a2011-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 Menge86a6cd2016-01-11 22:41:22 -0800416void redundant_init(struct tsec_private *priv)
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500417{
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300418 struct tsec __iomem *regs = priv->regs;
chenhui zhaoc8caa8a2011-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 Sixc29fcc72018-01-15 11:08:21 +0100451 u16 status;
452
Bin Menge86a6cd2016-01-11 22:41:22 -0800453 tsec_send(priv->dev, (void *)pkt, sizeof(pkt));
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500454
455 /* Wait for buffer to be received */
Bin Meng1120c542016-01-11 22:41:20 -0800456 for (t = 0;
457 in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY;
Bin Meng76f53992016-01-11 22:41:19 -0800458 t++) {
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500459 if (t >= 10 * TOUT_LOOP) {
Bin Menge86a6cd2016-01-11 22:41:22 -0800460 printf("%s: tsec: rx error\n", priv->dev->name);
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500461 break;
462 }
463 }
464
Bin Meng76f53992016-01-11 22:41:19 -0800465 if (!memcmp(pkt, net_rx_packets[priv->rx_idx], sizeof(pkt)))
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500466 fail = 0;
467
Bin Meng1120c542016-01-11 22:41:20 -0800468 out_be16(&priv->rxbd[priv->rx_idx].length, 0);
Claudiu Manoileec416b2013-10-04 19:13:53 +0300469 status = RXBD_EMPTY;
Bin Meng76f53992016-01-11 22:41:19 -0800470 if ((priv->rx_idx + 1) == PKTBUFSRX)
Claudiu Manoileec416b2013-10-04 19:13:53 +0300471 status |= RXBD_WRAP;
Bin Meng1120c542016-01-11 22:41:20 -0800472 out_be16(&priv->rxbd[priv->rx_idx].status, status);
Bin Meng76f53992016-01-11 22:41:19 -0800473 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
chenhui zhaoc8caa8a2011-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 Meng79cd33a2016-01-11 22:41:18 -0800496/*
497 * Set up the buffers and their descriptors, and bring up the
Mingkai Hue0653bf2011-01-27 12:52:46 +0800498 * interface
Jon Loeligerb7ced082006-10-10 17:03:43 -0500499 */
Bin Menge86a6cd2016-01-11 22:41:22 -0800500static void startup_tsec(struct tsec_private *priv)
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100501{
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300502 struct tsec __iomem *regs = priv->regs;
Mario Sixc29fcc72018-01-15 11:08:21 +0100503 u16 status;
Claudiu Manoileec416b2013-10-04 19:13:53 +0300504 int i;
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100505
Andy Fleming422effd2011-04-08 02:10:54 -0500506 /* reset the indices to zero */
Bin Meng76f53992016-01-11 22:41:19 -0800507 priv->rx_idx = 0;
508 priv->tx_idx = 0;
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500509#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
510 uint svr;
511#endif
Andy Fleming422effd2011-04-08 02:10:54 -0500512
Mingkai Hue0653bf2011-01-27 12:52:46 +0800513 /* Point to the buffer descriptors */
Bin Meng1120c542016-01-11 22:41:20 -0800514 out_be32(&regs->tbase, (u32)&priv->txbd[0]);
515 out_be32(&regs->rbase, (u32)&priv->rxbd[0]);
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100516
Mingkai Hue0653bf2011-01-27 12:52:46 +0800517 /* Initialize the Rx Buffer descriptors */
518 for (i = 0; i < PKTBUFSRX; i++) {
Bin Meng1120c542016-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 Hue0653bf2011-01-27 12:52:46 +0800522 }
Bin Meng1120c542016-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);
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100525
Mingkai Hue0653bf2011-01-27 12:52:46 +0800526 /* Initialize the TX Buffer Descriptors */
527 for (i = 0; i < TX_BUF_CNT; i++) {
Bin Meng1120c542016-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);
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100531 }
Bin Meng1120c542016-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);
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100534
chenhui zhaoc8caa8a2011-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 Menge86a6cd2016-01-11 22:41:22 -0800538 redundant_init(priv);
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500539#endif
Mingkai Hue0653bf2011-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);
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100548}
549
Bin Meng79cd33a2016-01-11 22:41:18 -0800550/*
Bin Meng79cd33a2016-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 Hue0653bf2011-01-27 12:52:46 +0800553 * that it returns success if the link is up, failure otherwise.
Bin Meng79cd33a2016-01-11 22:41:18 -0800554 * This allows U-Boot to find the first active controller.
Jon Loeligerb7ced082006-10-10 17:03:43 -0500555 */
Bin Meng1048f612016-01-11 22:41:24 -0800556#ifndef CONFIG_DM_ETH
Mario Sixc29fcc72018-01-15 11:08:21 +0100557static int tsec_init(struct eth_device *dev, bd_t *bd)
Bin Meng1048f612016-01-11 22:41:24 -0800558#else
559static int tsec_init(struct udevice *dev)
560#endif
wdenka445ddf2004-06-09 00:34:46 +0000561{
Mingkai Hue0653bf2011-01-27 12:52:46 +0800562 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Bin Meng1048f612016-01-11 22:41:24 -0800563#ifdef CONFIG_DM_ETH
564 struct eth_pdata *pdata = dev_get_platdata(dev);
Vladimir Oltean9953c792019-07-19 00:29:57 +0300565#else
566 struct eth_device *pdata = dev;
Bin Meng1048f612016-01-11 22:41:24 -0800567#endif
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300568 struct tsec __iomem *regs = priv->regs;
Claudiu Manoildcb38fe2013-09-30 12:44:47 +0300569 u32 tempval;
Timur Tabi42387462012-07-09 08:52:43 +0000570 int ret;
wdenka445ddf2004-06-09 00:34:46 +0000571
Mingkai Hue0653bf2011-01-27 12:52:46 +0800572 /* Make sure the controller is stopped */
573 tsec_halt(dev);
wdenka445ddf2004-06-09 00:34:46 +0000574
Mingkai Hue0653bf2011-01-27 12:52:46 +0800575 /* Init MACCFG2. Defaults to GMII */
576 out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
wdenka445ddf2004-06-09 00:34:46 +0000577
Mingkai Hue0653bf2011-01-27 12:52:46 +0800578 /* Init ECNTRL */
579 out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
wdenka445ddf2004-06-09 00:34:46 +0000580
Bin Meng79cd33a2016-01-11 22:41:18 -0800581 /*
582 * Copy the station address into the address registers.
Claudiu Manoildcb38fe2013-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 Meng1048f612016-01-11 22:41:24 -0800587 tempval = (pdata->enetaddr[5] << 24) | (pdata->enetaddr[4] << 16) |
588 (pdata->enetaddr[3] << 8) | pdata->enetaddr[2];
wdenka445ddf2004-06-09 00:34:46 +0000589
Mingkai Hue0653bf2011-01-27 12:52:46 +0800590 out_be32(&regs->macstnaddr1, tempval);
wdenka445ddf2004-06-09 00:34:46 +0000591
Bin Meng1048f612016-01-11 22:41:24 -0800592 tempval = (pdata->enetaddr[1] << 24) | (pdata->enetaddr[0] << 16);
wdenka445ddf2004-06-09 00:34:46 +0000593
Mingkai Hue0653bf2011-01-27 12:52:46 +0800594 out_be32(&regs->macstnaddr2, tempval);
wdenka445ddf2004-06-09 00:34:46 +0000595
Mingkai Hue0653bf2011-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 Menge86a6cd2016-01-11 22:41:22 -0800600 startup_tsec(priv);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800601
Andy Fleming422effd2011-04-08 02:10:54 -0500602 /* Start up the PHY */
Timur Tabi42387462012-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 Fleming422effd2011-04-08 02:10:54 -0500609
610 adjust_link(priv, priv->phydev);
611
Mingkai Hue0653bf2011-01-27 12:52:46 +0800612 /* If there's no link, fail */
Andy Fleming422effd2011-04-08 02:10:54 -0500613 return priv->phydev->link ? 0 : -1;
614}
615
616static phy_interface_t tsec_get_interface(struct tsec_private *priv)
617{
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300618 struct tsec __iomem *regs = priv->regs;
Andy Fleming422effd2011-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 Sixc29fcc72018-01-15 11:08:21 +0100634 phy_interface_t interface;
635
Andy Fleming422effd2011-04-08 02:10:54 -0500636 if (ecntrl & ECNTRL_REDUCED_MII_MODE)
637 return PHY_INTERFACE_MODE_RMII;
Andy Fleming422effd2011-04-08 02:10:54 -0500638
Mario Sixc29fcc72018-01-15 11:08:21 +0100639 interface = priv->interface;
Andy Fleming422effd2011-04-08 02:10:54 -0500640
Mario Sixc29fcc72018-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 Fleming422effd2011-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;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800657}
658
Bin Meng79cd33a2016-01-11 22:41:18 -0800659/*
660 * Discover which PHY is attached to the device, and configure it
Mingkai Hue0653bf2011-01-27 12:52:46 +0800661 * properly. If the PHY is not recognized, then return 0
662 * (failure). Otherwise, return 1
wdenk78924a72004-04-18 21:45:42 +0000663 */
Bin Menge86a6cd2016-01-11 22:41:22 -0800664static int init_phy(struct tsec_private *priv)
wdenk78924a72004-04-18 21:45:42 +0000665{
Andy Fleming422effd2011-04-08 02:10:54 -0500666 struct phy_device *phydev;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300667 struct tsec __iomem *regs = priv->regs;
Andy Fleming422effd2011-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;
wdenk78924a72004-04-18 21:45:42 +0000675
Mingkai Hue0653bf2011-01-27 12:52:46 +0800676 /* Assign a Physical address to the TBI */
Bin Meng74314f12016-01-11 22:41:25 -0800677 out_be32(&regs->tbipa, priv->tbiaddr);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800678
Andy Fleming422effd2011-04-08 02:10:54 -0500679 priv->interface = tsec_get_interface(priv);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800680
Andy Fleming422effd2011-04-08 02:10:54 -0500681 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
682 tsec_configure_serdes(priv);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800683
Bin Menge86a6cd2016-01-11 22:41:22 -0800684 phydev = phy_connect(priv->bus, priv->phyaddr, priv->dev,
685 priv->interface);
Claudiu Manoilfe56fec2013-12-10 15:21:04 +0200686 if (!phydev)
687 return 0;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800688
Andy Fleming422effd2011-04-08 02:10:54 -0500689 phydev->supported &= supported;
690 phydev->advertising = phydev->supported;
wdenka445ddf2004-06-09 00:34:46 +0000691
Andy Fleming422effd2011-04-08 02:10:54 -0500692 priv->phydev = phydev;
wdenk78924a72004-04-18 21:45:42 +0000693
Andy Fleming422effd2011-04-08 02:10:54 -0500694 phy_config(phydev);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800695
696 return 1;
wdenk78924a72004-04-18 21:45:42 +0000697}
698
Bin Meng1048f612016-01-11 22:41:24 -0800699#ifndef CONFIG_DM_ETH
Bin Meng79cd33a2016-01-11 22:41:18 -0800700/*
701 * Initialize device structure. Returns success if PHY
Mingkai Hue0653bf2011-01-27 12:52:46 +0800702 * initialization succeeded (i.e. if it recognizes the PHY)
wdenk78924a72004-04-18 21:45:42 +0000703 */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800704static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
wdenk78924a72004-04-18 21:45:42 +0000705{
Vladimir Olteana11c89d2019-07-19 00:29:55 +0300706 struct tsec_private *priv;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800707 struct eth_device *dev;
708 int i;
wdenka445ddf2004-06-09 00:34:46 +0000709
Mario Sixc29fcc72018-01-15 11:08:21 +0100710 dev = (struct eth_device *)malloc(sizeof(*dev));
wdenk78924a72004-04-18 21:45:42 +0000711
Mario Sixc29fcc72018-01-15 11:08:21 +0100712 if (!dev)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800713 return 0;
wdenk78924a72004-04-18 21:45:42 +0000714
Mario Sixc29fcc72018-01-15 11:08:21 +0100715 memset(dev, 0, sizeof(*dev));
wdenka445ddf2004-06-09 00:34:46 +0000716
Mingkai Hue0653bf2011-01-27 12:52:46 +0800717 priv = (struct tsec_private *)malloc(sizeof(*priv));
718
Mario Six878b1d22018-01-15 11:08:22 +0100719 if (!priv) {
720 free(dev);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800721 return 0;
Mario Six878b1d22018-01-15 11:08:22 +0100722 }
Mingkai Hue0653bf2011-01-27 12:52:46 +0800723
Mingkai Hue0653bf2011-01-27 12:52:46 +0800724 priv->regs = tsec_info->regs;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800725 priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
726
727 priv->phyaddr = tsec_info->phyaddr;
Bin Meng74314f12016-01-11 22:41:25 -0800728 priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800729 priv->flags = tsec_info->flags;
wdenka445ddf2004-06-09 00:34:46 +0000730
Ben Whitten34fd6c92015-12-30 13:05:58 +0000731 strcpy(dev->name, tsec_info->devname);
Andy Fleming422effd2011-04-08 02:10:54 -0500732 priv->interface = tsec_info->interface;
733 priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
Bin Menge86a6cd2016-01-11 22:41:22 -0800734 priv->dev = dev;
Mingkai Hue0653bf2011-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 Hue0653bf2011-01-27 12:52:46 +0800741 dev->mcast = tsec_mcast_addr;
David Updegraff7280da72007-06-11 10:41:07 -0500742
Bin Meng79cd33a2016-01-11 22:41:18 -0800743 /* Tell U-Boot to get the addr from the env */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800744 for (i = 0; i < 6; i++)
745 dev->enetaddr[i] = 0;
David Updegraff7280da72007-06-11 10:41:07 -0500746
Mingkai Hue0653bf2011-01-27 12:52:46 +0800747 eth_register(dev);
David Updegraff7280da72007-06-11 10:41:07 -0500748
Mingkai Hue0653bf2011-01-27 12:52:46 +0800749 /* 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);
David Updegraff7280da72007-06-11 10:41:07 -0500753
Mingkai Hue0653bf2011-01-27 12:52:46 +0800754 /* Try to initialize PHY here, and return */
Bin Menge86a6cd2016-01-11 22:41:22 -0800755 return init_phy(priv);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800756}
David Updegraff7280da72007-06-11 10:41:07 -0500757
Mingkai Hue0653bf2011-01-27 12:52:46 +0800758/*
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 Sixc29fcc72018-01-15 11:08:21 +0100766 int count = 0;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800767
768 for (i = 0; i < num; i++) {
Mario Sixc29fcc72018-01-15 11:08:21 +0100769 int ret = tsec_initialize(bis, &tsecs[i]);
770
Mingkai Hue0653bf2011-01-27 12:52:46 +0800771 if (ret > 0)
772 count += ret;
David Updegraff7280da72007-06-11 10:41:07 -0500773 }
Mingkai Hue0653bf2011-01-27 12:52:46 +0800774
775 return count;
David Updegraff7280da72007-06-11 10:41:07 -0500776}
Mingkai Hue0653bf2011-01-27 12:52:46 +0800777
778int tsec_standard_init(bd_t *bis)
779{
Andy Fleming422effd2011-04-08 02:10:54 -0500780 struct fsl_pq_mdio_info info;
781
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300782 info.regs = TSEC_GET_MDIO_REGS_BASE(1);
Andy Fleming422effd2011-04-08 02:10:54 -0500783 info.name = DEFAULT_MII_NAME;
784
785 fsl_pq_mdio_init(bis, &info);
786
Mingkai Hue0653bf2011-01-27 12:52:46 +0800787 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
788}
Bin Meng1048f612016-01-11 22:41:24 -0800789#else /* CONFIG_DM_ETH */
790int tsec_probe(struct udevice *dev)
791{
Bin Meng1048f612016-01-11 22:41:24 -0800792 struct eth_pdata *pdata = dev_get_platdata(dev);
Vladimir Olteana11c89d2019-07-19 00:29:55 +0300793 struct tsec_private *priv = dev_get_priv(dev);
Hou Zhiqiang53907d52020-05-03 22:48:43 +0800794 struct tsec_mii_mng __iomem *ext_phyregs_mii;
Mario Six00ba0552018-01-15 11:08:23 +0100795 struct ofnode_phandle_args phandle_args;
Vladimir Olteand6392202019-07-19 00:29:53 +0300796 u32 tbiaddr = CONFIG_SYS_TBIPA_VALUE;
Vladimir Olteana11c89d2019-07-19 00:29:55 +0300797 struct fsl_pq_mdio_info mdio_info;
Bin Meng1048f612016-01-11 22:41:24 -0800798 const char *phy_mode;
Vladimir Oltean3095e342019-07-19 00:29:54 +0300799 fdt_addr_t reg;
Vladimir Olteana11c89d2019-07-19 00:29:55 +0300800 ofnode parent;
Bin Meng1048f612016-01-11 22:41:24 -0800801 int ret;
802
Mario Six00ba0552018-01-15 11:08:23 +0100803 pdata->iobase = (phys_addr_t)dev_read_addr(dev);
Hou Zhiqiang7b69ce72020-05-03 22:48:42 +0800804 priv->regs = dev_remap_addr(dev);
Bin Meng1048f612016-01-11 22:41:24 -0800805
Mario Six00ba0552018-01-15 11:08:23 +0100806 if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
807 &phandle_args)) {
Vladimir Oltean8ec8eaa2019-07-19 00:29:56 +0300808 printf("phy-handle does not exist under tsec %s\n", dev->name);
Bin Meng1048f612016-01-11 22:41:24 -0800809 return -ENOENT;
Mario Six00ba0552018-01-15 11:08:23 +0100810 } else {
811 int reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
812
813 priv->phyaddr = reg;
Bin Meng1048f612016-01-11 22:41:24 -0800814 }
815
Mario Six00ba0552018-01-15 11:08:23 +0100816 parent = ofnode_get_parent(phandle_args.node);
Vladimir Oltean3095e342019-07-19 00:29:54 +0300817 if (!ofnode_valid(parent)) {
818 printf("No parent node for PHY?\n");
Bin Meng1048f612016-01-11 22:41:24 -0800819 return -ENOENT;
820 }
821
Vladimir Oltean3095e342019-07-19 00:29:54 +0300822 reg = ofnode_get_addr_index(parent, 0);
Hou Zhiqiang7b69ce72020-05-03 22:48:42 +0800823 if (reg == FDT_ADDR_T_NONE) {
824 printf("No 'reg' property of MII for external PHY\n");
825 return -ENOENT;
826 }
827
Hou Zhiqiang53907d52020-05-03 22:48:43 +0800828 ext_phyregs_mii = map_physmem(reg + TSEC_MDIO_REGS_OFFSET, 0,
829 MAP_NOCACHE);
Vladimir Oltean3095e342019-07-19 00:29:54 +0300830
Vladimir Olteand6392202019-07-19 00:29:53 +0300831 ret = dev_read_phandle_with_args(dev, "tbi-handle", NULL, 0, 0,
832 &phandle_args);
Hou Zhiqiang53907d52020-05-03 22:48:43 +0800833 if (ret == 0) {
Vladimir Olteand6392202019-07-19 00:29:53 +0300834 ofnode_read_u32(phandle_args.node, "reg", &tbiaddr);
835
Hou Zhiqiang53907d52020-05-03 22:48:43 +0800836 parent = ofnode_get_parent(phandle_args.node);
837 if (!ofnode_valid(parent)) {
838 printf("No parent node for TBI PHY?\n");
839 return -ENOENT;
840 }
841
842 reg = ofnode_get_addr_index(parent, 0);
843 if (reg == FDT_ADDR_T_NONE) {
844 printf("No 'reg' property of MII for TBI PHY\n");
845 return -ENOENT;
846 }
847
848 priv->phyregs_sgmii = map_physmem(reg + TSEC_MDIO_REGS_OFFSET,
849 0, MAP_NOCACHE);
850 }
851
Vladimir Olteand6392202019-07-19 00:29:53 +0300852 priv->tbiaddr = tbiaddr;
Bin Meng74314f12016-01-11 22:41:25 -0800853
Mario Six00ba0552018-01-15 11:08:23 +0100854 phy_mode = dev_read_prop(dev, "phy-connection-type", NULL);
Bin Meng1048f612016-01-11 22:41:24 -0800855 if (phy_mode)
856 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
857 if (pdata->phy_interface == -1) {
Vladimir Oltean8ec8eaa2019-07-19 00:29:56 +0300858 printf("Invalid PHY interface '%s'\n", phy_mode);
Bin Meng1048f612016-01-11 22:41:24 -0800859 return -EINVAL;
860 }
861 priv->interface = pdata->phy_interface;
862
863 /* Initialize flags */
864 priv->flags = TSEC_GIGABIT;
865 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
866 priv->flags |= TSEC_SGMII;
867
Hou Zhiqiang53907d52020-05-03 22:48:43 +0800868 mdio_info.regs = ext_phyregs_mii;
Bin Meng1048f612016-01-11 22:41:24 -0800869 mdio_info.name = (char *)dev->name;
870 ret = fsl_pq_mdio_init(NULL, &mdio_info);
871 if (ret)
872 return ret;
873
874 /* Reset the MAC */
875 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
876 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
877 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
878
879 priv->dev = dev;
880 priv->bus = miiphy_get_dev_by_name(dev->name);
881
882 /* Try to initialize PHY here, and return */
883 return !init_phy(priv);
884}
885
886int tsec_remove(struct udevice *dev)
887{
888 struct tsec_private *priv = dev->priv;
889
890 free(priv->phydev);
891 mdio_unregister(priv->bus);
892 mdio_free(priv->bus);
893
894 return 0;
895}
896
897static const struct eth_ops tsec_ops = {
898 .start = tsec_init,
899 .send = tsec_send,
900 .recv = tsec_recv,
901 .free_pkt = tsec_free_pkt,
902 .stop = tsec_halt,
Bin Meng1048f612016-01-11 22:41:24 -0800903 .mcast = tsec_mcast_addr,
Bin Meng1048f612016-01-11 22:41:24 -0800904};
905
906static const struct udevice_id tsec_ids[] = {
Vladimir Oltean7c043ea2019-07-19 00:29:58 +0300907 { .compatible = "fsl,etsec2" },
Bin Meng1048f612016-01-11 22:41:24 -0800908 { }
909};
910
911U_BOOT_DRIVER(eth_tsec) = {
912 .name = "tsec",
913 .id = UCLASS_ETH,
914 .of_match = tsec_ids,
915 .probe = tsec_probe,
916 .remove = tsec_remove,
917 .ops = &tsec_ops,
918 .priv_auto_alloc_size = sizeof(struct tsec_private),
919 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
920 .flags = DM_FLAG_ALLOC_PRIV_DMA,
921};
922#endif /* CONFIG_DM_ETH */