blob: 289229a42b2759b8f7c86e03480f8d7f5b24aa59 [file] [log] [blame]
wdenk9c53f402003-10-15 23:53:47 +00001/*
wdenka445ddf2004-06-09 00:34:46 +00002 * Freescale Three Speed Ethernet Controller driver
wdenk9c53f402003-10-15 23:53:47 +00003 *
4 * This software may be used and distributed according to the
5 * terms of the GNU Public License, Version 2, incorporated
6 * herein by reference.
7 *
Claudiu Manoilcd0c4122013-09-30 12:44:42 +03008 * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc.
wdenk9c53f402003-10-15 23:53:47 +00009 * (C) Copyright 2003, Motorola, Inc.
wdenk9c53f402003-10-15 23:53:47 +000010 * author Andy Fleming
11 *
12 */
13
14#include <config.h>
wdenk9c53f402003-10-15 23:53:47 +000015#include <common.h>
16#include <malloc.h>
17#include <net.h>
18#include <command.h>
Andy Flemingc067fc12008-08-31 16:33:25 -050019#include <tsec.h>
Andy Fleming422effd2011-04-08 02:10:54 -050020#include <fsl_mdio.h>
Kim Phillipsae4dd972009-08-24 14:32:26 -050021#include <asm/errno.h>
chenhui zhaoc8caa8a2011-10-03 08:38:50 -050022#include <asm/processor.h>
wdenk9c53f402003-10-15 23:53:47 +000023
Wolfgang Denk6405a152006-03-31 18:32:53 +020024DECLARE_GLOBAL_DATA_PTR;
25
Marian Balakowiczaab8c492005-10-28 22:30:33 +020026#define TX_BUF_CNT 2
wdenk9c53f402003-10-15 23:53:47 +000027
Claudiu Manoilc739af42013-09-30 12:44:44 +030028static uint rx_idx; /* index of the current RX buffer */
29static uint tx_idx; /* index of the current TX buffer */
wdenk9c53f402003-10-15 23:53:47 +000030
31typedef volatile struct rtxbd {
32 txbd8_t txbd[TX_BUF_CNT];
33 rxbd8_t rxbd[PKTBUFSRX];
Jon Loeligerb7ced082006-10-10 17:03:43 -050034} RTXBD;
wdenk9c53f402003-10-15 23:53:47 +000035
36#ifdef __GNUC__
37static RTXBD rtx __attribute__ ((aligned(8)));
38#else
39#error "rtx must be 64-bit aligned"
40#endif
41
Joe Hershberger5d289fe2012-05-21 09:46:36 +000042static int tsec_send(struct eth_device *dev, void *packet, int length);
chenhui zhaoc8caa8a2011-10-03 08:38:50 -050043
Andy Flemingfecff2b2008-08-31 16:33:26 -050044/* Default initializations for TSEC controllers. */
45
46static struct tsec_info_struct tsec_info[] = {
47#ifdef CONFIG_TSEC1
48 STD_TSEC_INFO(1), /* TSEC1 */
49#endif
50#ifdef CONFIG_TSEC2
51 STD_TSEC_INFO(2), /* TSEC2 */
52#endif
53#ifdef CONFIG_MPC85XX_FEC
54 {
Claudiu Manoilcd0c4122013-09-30 12:44:42 +030055 .regs = TSEC_GET_REGS(2, 0x2000),
Andy Flemingfecff2b2008-08-31 16:33:26 -050056 .devname = CONFIG_MPC85XX_FEC_NAME,
57 .phyaddr = FEC_PHY_ADDR,
Andy Fleming422effd2011-04-08 02:10:54 -050058 .flags = FEC_FLAGS,
59 .mii_devname = DEFAULT_MII_NAME
Andy Flemingfecff2b2008-08-31 16:33:26 -050060 }, /* FEC */
61#endif
62#ifdef CONFIG_TSEC3
63 STD_TSEC_INFO(3), /* TSEC3 */
64#endif
65#ifdef CONFIG_TSEC4
66 STD_TSEC_INFO(4), /* TSEC4 */
67#endif
68};
69
Andy Flemingac65e072008-08-31 16:33:27 -050070#define TBIANA_SETTINGS ( \
71 TBIANA_ASYMMETRIC_PAUSE \
72 | TBIANA_SYMMETRIC_PAUSE \
73 | TBIANA_FULL_DUPLEX \
74 )
75
Felix Radensky27f98e02010-06-28 01:57:39 +030076/* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
77#ifndef CONFIG_TSEC_TBICR_SETTINGS
Kumar Galac1457f92010-12-01 22:55:54 -060078#define CONFIG_TSEC_TBICR_SETTINGS ( \
Andy Flemingac65e072008-08-31 16:33:27 -050079 TBICR_PHY_RESET \
Kumar Galac1457f92010-12-01 22:55:54 -060080 | TBICR_ANEG_ENABLE \
Andy Flemingac65e072008-08-31 16:33:27 -050081 | TBICR_FULL_DUPLEX \
82 | TBICR_SPEED1_SET \
83 )
Felix Radensky27f98e02010-06-28 01:57:39 +030084#endif /* CONFIG_TSEC_TBICR_SETTINGS */
Peter Tyser583c1f42009-11-03 17:52:07 -060085
Andy Flemingac65e072008-08-31 16:33:27 -050086/* Configure the TBI for SGMII operation */
87static void tsec_configure_serdes(struct tsec_private *priv)
88{
Peter Tyser4ef03c02009-11-09 13:09:46 -060089 /* Access TBI PHY registers at given TSEC register offset as opposed
90 * to the register offset used for external PHY accesses */
Andy Fleming422effd2011-04-08 02:10:54 -050091 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
92 0, TBI_ANA, TBIANA_SETTINGS);
93 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
94 0, TBI_TBICON, TBICON_CLK_SELECT);
95 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
96 0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
David Updegraff0451b012007-04-20 14:34:48 -050097}
98
Mingkai Hue0653bf2011-01-27 12:52:46 +080099#ifdef CONFIG_MCAST_TFTP
100
101/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
102
103/* Set the appropriate hash bit for the given addr */
104
105/* The algorithm works like so:
106 * 1) Take the Destination Address (ie the multicast address), and
107 * do a CRC on it (little endian), and reverse the bits of the
108 * result.
109 * 2) Use the 8 most significant bits as a hash into a 256-entry
110 * table. The table is controlled through 8 32-bit registers:
Claudiu Manoil461511b2013-09-30 12:44:40 +0300111 * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is entry
112 * 255. This means that the 3 most significant bits in the
Mingkai Hue0653bf2011-01-27 12:52:46 +0800113 * hash index which gaddr register to use, and the 5 other bits
114 * indicate which bit (assuming an IBM numbering scheme, which
Claudiu Manoil461511b2013-09-30 12:44:40 +0300115 * for PowerPC (tm) is usually the case) in the register holds
Mingkai Hue0653bf2011-01-27 12:52:46 +0800116 * the entry. */
117static int
Claudiu Manoil5c473572013-09-30 12:44:39 +0300118tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800119{
Claudiu Manoil766c8942013-09-30 12:44:41 +0300120 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoil461511b2013-09-30 12:44:40 +0300121 struct tsec __iomem *regs = priv->regs;
122 u32 result, value;
123 u8 whichbit, whichreg;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800124
Claudiu Manoil461511b2013-09-30 12:44:40 +0300125 result = ether_crc(MAC_ADDR_LEN, mcast_mac);
126 whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */
127 whichreg = result >> 29; /* the 3 MSB = which reg to set it in */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800128
Claudiu Manoil461511b2013-09-30 12:44:40 +0300129 value = 1 << (31-whichbit);
130
131 if (set)
132 setbits_be32(&regs->hash.gaddr0 + whichreg, value);
133 else
134 clrbits_be32(&regs->hash.gaddr0 + whichreg, value);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800135
Mingkai Hue0653bf2011-01-27 12:52:46 +0800136 return 0;
137}
138#endif /* Multicast TFTP ? */
139
140/* Initialized required registers to appropriate values, zeroing
141 * those we don't care about (unless zero is bad, in which case,
142 * choose a more appropriate value)
143 */
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300144static void init_registers(struct tsec __iomem *regs)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800145{
146 /* Clear IEVENT */
147 out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
148
149 out_be32(&regs->imask, IMASK_INIT_CLEAR);
150
151 out_be32(&regs->hash.iaddr0, 0);
152 out_be32(&regs->hash.iaddr1, 0);
153 out_be32(&regs->hash.iaddr2, 0);
154 out_be32(&regs->hash.iaddr3, 0);
155 out_be32(&regs->hash.iaddr4, 0);
156 out_be32(&regs->hash.iaddr5, 0);
157 out_be32(&regs->hash.iaddr6, 0);
158 out_be32(&regs->hash.iaddr7, 0);
159
160 out_be32(&regs->hash.gaddr0, 0);
161 out_be32(&regs->hash.gaddr1, 0);
162 out_be32(&regs->hash.gaddr2, 0);
163 out_be32(&regs->hash.gaddr3, 0);
164 out_be32(&regs->hash.gaddr4, 0);
165 out_be32(&regs->hash.gaddr5, 0);
166 out_be32(&regs->hash.gaddr6, 0);
167 out_be32(&regs->hash.gaddr7, 0);
168
169 out_be32(&regs->rctrl, 0x00000000);
170
171 /* Init RMON mib registers */
172 memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
173
174 out_be32(&regs->rmon.cam1, 0xffffffff);
175 out_be32(&regs->rmon.cam2, 0xffffffff);
176
177 out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
178
179 out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
180
181 out_be32(&regs->attr, ATTR_INIT_SETTINGS);
182 out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
183
184}
185
186/* Configure maccfg2 based on negotiated speed and duplex
187 * reported by PHY handling code
188 */
Andy Fleming422effd2011-04-08 02:10:54 -0500189static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800190{
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300191 struct tsec __iomem *regs = priv->regs;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800192 u32 ecntrl, maccfg2;
193
Andy Fleming422effd2011-04-08 02:10:54 -0500194 if (!phydev->link) {
195 printf("%s: No link.\n", phydev->dev->name);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800196 return;
197 }
198
199 /* clear all bits relative with interface mode */
200 ecntrl = in_be32(&regs->ecntrl);
201 ecntrl &= ~ECNTRL_R100;
202
203 maccfg2 = in_be32(&regs->maccfg2);
204 maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
205
Andy Fleming422effd2011-04-08 02:10:54 -0500206 if (phydev->duplex)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800207 maccfg2 |= MACCFG2_FULL_DUPLEX;
208
Andy Fleming422effd2011-04-08 02:10:54 -0500209 switch (phydev->speed) {
Mingkai Hue0653bf2011-01-27 12:52:46 +0800210 case 1000:
211 maccfg2 |= MACCFG2_GMII;
212 break;
213 case 100:
214 case 10:
215 maccfg2 |= MACCFG2_MII;
216
217 /* Set R100 bit in all modes although
218 * it is only used in RGMII mode
219 */
Andy Fleming422effd2011-04-08 02:10:54 -0500220 if (phydev->speed == 100)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800221 ecntrl |= ECNTRL_R100;
222 break;
223 default:
Andy Fleming422effd2011-04-08 02:10:54 -0500224 printf("%s: Speed was bad\n", phydev->dev->name);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800225 break;
226 }
227
228 out_be32(&regs->ecntrl, ecntrl);
229 out_be32(&regs->maccfg2, maccfg2);
wdenkf41ff3b2005-04-04 23:43:44 +0000230
Andy Fleming422effd2011-04-08 02:10:54 -0500231 printf("Speed: %d, %s duplex%s\n", phydev->speed,
232 (phydev->duplex) ? "full" : "half",
233 (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
Mingkai Hue0653bf2011-01-27 12:52:46 +0800234}
wdenkbfad55d2005-03-14 23:56:42 +0000235
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500236#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
237/*
238 * When MACCFG1[Rx_EN] is enabled during system boot as part
239 * of the eTSEC port initialization sequence,
240 * the eTSEC Rx logic may not be properly initialized.
241 */
242void redundant_init(struct eth_device *dev)
243{
244 struct tsec_private *priv = dev->priv;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300245 struct tsec __iomem *regs = priv->regs;
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500246 uint t, count = 0;
247 int fail = 1;
248 static const u8 pkt[] = {
249 0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25,
250 0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00,
251 0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01,
252 0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1,
253 0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00,
254 0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
255 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
256 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
257 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
258 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
259 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
260 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
261 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
262 0x71, 0x72};
263
264 /* Enable promiscuous mode */
265 setbits_be32(&regs->rctrl, 0x8);
266 /* Enable loopback mode */
267 setbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
268 /* Enable transmit and receive */
269 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
270
271 /* Tell the DMA it is clear to go */
272 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
273 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
274 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
275 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
276
277 do {
278 tsec_send(dev, (void *)pkt, sizeof(pkt));
279
280 /* Wait for buffer to be received */
Claudiu Manoilc739af42013-09-30 12:44:44 +0300281 for (t = 0; rtx.rxbd[rx_idx].status & RXBD_EMPTY; t++) {
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500282 if (t >= 10 * TOUT_LOOP) {
283 printf("%s: tsec: rx error\n", dev->name);
284 break;
285 }
286 }
287
Claudiu Manoilc739af42013-09-30 12:44:44 +0300288 if (!memcmp(pkt, (void *)NetRxPackets[rx_idx], sizeof(pkt)))
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500289 fail = 0;
290
Claudiu Manoilc739af42013-09-30 12:44:44 +0300291 rtx.rxbd[rx_idx].length = 0;
292 rtx.rxbd[rx_idx].status =
293 RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
294 rx_idx = (rx_idx + 1) % PKTBUFSRX;
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500295
296 if (in_be32(&regs->ievent) & IEVENT_BSY) {
297 out_be32(&regs->ievent, IEVENT_BSY);
298 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
299 }
300 if (fail) {
301 printf("loopback recv packet error!\n");
302 clrbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
303 udelay(1000);
304 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
305 }
306 } while ((count++ < 4) && (fail == 1));
307
308 if (fail)
309 panic("eTSEC init fail!\n");
310 /* Disable promiscuous mode */
311 clrbits_be32(&regs->rctrl, 0x8);
312 /* Disable loopback mode */
313 clrbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
314}
315#endif
316
Mingkai Hue0653bf2011-01-27 12:52:46 +0800317/* Set up the buffers and their descriptors, and bring up the
318 * interface
Jon Loeligerb7ced082006-10-10 17:03:43 -0500319 */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800320static void startup_tsec(struct eth_device *dev)
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100321{
Mingkai Hue0653bf2011-01-27 12:52:46 +0800322 int i;
323 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300324 struct tsec __iomem *regs = priv->regs;
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100325
Andy Fleming422effd2011-04-08 02:10:54 -0500326 /* reset the indices to zero */
Claudiu Manoilc739af42013-09-30 12:44:44 +0300327 rx_idx = 0;
328 tx_idx = 0;
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500329#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
330 uint svr;
331#endif
Andy Fleming422effd2011-04-08 02:10:54 -0500332
Mingkai Hue0653bf2011-01-27 12:52:46 +0800333 /* Point to the buffer descriptors */
Claudiu Manoilc739af42013-09-30 12:44:44 +0300334 out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[tx_idx]));
335 out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rx_idx]));
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100336
Mingkai Hue0653bf2011-01-27 12:52:46 +0800337 /* Initialize the Rx Buffer descriptors */
338 for (i = 0; i < PKTBUFSRX; i++) {
339 rtx.rxbd[i].status = RXBD_EMPTY;
340 rtx.rxbd[i].length = 0;
Claudiu Manoilc739af42013-09-30 12:44:44 +0300341 rtx.rxbd[i].bufptr = (uint) NetRxPackets[i];
Mingkai Hue0653bf2011-01-27 12:52:46 +0800342 }
343 rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100344
Mingkai Hue0653bf2011-01-27 12:52:46 +0800345 /* Initialize the TX Buffer Descriptors */
346 for (i = 0; i < TX_BUF_CNT; i++) {
347 rtx.txbd[i].status = 0;
348 rtx.txbd[i].length = 0;
Claudiu Manoilc739af42013-09-30 12:44:44 +0300349 rtx.txbd[i].bufptr = 0;
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100350 }
Mingkai Hue0653bf2011-01-27 12:52:46 +0800351 rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100352
chenhui zhaoc8caa8a2011-10-03 08:38:50 -0500353#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
354 svr = get_svr();
355 if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
356 redundant_init(dev);
357#endif
Mingkai Hue0653bf2011-01-27 12:52:46 +0800358 /* Enable Transmit and Receive */
359 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
360
361 /* Tell the DMA it is clear to go */
362 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
363 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
364 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
365 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100366}
367
Mingkai Hue0653bf2011-01-27 12:52:46 +0800368/* This returns the status bits of the device. The return value
369 * is never checked, and this is what the 8260 driver did, so we
370 * do the same. Presumably, this would be zero if there were no
371 * errors
372 */
Joe Hershberger5d289fe2012-05-21 09:46:36 +0000373static int tsec_send(struct eth_device *dev, void *packet, int length)
Mingkai Hue0653bf2011-01-27 12:52:46 +0800374{
375 int i;
376 int result = 0;
377 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300378 struct tsec __iomem *regs = priv->regs;
Wolfgang Denkf0c4e462006-03-12 22:50:55 +0100379
Mingkai Hue0653bf2011-01-27 12:52:46 +0800380 /* Find an empty buffer descriptor */
Claudiu Manoilc739af42013-09-30 12:44:44 +0300381 for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) {
Mingkai Hue0653bf2011-01-27 12:52:46 +0800382 if (i >= TOUT_LOOP) {
383 debug("%s: tsec: tx buffers full\n", dev->name);
384 return result;
385 }
386 }
Dave Liua304a282008-01-11 18:45:28 +0800387
Claudiu Manoilc739af42013-09-30 12:44:44 +0300388 rtx.txbd[tx_idx].bufptr = (uint) packet;
389 rtx.txbd[tx_idx].length = length;
390 rtx.txbd[tx_idx].status |=
Mingkai Hue0653bf2011-01-27 12:52:46 +0800391 (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
Li Yang25e38bd2011-01-27 19:02:50 +0800392
Mingkai Hue0653bf2011-01-27 12:52:46 +0800393 /* Tell the DMA to go */
394 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
wdenka445ddf2004-06-09 00:34:46 +0000395
Mingkai Hue0653bf2011-01-27 12:52:46 +0800396 /* Wait for buffer to be transmitted */
Claudiu Manoilc739af42013-09-30 12:44:44 +0300397 for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) {
Mingkai Hue0653bf2011-01-27 12:52:46 +0800398 if (i >= TOUT_LOOP) {
399 debug("%s: tsec: tx error\n", dev->name);
400 return result;
401 }
402 }
403
Claudiu Manoilc739af42013-09-30 12:44:44 +0300404 tx_idx = (tx_idx + 1) % TX_BUF_CNT;
405 result = rtx.txbd[tx_idx].status & TXBD_STATS;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800406
407 return result;
408}
409
410static int tsec_recv(struct eth_device *dev)
wdenka445ddf2004-06-09 00:34:46 +0000411{
Mingkai Hue0653bf2011-01-27 12:52:46 +0800412 int length;
wdenka445ddf2004-06-09 00:34:46 +0000413 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300414 struct tsec __iomem *regs = priv->regs;
wdenka445ddf2004-06-09 00:34:46 +0000415
Claudiu Manoilc739af42013-09-30 12:44:44 +0300416 while (!(rtx.rxbd[rx_idx].status & RXBD_EMPTY)) {
wdenka445ddf2004-06-09 00:34:46 +0000417
Claudiu Manoilc739af42013-09-30 12:44:44 +0300418 length = rtx.rxbd[rx_idx].length;
wdenka445ddf2004-06-09 00:34:46 +0000419
Mingkai Hue0653bf2011-01-27 12:52:46 +0800420 /* Send the packet up if there were no errors */
Claudiu Manoilc739af42013-09-30 12:44:44 +0300421 if (!(rtx.rxbd[rx_idx].status & RXBD_STATS)) {
422 NetReceive(NetRxPackets[rx_idx], length - 4);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800423 } else {
424 printf("Got error %x\n",
Claudiu Manoilc739af42013-09-30 12:44:44 +0300425 (rtx.rxbd[rx_idx].status & RXBD_STATS));
Andy Flemingb2d14f42007-05-09 00:54:20 -0500426 }
Mingkai Hue0653bf2011-01-27 12:52:46 +0800427
Claudiu Manoilc739af42013-09-30 12:44:44 +0300428 rtx.rxbd[rx_idx].length = 0;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800429
430 /* Set the wrap bit if this is the last element in the list */
Claudiu Manoilc739af42013-09-30 12:44:44 +0300431 rtx.rxbd[rx_idx].status =
432 RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800433
Claudiu Manoilc739af42013-09-30 12:44:44 +0300434 rx_idx = (rx_idx + 1) % PKTBUFSRX;
wdenka445ddf2004-06-09 00:34:46 +0000435 }
436
Mingkai Hue0653bf2011-01-27 12:52:46 +0800437 if (in_be32(&regs->ievent) & IEVENT_BSY) {
438 out_be32(&regs->ievent, IEVENT_BSY);
439 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
wdenka445ddf2004-06-09 00:34:46 +0000440 }
441
Mingkai Hue0653bf2011-01-27 12:52:46 +0800442 return -1;
443
wdenka445ddf2004-06-09 00:34:46 +0000444}
445
Mingkai Hue0653bf2011-01-27 12:52:46 +0800446/* Stop the interface */
447static void tsec_halt(struct eth_device *dev)
448{
449 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300450 struct tsec __iomem *regs = priv->regs;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800451
452 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
453 setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
454
455 while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
456 != (IEVENT_GRSC | IEVENT_GTSC))
457 ;
458
459 clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
460
461 /* Shut down the PHY, as needed */
Andy Fleming422effd2011-04-08 02:10:54 -0500462 phy_shutdown(priv->phydev);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800463}
464
465/* Initializes data structures and registers for the controller,
466 * and brings the interface up. Returns the link status, meaning
467 * that it returns success if the link is up, failure otherwise.
468 * This allows u-boot to find the first active controller.
Jon Loeligerb7ced082006-10-10 17:03:43 -0500469 */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800470static int tsec_init(struct eth_device *dev, bd_t * bd)
wdenka445ddf2004-06-09 00:34:46 +0000471{
Mingkai Hue0653bf2011-01-27 12:52:46 +0800472 uint tempval;
473 char tmpbuf[MAC_ADDR_LEN];
wdenka445ddf2004-06-09 00:34:46 +0000474 int i;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800475 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300476 struct tsec __iomem *regs = priv->regs;
Timur Tabi42387462012-07-09 08:52:43 +0000477 int ret;
wdenka445ddf2004-06-09 00:34:46 +0000478
Mingkai Hue0653bf2011-01-27 12:52:46 +0800479 /* Make sure the controller is stopped */
480 tsec_halt(dev);
wdenka445ddf2004-06-09 00:34:46 +0000481
Mingkai Hue0653bf2011-01-27 12:52:46 +0800482 /* Init MACCFG2. Defaults to GMII */
483 out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
wdenka445ddf2004-06-09 00:34:46 +0000484
Mingkai Hue0653bf2011-01-27 12:52:46 +0800485 /* Init ECNTRL */
486 out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
wdenka445ddf2004-06-09 00:34:46 +0000487
Mingkai Hue0653bf2011-01-27 12:52:46 +0800488 /* Copy the station address into the address registers.
489 * Backwards, because little endian MACS are dumb */
490 for (i = 0; i < MAC_ADDR_LEN; i++)
491 tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
wdenka445ddf2004-06-09 00:34:46 +0000492
Mingkai Hue0653bf2011-01-27 12:52:46 +0800493 tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
494 tmpbuf[3];
wdenka445ddf2004-06-09 00:34:46 +0000495
Mingkai Hue0653bf2011-01-27 12:52:46 +0800496 out_be32(&regs->macstnaddr1, tempval);
wdenka445ddf2004-06-09 00:34:46 +0000497
Mingkai Hue0653bf2011-01-27 12:52:46 +0800498 tempval = *((uint *) (tmpbuf + 4));
wdenka445ddf2004-06-09 00:34:46 +0000499
Mingkai Hue0653bf2011-01-27 12:52:46 +0800500 out_be32(&regs->macstnaddr2, tempval);
wdenka445ddf2004-06-09 00:34:46 +0000501
Mingkai Hue0653bf2011-01-27 12:52:46 +0800502 /* Clear out (for the most part) the other registers */
503 init_registers(regs);
504
505 /* Ready the device for tx/rx */
506 startup_tsec(dev);
507
Andy Fleming422effd2011-04-08 02:10:54 -0500508 /* Start up the PHY */
Timur Tabi42387462012-07-09 08:52:43 +0000509 ret = phy_startup(priv->phydev);
510 if (ret) {
511 printf("Could not initialize PHY %s\n",
512 priv->phydev->dev->name);
513 return ret;
514 }
Andy Fleming422effd2011-04-08 02:10:54 -0500515
516 adjust_link(priv, priv->phydev);
517
Mingkai Hue0653bf2011-01-27 12:52:46 +0800518 /* If there's no link, fail */
Andy Fleming422effd2011-04-08 02:10:54 -0500519 return priv->phydev->link ? 0 : -1;
520}
521
522static phy_interface_t tsec_get_interface(struct tsec_private *priv)
523{
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300524 struct tsec __iomem *regs = priv->regs;
Andy Fleming422effd2011-04-08 02:10:54 -0500525 u32 ecntrl;
526
527 ecntrl = in_be32(&regs->ecntrl);
528
529 if (ecntrl & ECNTRL_SGMII_MODE)
530 return PHY_INTERFACE_MODE_SGMII;
531
532 if (ecntrl & ECNTRL_TBI_MODE) {
533 if (ecntrl & ECNTRL_REDUCED_MODE)
534 return PHY_INTERFACE_MODE_RTBI;
535 else
536 return PHY_INTERFACE_MODE_TBI;
537 }
538
539 if (ecntrl & ECNTRL_REDUCED_MODE) {
540 if (ecntrl & ECNTRL_REDUCED_MII_MODE)
541 return PHY_INTERFACE_MODE_RMII;
542 else {
543 phy_interface_t interface = priv->interface;
544
545 /*
546 * This isn't autodetected, so it must
547 * be set by the platform code.
548 */
549 if ((interface == PHY_INTERFACE_MODE_RGMII_ID) ||
550 (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
551 (interface == PHY_INTERFACE_MODE_RGMII_RXID))
552 return interface;
553
554 return PHY_INTERFACE_MODE_RGMII;
555 }
556 }
557
558 if (priv->flags & TSEC_GIGABIT)
559 return PHY_INTERFACE_MODE_GMII;
560
561 return PHY_INTERFACE_MODE_MII;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800562}
563
Andy Fleming422effd2011-04-08 02:10:54 -0500564
Mingkai Hue0653bf2011-01-27 12:52:46 +0800565/* Discover which PHY is attached to the device, and configure it
566 * properly. If the PHY is not recognized, then return 0
567 * (failure). Otherwise, return 1
wdenk78924a72004-04-18 21:45:42 +0000568 */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800569static int init_phy(struct eth_device *dev)
wdenk78924a72004-04-18 21:45:42 +0000570{
Mingkai Hue0653bf2011-01-27 12:52:46 +0800571 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Andy Fleming422effd2011-04-08 02:10:54 -0500572 struct phy_device *phydev;
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300573 struct tsec __iomem *regs = priv->regs;
Andy Fleming422effd2011-04-08 02:10:54 -0500574 u32 supported = (SUPPORTED_10baseT_Half |
575 SUPPORTED_10baseT_Full |
576 SUPPORTED_100baseT_Half |
577 SUPPORTED_100baseT_Full);
578
579 if (priv->flags & TSEC_GIGABIT)
580 supported |= SUPPORTED_1000baseT_Full;
wdenk78924a72004-04-18 21:45:42 +0000581
Mingkai Hue0653bf2011-01-27 12:52:46 +0800582 /* Assign a Physical address to the TBI */
583 out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
584
Andy Fleming422effd2011-04-08 02:10:54 -0500585 priv->interface = tsec_get_interface(priv);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800586
Andy Fleming422effd2011-04-08 02:10:54 -0500587 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
588 tsec_configure_serdes(priv);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800589
Andy Fleming422effd2011-04-08 02:10:54 -0500590 phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800591
Andy Fleming422effd2011-04-08 02:10:54 -0500592 phydev->supported &= supported;
593 phydev->advertising = phydev->supported;
wdenka445ddf2004-06-09 00:34:46 +0000594
Andy Fleming422effd2011-04-08 02:10:54 -0500595 priv->phydev = phydev;
wdenk78924a72004-04-18 21:45:42 +0000596
Andy Fleming422effd2011-04-08 02:10:54 -0500597 phy_config(phydev);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800598
599 return 1;
wdenk78924a72004-04-18 21:45:42 +0000600}
601
Mingkai Hue0653bf2011-01-27 12:52:46 +0800602/* Initialize device structure. Returns success if PHY
603 * initialization succeeded (i.e. if it recognizes the PHY)
wdenk78924a72004-04-18 21:45:42 +0000604 */
Mingkai Hue0653bf2011-01-27 12:52:46 +0800605static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
wdenk78924a72004-04-18 21:45:42 +0000606{
Mingkai Hue0653bf2011-01-27 12:52:46 +0800607 struct eth_device *dev;
608 int i;
609 struct tsec_private *priv;
wdenka445ddf2004-06-09 00:34:46 +0000610
Mingkai Hue0653bf2011-01-27 12:52:46 +0800611 dev = (struct eth_device *)malloc(sizeof *dev);
wdenk78924a72004-04-18 21:45:42 +0000612
Mingkai Hue0653bf2011-01-27 12:52:46 +0800613 if (NULL == dev)
614 return 0;
wdenk78924a72004-04-18 21:45:42 +0000615
Mingkai Hue0653bf2011-01-27 12:52:46 +0800616 memset(dev, 0, sizeof *dev);
wdenka445ddf2004-06-09 00:34:46 +0000617
Mingkai Hue0653bf2011-01-27 12:52:46 +0800618 priv = (struct tsec_private *)malloc(sizeof(*priv));
619
620 if (NULL == priv)
621 return 0;
622
Mingkai Hue0653bf2011-01-27 12:52:46 +0800623 priv->regs = tsec_info->regs;
Mingkai Hue0653bf2011-01-27 12:52:46 +0800624 priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
625
626 priv->phyaddr = tsec_info->phyaddr;
627 priv->flags = tsec_info->flags;
wdenka445ddf2004-06-09 00:34:46 +0000628
Mingkai Hue0653bf2011-01-27 12:52:46 +0800629 sprintf(dev->name, tsec_info->devname);
Andy Fleming422effd2011-04-08 02:10:54 -0500630 priv->interface = tsec_info->interface;
631 priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
Mingkai Hue0653bf2011-01-27 12:52:46 +0800632 dev->iobase = 0;
633 dev->priv = priv;
634 dev->init = tsec_init;
635 dev->halt = tsec_halt;
636 dev->send = tsec_send;
637 dev->recv = tsec_recv;
David Updegraff7280da72007-06-11 10:41:07 -0500638#ifdef CONFIG_MCAST_TFTP
Mingkai Hue0653bf2011-01-27 12:52:46 +0800639 dev->mcast = tsec_mcast_addr;
640#endif
David Updegraff7280da72007-06-11 10:41:07 -0500641
Mingkai Hue0653bf2011-01-27 12:52:46 +0800642 /* Tell u-boot to get the addr from the env */
643 for (i = 0; i < 6; i++)
644 dev->enetaddr[i] = 0;
David Updegraff7280da72007-06-11 10:41:07 -0500645
Mingkai Hue0653bf2011-01-27 12:52:46 +0800646 eth_register(dev);
David Updegraff7280da72007-06-11 10:41:07 -0500647
Mingkai Hue0653bf2011-01-27 12:52:46 +0800648 /* Reset the MAC */
649 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
650 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
651 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
David Updegraff7280da72007-06-11 10:41:07 -0500652
Mingkai Hue0653bf2011-01-27 12:52:46 +0800653 /* Try to initialize PHY here, and return */
654 return init_phy(dev);
655}
David Updegraff7280da72007-06-11 10:41:07 -0500656
Mingkai Hue0653bf2011-01-27 12:52:46 +0800657/*
658 * Initialize all the TSEC devices
659 *
660 * Returns the number of TSEC devices that were initialized
661 */
662int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
663{
664 int i;
665 int ret, count = 0;
666
667 for (i = 0; i < num; i++) {
668 ret = tsec_initialize(bis, &tsecs[i]);
669 if (ret > 0)
670 count += ret;
David Updegraff7280da72007-06-11 10:41:07 -0500671 }
Mingkai Hue0653bf2011-01-27 12:52:46 +0800672
673 return count;
David Updegraff7280da72007-06-11 10:41:07 -0500674}
Mingkai Hue0653bf2011-01-27 12:52:46 +0800675
676int tsec_standard_init(bd_t *bis)
677{
Andy Fleming422effd2011-04-08 02:10:54 -0500678 struct fsl_pq_mdio_info info;
679
Claudiu Manoilcd0c4122013-09-30 12:44:42 +0300680 info.regs = TSEC_GET_MDIO_REGS_BASE(1);
Andy Fleming422effd2011-04-08 02:10:54 -0500681 info.name = DEFAULT_MII_NAME;
682
683 fsl_pq_mdio_init(bis, &info);
684
Mingkai Hue0653bf2011-01-27 12:52:46 +0800685 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
686}