blob: 943c4b3711bb7d99303431977ac8410ccbb2bac7 [file] [log] [blame]
wdenk42d1f032003-10-15 23:53:47 +00001/*
wdenk97d80fc2004-06-09 00:34:46 +00002 * Freescale Three Speed Ethernet Controller driver
wdenk42d1f032003-10-15 23:53:47 +00003 *
Claudiu Manoilaec84bf2013-09-30 12:44:42 +03004 * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc.
wdenk42d1f032003-10-15 23:53:47 +00005 * (C) Copyright 2003, Motorola, Inc.
wdenk42d1f032003-10-15 23:53:47 +00006 * author Andy Fleming
7 *
Bin Meng9872b732016-01-11 22:41:18 -08008 * SPDX-License-Identifier: GPL-2.0+
wdenk42d1f032003-10-15 23:53:47 +00009 */
10
11#include <config.h>
wdenk42d1f032003-10-15 23:53:47 +000012#include <common.h>
13#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>
Kim Phillips0d071cd2009-08-24 14:32:26 -050018#include <asm/errno.h>
chenhui zhaoaada81d2011-10-03 08:38:50 -050019#include <asm/processor.h>
Alison Wang52d00a82014-09-05 13:52:38 +080020#include <asm/io.h>
wdenk42d1f032003-10-15 23:53:47 +000021
Wolfgang Denkd87080b2006-03-31 18:32:53 +020022DECLARE_GLOBAL_DATA_PTR;
23
Marian Balakowicz63ff0042005-10-28 22:30:33 +020024#define TX_BUF_CNT 2
wdenk42d1f032003-10-15 23:53:47 +000025
wdenk42d1f032003-10-15 23:53:47 +000026#ifdef __GNUC__
Claudiu Manoil9c9141f2013-10-04 19:13:53 +030027static struct txbd8 __iomem txbd[TX_BUF_CNT] __aligned(8);
28static struct rxbd8 __iomem rxbd[PKTBUFSRX] __aligned(8);
29
wdenk42d1f032003-10-15 23:53:47 +000030#else
31#error "rtx must be 64-bit aligned"
32#endif
33
Joe Hershbergerc8a60b52012-05-21 09:46:36 +000034static int tsec_send(struct eth_device *dev, void *packet, int length);
chenhui zhaoaada81d2011-10-03 08:38:50 -050035
Andy Fleming75b9d4a2008-08-31 16:33:26 -050036/* Default initializations for TSEC controllers. */
37
38static struct tsec_info_struct tsec_info[] = {
39#ifdef CONFIG_TSEC1
40 STD_TSEC_INFO(1), /* TSEC1 */
41#endif
42#ifdef CONFIG_TSEC2
43 STD_TSEC_INFO(2), /* TSEC2 */
44#endif
45#ifdef CONFIG_MPC85XX_FEC
46 {
Claudiu Manoilaec84bf2013-09-30 12:44:42 +030047 .regs = TSEC_GET_REGS(2, 0x2000),
Andy Fleming75b9d4a2008-08-31 16:33:26 -050048 .devname = CONFIG_MPC85XX_FEC_NAME,
49 .phyaddr = FEC_PHY_ADDR,
Andy Fleming063c1262011-04-08 02:10:54 -050050 .flags = FEC_FLAGS,
51 .mii_devname = DEFAULT_MII_NAME
Andy Fleming75b9d4a2008-08-31 16:33:26 -050052 }, /* FEC */
53#endif
54#ifdef CONFIG_TSEC3
55 STD_TSEC_INFO(3), /* TSEC3 */
56#endif
57#ifdef CONFIG_TSEC4
58 STD_TSEC_INFO(4), /* TSEC4 */
59#endif
60};
61
Andy Fleming2abe3612008-08-31 16:33:27 -050062#define TBIANA_SETTINGS ( \
63 TBIANA_ASYMMETRIC_PAUSE \
64 | TBIANA_SYMMETRIC_PAUSE \
65 | TBIANA_FULL_DUPLEX \
66 )
67
Felix Radensky90b5bf22010-06-28 01:57:39 +030068/* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
69#ifndef CONFIG_TSEC_TBICR_SETTINGS
Kumar Gala72c96a62010-12-01 22:55:54 -060070#define CONFIG_TSEC_TBICR_SETTINGS ( \
Andy Fleming2abe3612008-08-31 16:33:27 -050071 TBICR_PHY_RESET \
Kumar Gala72c96a62010-12-01 22:55:54 -060072 | TBICR_ANEG_ENABLE \
Andy Fleming2abe3612008-08-31 16:33:27 -050073 | TBICR_FULL_DUPLEX \
74 | TBICR_SPEED1_SET \
75 )
Felix Radensky90b5bf22010-06-28 01:57:39 +030076#endif /* CONFIG_TSEC_TBICR_SETTINGS */
Peter Tyser46e91672009-11-03 17:52:07 -060077
Andy Fleming2abe3612008-08-31 16:33:27 -050078/* Configure the TBI for SGMII operation */
79static void tsec_configure_serdes(struct tsec_private *priv)
80{
Bin Meng9872b732016-01-11 22:41:18 -080081 /*
82 * Access TBI PHY registers at given TSEC register offset as opposed
83 * to the register offset used for external PHY accesses
84 */
Andy Fleming063c1262011-04-08 02:10:54 -050085 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
86 0, TBI_ANA, TBIANA_SETTINGS);
87 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
88 0, TBI_TBICON, TBICON_CLK_SELECT);
89 tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
90 0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
Andy Fleming2abe3612008-08-31 16:33:27 -050091}
michael.firth@bt.com55fe7c52008-01-16 11:40:51 +000092
David Updegraff53a5c422007-06-11 10:41:07 -050093#ifdef CONFIG_MCAST_TFTP
94
95/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
96
97/* Set the appropriate hash bit for the given addr */
98
Bin Meng9872b732016-01-11 22:41:18 -080099/*
100 * The algorithm works like so:
David Updegraff53a5c422007-06-11 10:41:07 -0500101 * 1) Take the Destination Address (ie the multicast address), and
102 * do a CRC on it (little endian), and reverse the bits of the
103 * result.
104 * 2) Use the 8 most significant bits as a hash into a 256-entry
105 * table. The table is controlled through 8 32-bit registers:
Claudiu Manoil876d4512013-09-30 12:44:40 +0300106 * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is entry
107 * 255. This means that the 3 most significant bits in the
David Updegraff53a5c422007-06-11 10:41:07 -0500108 * hash index which gaddr register to use, and the 5 other bits
109 * indicate which bit (assuming an IBM numbering scheme, which
Claudiu Manoil876d4512013-09-30 12:44:40 +0300110 * for PowerPC (tm) is usually the case) in the register holds
Bin Meng9872b732016-01-11 22:41:18 -0800111 * the entry.
112 */
113static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set)
David Updegraff53a5c422007-06-11 10:41:07 -0500114{
Claudiu Manoilb2002042013-09-30 12:44:41 +0300115 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoil876d4512013-09-30 12:44:40 +0300116 struct tsec __iomem *regs = priv->regs;
117 u32 result, value;
118 u8 whichbit, whichreg;
David Updegraff53a5c422007-06-11 10:41:07 -0500119
Claudiu Manoil876d4512013-09-30 12:44:40 +0300120 result = ether_crc(MAC_ADDR_LEN, mcast_mac);
121 whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */
122 whichreg = result >> 29; /* the 3 MSB = which reg to set it in */
David Updegraff53a5c422007-06-11 10:41:07 -0500123
Claudiu Manoil876d4512013-09-30 12:44:40 +0300124 value = 1 << (31-whichbit);
David Updegraff53a5c422007-06-11 10:41:07 -0500125
Claudiu Manoil876d4512013-09-30 12:44:40 +0300126 if (set)
127 setbits_be32(&regs->hash.gaddr0 + whichreg, value);
128 else
129 clrbits_be32(&regs->hash.gaddr0 + whichreg, value);
130
David Updegraff53a5c422007-06-11 10:41:07 -0500131 return 0;
132}
133#endif /* Multicast TFTP ? */
Mingkai Hu90751912011-01-27 12:52:46 +0800134
Bin Meng9872b732016-01-11 22:41:18 -0800135/*
136 * Initialized required registers to appropriate values, zeroing
Mingkai Hu90751912011-01-27 12:52:46 +0800137 * those we don't care about (unless zero is bad, in which case,
138 * choose a more appropriate value)
139 */
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300140static void init_registers(struct tsec __iomem *regs)
Mingkai Hu90751912011-01-27 12:52:46 +0800141{
142 /* Clear IEVENT */
143 out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
144
145 out_be32(&regs->imask, IMASK_INIT_CLEAR);
146
147 out_be32(&regs->hash.iaddr0, 0);
148 out_be32(&regs->hash.iaddr1, 0);
149 out_be32(&regs->hash.iaddr2, 0);
150 out_be32(&regs->hash.iaddr3, 0);
151 out_be32(&regs->hash.iaddr4, 0);
152 out_be32(&regs->hash.iaddr5, 0);
153 out_be32(&regs->hash.iaddr6, 0);
154 out_be32(&regs->hash.iaddr7, 0);
155
156 out_be32(&regs->hash.gaddr0, 0);
157 out_be32(&regs->hash.gaddr1, 0);
158 out_be32(&regs->hash.gaddr2, 0);
159 out_be32(&regs->hash.gaddr3, 0);
160 out_be32(&regs->hash.gaddr4, 0);
161 out_be32(&regs->hash.gaddr5, 0);
162 out_be32(&regs->hash.gaddr6, 0);
163 out_be32(&regs->hash.gaddr7, 0);
164
165 out_be32(&regs->rctrl, 0x00000000);
166
167 /* Init RMON mib registers */
Claudiu Manoil82ef75c2013-09-30 12:44:46 +0300168 memset((void *)&regs->rmon, 0, sizeof(regs->rmon));
Mingkai Hu90751912011-01-27 12:52:46 +0800169
170 out_be32(&regs->rmon.cam1, 0xffffffff);
171 out_be32(&regs->rmon.cam2, 0xffffffff);
172
173 out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
174
175 out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
176
177 out_be32(&regs->attr, ATTR_INIT_SETTINGS);
178 out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
179
180}
181
Bin Meng9872b732016-01-11 22:41:18 -0800182/*
183 * Configure maccfg2 based on negotiated speed and duplex
Mingkai Hu90751912011-01-27 12:52:46 +0800184 * reported by PHY handling code
185 */
Andy Fleming063c1262011-04-08 02:10:54 -0500186static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
Mingkai Hu90751912011-01-27 12:52:46 +0800187{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300188 struct tsec __iomem *regs = priv->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800189 u32 ecntrl, maccfg2;
190
Andy Fleming063c1262011-04-08 02:10:54 -0500191 if (!phydev->link) {
192 printf("%s: No link.\n", phydev->dev->name);
Mingkai Hu90751912011-01-27 12:52:46 +0800193 return;
194 }
195
196 /* clear all bits relative with interface mode */
197 ecntrl = in_be32(&regs->ecntrl);
198 ecntrl &= ~ECNTRL_R100;
199
200 maccfg2 = in_be32(&regs->maccfg2);
201 maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
202
Andy Fleming063c1262011-04-08 02:10:54 -0500203 if (phydev->duplex)
Mingkai Hu90751912011-01-27 12:52:46 +0800204 maccfg2 |= MACCFG2_FULL_DUPLEX;
205
Andy Fleming063c1262011-04-08 02:10:54 -0500206 switch (phydev->speed) {
Mingkai Hu90751912011-01-27 12:52:46 +0800207 case 1000:
208 maccfg2 |= MACCFG2_GMII;
209 break;
210 case 100:
211 case 10:
212 maccfg2 |= MACCFG2_MII;
213
Bin Meng9872b732016-01-11 22:41:18 -0800214 /*
215 * Set R100 bit in all modes although
Mingkai Hu90751912011-01-27 12:52:46 +0800216 * it is only used in RGMII mode
217 */
Andy Fleming063c1262011-04-08 02:10:54 -0500218 if (phydev->speed == 100)
Mingkai Hu90751912011-01-27 12:52:46 +0800219 ecntrl |= ECNTRL_R100;
220 break;
221 default:
Andy Fleming063c1262011-04-08 02:10:54 -0500222 printf("%s: Speed was bad\n", phydev->dev->name);
Mingkai Hu90751912011-01-27 12:52:46 +0800223 break;
224 }
225
226 out_be32(&regs->ecntrl, ecntrl);
227 out_be32(&regs->maccfg2, maccfg2);
228
Andy Fleming063c1262011-04-08 02:10:54 -0500229 printf("Speed: %d, %s duplex%s\n", phydev->speed,
230 (phydev->duplex) ? "full" : "half",
231 (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
Mingkai Hu90751912011-01-27 12:52:46 +0800232}
233
chenhui zhaoaada81d2011-10-03 08:38:50 -0500234#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
235/*
236 * When MACCFG1[Rx_EN] is enabled during system boot as part
237 * of the eTSEC port initialization sequence,
238 * the eTSEC Rx logic may not be properly initialized.
239 */
240void redundant_init(struct eth_device *dev)
241{
242 struct tsec_private *priv = dev->priv;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300243 struct tsec __iomem *regs = priv->regs;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500244 uint t, count = 0;
245 int fail = 1;
246 static const u8 pkt[] = {
247 0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25,
248 0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00,
249 0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01,
250 0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1,
251 0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00,
252 0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
253 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
254 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
255 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
256 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
257 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
258 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
259 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
260 0x71, 0x72};
261
262 /* Enable promiscuous mode */
263 setbits_be32(&regs->rctrl, 0x8);
264 /* Enable loopback mode */
265 setbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
266 /* Enable transmit and receive */
267 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
268
269 /* Tell the DMA it is clear to go */
270 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
271 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
272 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
273 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
274
275 do {
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300276 uint16_t status;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500277 tsec_send(dev, (void *)pkt, sizeof(pkt));
278
279 /* Wait for buffer to be received */
Bin Meng362b1232016-01-11 22:41:19 -0800280 for (t = 0; in_be16(&rxbd[priv->rx_idx].status) & RXBD_EMPTY;
281 t++) {
chenhui zhaoaada81d2011-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
Bin Meng362b1232016-01-11 22:41:19 -0800288 if (!memcmp(pkt, net_rx_packets[priv->rx_idx], sizeof(pkt)))
chenhui zhaoaada81d2011-10-03 08:38:50 -0500289 fail = 0;
290
Bin Meng362b1232016-01-11 22:41:19 -0800291 out_be16(&rxbd[priv->rx_idx].length, 0);
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300292 status = RXBD_EMPTY;
Bin Meng362b1232016-01-11 22:41:19 -0800293 if ((priv->rx_idx + 1) == PKTBUFSRX)
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300294 status |= RXBD_WRAP;
Bin Meng362b1232016-01-11 22:41:19 -0800295 out_be16(&rxbd[priv->rx_idx].status, status);
296 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500297
298 if (in_be32(&regs->ievent) & IEVENT_BSY) {
299 out_be32(&regs->ievent, IEVENT_BSY);
300 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
301 }
302 if (fail) {
303 printf("loopback recv packet error!\n");
304 clrbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
305 udelay(1000);
306 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN);
307 }
308 } while ((count++ < 4) && (fail == 1));
309
310 if (fail)
311 panic("eTSEC init fail!\n");
312 /* Disable promiscuous mode */
313 clrbits_be32(&regs->rctrl, 0x8);
314 /* Disable loopback mode */
315 clrbits_be32(&regs->maccfg1, MACCFG1_LOOPBACK);
316}
317#endif
318
Bin Meng9872b732016-01-11 22:41:18 -0800319/*
320 * Set up the buffers and their descriptors, and bring up the
Mingkai Hu90751912011-01-27 12:52:46 +0800321 * interface
322 */
323static void startup_tsec(struct eth_device *dev)
324{
Mingkai Hu90751912011-01-27 12:52:46 +0800325 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300326 struct tsec __iomem *regs = priv->regs;
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300327 uint16_t status;
328 int i;
Mingkai Hu90751912011-01-27 12:52:46 +0800329
Andy Fleming063c1262011-04-08 02:10:54 -0500330 /* reset the indices to zero */
Bin Meng362b1232016-01-11 22:41:19 -0800331 priv->rx_idx = 0;
332 priv->tx_idx = 0;
chenhui zhaoaada81d2011-10-03 08:38:50 -0500333#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
334 uint svr;
335#endif
Andy Fleming063c1262011-04-08 02:10:54 -0500336
Mingkai Hu90751912011-01-27 12:52:46 +0800337 /* Point to the buffer descriptors */
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300338 out_be32(&regs->tbase, (u32)&txbd[0]);
339 out_be32(&regs->rbase, (u32)&rxbd[0]);
Mingkai Hu90751912011-01-27 12:52:46 +0800340
341 /* Initialize the Rx Buffer descriptors */
342 for (i = 0; i < PKTBUFSRX; i++) {
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300343 out_be16(&rxbd[i].status, RXBD_EMPTY);
344 out_be16(&rxbd[i].length, 0);
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500345 out_be32(&rxbd[i].bufptr, (u32)net_rx_packets[i]);
Mingkai Hu90751912011-01-27 12:52:46 +0800346 }
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300347 status = in_be16(&rxbd[PKTBUFSRX - 1].status);
348 out_be16(&rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
Mingkai Hu90751912011-01-27 12:52:46 +0800349
350 /* Initialize the TX Buffer Descriptors */
351 for (i = 0; i < TX_BUF_CNT; i++) {
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300352 out_be16(&txbd[i].status, 0);
353 out_be16(&txbd[i].length, 0);
354 out_be32(&txbd[i].bufptr, 0);
Mingkai Hu90751912011-01-27 12:52:46 +0800355 }
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300356 status = in_be16(&txbd[TX_BUF_CNT - 1].status);
357 out_be16(&txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
Mingkai Hu90751912011-01-27 12:52:46 +0800358
chenhui zhaoaada81d2011-10-03 08:38:50 -0500359#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
360 svr = get_svr();
361 if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
362 redundant_init(dev);
363#endif
Mingkai Hu90751912011-01-27 12:52:46 +0800364 /* Enable Transmit and Receive */
365 setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
366
367 /* Tell the DMA it is clear to go */
368 setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
369 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
370 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
371 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
372}
373
Bin Meng9872b732016-01-11 22:41:18 -0800374/*
375 * This returns the status bits of the device. The return value
Mingkai Hu90751912011-01-27 12:52:46 +0800376 * is never checked, and this is what the 8260 driver did, so we
Bin Meng9872b732016-01-11 22:41:18 -0800377 * do the same. Presumably, this would be zero if there were no
Mingkai Hu90751912011-01-27 12:52:46 +0800378 * errors
379 */
Joe Hershbergerc8a60b52012-05-21 09:46:36 +0000380static int tsec_send(struct eth_device *dev, void *packet, int length)
Mingkai Hu90751912011-01-27 12:52:46 +0800381{
Mingkai Hu90751912011-01-27 12:52:46 +0800382 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300383 struct tsec __iomem *regs = priv->regs;
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300384 uint16_t status;
385 int result = 0;
386 int i;
Mingkai Hu90751912011-01-27 12:52:46 +0800387
388 /* Find an empty buffer descriptor */
Bin Meng362b1232016-01-11 22:41:19 -0800389 for (i = 0; in_be16(&txbd[priv->tx_idx].status) & TXBD_READY; i++) {
Mingkai Hu90751912011-01-27 12:52:46 +0800390 if (i >= TOUT_LOOP) {
391 debug("%s: tsec: tx buffers full\n", dev->name);
392 return result;
393 }
394 }
395
Bin Meng362b1232016-01-11 22:41:19 -0800396 out_be32(&txbd[priv->tx_idx].bufptr, (u32)packet);
397 out_be16(&txbd[priv->tx_idx].length, length);
398 status = in_be16(&txbd[priv->tx_idx].status);
399 out_be16(&txbd[priv->tx_idx].status, status |
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300400 (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
Mingkai Hu90751912011-01-27 12:52:46 +0800401
402 /* Tell the DMA to go */
403 out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
404
405 /* Wait for buffer to be transmitted */
Bin Meng362b1232016-01-11 22:41:19 -0800406 for (i = 0; in_be16(&txbd[priv->tx_idx].status) & TXBD_READY; i++) {
Mingkai Hu90751912011-01-27 12:52:46 +0800407 if (i >= TOUT_LOOP) {
408 debug("%s: tsec: tx error\n", dev->name);
409 return result;
410 }
411 }
412
Bin Meng362b1232016-01-11 22:41:19 -0800413 priv->tx_idx = (priv->tx_idx + 1) % TX_BUF_CNT;
414 result = in_be16(&txbd[priv->tx_idx].status) & TXBD_STATS;
Mingkai Hu90751912011-01-27 12:52:46 +0800415
416 return result;
417}
418
419static int tsec_recv(struct eth_device *dev)
420{
Mingkai Hu90751912011-01-27 12:52:46 +0800421 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300422 struct tsec __iomem *regs = priv->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800423
Bin Meng362b1232016-01-11 22:41:19 -0800424 while (!(in_be16(&rxbd[priv->rx_idx].status) & RXBD_EMPTY)) {
425 int length = in_be16(&rxbd[priv->rx_idx].length);
426 uint16_t status = in_be16(&rxbd[priv->rx_idx].status);
427 uchar *packet = net_rx_packets[priv->rx_idx];
Mingkai Hu90751912011-01-27 12:52:46 +0800428
429 /* Send the packet up if there were no errors */
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300430 if (!(status & RXBD_STATS))
Bin Meng362b1232016-01-11 22:41:19 -0800431 net_process_received_packet(packet, length - 4);
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300432 else
433 printf("Got error %x\n", (status & RXBD_STATS));
Mingkai Hu90751912011-01-27 12:52:46 +0800434
Bin Meng362b1232016-01-11 22:41:19 -0800435 out_be16(&rxbd[priv->rx_idx].length, 0);
Mingkai Hu90751912011-01-27 12:52:46 +0800436
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300437 status = RXBD_EMPTY;
Mingkai Hu90751912011-01-27 12:52:46 +0800438 /* Set the wrap bit if this is the last element in the list */
Bin Meng362b1232016-01-11 22:41:19 -0800439 if ((priv->rx_idx + 1) == PKTBUFSRX)
Claudiu Manoil9c9141f2013-10-04 19:13:53 +0300440 status |= RXBD_WRAP;
Bin Meng362b1232016-01-11 22:41:19 -0800441 out_be16(&rxbd[priv->rx_idx].status, status);
Mingkai Hu90751912011-01-27 12:52:46 +0800442
Bin Meng362b1232016-01-11 22:41:19 -0800443 priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX;
Mingkai Hu90751912011-01-27 12:52:46 +0800444 }
445
446 if (in_be32(&regs->ievent) & IEVENT_BSY) {
447 out_be32(&regs->ievent, IEVENT_BSY);
448 out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
449 }
450
451 return -1;
Mingkai Hu90751912011-01-27 12:52:46 +0800452}
453
454/* Stop the interface */
455static void tsec_halt(struct eth_device *dev)
456{
457 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300458 struct tsec __iomem *regs = priv->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800459
460 clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
461 setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
462
463 while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
464 != (IEVENT_GRSC | IEVENT_GTSC))
465 ;
466
467 clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
468
469 /* Shut down the PHY, as needed */
Andy Fleming063c1262011-04-08 02:10:54 -0500470 phy_shutdown(priv->phydev);
Mingkai Hu90751912011-01-27 12:52:46 +0800471}
472
Bin Meng9872b732016-01-11 22:41:18 -0800473/*
474 * Initializes data structures and registers for the controller,
475 * and brings the interface up. Returns the link status, meaning
Mingkai Hu90751912011-01-27 12:52:46 +0800476 * that it returns success if the link is up, failure otherwise.
Bin Meng9872b732016-01-11 22:41:18 -0800477 * This allows U-Boot to find the first active controller.
Mingkai Hu90751912011-01-27 12:52:46 +0800478 */
479static int tsec_init(struct eth_device *dev, bd_t * bd)
480{
Mingkai Hu90751912011-01-27 12:52:46 +0800481 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300482 struct tsec __iomem *regs = priv->regs;
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300483 u32 tempval;
Timur Tabi11af8d62012-07-09 08:52:43 +0000484 int ret;
Mingkai Hu90751912011-01-27 12:52:46 +0800485
486 /* Make sure the controller is stopped */
487 tsec_halt(dev);
488
489 /* Init MACCFG2. Defaults to GMII */
490 out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
491
492 /* Init ECNTRL */
493 out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
494
Bin Meng9872b732016-01-11 22:41:18 -0800495 /*
496 * Copy the station address into the address registers.
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300497 * For a station address of 0x12345678ABCD in transmission
498 * order (BE), MACnADDR1 is set to 0xCDAB7856 and
499 * MACnADDR2 is set to 0x34120000.
500 */
501 tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) |
502 (dev->enetaddr[3] << 8) | dev->enetaddr[2];
Mingkai Hu90751912011-01-27 12:52:46 +0800503
504 out_be32(&regs->macstnaddr1, tempval);
505
Claudiu Manoilb1690bc2013-09-30 12:44:47 +0300506 tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16);
Mingkai Hu90751912011-01-27 12:52:46 +0800507
508 out_be32(&regs->macstnaddr2, tempval);
509
Mingkai Hu90751912011-01-27 12:52:46 +0800510 /* Clear out (for the most part) the other registers */
511 init_registers(regs);
512
513 /* Ready the device for tx/rx */
514 startup_tsec(dev);
515
Andy Fleming063c1262011-04-08 02:10:54 -0500516 /* Start up the PHY */
Timur Tabi11af8d62012-07-09 08:52:43 +0000517 ret = phy_startup(priv->phydev);
518 if (ret) {
519 printf("Could not initialize PHY %s\n",
520 priv->phydev->dev->name);
521 return ret;
522 }
Andy Fleming063c1262011-04-08 02:10:54 -0500523
524 adjust_link(priv, priv->phydev);
525
Mingkai Hu90751912011-01-27 12:52:46 +0800526 /* If there's no link, fail */
Andy Fleming063c1262011-04-08 02:10:54 -0500527 return priv->phydev->link ? 0 : -1;
Mingkai Hu90751912011-01-27 12:52:46 +0800528}
529
Andy Fleming063c1262011-04-08 02:10:54 -0500530static phy_interface_t tsec_get_interface(struct tsec_private *priv)
531{
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300532 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500533 u32 ecntrl;
534
535 ecntrl = in_be32(&regs->ecntrl);
536
537 if (ecntrl & ECNTRL_SGMII_MODE)
538 return PHY_INTERFACE_MODE_SGMII;
539
540 if (ecntrl & ECNTRL_TBI_MODE) {
541 if (ecntrl & ECNTRL_REDUCED_MODE)
542 return PHY_INTERFACE_MODE_RTBI;
543 else
544 return PHY_INTERFACE_MODE_TBI;
545 }
546
547 if (ecntrl & ECNTRL_REDUCED_MODE) {
548 if (ecntrl & ECNTRL_REDUCED_MII_MODE)
549 return PHY_INTERFACE_MODE_RMII;
550 else {
551 phy_interface_t interface = priv->interface;
552
553 /*
554 * This isn't autodetected, so it must
555 * be set by the platform code.
556 */
557 if ((interface == PHY_INTERFACE_MODE_RGMII_ID) ||
Bin Meng9872b732016-01-11 22:41:18 -0800558 (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
559 (interface == PHY_INTERFACE_MODE_RGMII_RXID))
Andy Fleming063c1262011-04-08 02:10:54 -0500560 return interface;
561
562 return PHY_INTERFACE_MODE_RGMII;
563 }
564 }
565
566 if (priv->flags & TSEC_GIGABIT)
567 return PHY_INTERFACE_MODE_GMII;
568
569 return PHY_INTERFACE_MODE_MII;
570}
571
Bin Meng9872b732016-01-11 22:41:18 -0800572/*
573 * Discover which PHY is attached to the device, and configure it
Mingkai Hu90751912011-01-27 12:52:46 +0800574 * properly. If the PHY is not recognized, then return 0
575 * (failure). Otherwise, return 1
576 */
577static int init_phy(struct eth_device *dev)
578{
579 struct tsec_private *priv = (struct tsec_private *)dev->priv;
Andy Fleming063c1262011-04-08 02:10:54 -0500580 struct phy_device *phydev;
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300581 struct tsec __iomem *regs = priv->regs;
Andy Fleming063c1262011-04-08 02:10:54 -0500582 u32 supported = (SUPPORTED_10baseT_Half |
583 SUPPORTED_10baseT_Full |
584 SUPPORTED_100baseT_Half |
585 SUPPORTED_100baseT_Full);
586
587 if (priv->flags & TSEC_GIGABIT)
588 supported |= SUPPORTED_1000baseT_Full;
Mingkai Hu90751912011-01-27 12:52:46 +0800589
590 /* Assign a Physical address to the TBI */
591 out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
592
Andy Fleming063c1262011-04-08 02:10:54 -0500593 priv->interface = tsec_get_interface(priv);
Mingkai Hu90751912011-01-27 12:52:46 +0800594
Andy Fleming063c1262011-04-08 02:10:54 -0500595 if (priv->interface == PHY_INTERFACE_MODE_SGMII)
Mingkai Hu90751912011-01-27 12:52:46 +0800596 tsec_configure_serdes(priv);
597
Andy Fleming063c1262011-04-08 02:10:54 -0500598 phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
Claudiu Manoil7f233c02013-12-10 15:21:04 +0200599 if (!phydev)
600 return 0;
Mingkai Hu90751912011-01-27 12:52:46 +0800601
Andy Fleming063c1262011-04-08 02:10:54 -0500602 phydev->supported &= supported;
603 phydev->advertising = phydev->supported;
604
605 priv->phydev = phydev;
606
607 phy_config(phydev);
Mingkai Hu90751912011-01-27 12:52:46 +0800608
609 return 1;
610}
611
Bin Meng9872b732016-01-11 22:41:18 -0800612/*
613 * Initialize device structure. Returns success if PHY
Mingkai Hu90751912011-01-27 12:52:46 +0800614 * initialization succeeded (i.e. if it recognizes the PHY)
615 */
616static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
617{
618 struct eth_device *dev;
619 int i;
620 struct tsec_private *priv;
621
622 dev = (struct eth_device *)malloc(sizeof *dev);
623
624 if (NULL == dev)
625 return 0;
626
627 memset(dev, 0, sizeof *dev);
628
629 priv = (struct tsec_private *)malloc(sizeof(*priv));
630
631 if (NULL == priv)
632 return 0;
633
Mingkai Hu90751912011-01-27 12:52:46 +0800634 priv->regs = tsec_info->regs;
Mingkai Hu90751912011-01-27 12:52:46 +0800635 priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
636
637 priv->phyaddr = tsec_info->phyaddr;
638 priv->flags = tsec_info->flags;
639
640 sprintf(dev->name, tsec_info->devname);
Andy Fleming063c1262011-04-08 02:10:54 -0500641 priv->interface = tsec_info->interface;
642 priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
Mingkai Hu90751912011-01-27 12:52:46 +0800643 dev->iobase = 0;
644 dev->priv = priv;
645 dev->init = tsec_init;
646 dev->halt = tsec_halt;
647 dev->send = tsec_send;
648 dev->recv = tsec_recv;
649#ifdef CONFIG_MCAST_TFTP
650 dev->mcast = tsec_mcast_addr;
651#endif
652
Bin Meng9872b732016-01-11 22:41:18 -0800653 /* Tell U-Boot to get the addr from the env */
Mingkai Hu90751912011-01-27 12:52:46 +0800654 for (i = 0; i < 6; i++)
655 dev->enetaddr[i] = 0;
656
657 eth_register(dev);
658
659 /* Reset the MAC */
660 setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
661 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */
662 clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
663
Mingkai Hu90751912011-01-27 12:52:46 +0800664 /* Try to initialize PHY here, and return */
665 return init_phy(dev);
666}
667
668/*
669 * Initialize all the TSEC devices
670 *
671 * Returns the number of TSEC devices that were initialized
672 */
673int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
674{
675 int i;
676 int ret, count = 0;
677
678 for (i = 0; i < num; i++) {
679 ret = tsec_initialize(bis, &tsecs[i]);
680 if (ret > 0)
681 count += ret;
682 }
683
684 return count;
685}
686
687int tsec_standard_init(bd_t *bis)
688{
Andy Fleming063c1262011-04-08 02:10:54 -0500689 struct fsl_pq_mdio_info info;
690
Claudiu Manoilaec84bf2013-09-30 12:44:42 +0300691 info.regs = TSEC_GET_MDIO_REGS_BASE(1);
Andy Fleming063c1262011-04-08 02:10:54 -0500692 info.name = DEFAULT_MII_NAME;
693
694 fsl_pq_mdio_init(bis, &info);
695
Mingkai Hu90751912011-01-27 12:52:46 +0800696 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
697}