]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Freescale Three Speed Ethernet Controller driver | |
3 | * | |
4 | * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc. | |
5 | * (C) Copyright 2003, Motorola, Inc. | |
6 | * author Andy Fleming | |
7 | * | |
8 | * SPDX-License-Identifier: GPL-2.0+ | |
9 | */ | |
10 | ||
11 | #include <config.h> | |
12 | #include <common.h> | |
13 | #include <dm.h> | |
14 | #include <malloc.h> | |
15 | #include <net.h> | |
16 | #include <command.h> | |
17 | #include <tsec.h> | |
18 | #include <fsl_mdio.h> | |
19 | #include <linux/errno.h> | |
20 | #include <asm/processor.h> | |
21 | #include <asm/io.h> | |
22 | ||
23 | DECLARE_GLOBAL_DATA_PTR; | |
24 | ||
25 | #ifndef CONFIG_DM_ETH | |
26 | /* Default initializations for TSEC controllers. */ | |
27 | ||
28 | static struct tsec_info_struct tsec_info[] = { | |
29 | #ifdef CONFIG_TSEC1 | |
30 | STD_TSEC_INFO(1), /* TSEC1 */ | |
31 | #endif | |
32 | #ifdef CONFIG_TSEC2 | |
33 | STD_TSEC_INFO(2), /* TSEC2 */ | |
34 | #endif | |
35 | #ifdef CONFIG_MPC85XX_FEC | |
36 | { | |
37 | .regs = TSEC_GET_REGS(2, 0x2000), | |
38 | .devname = CONFIG_MPC85XX_FEC_NAME, | |
39 | .phyaddr = FEC_PHY_ADDR, | |
40 | .flags = FEC_FLAGS, | |
41 | .mii_devname = DEFAULT_MII_NAME | |
42 | }, /* FEC */ | |
43 | #endif | |
44 | #ifdef CONFIG_TSEC3 | |
45 | STD_TSEC_INFO(3), /* TSEC3 */ | |
46 | #endif | |
47 | #ifdef CONFIG_TSEC4 | |
48 | STD_TSEC_INFO(4), /* TSEC4 */ | |
49 | #endif | |
50 | }; | |
51 | #endif /* CONFIG_DM_ETH */ | |
52 | ||
53 | #define TBIANA_SETTINGS ( \ | |
54 | TBIANA_ASYMMETRIC_PAUSE \ | |
55 | | TBIANA_SYMMETRIC_PAUSE \ | |
56 | | TBIANA_FULL_DUPLEX \ | |
57 | ) | |
58 | ||
59 | /* By default force the TBI PHY into 1000Mbps full duplex when in SGMII mode */ | |
60 | #ifndef CONFIG_TSEC_TBICR_SETTINGS | |
61 | #define CONFIG_TSEC_TBICR_SETTINGS ( \ | |
62 | TBICR_PHY_RESET \ | |
63 | | TBICR_ANEG_ENABLE \ | |
64 | | TBICR_FULL_DUPLEX \ | |
65 | | TBICR_SPEED1_SET \ | |
66 | ) | |
67 | #endif /* CONFIG_TSEC_TBICR_SETTINGS */ | |
68 | ||
69 | /* Configure the TBI for SGMII operation */ | |
70 | static void tsec_configure_serdes(struct tsec_private *priv) | |
71 | { | |
72 | /* | |
73 | * Access TBI PHY registers at given TSEC register offset as opposed | |
74 | * to the register offset used for external PHY accesses | |
75 | */ | |
76 | tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa), | |
77 | 0, TBI_ANA, TBIANA_SETTINGS); | |
78 | tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa), | |
79 | 0, TBI_TBICON, TBICON_CLK_SELECT); | |
80 | tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa), | |
81 | 0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS); | |
82 | } | |
83 | ||
84 | #ifdef CONFIG_MCAST_TFTP | |
85 | ||
86 | /* CREDITS: linux gianfar driver, slightly adjusted... thanx. */ | |
87 | ||
88 | /* Set the appropriate hash bit for the given addr */ | |
89 | ||
90 | /* | |
91 | * The algorithm works like so: | |
92 | * 1) Take the Destination Address (ie the multicast address), and | |
93 | * do a CRC on it (little endian), and reverse the bits of the | |
94 | * result. | |
95 | * 2) Use the 8 most significant bits as a hash into a 256-entry | |
96 | * table. The table is controlled through 8 32-bit registers: | |
97 | * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is entry | |
98 | * 255. This means that the 3 most significant bits in the | |
99 | * hash index which gaddr register to use, and the 5 other bits | |
100 | * indicate which bit (assuming an IBM numbering scheme, which | |
101 | * for PowerPC (tm) is usually the case) in the register holds | |
102 | * the entry. | |
103 | */ | |
104 | #ifndef CONFIG_DM_ETH | |
105 | static int tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set) | |
106 | #else | |
107 | static int tsec_mcast_addr(struct udevice *dev, const u8 *mcast_mac, int set) | |
108 | #endif | |
109 | { | |
110 | struct tsec_private *priv = (struct tsec_private *)dev->priv; | |
111 | struct tsec __iomem *regs = priv->regs; | |
112 | u32 result, value; | |
113 | u8 whichbit, whichreg; | |
114 | ||
115 | result = ether_crc(MAC_ADDR_LEN, mcast_mac); | |
116 | whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */ | |
117 | whichreg = result >> 29; /* the 3 MSB = which reg to set it in */ | |
118 | ||
119 | value = 1 << (31-whichbit); | |
120 | ||
121 | if (set) | |
122 | setbits_be32(®s->hash.gaddr0 + whichreg, value); | |
123 | else | |
124 | clrbits_be32(®s->hash.gaddr0 + whichreg, value); | |
125 | ||
126 | return 0; | |
127 | } | |
128 | #endif /* Multicast TFTP ? */ | |
129 | ||
130 | /* | |
131 | * Initialized required registers to appropriate values, zeroing | |
132 | * those we don't care about (unless zero is bad, in which case, | |
133 | * choose a more appropriate value) | |
134 | */ | |
135 | static void init_registers(struct tsec __iomem *regs) | |
136 | { | |
137 | /* Clear IEVENT */ | |
138 | out_be32(®s->ievent, IEVENT_INIT_CLEAR); | |
139 | ||
140 | out_be32(®s->imask, IMASK_INIT_CLEAR); | |
141 | ||
142 | out_be32(®s->hash.iaddr0, 0); | |
143 | out_be32(®s->hash.iaddr1, 0); | |
144 | out_be32(®s->hash.iaddr2, 0); | |
145 | out_be32(®s->hash.iaddr3, 0); | |
146 | out_be32(®s->hash.iaddr4, 0); | |
147 | out_be32(®s->hash.iaddr5, 0); | |
148 | out_be32(®s->hash.iaddr6, 0); | |
149 | out_be32(®s->hash.iaddr7, 0); | |
150 | ||
151 | out_be32(®s->hash.gaddr0, 0); | |
152 | out_be32(®s->hash.gaddr1, 0); | |
153 | out_be32(®s->hash.gaddr2, 0); | |
154 | out_be32(®s->hash.gaddr3, 0); | |
155 | out_be32(®s->hash.gaddr4, 0); | |
156 | out_be32(®s->hash.gaddr5, 0); | |
157 | out_be32(®s->hash.gaddr6, 0); | |
158 | out_be32(®s->hash.gaddr7, 0); | |
159 | ||
160 | out_be32(®s->rctrl, 0x00000000); | |
161 | ||
162 | /* Init RMON mib registers */ | |
163 | memset((void *)®s->rmon, 0, sizeof(regs->rmon)); | |
164 | ||
165 | out_be32(®s->rmon.cam1, 0xffffffff); | |
166 | out_be32(®s->rmon.cam2, 0xffffffff); | |
167 | ||
168 | out_be32(®s->mrblr, MRBLR_INIT_SETTINGS); | |
169 | ||
170 | out_be32(®s->minflr, MINFLR_INIT_SETTINGS); | |
171 | ||
172 | out_be32(®s->attr, ATTR_INIT_SETTINGS); | |
173 | out_be32(®s->attreli, ATTRELI_INIT_SETTINGS); | |
174 | ||
175 | } | |
176 | ||
177 | /* | |
178 | * Configure maccfg2 based on negotiated speed and duplex | |
179 | * reported by PHY handling code | |
180 | */ | |
181 | static void adjust_link(struct tsec_private *priv, struct phy_device *phydev) | |
182 | { | |
183 | struct tsec __iomem *regs = priv->regs; | |
184 | u32 ecntrl, maccfg2; | |
185 | ||
186 | if (!phydev->link) { | |
187 | printf("%s: No link.\n", phydev->dev->name); | |
188 | return; | |
189 | } | |
190 | ||
191 | /* clear all bits relative with interface mode */ | |
192 | ecntrl = in_be32(®s->ecntrl); | |
193 | ecntrl &= ~ECNTRL_R100; | |
194 | ||
195 | maccfg2 = in_be32(®s->maccfg2); | |
196 | maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX); | |
197 | ||
198 | if (phydev->duplex) | |
199 | maccfg2 |= MACCFG2_FULL_DUPLEX; | |
200 | ||
201 | switch (phydev->speed) { | |
202 | case 1000: | |
203 | maccfg2 |= MACCFG2_GMII; | |
204 | break; | |
205 | case 100: | |
206 | case 10: | |
207 | maccfg2 |= MACCFG2_MII; | |
208 | ||
209 | /* | |
210 | * Set R100 bit in all modes although | |
211 | * it is only used in RGMII mode | |
212 | */ | |
213 | if (phydev->speed == 100) | |
214 | ecntrl |= ECNTRL_R100; | |
215 | break; | |
216 | default: | |
217 | printf("%s: Speed was bad\n", phydev->dev->name); | |
218 | break; | |
219 | } | |
220 | ||
221 | out_be32(®s->ecntrl, ecntrl); | |
222 | out_be32(®s->maccfg2, maccfg2); | |
223 | ||
224 | printf("Speed: %d, %s duplex%s\n", phydev->speed, | |
225 | (phydev->duplex) ? "full" : "half", | |
226 | (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); | |
227 | } | |
228 | ||
229 | /* | |
230 | * This returns the status bits of the device. The return value | |
231 | * is never checked, and this is what the 8260 driver did, so we | |
232 | * do the same. Presumably, this would be zero if there were no | |
233 | * errors | |
234 | */ | |
235 | #ifndef CONFIG_DM_ETH | |
236 | static int tsec_send(struct eth_device *dev, void *packet, int length) | |
237 | #else | |
238 | static int tsec_send(struct udevice *dev, void *packet, int length) | |
239 | #endif | |
240 | { | |
241 | struct tsec_private *priv = (struct tsec_private *)dev->priv; | |
242 | struct tsec __iomem *regs = priv->regs; | |
243 | uint16_t status; | |
244 | int result = 0; | |
245 | int i; | |
246 | ||
247 | /* Find an empty buffer descriptor */ | |
248 | for (i = 0; | |
249 | in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY; | |
250 | i++) { | |
251 | if (i >= TOUT_LOOP) { | |
252 | debug("%s: tsec: tx buffers full\n", dev->name); | |
253 | return result; | |
254 | } | |
255 | } | |
256 | ||
257 | out_be32(&priv->txbd[priv->tx_idx].bufptr, (u32)packet); | |
258 | out_be16(&priv->txbd[priv->tx_idx].length, length); | |
259 | status = in_be16(&priv->txbd[priv->tx_idx].status); | |
260 | out_be16(&priv->txbd[priv->tx_idx].status, status | | |
261 | (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT)); | |
262 | ||
263 | /* Tell the DMA to go */ | |
264 | out_be32(®s->tstat, TSTAT_CLEAR_THALT); | |
265 | ||
266 | /* Wait for buffer to be transmitted */ | |
267 | for (i = 0; | |
268 | in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_READY; | |
269 | i++) { | |
270 | if (i >= TOUT_LOOP) { | |
271 | debug("%s: tsec: tx error\n", dev->name); | |
272 | return result; | |
273 | } | |
274 | } | |
275 | ||
276 | priv->tx_idx = (priv->tx_idx + 1) % TX_BUF_CNT; | |
277 | result = in_be16(&priv->txbd[priv->tx_idx].status) & TXBD_STATS; | |
278 | ||
279 | return result; | |
280 | } | |
281 | ||
282 | #ifndef CONFIG_DM_ETH | |
283 | static int tsec_recv(struct eth_device *dev) | |
284 | { | |
285 | struct tsec_private *priv = (struct tsec_private *)dev->priv; | |
286 | struct tsec __iomem *regs = priv->regs; | |
287 | ||
288 | while (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) { | |
289 | int length = in_be16(&priv->rxbd[priv->rx_idx].length); | |
290 | uint16_t status = in_be16(&priv->rxbd[priv->rx_idx].status); | |
291 | uchar *packet = net_rx_packets[priv->rx_idx]; | |
292 | ||
293 | /* Send the packet up if there were no errors */ | |
294 | if (!(status & RXBD_STATS)) | |
295 | net_process_received_packet(packet, length - 4); | |
296 | else | |
297 | printf("Got error %x\n", (status & RXBD_STATS)); | |
298 | ||
299 | out_be16(&priv->rxbd[priv->rx_idx].length, 0); | |
300 | ||
301 | status = RXBD_EMPTY; | |
302 | /* Set the wrap bit if this is the last element in the list */ | |
303 | if ((priv->rx_idx + 1) == PKTBUFSRX) | |
304 | status |= RXBD_WRAP; | |
305 | out_be16(&priv->rxbd[priv->rx_idx].status, status); | |
306 | ||
307 | priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX; | |
308 | } | |
309 | ||
310 | if (in_be32(®s->ievent) & IEVENT_BSY) { | |
311 | out_be32(®s->ievent, IEVENT_BSY); | |
312 | out_be32(®s->rstat, RSTAT_CLEAR_RHALT); | |
313 | } | |
314 | ||
315 | return -1; | |
316 | } | |
317 | #else | |
318 | static int tsec_recv(struct udevice *dev, int flags, uchar **packetp) | |
319 | { | |
320 | struct tsec_private *priv = (struct tsec_private *)dev->priv; | |
321 | struct tsec __iomem *regs = priv->regs; | |
322 | int ret = -1; | |
323 | ||
324 | if (!(in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY)) { | |
325 | int length = in_be16(&priv->rxbd[priv->rx_idx].length); | |
326 | uint16_t status = in_be16(&priv->rxbd[priv->rx_idx].status); | |
327 | uint32_t buf; | |
328 | ||
329 | /* Send the packet up if there were no errors */ | |
330 | if (!(status & RXBD_STATS)) { | |
331 | buf = in_be32(&priv->rxbd[priv->rx_idx].bufptr); | |
332 | *packetp = (uchar *)buf; | |
333 | ret = length - 4; | |
334 | } else { | |
335 | printf("Got error %x\n", (status & RXBD_STATS)); | |
336 | } | |
337 | } | |
338 | ||
339 | if (in_be32(®s->ievent) & IEVENT_BSY) { | |
340 | out_be32(®s->ievent, IEVENT_BSY); | |
341 | out_be32(®s->rstat, RSTAT_CLEAR_RHALT); | |
342 | } | |
343 | ||
344 | return ret; | |
345 | } | |
346 | ||
347 | static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length) | |
348 | { | |
349 | struct tsec_private *priv = (struct tsec_private *)dev->priv; | |
350 | uint16_t status; | |
351 | ||
352 | out_be16(&priv->rxbd[priv->rx_idx].length, 0); | |
353 | ||
354 | status = RXBD_EMPTY; | |
355 | /* Set the wrap bit if this is the last element in the list */ | |
356 | if ((priv->rx_idx + 1) == PKTBUFSRX) | |
357 | status |= RXBD_WRAP; | |
358 | out_be16(&priv->rxbd[priv->rx_idx].status, status); | |
359 | ||
360 | priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX; | |
361 | ||
362 | return 0; | |
363 | } | |
364 | #endif | |
365 | ||
366 | /* Stop the interface */ | |
367 | #ifndef CONFIG_DM_ETH | |
368 | static void tsec_halt(struct eth_device *dev) | |
369 | #else | |
370 | static void tsec_halt(struct udevice *dev) | |
371 | #endif | |
372 | { | |
373 | struct tsec_private *priv = (struct tsec_private *)dev->priv; | |
374 | struct tsec __iomem *regs = priv->regs; | |
375 | ||
376 | clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); | |
377 | setbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); | |
378 | ||
379 | while ((in_be32(®s->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) | |
380 | != (IEVENT_GRSC | IEVENT_GTSC)) | |
381 | ; | |
382 | ||
383 | clrbits_be32(®s->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN); | |
384 | ||
385 | /* Shut down the PHY, as needed */ | |
386 | phy_shutdown(priv->phydev); | |
387 | } | |
388 | ||
389 | #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129 | |
390 | /* | |
391 | * When MACCFG1[Rx_EN] is enabled during system boot as part | |
392 | * of the eTSEC port initialization sequence, | |
393 | * the eTSEC Rx logic may not be properly initialized. | |
394 | */ | |
395 | void redundant_init(struct tsec_private *priv) | |
396 | { | |
397 | struct tsec __iomem *regs = priv->regs; | |
398 | uint t, count = 0; | |
399 | int fail = 1; | |
400 | static const u8 pkt[] = { | |
401 | 0x00, 0x1e, 0x4f, 0x12, 0xcb, 0x2c, 0x00, 0x25, | |
402 | 0x64, 0xbb, 0xd1, 0xab, 0x08, 0x00, 0x45, 0x00, | |
403 | 0x00, 0x5c, 0xdd, 0x22, 0x00, 0x00, 0x80, 0x01, | |
404 | 0x1f, 0x71, 0x0a, 0xc1, 0x14, 0x22, 0x0a, 0xc1, | |
405 | 0x14, 0x6a, 0x08, 0x00, 0xef, 0x7e, 0x02, 0x00, | |
406 | 0x94, 0x05, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, | |
407 | 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, | |
408 | 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, | |
409 | 0x77, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | |
410 | 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, | |
411 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, | |
412 | 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, | |
413 | 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, | |
414 | 0x71, 0x72}; | |
415 | ||
416 | /* Enable promiscuous mode */ | |
417 | setbits_be32(®s->rctrl, 0x8); | |
418 | /* Enable loopback mode */ | |
419 | setbits_be32(®s->maccfg1, MACCFG1_LOOPBACK); | |
420 | /* Enable transmit and receive */ | |
421 | setbits_be32(®s->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN); | |
422 | ||
423 | /* Tell the DMA it is clear to go */ | |
424 | setbits_be32(®s->dmactrl, DMACTRL_INIT_SETTINGS); | |
425 | out_be32(®s->tstat, TSTAT_CLEAR_THALT); | |
426 | out_be32(®s->rstat, RSTAT_CLEAR_RHALT); | |
427 | clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); | |
428 | ||
429 | do { | |
430 | uint16_t status; | |
431 | tsec_send(priv->dev, (void *)pkt, sizeof(pkt)); | |
432 | ||
433 | /* Wait for buffer to be received */ | |
434 | for (t = 0; | |
435 | in_be16(&priv->rxbd[priv->rx_idx].status) & RXBD_EMPTY; | |
436 | t++) { | |
437 | if (t >= 10 * TOUT_LOOP) { | |
438 | printf("%s: tsec: rx error\n", priv->dev->name); | |
439 | break; | |
440 | } | |
441 | } | |
442 | ||
443 | if (!memcmp(pkt, net_rx_packets[priv->rx_idx], sizeof(pkt))) | |
444 | fail = 0; | |
445 | ||
446 | out_be16(&priv->rxbd[priv->rx_idx].length, 0); | |
447 | status = RXBD_EMPTY; | |
448 | if ((priv->rx_idx + 1) == PKTBUFSRX) | |
449 | status |= RXBD_WRAP; | |
450 | out_be16(&priv->rxbd[priv->rx_idx].status, status); | |
451 | priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX; | |
452 | ||
453 | if (in_be32(®s->ievent) & IEVENT_BSY) { | |
454 | out_be32(®s->ievent, IEVENT_BSY); | |
455 | out_be32(®s->rstat, RSTAT_CLEAR_RHALT); | |
456 | } | |
457 | if (fail) { | |
458 | printf("loopback recv packet error!\n"); | |
459 | clrbits_be32(®s->maccfg1, MACCFG1_RX_EN); | |
460 | udelay(1000); | |
461 | setbits_be32(®s->maccfg1, MACCFG1_RX_EN); | |
462 | } | |
463 | } while ((count++ < 4) && (fail == 1)); | |
464 | ||
465 | if (fail) | |
466 | panic("eTSEC init fail!\n"); | |
467 | /* Disable promiscuous mode */ | |
468 | clrbits_be32(®s->rctrl, 0x8); | |
469 | /* Disable loopback mode */ | |
470 | clrbits_be32(®s->maccfg1, MACCFG1_LOOPBACK); | |
471 | } | |
472 | #endif | |
473 | ||
474 | /* | |
475 | * Set up the buffers and their descriptors, and bring up the | |
476 | * interface | |
477 | */ | |
478 | static void startup_tsec(struct tsec_private *priv) | |
479 | { | |
480 | struct tsec __iomem *regs = priv->regs; | |
481 | uint16_t status; | |
482 | int i; | |
483 | ||
484 | /* reset the indices to zero */ | |
485 | priv->rx_idx = 0; | |
486 | priv->tx_idx = 0; | |
487 | #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129 | |
488 | uint svr; | |
489 | #endif | |
490 | ||
491 | /* Point to the buffer descriptors */ | |
492 | out_be32(®s->tbase, (u32)&priv->txbd[0]); | |
493 | out_be32(®s->rbase, (u32)&priv->rxbd[0]); | |
494 | ||
495 | /* Initialize the Rx Buffer descriptors */ | |
496 | for (i = 0; i < PKTBUFSRX; i++) { | |
497 | out_be16(&priv->rxbd[i].status, RXBD_EMPTY); | |
498 | out_be16(&priv->rxbd[i].length, 0); | |
499 | out_be32(&priv->rxbd[i].bufptr, (u32)net_rx_packets[i]); | |
500 | } | |
501 | status = in_be16(&priv->rxbd[PKTBUFSRX - 1].status); | |
502 | out_be16(&priv->rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP); | |
503 | ||
504 | /* Initialize the TX Buffer Descriptors */ | |
505 | for (i = 0; i < TX_BUF_CNT; i++) { | |
506 | out_be16(&priv->txbd[i].status, 0); | |
507 | out_be16(&priv->txbd[i].length, 0); | |
508 | out_be32(&priv->txbd[i].bufptr, 0); | |
509 | } | |
510 | status = in_be16(&priv->txbd[TX_BUF_CNT - 1].status); | |
511 | out_be16(&priv->txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP); | |
512 | ||
513 | #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129 | |
514 | svr = get_svr(); | |
515 | if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0)) | |
516 | redundant_init(priv); | |
517 | #endif | |
518 | /* Enable Transmit and Receive */ | |
519 | setbits_be32(®s->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN); | |
520 | ||
521 | /* Tell the DMA it is clear to go */ | |
522 | setbits_be32(®s->dmactrl, DMACTRL_INIT_SETTINGS); | |
523 | out_be32(®s->tstat, TSTAT_CLEAR_THALT); | |
524 | out_be32(®s->rstat, RSTAT_CLEAR_RHALT); | |
525 | clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); | |
526 | } | |
527 | ||
528 | /* | |
529 | * Initializes data structures and registers for the controller, | |
530 | * and brings the interface up. Returns the link status, meaning | |
531 | * that it returns success if the link is up, failure otherwise. | |
532 | * This allows U-Boot to find the first active controller. | |
533 | */ | |
534 | #ifndef CONFIG_DM_ETH | |
535 | static int tsec_init(struct eth_device *dev, bd_t * bd) | |
536 | #else | |
537 | static int tsec_init(struct udevice *dev) | |
538 | #endif | |
539 | { | |
540 | struct tsec_private *priv = (struct tsec_private *)dev->priv; | |
541 | #ifdef CONFIG_DM_ETH | |
542 | struct eth_pdata *pdata = dev_get_platdata(dev); | |
543 | #endif | |
544 | struct tsec __iomem *regs = priv->regs; | |
545 | u32 tempval; | |
546 | int ret; | |
547 | ||
548 | /* Make sure the controller is stopped */ | |
549 | tsec_halt(dev); | |
550 | ||
551 | /* Init MACCFG2. Defaults to GMII */ | |
552 | out_be32(®s->maccfg2, MACCFG2_INIT_SETTINGS); | |
553 | ||
554 | /* Init ECNTRL */ | |
555 | out_be32(®s->ecntrl, ECNTRL_INIT_SETTINGS); | |
556 | ||
557 | /* | |
558 | * Copy the station address into the address registers. | |
559 | * For a station address of 0x12345678ABCD in transmission | |
560 | * order (BE), MACnADDR1 is set to 0xCDAB7856 and | |
561 | * MACnADDR2 is set to 0x34120000. | |
562 | */ | |
563 | #ifndef CONFIG_DM_ETH | |
564 | tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) | | |
565 | (dev->enetaddr[3] << 8) | dev->enetaddr[2]; | |
566 | #else | |
567 | tempval = (pdata->enetaddr[5] << 24) | (pdata->enetaddr[4] << 16) | | |
568 | (pdata->enetaddr[3] << 8) | pdata->enetaddr[2]; | |
569 | #endif | |
570 | ||
571 | out_be32(®s->macstnaddr1, tempval); | |
572 | ||
573 | #ifndef CONFIG_DM_ETH | |
574 | tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16); | |
575 | #else | |
576 | tempval = (pdata->enetaddr[1] << 24) | (pdata->enetaddr[0] << 16); | |
577 | #endif | |
578 | ||
579 | out_be32(®s->macstnaddr2, tempval); | |
580 | ||
581 | /* Clear out (for the most part) the other registers */ | |
582 | init_registers(regs); | |
583 | ||
584 | /* Ready the device for tx/rx */ | |
585 | startup_tsec(priv); | |
586 | ||
587 | /* Start up the PHY */ | |
588 | ret = phy_startup(priv->phydev); | |
589 | if (ret) { | |
590 | printf("Could not initialize PHY %s\n", | |
591 | priv->phydev->dev->name); | |
592 | return ret; | |
593 | } | |
594 | ||
595 | adjust_link(priv, priv->phydev); | |
596 | ||
597 | /* If there's no link, fail */ | |
598 | return priv->phydev->link ? 0 : -1; | |
599 | } | |
600 | ||
601 | static phy_interface_t tsec_get_interface(struct tsec_private *priv) | |
602 | { | |
603 | struct tsec __iomem *regs = priv->regs; | |
604 | u32 ecntrl; | |
605 | ||
606 | ecntrl = in_be32(®s->ecntrl); | |
607 | ||
608 | if (ecntrl & ECNTRL_SGMII_MODE) | |
609 | return PHY_INTERFACE_MODE_SGMII; | |
610 | ||
611 | if (ecntrl & ECNTRL_TBI_MODE) { | |
612 | if (ecntrl & ECNTRL_REDUCED_MODE) | |
613 | return PHY_INTERFACE_MODE_RTBI; | |
614 | else | |
615 | return PHY_INTERFACE_MODE_TBI; | |
616 | } | |
617 | ||
618 | if (ecntrl & ECNTRL_REDUCED_MODE) { | |
619 | if (ecntrl & ECNTRL_REDUCED_MII_MODE) | |
620 | return PHY_INTERFACE_MODE_RMII; | |
621 | else { | |
622 | phy_interface_t interface = priv->interface; | |
623 | ||
624 | /* | |
625 | * This isn't autodetected, so it must | |
626 | * be set by the platform code. | |
627 | */ | |
628 | if ((interface == PHY_INTERFACE_MODE_RGMII_ID) || | |
629 | (interface == PHY_INTERFACE_MODE_RGMII_TXID) || | |
630 | (interface == PHY_INTERFACE_MODE_RGMII_RXID)) | |
631 | return interface; | |
632 | ||
633 | return PHY_INTERFACE_MODE_RGMII; | |
634 | } | |
635 | } | |
636 | ||
637 | if (priv->flags & TSEC_GIGABIT) | |
638 | return PHY_INTERFACE_MODE_GMII; | |
639 | ||
640 | return PHY_INTERFACE_MODE_MII; | |
641 | } | |
642 | ||
643 | /* | |
644 | * Discover which PHY is attached to the device, and configure it | |
645 | * properly. If the PHY is not recognized, then return 0 | |
646 | * (failure). Otherwise, return 1 | |
647 | */ | |
648 | static int init_phy(struct tsec_private *priv) | |
649 | { | |
650 | struct phy_device *phydev; | |
651 | struct tsec __iomem *regs = priv->regs; | |
652 | u32 supported = (SUPPORTED_10baseT_Half | | |
653 | SUPPORTED_10baseT_Full | | |
654 | SUPPORTED_100baseT_Half | | |
655 | SUPPORTED_100baseT_Full); | |
656 | ||
657 | if (priv->flags & TSEC_GIGABIT) | |
658 | supported |= SUPPORTED_1000baseT_Full; | |
659 | ||
660 | /* Assign a Physical address to the TBI */ | |
661 | out_be32(®s->tbipa, priv->tbiaddr); | |
662 | ||
663 | priv->interface = tsec_get_interface(priv); | |
664 | ||
665 | if (priv->interface == PHY_INTERFACE_MODE_SGMII) | |
666 | tsec_configure_serdes(priv); | |
667 | ||
668 | phydev = phy_connect(priv->bus, priv->phyaddr, priv->dev, | |
669 | priv->interface); | |
670 | if (!phydev) | |
671 | return 0; | |
672 | ||
673 | phydev->supported &= supported; | |
674 | phydev->advertising = phydev->supported; | |
675 | ||
676 | priv->phydev = phydev; | |
677 | ||
678 | phy_config(phydev); | |
679 | ||
680 | return 1; | |
681 | } | |
682 | ||
683 | #ifndef CONFIG_DM_ETH | |
684 | /* | |
685 | * Initialize device structure. Returns success if PHY | |
686 | * initialization succeeded (i.e. if it recognizes the PHY) | |
687 | */ | |
688 | static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info) | |
689 | { | |
690 | struct eth_device *dev; | |
691 | int i; | |
692 | struct tsec_private *priv; | |
693 | ||
694 | dev = (struct eth_device *)malloc(sizeof *dev); | |
695 | ||
696 | if (NULL == dev) | |
697 | return 0; | |
698 | ||
699 | memset(dev, 0, sizeof *dev); | |
700 | ||
701 | priv = (struct tsec_private *)malloc(sizeof(*priv)); | |
702 | ||
703 | if (NULL == priv) | |
704 | return 0; | |
705 | ||
706 | priv->regs = tsec_info->regs; | |
707 | priv->phyregs_sgmii = tsec_info->miiregs_sgmii; | |
708 | ||
709 | priv->phyaddr = tsec_info->phyaddr; | |
710 | priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE; | |
711 | priv->flags = tsec_info->flags; | |
712 | ||
713 | strcpy(dev->name, tsec_info->devname); | |
714 | priv->interface = tsec_info->interface; | |
715 | priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname); | |
716 | priv->dev = dev; | |
717 | dev->iobase = 0; | |
718 | dev->priv = priv; | |
719 | dev->init = tsec_init; | |
720 | dev->halt = tsec_halt; | |
721 | dev->send = tsec_send; | |
722 | dev->recv = tsec_recv; | |
723 | #ifdef CONFIG_MCAST_TFTP | |
724 | dev->mcast = tsec_mcast_addr; | |
725 | #endif | |
726 | ||
727 | /* Tell U-Boot to get the addr from the env */ | |
728 | for (i = 0; i < 6; i++) | |
729 | dev->enetaddr[i] = 0; | |
730 | ||
731 | eth_register(dev); | |
732 | ||
733 | /* Reset the MAC */ | |
734 | setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); | |
735 | udelay(2); /* Soft Reset must be asserted for 3 TX clocks */ | |
736 | clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); | |
737 | ||
738 | /* Try to initialize PHY here, and return */ | |
739 | return init_phy(priv); | |
740 | } | |
741 | ||
742 | /* | |
743 | * Initialize all the TSEC devices | |
744 | * | |
745 | * Returns the number of TSEC devices that were initialized | |
746 | */ | |
747 | int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num) | |
748 | { | |
749 | int i; | |
750 | int ret, count = 0; | |
751 | ||
752 | for (i = 0; i < num; i++) { | |
753 | ret = tsec_initialize(bis, &tsecs[i]); | |
754 | if (ret > 0) | |
755 | count += ret; | |
756 | } | |
757 | ||
758 | return count; | |
759 | } | |
760 | ||
761 | int tsec_standard_init(bd_t *bis) | |
762 | { | |
763 | struct fsl_pq_mdio_info info; | |
764 | ||
765 | info.regs = TSEC_GET_MDIO_REGS_BASE(1); | |
766 | info.name = DEFAULT_MII_NAME; | |
767 | ||
768 | fsl_pq_mdio_init(bis, &info); | |
769 | ||
770 | return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info)); | |
771 | } | |
772 | #else /* CONFIG_DM_ETH */ | |
773 | int tsec_probe(struct udevice *dev) | |
774 | { | |
775 | struct tsec_private *priv = dev_get_priv(dev); | |
776 | struct eth_pdata *pdata = dev_get_platdata(dev); | |
777 | struct fsl_pq_mdio_info mdio_info; | |
778 | int offset = 0; | |
779 | int reg; | |
780 | const char *phy_mode; | |
781 | int ret; | |
782 | ||
783 | pdata->iobase = (phys_addr_t)devfdt_get_addr(dev); | |
784 | priv->regs = (struct tsec *)pdata->iobase; | |
785 | ||
786 | offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), | |
787 | "phy-handle"); | |
788 | if (offset > 0) { | |
789 | reg = fdtdec_get_int(gd->fdt_blob, offset, "reg", 0); | |
790 | priv->phyaddr = reg; | |
791 | } else { | |
792 | debug("phy-handle does not exist under tsec %s\n", dev->name); | |
793 | return -ENOENT; | |
794 | } | |
795 | ||
796 | offset = fdt_parent_offset(gd->fdt_blob, offset); | |
797 | if (offset > 0) { | |
798 | reg = fdtdec_get_int(gd->fdt_blob, offset, "reg", 0); | |
799 | priv->phyregs_sgmii = (struct tsec_mii_mng *)(reg + 0x520); | |
800 | } else { | |
801 | debug("No parent node for PHY?\n"); | |
802 | return -ENOENT; | |
803 | } | |
804 | ||
805 | offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), | |
806 | "tbi-handle"); | |
807 | if (offset > 0) { | |
808 | reg = fdtdec_get_int(gd->fdt_blob, offset, "reg", | |
809 | CONFIG_SYS_TBIPA_VALUE); | |
810 | priv->tbiaddr = reg; | |
811 | } else { | |
812 | priv->tbiaddr = CONFIG_SYS_TBIPA_VALUE; | |
813 | } | |
814 | ||
815 | phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), | |
816 | "phy-connection-type", NULL); | |
817 | if (phy_mode) | |
818 | pdata->phy_interface = phy_get_interface_by_name(phy_mode); | |
819 | if (pdata->phy_interface == -1) { | |
820 | debug("Invalid PHY interface '%s'\n", phy_mode); | |
821 | return -EINVAL; | |
822 | } | |
823 | priv->interface = pdata->phy_interface; | |
824 | ||
825 | /* Initialize flags */ | |
826 | priv->flags = TSEC_GIGABIT; | |
827 | if (priv->interface == PHY_INTERFACE_MODE_SGMII) | |
828 | priv->flags |= TSEC_SGMII; | |
829 | ||
830 | mdio_info.regs = priv->phyregs_sgmii; | |
831 | mdio_info.name = (char *)dev->name; | |
832 | ret = fsl_pq_mdio_init(NULL, &mdio_info); | |
833 | if (ret) | |
834 | return ret; | |
835 | ||
836 | /* Reset the MAC */ | |
837 | setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); | |
838 | udelay(2); /* Soft Reset must be asserted for 3 TX clocks */ | |
839 | clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); | |
840 | ||
841 | priv->dev = dev; | |
842 | priv->bus = miiphy_get_dev_by_name(dev->name); | |
843 | ||
844 | /* Try to initialize PHY here, and return */ | |
845 | return !init_phy(priv); | |
846 | } | |
847 | ||
848 | int tsec_remove(struct udevice *dev) | |
849 | { | |
850 | struct tsec_private *priv = dev->priv; | |
851 | ||
852 | free(priv->phydev); | |
853 | mdio_unregister(priv->bus); | |
854 | mdio_free(priv->bus); | |
855 | ||
856 | return 0; | |
857 | } | |
858 | ||
859 | static const struct eth_ops tsec_ops = { | |
860 | .start = tsec_init, | |
861 | .send = tsec_send, | |
862 | .recv = tsec_recv, | |
863 | .free_pkt = tsec_free_pkt, | |
864 | .stop = tsec_halt, | |
865 | #ifdef CONFIG_MCAST_TFTP | |
866 | .mcast = tsec_mcast_addr, | |
867 | #endif | |
868 | }; | |
869 | ||
870 | static const struct udevice_id tsec_ids[] = { | |
871 | { .compatible = "fsl,tsec" }, | |
872 | { } | |
873 | }; | |
874 | ||
875 | U_BOOT_DRIVER(eth_tsec) = { | |
876 | .name = "tsec", | |
877 | .id = UCLASS_ETH, | |
878 | .of_match = tsec_ids, | |
879 | .probe = tsec_probe, | |
880 | .remove = tsec_remove, | |
881 | .ops = &tsec_ops, | |
882 | .priv_auto_alloc_size = sizeof(struct tsec_private), | |
883 | .platdata_auto_alloc_size = sizeof(struct eth_pdata), | |
884 | .flags = DM_FLAG_ALLOC_PRIV_DMA, | |
885 | }; | |
886 | #endif /* CONFIG_DM_ETH */ |