1 /*
2 * Copyright 2014-2017 Cavium, Inc.
3 * The contents of this file are subject to the terms of the Common Development
4 * and Distribution License, v.1, (the "License").
5 *
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the License at available
9 * at http://opensource.org/licenses/CDDL-1.0
10 *
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 #include "54xx_reg.h"
16 #include "serdes.h"
17 #include "lm5706.h"
18 #include "netlink.h"
19
20
21
22 /*******************************************************************************
23 * Macros.
24 ******************************************************************************/
25
26 #define MII_REG(_type, _field) (OFFSETOF(_type, _field)/2)
27
28
29
30 /*******************************************************************************
31 * Description:
32 *
33 * Return:
34 ******************************************************************************/
35 lm_status_t
lm_mwrite(lm_device_t * pdev,u32_t phy_addr,u32_t reg,u32_t val)36 lm_mwrite(
37 lm_device_t *pdev,
38 u32_t phy_addr,
39 u32_t reg,
40 u32_t val)
41 {
42 lm_status_t lm_status;
43 u32_t tmp;
44 u32_t cnt;
45
46 DbgBreakIf(pdev->params.enable_remote_phy);
47
48 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
49 {
50 REG_RD(pdev, emac.emac_mdio_mode, &tmp);
51 tmp &= ~EMAC_MDIO_MODE_AUTO_POLL;
52
53 REG_WR(pdev, emac.emac_mdio_mode, tmp);
54
55 mm_wait(pdev, 40);
56 }
57
58 tmp = (phy_addr << 21) |
59 (reg << 16) |
60 val |
61 EMAC_MDIO_COMM_COMMAND_WRITE_TE |
62 EMAC_MDIO_COMM_START_BUSY |
63 EMAC_MDIO_COMM_DISEXT;
64
65 REG_WR(pdev, emac.emac_mdio_comm, tmp);
66
67 for(cnt = 0; cnt < 1000; cnt++)
68 {
69 mm_wait(pdev, 10);
70
71 REG_RD(pdev, emac.emac_mdio_comm, &tmp);
72 if(!(tmp & EMAC_MDIO_COMM_START_BUSY))
73 {
74 mm_wait(pdev, 5);
75 break;
76 }
77 }
78
79 if(tmp & EMAC_MDIO_COMM_START_BUSY)
80 {
81 DbgBreakMsg("Write phy register failed\n");
82
83 lm_status = LM_STATUS_FAILURE;
84 }
85 else
86 {
87 lm_status = LM_STATUS_SUCCESS;
88 }
89
90 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
91 {
92 REG_RD(pdev, emac.emac_mdio_mode, &tmp);
93 tmp |= EMAC_MDIO_MODE_AUTO_POLL;
94
95 REG_WR(pdev, emac.emac_mdio_mode, tmp);
96 }
97
98 return lm_status;
99 } /* lm_mwrite */
100
101
102
103 /*******************************************************************************
104 * Description:
105 *
106 * Return:
107 ******************************************************************************/
108 lm_status_t
lm_mread(lm_device_t * pdev,u32_t phy_addr,u32_t reg,u32_t * ret_val)109 lm_mread(
110 lm_device_t *pdev,
111 u32_t phy_addr,
112 u32_t reg,
113 u32_t *ret_val)
114 {
115 lm_status_t lm_status;
116 u32_t val;
117 u32_t cnt;
118
119 DbgBreakIf(pdev->params.enable_remote_phy);
120
121 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
122 {
123 REG_RD(pdev, emac.emac_mdio_mode, &val);
124 val &= ~EMAC_MDIO_MODE_AUTO_POLL;
125
126 REG_WR(pdev, emac.emac_mdio_mode, val);
127
128 mm_wait(pdev, 40);
129 }
130
131 val = (phy_addr << 21) |
132 (reg << 16) |
133 EMAC_MDIO_COMM_COMMAND_READ_TE |
134 EMAC_MDIO_COMM_DISEXT |
135 EMAC_MDIO_COMM_START_BUSY;
136
137 REG_WR(pdev, emac.emac_mdio_comm, val);
138
139 for(cnt = 0; cnt < 1000; cnt++)
140 {
141 mm_wait(pdev, 10);
142
143 REG_RD(pdev, emac.emac_mdio_comm, &val);
144 if(!(val & EMAC_MDIO_COMM_START_BUSY))
145 {
146 /* There is a bug here. The MI_COM_BUSY bit may be cleared
147 * before the data is loaded into the register. */
148 REG_RD(pdev, emac.emac_mdio_comm, &val);
149
150 REG_RD(pdev, emac.emac_mdio_comm, &val);
151 val &= EMAC_MDIO_COMM_DATA;
152
153 break;
154 }
155 }
156
157 if(val & EMAC_MDIO_COMM_START_BUSY)
158 {
159 DbgBreakMsg("Read phy register failed\n");
160
161 val = 0;
162
163 lm_status = LM_STATUS_FAILURE;
164 }
165 else
166 {
167 lm_status = LM_STATUS_SUCCESS;
168 }
169
170 *ret_val = val;
171
172 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
173 {
174 REG_RD(pdev, emac.emac_mdio_mode, &val);
175 val |= EMAC_MDIO_MODE_AUTO_POLL;
176
177 REG_WR(pdev, emac.emac_mdio_mode, val);
178 }
179
180 return lm_status;
181 } /* lm_mread */
182
183
184
185 /*******************************************************************************
186 * Description:
187 *
188 * Return:
189 ******************************************************************************/
190 STATIC u32_t
phy_ad_settings(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl)191 phy_ad_settings(
192 lm_device_t *pdev,
193 lm_medium_t req_medium,
194 lm_flow_control_t flow_ctrl)
195 {
196 u32_t val;
197
198 val = 0;
199
200 /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */
201 if((flow_ctrl == LM_FLOW_CONTROL_AUTO_PAUSE) ||
202 ((flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
203 (flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
204 {
205 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER)
206 {
207 if(CHIP_NUM(pdev) == CHIP_NUM_5706)
208 {
209 val |= PHY_AN_AD_1000X_PAUSE_CAPABLE |
210 PHY_AN_AD_1000X_ASYM_PAUSE;
211 }
212 else
213 {
214 val |= MII_ADVERT_PAUSE;
215 }
216 }
217 else
218 {
219 val |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
220 }
221 }
222 else if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
223 {
224 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER)
225 {
226 if(CHIP_NUM(pdev) == CHIP_NUM_5706)
227 {
228 val |= PHY_AN_AD_1000X_ASYM_PAUSE;
229 }
230 else
231 {
232 val |= MII_ADVERT_ASYM_PAUSE;
233 }
234 }
235 else
236 {
237 val |= PHY_AN_AD_ASYM_PAUSE;
238 }
239 }
240 else if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
241 {
242 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER)
243 {
244 if(CHIP_NUM(pdev) == CHIP_NUM_5706)
245 {
246 val |= PHY_AN_AD_1000X_PAUSE_CAPABLE |
247 PHY_AN_AD_1000X_ASYM_PAUSE;
248 }
249 else
250 {
251 val |= MII_ADVERT_PAUSE;
252 }
253 }
254 else
255 {
256 val |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
257 }
258 }
259
260 return val;
261 } /* phy_ad_settings */
262
263
264
265 /*******************************************************************************
266 * Description:
267 *
268 * Return:
269 ******************************************************************************/
270 STATIC lm_status_t
init_utp(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wire_speed,u32_t wait_link_timeout_us)271 init_utp(
272 lm_device_t *pdev,
273 lm_medium_t req_medium,
274 lm_flow_control_t flow_ctrl,
275 u32_t selective_autoneg,
276 u32_t wire_speed,
277 u32_t wait_link_timeout_us)
278 {
279 u32_t restart_autoneg;
280 lm_status_t lm_status;
281 lm_medium_t duplex;
282 lm_medium_t speed;
283 u32_t val;
284 u32_t cnt;
285
286 if(GET_MEDIUM_TYPE(req_medium) != LM_MEDIUM_TYPE_UTP)
287 {
288 return LM_STATUS_INVALID_PARAMETER;
289 }
290
291 speed = GET_MEDIUM_SPEED(req_medium);
292 duplex = GET_MEDIUM_DUPLEX(req_medium);
293
294 lm_status = LM_STATUS_SUCCESS;
295
296 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
297 for(cnt = 0; cnt < 1000; cnt++)
298 {
299 mm_wait(pdev, 5);
300
301 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val);
302
303 if(!(val & PHY_CTRL_PHY_RESET))
304 {
305 mm_wait(pdev, 5);
306
307 break;
308 }
309 }
310
311 DbgBreakIf(val & PHY_CTRL_PHY_RESET);
312
313 /* Get the PHY id. */
314 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val);
315 pdev->hw_info.phy_id = val << 16;
316 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
317
318 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val);
319 pdev->hw_info.phy_id |= val & 0xffff;
320 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
321
322 DbgBreakIf(
323 (pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
324 pdev->hw_info.phy_id == 0);
325
326 if(CHIP_REV(pdev) == CHIP_REV_FPGA)
327 {
328 /* Configure how the MAC obtain link from the external PHY.
329 * On the FPGA board, LED2 is used as a link signal into the
330 * MAC. Configure LED2 to a link event on the AC101L PHY. */
331 (void) lm_mwrite(pdev, pdev->params.phy_addr, 28, 0x3044);
332 (void) lm_mwrite(pdev, pdev->params.phy_addr, 29, 0x0100);
333 }
334 else
335 {
336 if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
337 {
338 /* Gen6 PHY core has a slight increase in CRC error.
339 * This will workaround the problem which will be
340 * fixed in Gen7 PHY core. */
341 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0c00);
342 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x000a);
343 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x310b);
344 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x201f);
345 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x9506);
346 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x401f);
347 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x14e2);
348 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400);
349 }
350
351 /* Enable/Disable Ethernet@WireSpeed. */
352 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x7007);
353 (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val);
354
355 val &= 0x0ff8;
356
357 if(wire_speed)
358 {
359 val |= 0x10;
360 }
361 else
362 {
363 val &= ~0x10;
364 }
365 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, val | 0x8000 | 0x7);
366
367 /*
368 * Cont00039501 Issue Description: Auto MDIX mode doesn't work in forced speed
369 * while two 5716 connected back-to-back
370 */
371 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x7007);
372 (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val);
373 val |= BIT_9; /*auto mdix*/
374 (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, val | 0x8000 | 0x7);
375
376 }
377
378 /* Expansion register 0x8 is the 10BT control register. BIT 8 of this
379 * register controls the Early DAC Wakeup Enable. this bit allows the
380 * transmitter to be shutdown in 10BT mode except for sending out link
381 * pulses. This allows for a low power operation in 10BT mode which is
382 * useful in WOL application. The default value of this register bit
383 * gets loaded from a strap value on the GPHY provided by the chip that
384 * instantiates the PHY. in Xinan this strap value is 1, meaning that
385 * the early DAC Wakeup Enable bit is set by default. FW/Driver needs to
386 * clear this bit when bringing the PHY out of reset. */
387 if(CHIP_ID(pdev) == CHIP_ID_5709_A0 ||
388 CHIP_ID(pdev) == CHIP_ID_5709_A1 ||
389 CHIP_ID(pdev) == CHIP_ID_5709_B0 ||
390 CHIP_ID(pdev) == CHIP_ID_5709_B1)
391 {
392 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0xf08);
393 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &val);
394 val &= ~0x100;
395 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, val);
396 }
397
398 /* Configure the PHY for jumbo frame. */
399 if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE)
400 {
401 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x0001);
402 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x4400);
403 }
404 else
405 {
406 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x0000);
407 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400);
408 }
409
410 /* Configure line speed. */
411 restart_autoneg = FALSE;
412
413 switch(speed)
414 {
415 case LM_MEDIUM_SPEED_10MBPS:
416 /* Don't advertise 1000mb. This register is undefined on a
417 * 10/100 Mb PHY. */
418 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, 0);
419
420 /* Setup AN_AD to advertise 10mb. */
421 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
422 val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
423
424 if(duplex == LM_MEDIUM_FULL_DUPLEX)
425 {
426 val |= PHY_AN_AD_10BASET_FULL;
427
428 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
429 {
430 val |= PHY_AN_AD_10BASET_HALF;
431 }
432 }
433 else
434 {
435 val |= PHY_AN_AD_10BASET_HALF;
436 }
437
438 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
439
440 /* Forcing or advertising 10mb. */
441 if(selective_autoneg)
442 {
443 restart_autoneg = TRUE;
444
445 DbgMessage(pdev, INFORM, "autoneg 10mb hd\n");
446 if(duplex == LM_MEDIUM_FULL_DUPLEX)
447 {
448 DbgMessage(pdev, INFORM, "and 10mb fd\n");
449 }
450 }
451 else
452 {
453 if(duplex == LM_MEDIUM_HALF_DUPLEX)
454 {
455 DbgMessage(pdev, INFORM, "force 10mb hd\n");
456 (void) lm_mwrite(
457 pdev,
458 pdev->params.phy_addr,
459 PHY_CTRL_REG,
460 PHY_CTRL_SPEED_SELECT_10MBPS);
461 }
462 else
463 {
464 DbgMessage(pdev, INFORM, "force 10mb fd\n");
465 (void) lm_mwrite(
466 pdev,
467 pdev->params.phy_addr,
468 PHY_CTRL_REG,
469 PHY_CTRL_SPEED_SELECT_10MBPS |
470 PHY_CTRL_FULL_DUPLEX_MODE);
471 }
472 }
473
474 break;
475
476 case LM_MEDIUM_SPEED_100MBPS:
477 /* Don't advertise 1000mb. This register is undefined on a
478 * 10/100 PHY. */
479 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, 0);
480
481 /* Setup AN_AD to advertise 10/100mb. */
482 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
483 val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
484
485 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
486 {
487 val |= PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL;
488 }
489
490 if(duplex == LM_MEDIUM_FULL_DUPLEX)
491 {
492 val |= PHY_AN_AD_100BASETX_FULL;
493
494 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
495 {
496 val |= PHY_AN_AD_100BASETX_HALF;
497 }
498 }
499 else
500 {
501 val |= PHY_AN_AD_100BASETX_HALF;
502 }
503
504 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
505
506 /* Forcing or advertising 100mb. */
507 if(selective_autoneg)
508 {
509 restart_autoneg = TRUE;
510
511 DbgMessage(pdev, INFORM, "autoneg 10mb and 100mb hd\n");
512 if(duplex == LM_MEDIUM_FULL_DUPLEX)
513 {
514 DbgMessage(pdev, INFORM, "and 100mb fd\n");
515 }
516 }
517 else
518 {
519 if(duplex == LM_MEDIUM_HALF_DUPLEX)
520 {
521 DbgMessage(pdev, INFORM, "force 100mb hd\n");
522 (void) lm_mwrite(
523 pdev,
524 pdev->params.phy_addr,
525 PHY_CTRL_REG,
526 PHY_CTRL_SPEED_SELECT_100MBPS);
527 }
528 else
529 {
530 DbgMessage(pdev, INFORM, "force 100mb fd\n");
531 (void) lm_mwrite(
532 pdev,
533 pdev->params.phy_addr,
534 PHY_CTRL_REG,
535 PHY_CTRL_SPEED_SELECT_100MBPS |
536 PHY_CTRL_FULL_DUPLEX_MODE);
537 }
538 }
539
540 break;
541
542 case LM_MEDIUM_SPEED_1000MBPS:
543 /* Don't advertise 10/100mb. */
544 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
545 val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
546
547 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
548 {
549 val |= PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL;
550 val |= PHY_AN_AD_100BASETX_HALF | PHY_AN_AD_100BASETX_FULL;
551 }
552
553 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
554
555 /* Setup AN_AD to advertise 1000mb. This register is defined on
556 * a 10/100 Mb PHY. */
557 if(duplex == LM_MEDIUM_FULL_DUPLEX)
558 {
559 val |= PHY_AN_AD_1000BASET_FULL;
560
561 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
562 {
563 val |= PHY_AN_AD_1000BASET_HALF;
564 }
565 }
566 else
567 {
568 val |= PHY_AN_AD_1000BASET_HALF;
569 }
570
571 /* Forcing or advertising 1000mb. */
572 if(selective_autoneg)
573 {
574 DbgMessage(pdev, INFORM, "autoneg 10/100mb and 1000mb hd\n");
575 if(duplex == LM_MEDIUM_FULL_DUPLEX)
576 {
577 DbgMessage(pdev, INFORM, "and 1000mb fd\n");
578 }
579
580 restart_autoneg = TRUE;
581 }
582 else
583 {
584 /* external loopback at 1gb link. */
585 (void) lm_mwrite(
586 pdev,
587 pdev->params.phy_addr,
588 PHY_CTRL_REG,
589 PHY_CTRL_SPEED_SELECT_1000MBPS);
590
591 (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, 0x7);
592 (void) lm_mread(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, &val);
593 val |= BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK;
594 (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, val);
595
596 val = PHY_CONFIG_AS_MASTER | PHY_ENABLE_CONFIG_AS_MASTER;
597 }
598
599 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, val);
600 break;
601
602 default:
603 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
604 PHY_AN_AD_10BASET_HALF |
605 PHY_AN_AD_10BASET_FULL |
606 PHY_AN_AD_100BASETX_FULL |
607 PHY_AN_AD_100BASETX_HALF;
608 val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
609
610 /* Set up the 10/100 advertisement register. */
611 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
612
613 /* Advertise 1000Mbps. This register is undefined on a
614 * 10/100 Mb PHY. */
615 (void) lm_mwrite(
616 pdev,
617 pdev->params.phy_addr,
618 PHY_1000BASET_CTRL_REG,
619 PHY_AN_AD_1000BASET_HALF |
620 PHY_AN_AD_1000BASET_FULL);
621
622 restart_autoneg = TRUE;
623 speed = LM_MEDIUM_SPEED_AUTONEG;
624 break;
625 }
626
627 /* exit mac loopback. we could be in mac loopback mode if previously
628 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
629 * medium type for diagnostic. */
630 REG_RD(pdev, emac.emac_mode, &val);
631 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
632 REG_WR(pdev, emac.emac_mode, val);
633
634 /* Restart auto-negotation. */
635 if(restart_autoneg)
636 {
637 DbgMessage(pdev, INFORM, "phy init - restart autoneg\n");
638
639 (void) lm_mwrite(
640 pdev,
641 pdev->params.phy_addr,
642 PHY_CTRL_REG,
643 PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG);
644 }
645
646 /* Save current medium settings. */
647 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_UTP);
648 SET_MEDIUM_SPEED(pdev->vars.medium, speed);
649 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
650
651 pdev->vars.cable_is_attached = FALSE;
652
653 /* Wait for link. */
654 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
655
656 if(CHIP_REV(pdev) != CHIP_REV_FPGA)
657 {
658 /* Wait for link only if the cable is connected. */
659 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
660 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
661 if(val & 0x20)
662 {
663 for(; ;)
664 {
665 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
666 if(val & PHY_STATUS_LINK_PASS)
667 {
668 break;
669 }
670
671 mm_wait(pdev, 10);
672
673 if(wait_link_timeout_us <= 10)
674 {
675 break;
676 }
677
678 wait_link_timeout_us -= 10;
679 }
680
681 pdev->vars.cable_is_attached = TRUE;
682 }
683 }
684
685 /* Need to read a second time to get the current link status. */
686 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
687 if(val & PHY_STATUS_LINK_PASS)
688 {
689 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
690 DbgMessage(pdev, INFORM, "phy init link up\n");
691
692 pdev->vars.cable_is_attached = TRUE;
693 }
694 else
695 {
696 pdev->vars.link_status = LM_STATUS_LINK_DOWN;
697 DbgMessage(pdev, INFORM, "phy init link down\n");
698 }
699
700 return lm_status;
701 } /* init_utp */
702
703
704
705 /*******************************************************************************
706 * Description:
707 *
708 * Return:
709 ******************************************************************************/
710 STATIC u32_t
mii_get_serdes_link_status(lm_device_t * pdev)711 mii_get_serdes_link_status(
712 lm_device_t *pdev)
713 {
714 u32_t val;
715
716 /* The link status in the MII status register is not reliable for
717 * the SERDES part. We need to get the link info from the MAC. */
718 if(CHIP_NUM(pdev) == CHIP_NUM_5706 &&
719 lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
720 {
721 REG_RD(pdev, emac.emac_status, &val);
722 if(val & EMAC_STATUS_LINK)
723 {
724 val = PHY_STATUS_LINK_PASS;
725 }
726 else
727 {
728 val = 0;
729 }
730 }
731 else
732 {
733 /* The second read returns the current status. */
734 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
735 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
736 }
737
738 return val;
739 } /* mii_get_serdes_link_status */
740
741
742
743 /*******************************************************************************
744 * Description:
745 *
746 * Return:
747 ******************************************************************************/
748 STATIC u8_t
set_5708_serdes_pre_emphasis(lm_device_t * pdev,u32_t pre_emphasis)749 set_5708_serdes_pre_emphasis(
750 lm_device_t *pdev,
751 u32_t pre_emphasis)
752 {
753 u8_t restart_autoneg;
754 u32_t val;
755
756 restart_autoneg = FALSE;
757
758 if(pre_emphasis == 0)
759 {
760 (void) lm_mread(
761 pdev,
762 pdev->params.phy_addr,
763 MII_REG(serdes_reg_t, mii_aneg_nxt_pg_rcv2),
764 &pre_emphasis);
765 pre_emphasis &= 0xf;
766
767 if(pre_emphasis != pdev->vars.serdes_pre_emphasis)
768 {
769 pdev->vars.serdes_pre_emphasis = pre_emphasis;
770
771 restart_autoneg = TRUE;
772
773 /* Switch to Bank 5. */
774 (void) lm_mwrite(
775 pdev,
776 pdev->params.phy_addr,
777 MII_REG(serdes_reg_t, mii_block_addr),
778 MII_BLK_ADDR_TXMISC);
779
780 /* Write the new pre-emphasis. */
781 (void) lm_mread(
782 pdev,
783 pdev->params.phy_addr,
784 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3),
785 &val);
786
787 pre_emphasis =
788 ((pre_emphasis & 0x1) << 15) |
789 ((pre_emphasis & 0x2) << 13) |
790 ((pre_emphasis & 0x4) << 11) |
791 ((pre_emphasis & 0x8) << 9);
792 val = (val & 0x0fff) | pre_emphasis;
793
794 (void) lm_mwrite(
795 pdev,
796 pdev->params.phy_addr,
797 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3),
798 val);
799
800 /* Select Bank 0. */
801 (void) lm_mwrite(
802 pdev,
803 pdev->params.phy_addr,
804 MII_REG(serdes_reg_t, mii_block_addr),
805 MII_BLK_ADDR_DIGITAL);
806
807 /* Restart autoneg. */
808 (void) lm_mwrite(
809 pdev,
810 pdev->params.phy_addr,
811 MII_REG(serdes_reg_t, mii_ctrl),
812 MII_CTRL_RESTART_ANEG | MII_CTRL_ANEG_ENA);
813 }
814 }
815 else
816 {
817 (void) lm_mwrite(
818 pdev,
819 pdev->params.phy_addr,
820 MII_REG(serdes_reg_t, mii_block_addr),
821 MII_BLK_ADDR_TXMISC);
822
823 (void) lm_mwrite(
824 pdev,
825 pdev->params.phy_addr,
826 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3),
827 pre_emphasis);
828
829 (void) lm_mwrite(
830 pdev,
831 pdev->params.phy_addr,
832 MII_REG(serdes_reg_t, mii_block_addr),
833 MII_BLK_ADDR_DIGITAL);
834 }
835
836 return restart_autoneg;
837 } /* set_5708_serdes_pre_emphasis */
838
839
840
841 /*******************************************************************************
842 * Description:
843 *
844 * Return:
845 ******************************************************************************/
846 STATIC lm_status_t
init_5708_serdes(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wait_link_timeout_us)847 init_5708_serdes(
848 lm_device_t *pdev,
849 lm_medium_t req_medium,
850 lm_flow_control_t flow_ctrl,
851 u32_t selective_autoneg,
852 u32_t wait_link_timeout_us)
853 {
854 lm_medium_t duplex;
855 lm_medium_t speed;
856 u32_t cnt;
857 u32_t val;
858
859 if(GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_UNKNOWN)
860 {
861 selective_autoneg = FALSE;
862 }
863
864 speed = GET_MEDIUM_SPEED(req_medium);
865 duplex = GET_MEDIUM_DUPLEX(req_medium);
866
867 if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT)
868 {
869 REG_RD_IND(
870 pdev,
871 pdev->hw_info.shmem_base +
872 OFFSETOF(shmem_region_t, dev_info.port_hw_config.config),
873 &val);
874
875 switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK)
876 {
877 case PORT_HW_CFG_DEFAULT_LINK_1G:
878 speed = LM_MEDIUM_SPEED_1000MBPS;
879 break;
880
881 case PORT_HW_CFG_DEFAULT_LINK_2_5G:
882 speed = LM_MEDIUM_SPEED_2500MBPS;
883 break;
884
885 default:
886 speed = LM_MEDIUM_SPEED_UNKNOWN;
887 break;
888 }
889 }
890
891 /* Reset the SERDES. */
892 (void) lm_mwrite(
893 pdev,
894 pdev->params.phy_addr,
895 MII_REG(serdes_reg_t, mii_ctrl),
896 MII_CTRL_RESET);
897
898 for(cnt = 0; cnt < 1000; cnt++)
899 {
900 mm_wait(pdev, 5);
901
902 (void) lm_mread(
903 pdev,
904 pdev->params.phy_addr,
905 MII_REG(serdes_reg_t, mii_ctrl),
906 &val);
907
908 if(!(val & MII_CTRL_RESET))
909 {
910 mm_wait(pdev, 5);
911
912 break;
913 }
914 }
915
916 DbgBreakIf(val & MII_CTRL_RESET);
917
918 /* Workaround for 5708A0 and B0.
919 *
920 * Errata 1.75: Tx peak-to-peak amplitude was measured as low
921 * as 765mV under full PVT testing, whereas 800mV is considered
922 * a passing result. */
923 if(CHIP_NUM(pdev) == CHIP_NUM_5708)
924 {
925 /* Switch to Bank 5. */
926 (void) lm_mwrite(
927 pdev,
928 pdev->params.phy_addr,
929 MII_REG(serdes_reg_t, mii_block_addr),
930 MII_BLK_ADDR_TXMISC);
931
932 (void) lm_mread(
933 pdev,
934 pdev->params.phy_addr,
935 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl1),
936 &val);
937
938 val &= ~ MII_TXACTL1_DRIVER_VCM;
939
940 (void) lm_mwrite(
941 pdev,
942 pdev->params.phy_addr,
943 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl1),
944 val);
945 }
946
947 /* Set up pre-emphasis for a backplane application. */
948 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP)
949 {
950 (void) set_5708_serdes_pre_emphasis(pdev, pdev->params.serdes_pre_emphasis);
951 }
952
953 /* Reset the pre_emphasis. */
954 pdev->vars.serdes_pre_emphasis = 0;
955
956 /* Get the PHY id. */
957 (void) lm_mread(
958 pdev,
959 pdev->params.phy_addr,
960 MII_REG(serdes_reg_t, mii_phy_id_msb),
961 &val);
962 pdev->hw_info.phy_id = val << 16;
963 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
964
965 (void) lm_mread(
966 pdev,
967 pdev->params.phy_addr,
968 MII_REG(serdes_reg_t, mii_phy_id_lsb),
969 &val);
970 pdev->hw_info.phy_id |= val & 0xffff;
971 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
972
973 DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
974 pdev->hw_info.phy_id == 0);
975
976 /* Enable 2.5G register set to be accessible in the IEEE registers. */
977 (void) lm_mwrite(
978 pdev,
979 pdev->params.phy_addr,
980 MII_REG(serdes_reg_t, mii_block_addr),
981 MII_BLK_ADDR_DIGITAL3);
982 (void) lm_mwrite(
983 pdev,
984 pdev->params.phy_addr,
985 0x10+MII_REG(serdes_digital3_reg_t, mii_digctl_3_0),
986 MII_DIG3_USE_IEEE);
987
988 /* Switch back to the IEEE Bank. */
989 (void) lm_mwrite(
990 pdev,
991 pdev->params.phy_addr,
992 MII_REG(serdes_reg_t, mii_block_addr),
993 MII_BLK_ADDR_DIGITAL);
994
995 /* Enable SGMII/Fiber mode autodetection. */
996 (void) lm_mread(
997 pdev,
998 pdev->params.phy_addr,
999 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1000 &val);
1001
1002 val |= MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN;
1003
1004 /* Sigdet is enabled by default. For backplane application, we need
1005 * to disable Sigdet by clearing 0*0x10.2 of the Digital Bank. */
1006 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP)
1007 {
1008 val &= ~MII_1000X_CTL1_SIG_DET_EN;
1009 }
1010 else
1011 {
1012 val |= MII_1000X_CTL1_SIG_DET_EN;
1013 }
1014
1015 (void) lm_mwrite(
1016 pdev,
1017 pdev->params.phy_addr,
1018 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1019 val);
1020
1021 /* We should always enable parallel detection. */
1022 (void) lm_mread(
1023 pdev,
1024 pdev->params.phy_addr,
1025 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl2),
1026 &val);
1027
1028 val |= MII_1000X_CTL2_PAR_DET_EN;
1029
1030 (void) lm_mwrite(
1031 pdev,
1032 pdev->params.phy_addr,
1033 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl2),
1034 val);
1035
1036 /* Enable/disable 2.5G capability. */
1037 (void) lm_mread(
1038 pdev,
1039 pdev->params.phy_addr,
1040 MII_REG(serdes_reg_t, mii_aneg_nxt_pg_xmit1),
1041 &val);
1042
1043 val &= ~MII_ANEG_NXT_PG_XMIT1_2G5;
1044
1045 if(selective_autoneg)
1046 {
1047 if(speed == LM_MEDIUM_SPEED_2500MBPS)
1048 {
1049 val |= MII_ANEG_NXT_PG_XMIT1_2G5;
1050 }
1051 }
1052 else if(speed == LM_MEDIUM_SPEED_AUTONEG)
1053 {
1054 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_PHY_FIBER_2_5G)
1055 {
1056 val |= MII_ANEG_NXT_PG_XMIT1_2G5;
1057 }
1058 }
1059 else if(speed == LM_MEDIUM_SPEED_2500MBPS)
1060 {
1061 val |= MII_ANEG_NXT_PG_XMIT1_2G5;
1062 }
1063
1064 (void) lm_mwrite(
1065 pdev,
1066 pdev->params.phy_addr,
1067 MII_REG(serdes_reg_t, mii_aneg_nxt_pg_xmit1),
1068 val);
1069
1070 val = 0;
1071
1072 if(selective_autoneg || speed == LM_MEDIUM_SPEED_UNKNOWN)
1073 {
1074 val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
1075
1076 if((selective_autoneg && speed == LM_MEDIUM_SPEED_1000MBPS) ||
1077 speed == LM_MEDIUM_SPEED_UNKNOWN)
1078 {
1079 val |= MII_ABILITY_HALF | MII_ABILITY_FULL;
1080 }
1081
1082 (void) lm_mwrite(
1083 pdev,
1084 pdev->params.phy_addr,
1085 MII_REG(serdes_reg_t, mii_aneg_advert),
1086 val);
1087
1088 (void) lm_mwrite(
1089 pdev,
1090 pdev->params.phy_addr,
1091 MII_REG(serdes_reg_t, mii_ctrl),
1092 MII_CTRL_RESTART_ANEG | MII_CTRL_ANEG_ENA);
1093
1094 speed = LM_MEDIUM_SPEED_AUTONEG;
1095 }
1096 else
1097 {
1098 switch(speed)
1099 {
1100 case LM_MEDIUM_SPEED_10MBPS:
1101 if(duplex == LM_MEDIUM_FULL_DUPLEX)
1102 {
1103 val |= MII_CTRL_DUPLEX_MODE;
1104 }
1105
1106 (void) lm_mwrite(
1107 pdev,
1108 pdev->params.phy_addr,
1109 MII_REG(serdes_reg_t, mii_ctrl),
1110 val);
1111 /* Switch to SGMII mode and disable auto-detect */
1112 (void) lm_mread(
1113 pdev,
1114 pdev->params.phy_addr,
1115 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1116 &val);
1117 (void) lm_mwrite(
1118 pdev,
1119 pdev->params.phy_addr,
1120 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1121 val & ~(MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN));
1122 break;
1123
1124 case LM_MEDIUM_SPEED_100MBPS:
1125 if(duplex == LM_MEDIUM_FULL_DUPLEX)
1126 {
1127 val |= MII_CTRL_DUPLEX_MODE;
1128 }
1129
1130 val |= MII_CTRL_MANUAL_SPD0;
1131
1132 (void) lm_mwrite(
1133 pdev,
1134 pdev->params.phy_addr,
1135 MII_REG(serdes_reg_t, mii_ctrl),
1136 val);
1137 /* Switch to SGMII mode and disable auto-detect */
1138 (void) lm_mread(
1139 pdev,
1140 pdev->params.phy_addr,
1141 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1142 &val);
1143 (void) lm_mwrite(
1144 pdev,
1145 pdev->params.phy_addr,
1146 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1147 val & ~(MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN));
1148 break;
1149
1150 case LM_MEDIUM_SPEED_1000MBPS:
1151 if(duplex == LM_MEDIUM_FULL_DUPLEX)
1152 {
1153 val |= MII_CTRL_DUPLEX_MODE;
1154 }
1155
1156 val |= MII_CTRL_MANUAL_SPD1;
1157
1158 (void) lm_mwrite(
1159 pdev,
1160 pdev->params.phy_addr,
1161 MII_REG(serdes_reg_t, mii_ctrl),
1162 val);
1163 break;
1164
1165 case LM_MEDIUM_SPEED_2500MBPS:
1166 if(duplex == LM_MEDIUM_FULL_DUPLEX)
1167 {
1168 val |= MII_CTRL_DUPLEX_MODE;
1169 }
1170
1171 val |= MII_CTRL_MANUAL_FORCE_2500;
1172
1173 (void) lm_mwrite(
1174 pdev,
1175 pdev->params.phy_addr,
1176 MII_REG(serdes_reg_t, mii_ctrl),
1177 val);
1178 break;
1179 }
1180 }
1181
1182 /* exit mac loopback. we could be in mac loopback mode if previously
1183 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
1184 * medium type for diagnostic. */
1185 REG_RD(pdev, emac.emac_mode, &val);
1186 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
1187 REG_WR(pdev, emac.emac_mode, val);
1188
1189 /* Configure the PHY for jumbo frame. */
1190 if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE)
1191 {
1192 (void) lm_mwrite(
1193 pdev,
1194 pdev->params.phy_addr,
1195 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl3),
1196 MII_1000X_CTL3_FIFO_ELAST_10K);
1197 }
1198 else
1199 {
1200 (void) lm_mwrite(
1201 pdev,
1202 pdev->params.phy_addr,
1203 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl3),
1204 0);
1205 }
1206
1207 /* Save current medium settings. */
1208 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER);
1209 SET_MEDIUM_SPEED(pdev->vars.medium, speed);
1210 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
1211
1212 pdev->vars.cable_is_attached = FALSE;
1213
1214 /* Wait for link. */
1215 (void) lm_mread(
1216 pdev,
1217 pdev->params.phy_addr,
1218 MII_REG(serdes_reg_t, mii_status),
1219 &val);
1220
1221 for(; ;)
1222 {
1223 (void) lm_mread(
1224 pdev,
1225 pdev->params.phy_addr,
1226 MII_REG(serdes_reg_t, mii_status),
1227 &val);
1228 if(val & MII_STAT_LINK_STATUS)
1229 {
1230 break;
1231 }
1232
1233 mm_wait(pdev, 10);
1234
1235 if(wait_link_timeout_us <= 10)
1236 {
1237 break;
1238 }
1239
1240 wait_link_timeout_us -= 10;
1241 }
1242
1243 /* Need to read a second time to get the current link status. */
1244 (void) lm_mread(
1245 pdev,
1246 pdev->params.phy_addr,
1247 MII_REG(serdes_reg_t, mii_status),
1248 &val);
1249 if(val & MII_STAT_LINK_STATUS)
1250 {
1251 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1252 DbgMessage(pdev, INFORM, "phy init link up\n");
1253
1254 pdev->vars.cable_is_attached = TRUE;
1255 }
1256 else
1257 {
1258 pdev->vars.link_status = LM_STATUS_LINK_DOWN;
1259 DbgMessage(pdev, INFORM, "phy init link down\n");
1260 }
1261
1262 return LM_STATUS_SUCCESS;
1263 } /* init_5708_serdes */
1264
1265
1266
1267 /*******************************************************************************
1268 * Description:
1269 *
1270 * Return:
1271 ******************************************************************************/
1272 STATIC void
force_5709_serdes_link(lm_device_t * pdev,lm_medium_t speed,lm_medium_t duplex)1273 force_5709_serdes_link(
1274 lm_device_t *pdev,
1275 lm_medium_t speed,
1276 lm_medium_t duplex)
1277 {
1278 u32_t val;
1279
1280 /* select serdes digital block. */
1281 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300);
1282
1283 /* disable sgmii/fiber mode autodetection. */
1284 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1285 val &= ~0x10;
1286
1287 /* sgmii or 1000x_fiber mode. */
1288 val &= ~1;
1289 if(speed == LM_MEDIUM_SPEED_2500MBPS)
1290 {
1291 val |= 1;
1292 }
1293
1294 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1295
1296 /* select combo ieee0 block. */
1297 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1298
1299 /* phy control register. */
1300 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1301
1302 val &= ~0x1000; /* autoneg. */
1303 val &= ~0x100; /* duplex. */
1304 val &= ~0x2060; /* speed. */
1305
1306 if(duplex == LM_MEDIUM_FULL_DUPLEX)
1307 {
1308 val |= 0x100;
1309 }
1310
1311 if(speed == LM_MEDIUM_SPEED_10MBPS)
1312 {
1313 /* bit 13 and 6 are already cleared. */
1314 ;
1315 }
1316 else if(speed == LM_MEDIUM_SPEED_100MBPS)
1317 {
1318 val |= 0x2000;
1319 }
1320 else if(speed == LM_MEDIUM_SPEED_1000MBPS)
1321 {
1322 val |= 0x2040;
1323 }
1324 else if(speed == LM_MEDIUM_SPEED_2500MBPS)
1325 {
1326 val |= 0x20;
1327 }
1328 else
1329 {
1330 DbgBreakMsg("unknown forced speed.\n");
1331 }
1332
1333 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1334
1335 /* set speed. */
1336 if(speed == LM_MEDIUM_SPEED_2500MBPS)
1337 {
1338 /* select serdes digital block. */
1339 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300);
1340
1341 /* set 2.5g speed. */
1342 (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val);
1343 val &= 0xfff0;
1344 val |= 0x10;
1345 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, val);
1346 }
1347 } /* force_5709_serdes_link */
1348
1349
1350
1351 /*******************************************************************************
1352 * Description:
1353 *
1354 * Return:
1355 ******************************************************************************/
1356 STATIC void
init_5709_serdes_for_autoneg(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg)1357 init_5709_serdes_for_autoneg(
1358 lm_device_t *pdev,
1359 lm_medium_t req_medium,
1360 lm_flow_control_t flow_ctrl,
1361 u32_t selective_autoneg)
1362 {
1363 u32_t val;
1364
1365 if(GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_UNKNOWN)
1366 {
1367 selective_autoneg = FALSE;
1368 }
1369
1370 if(!(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_PHY_FIBER_2_5G) ||
1371 (selective_autoneg &&
1372 GET_MEDIUM_SPEED(req_medium) != LM_MEDIUM_SPEED_2500MBPS))
1373 {
1374 /* disable 2.5g adv */
1375 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8320);
1376 (void) lm_mread(pdev, pdev->params.phy_addr, 0x19, &val);
1377 val &= ~1;
1378 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x19, val);
1379 }
1380
1381 /* select serdes digital block. */
1382 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300);
1383
1384 /* enable sgmii/fiber mode autodetection. */
1385 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1386 val |= 0x10;
1387 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1388
1389 /* disable parallel detection. */
1390 if(selective_autoneg)
1391 {
1392 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1393 val &= ~0x1;
1394 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x11, val);
1395 }
1396
1397 /* select bam next page block. */
1398 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8350);
1399
1400 /* mp5_next_page_control. */
1401 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1402 val &= ~3;
1403 val |= 1; /* set bam mode. */
1404 val |= 2; /* enable t2 mode. */
1405 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1406
1407 /* select cl73_userb0 block. */
1408 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8370);
1409
1410 /* enable bam_en, bam_station_mngr_en, bam_np_after_bp_en. */
1411 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x12, 0xe000);
1412
1413 /* select ieee1 block. */
1414 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x10);
1415
1416 /* advertise 1000kx. */
1417 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1, &val);
1418 val |= 0x20;
1419 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1, val);
1420
1421 /* select ieee0 block. */
1422 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0);
1423
1424 /* enable cl73 aneg. */
1425 (void) lm_mread(pdev, pdev->params.phy_addr, 0x0, &val);
1426 val |= 0x1200;
1427 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x0, val);
1428
1429 /* select combo ieee0 block. */
1430 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1431
1432 /* advertise pause capability and duplex mode. */
1433 val = phy_ad_settings(pdev, req_medium, flow_ctrl);
1434 if(selective_autoneg &&
1435 GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_2500MBPS)
1436 {
1437 val &= ~0x60;
1438 }
1439 else
1440 {
1441 val |= 0x60; /* half/full duplex. */
1442 }
1443 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x14, val);
1444
1445 /* autoneg_enable and restart. */
1446 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1447 val |= 0x1200;
1448 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1449 } /* init_5709_serdes_for_autoneg */
1450
1451
1452
1453 /*******************************************************************************
1454 * Description:
1455 *
1456 * Return:
1457 ******************************************************************************/
1458 STATIC lm_status_t
init_5709_serdes(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wait_link_timeout_us)1459 init_5709_serdes(
1460 lm_device_t *pdev,
1461 lm_medium_t req_medium,
1462 lm_flow_control_t flow_ctrl,
1463 u32_t selective_autoneg,
1464 u32_t wait_link_timeout_us)
1465 {
1466 lm_medium_t duplex;
1467 lm_medium_t speed;
1468 u32_t idx;
1469 u32_t val;
1470
1471 speed = GET_MEDIUM_SPEED(req_medium);
1472 duplex = GET_MEDIUM_DUPLEX(req_medium);
1473
1474 /* use nvram link speed configuration. */
1475 if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT)
1476 {
1477 REG_RD_IND(
1478 pdev,
1479 pdev->hw_info.shmem_base +
1480 OFFSETOF(shmem_region_t, dev_info.port_hw_config.config),
1481 &val);
1482
1483 switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK)
1484 {
1485 case PORT_HW_CFG_DEFAULT_LINK_1G:
1486 speed = LM_MEDIUM_SPEED_1000MBPS;
1487 break;
1488
1489 case PORT_HW_CFG_DEFAULT_LINK_2_5G:
1490 speed = LM_MEDIUM_SPEED_2500MBPS;
1491 break;
1492
1493 default:
1494 speed = LM_MEDIUM_SPEED_UNKNOWN;
1495 break;
1496 }
1497
1498 selective_autoneg = FALSE;
1499 }
1500
1501 /* set an_mmd. an_mmd is the only register set we need for
1502 * programming xinan serdes. all other registers are can
1503 * be access through an_mmd. */
1504 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffd0);
1505 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1e, 0x3800);
1506
1507 /* select combo_ieee0 block. */
1508 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1509
1510 /* reset. */
1511 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, MII_CTRL_RESET);
1512 for(idx = 0; idx < 1000; idx++)
1513 {
1514 mm_wait(pdev, 5);
1515
1516 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1517 if(!(val & MII_CTRL_RESET))
1518 {
1519 mm_wait(pdev, 5);
1520 break;
1521 }
1522 }
1523 DbgBreakIf(val & MII_CTRL_RESET);
1524
1525 /* get phy id. */
1526 (void) lm_mread(pdev, pdev->params.phy_addr, 0x12, &val);
1527 pdev->hw_info.phy_id = val << 16;
1528 (void) lm_mread(pdev, pdev->params.phy_addr, 0x13, &val);
1529 pdev->hw_info.phy_id |= val & 0xffff;
1530
1531 if(speed == LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK)
1532 {
1533 speed = LM_MEDIUM_SPEED_AUTONEG;
1534 }
1535
1536 /* config link speed or autoneg setting. */
1537 if(speed == LM_MEDIUM_SPEED_AUTONEG || selective_autoneg)
1538 {
1539 init_5709_serdes_for_autoneg(
1540 pdev,
1541 req_medium,
1542 flow_ctrl,
1543 selective_autoneg);
1544 }
1545 else
1546 {
1547 force_5709_serdes_link(pdev, speed, duplex);
1548 }
1549
1550 /* exit mac loopback. we could be in mac loopback mode if previously
1551 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
1552 * medium type for diagnostic. */
1553 REG_RD(pdev, emac.emac_mode, &val);
1554 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
1555 REG_WR(pdev, emac.emac_mode, val);
1556
1557 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER);
1558 SET_MEDIUM_SPEED(pdev->vars.medium, speed);
1559 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
1560
1561 pdev->vars.cable_is_attached = FALSE;
1562
1563 /* select combo_ieee0 block. */
1564 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1565
1566 /* wait for link. */
1567 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1568
1569 for(; ;)
1570 {
1571 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1572 if(val & 0x4)
1573 {
1574 break;
1575 }
1576
1577 mm_wait(pdev, 10);
1578
1579 if(wait_link_timeout_us <= 10)
1580 {
1581 break;
1582 }
1583
1584 wait_link_timeout_us -= 10;
1585 }
1586
1587 /* need to read a second time to get the current link status. */
1588 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1589
1590 if(val & MII_STAT_LINK_STATUS)
1591 {
1592 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1593 pdev->vars.cable_is_attached = TRUE;
1594 }
1595 else
1596 {
1597 pdev->vars.link_status = LM_STATUS_LINK_DOWN;
1598 }
1599
1600 return LM_STATUS_SUCCESS;
1601 } /* init_5709_serdes */
1602
1603
1604
1605 /*******************************************************************************
1606 * Description:
1607 *
1608 * Return:
1609 ******************************************************************************/
1610 STATIC lm_status_t
init_5706_serdes(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t wait_link_timeout_us)1611 init_5706_serdes(
1612 lm_device_t *pdev,
1613 lm_medium_t req_medium,
1614 lm_flow_control_t flow_ctrl,
1615 u32_t wait_link_timeout_us)
1616 {
1617 lm_medium_t duplex;
1618 lm_medium_t speed;
1619 u32_t val;
1620 u32_t cnt;
1621
1622 speed = GET_MEDIUM_SPEED(req_medium);
1623 duplex = GET_MEDIUM_DUPLEX(req_medium);
1624
1625 if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT)
1626 {
1627 REG_RD_IND(
1628 pdev,
1629 pdev->hw_info.shmem_base +
1630 OFFSETOF(shmem_region_t, dev_info.port_hw_config.config),
1631 &val);
1632 switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK)
1633 {
1634 case PORT_HW_CFG_DEFAULT_LINK_1G:
1635 speed = LM_MEDIUM_SPEED_1000MBPS;
1636 break;
1637
1638 case PORT_HW_CFG_DEFAULT_LINK_2_5G:
1639 speed = LM_MEDIUM_SPEED_2500MBPS;
1640 break;
1641
1642 case PORT_HW_CFG_DEFAULT_LINK_AN_1G_FALLBACK:
1643 speed = LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK;
1644 break;
1645
1646 case PORT_HW_CFG_DEFAULT_LINK_AN_2_5G_FALLBACK:
1647 speed = LM_MEDIUM_SPEED_AUTONEG_2_5G_FALLBACK;
1648 break;
1649
1650 default:
1651 speed = LM_MEDIUM_SPEED_UNKNOWN;
1652 }
1653 }
1654
1655 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
1656 for(cnt = 0; cnt < 1000; cnt++)
1657 {
1658 mm_wait(pdev, 5);
1659
1660 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val);
1661
1662 if(!(val & PHY_CTRL_PHY_RESET))
1663 {
1664 mm_wait(pdev, 5);
1665
1666 break;
1667 }
1668 }
1669
1670 DbgBreakIf(val & PHY_CTRL_PHY_RESET);
1671
1672 /* Get the PHY id. */
1673 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val);
1674 pdev->hw_info.phy_id = val << 16;
1675 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
1676
1677 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val);
1678 pdev->hw_info.phy_id |= val & 0xffff;
1679 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
1680
1681 DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
1682 pdev->hw_info.phy_id == 0);
1683
1684 /* The 5706S has problem determining link so getting link from
1685 * the MII status register is not reliable. This will force
1686 * the MAC to qualify the link ready signal with signal detect.
1687 * We will need to get the link status from the MAC instead of
1688 * the SERDES (MII status register). */
1689 if(CHIP_NUM(pdev) == CHIP_NUM_5706 &&
1690 lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
1691 {
1692 REG_WR(pdev, misc.misc_gp_hw_ctl0,
1693 MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE |
1694 MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE);
1695 }
1696
1697 /* Setup flow control capabilities advertisement. */
1698 val = PHY_AN_AD_1000X_HALF_DUPLEX;
1699 if(duplex == LM_MEDIUM_FULL_DUPLEX)
1700 {
1701 val |= PHY_AN_AD_1000X_FULL_DUPLEX;
1702 }
1703 val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
1704
1705 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
1706
1707 /* Determine the fallback selection. */
1708 switch(speed)
1709 {
1710 case LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK:
1711 DbgMessage(pdev, INFORM, "enable serdes_fallback_1g\n");
1712 pdev->vars.serdes_fallback_select = SERDES_FALLBACK_1G;
1713 break;
1714
1715 case LM_MEDIUM_SPEED_AUTONEG_2_5G_FALLBACK:
1716 DbgMessage(pdev, INFORM, "enable serdes_fallback_2.5g\n");
1717 pdev->vars.serdes_fallback_select = SERDES_FALLBACK_2_5G;
1718 break;
1719
1720 default:
1721 DbgMessage(pdev, INFORM, "disable serdes_fallback.\n");
1722 pdev->vars.serdes_fallback_select = SERDES_FALLBACK_NONE;
1723 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE;
1724 break;
1725 }
1726
1727 /* This routine could be called anytime. So if has not gone down
1728 * yet, we want to perserve the fallback setting. */
1729 if(pdev->vars.serdes_fallback_select != SERDES_FALLBACK_NONE)
1730 {
1731 speed = LM_MEDIUM_SPEED_AUTONEG;
1732
1733 if(pdev->vars.link_status == LM_STATUS_LINK_ACTIVE)
1734 {
1735 if(pdev->vars.serdes_fallback_status == SERDES_FALLBACK_1G)
1736 {
1737 speed = LM_MEDIUM_SPEED_1000MBPS;
1738 }
1739 else if(pdev->vars.serdes_fallback_status == SERDES_FALLBACK_2_5G)
1740 {
1741 speed = LM_MEDIUM_SPEED_2500MBPS;
1742 }
1743 }
1744 }
1745
1746 if(speed == LM_MEDIUM_SPEED_1000MBPS)
1747 {
1748 val = PHY_CTRL_SPEED_SELECT_1000MBPS;
1749 if(duplex == LM_MEDIUM_FULL_DUPLEX)
1750 {
1751 val |= PHY_CTRL_FULL_DUPLEX_MODE;
1752 }
1753
1754 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, val);
1755 }
1756 else
1757 {
1758 val = PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG;
1759
1760 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, val);
1761
1762 speed = LM_MEDIUM_SPEED_AUTONEG;
1763 }
1764
1765 /* exit mac loopback. we could be in mac loopback mode if previously
1766 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
1767 * medium type for diagnostic. */
1768 REG_RD(pdev, emac.emac_mode, &val);
1769 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
1770 REG_WR(pdev, emac.emac_mode, val);
1771
1772 /* Configure the PHY for jumbo frame. */
1773 if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE)
1774 {
1775 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x4400);
1776 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0xec87);
1777 }
1778 else
1779 {
1780 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400);
1781 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0xec85);
1782 }
1783
1784 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER);
1785 SET_MEDIUM_SPEED(pdev->vars.medium, speed);
1786 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
1787
1788 pdev->vars.cable_is_attached = FALSE;
1789
1790 /* Clear the latch bits. The second read below will get the
1791 * current status. */
1792 val = mii_get_serdes_link_status(pdev);
1793
1794 /* Wait for link only if the cable is connected. */
1795 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
1796 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
1797 if(val & 0x10)
1798 {
1799 for(; ;)
1800 {
1801 val = mii_get_serdes_link_status(pdev);
1802
1803 if(val & PHY_STATUS_LINK_PASS)
1804 {
1805 break;
1806 }
1807
1808 mm_wait(pdev, 10);
1809
1810 if(wait_link_timeout_us <= 10)
1811 {
1812 break;
1813 }
1814
1815 wait_link_timeout_us -= 10;
1816 }
1817
1818 pdev->vars.cable_is_attached = TRUE;
1819 }
1820
1821 /* Need to read a second time to get the current link status. */
1822 val = mii_get_serdes_link_status(pdev);
1823
1824 if(val & PHY_STATUS_LINK_PASS)
1825 {
1826 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1827 DbgMessage(pdev, INFORM, "phy init link up\n");
1828 }
1829 else
1830 {
1831 pdev->vars.link_status = LM_STATUS_LINK_DOWN;
1832 DbgMessage(pdev, INFORM, "phy init link down\n");
1833 }
1834
1835 return LM_STATUS_SUCCESS;
1836 } /* init_5706_serdes */
1837
1838
1839
1840 /*******************************************************************************
1841 * Description:
1842 *
1843 * Return:
1844 ******************************************************************************/
1845 STATIC void
init_serdes_or_phy_loopback(lm_device_t * pdev)1846 init_serdes_or_phy_loopback(
1847 lm_device_t *pdev)
1848 {
1849 u32_t cnt;
1850 u32_t val;
1851
1852 (void) lm_mwrite(
1853 pdev,
1854 pdev->params.phy_addr,
1855 PHY_CTRL_REG,
1856 PHY_CTRL_PHY_RESET);
1857 for(cnt = 0; cnt < 1000; cnt++)
1858 {
1859 mm_wait(pdev, 5);
1860
1861 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val);
1862
1863 if(!(val & PHY_CTRL_PHY_RESET))
1864 {
1865 mm_wait(pdev, 5);
1866 break;
1867 }
1868 }
1869
1870 DbgBreakIf(val & PHY_CTRL_PHY_RESET);
1871
1872 /* Get the PHY id. */
1873 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val);
1874 pdev->hw_info.phy_id = val << 16;
1875 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
1876
1877 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val);
1878 pdev->hw_info.phy_id |= val & 0xffff;
1879 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
1880
1881 DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
1882 pdev->hw_info.phy_id == 0);
1883
1884 REG_WR(pdev, emac.emac_tx_lengths, 0x26ff);
1885
1886 /* Set the phy into loopback mode. */
1887 (void) lm_mwrite(
1888 pdev,
1889 pdev->params.phy_addr,
1890 PHY_CTRL_REG,
1891 PHY_CTRL_LOOPBACK_MODE |
1892 PHY_CTRL_FULL_DUPLEX_MODE |
1893 PHY_CTRL_SPEED_SELECT_1000MBPS);
1894 } /* init_serdes_or_phy_loopback */
1895
1896
1897
1898 /*******************************************************************************
1899 * Description:
1900 *
1901 * Return:
1902 ******************************************************************************/
1903 STATIC void
init_5709_serdes_loopback(lm_device_t * pdev)1904 init_5709_serdes_loopback(
1905 lm_device_t *pdev)
1906 {
1907 u32_t val;
1908
1909 /*
1910 * reset causes the speed not be back to 2.5g intermittently
1911 * after phy lookback test when connecting to a switch.
1912 */
1913 #if 0
1914 /* select combo_ieee0 block. */
1915 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1916
1917 /* reset. */
1918 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, MII_CTRL_RESET);
1919 for(idx = 0; idx < 1000; idx++)
1920 {
1921 mm_wait(pdev, 5);
1922
1923 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1924 if(!(val & MII_CTRL_RESET))
1925 {
1926 mm_wait(pdev, 5);
1927 break;
1928 }
1929 }
1930 DbgBreakIf(val & MII_CTRL_RESET);
1931 #endif
1932
1933 /* set an_mmd. an_mmd is the only register set we need for
1934 * programming xinan serdes. all other registers are can
1935 * be access through an_mmd. */
1936 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffd0);
1937 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1e, 0x3800);
1938
1939 /* get phy id. */
1940 (void) lm_mread(pdev, pdev->params.phy_addr, 0x12, &val);
1941 pdev->hw_info.phy_id = val << 16;
1942 (void) lm_mread(pdev, pdev->params.phy_addr, 0x13, &val);
1943 pdev->hw_info.phy_id |= val & 0xffff;
1944
1945 /* select combo_ieee0 block. */
1946 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1947
1948 /*CQ31687:set autoneg_enable bit too.*/
1949 /* Set the phy into loopback mode. */
1950 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x5140);
1951
1952 } /* init_5709_serdes_loopback */
1953
1954
1955
1956 /*******************************************************************************
1957 * Description:
1958 *
1959 * Return:
1960 ******************************************************************************/
1961 STATIC lm_status_t
init_loopback_mac_link(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl)1962 init_loopback_mac_link(
1963 lm_device_t *pdev,
1964 lm_medium_t req_medium,
1965 lm_flow_control_t flow_ctrl)
1966 {
1967 lm_status_t lm_status;
1968 u32_t val;
1969
1970 lm_status = LM_STATUS_SUCCESS;
1971
1972 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_PHY_LOOPBACK)
1973 {
1974 if(CHIP_NUM(pdev) == CHIP_NUM_5709 &&
1975 lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
1976 {
1977 init_5709_serdes_loopback(pdev);
1978 }
1979 else
1980 {
1981 init_serdes_or_phy_loopback(pdev);
1982 }
1983
1984 REG_WR(pdev, emac.emac_tx_lengths, 0x26ff);
1985
1986 REG_RD(pdev, emac.emac_mode, &val);
1987 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_PORT);
1988 val |= EMAC_MODE_FORCE_LINK | EMAC_MODE_PORT_GMII;
1989 REG_WR(pdev, emac.emac_mode, val);
1990
1991 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_PHY_LOOPBACK);
1992 SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_UNKNOWN);
1993 SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX);
1994
1995 /* Save current link status. */
1996 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1997
1998 pdev->vars.cable_is_attached = TRUE;
1999 }
2000 else if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_MAC_LOOPBACK)
2001 {
2002 DbgMessage(pdev, INFORM, "Set up MAC loopback mode.\n");
2003
2004 /* Set the MAC into loopback mode. Mac loopback will intermittenly
2005 * fail if half_duplex bit is set. CQ#24594. */
2006 REG_RD(pdev, emac.emac_mode, &val);
2007 val &= ~(EMAC_MODE_PORT | EMAC_MODE_HALF_DUPLEX);
2008 val |= EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK;
2009
2010 /* The port mode must be set to none on the real chip. */
2011 if(CHIP_REV(pdev) == CHIP_REV_FPGA)
2012 {
2013 val |= EMAC_MODE_PORT_GMII;
2014 }
2015
2016 REG_WR(pdev, emac.emac_mode, val);
2017
2018 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_MAC_LOOPBACK);
2019 SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_UNKNOWN);
2020 SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX);
2021
2022 /* Save current link status. */
2023 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
2024
2025 pdev->vars.cable_is_attached = TRUE;
2026 }
2027 else
2028 {
2029 DbgBreakMsg("Not loopback medium type.\n");
2030
2031 lm_status = LM_STATUS_FAILURE;
2032
2033 /* Save current link status. */
2034 pdev->vars.link_status = LM_STATUS_LINK_DOWN;
2035
2036 pdev->vars.cable_is_attached = FALSE;
2037 }
2038
2039 /* Enable status block link attention. */
2040 REG_RD(pdev, hc.hc_attn_bits_enable, &val);
2041 val |= STATUS_ATTN_BITS_LINK_STATE;
2042 REG_WR(pdev, hc.hc_attn_bits_enable, val);
2043
2044 return lm_status;
2045 } /* init_loopback_mac_link */
2046
2047
2048
2049 /*******************************************************************************
2050 * Description:
2051 *
2052 * Return:
2053 ******************************************************************************/
2054 STATIC lm_status_t
init_null_phy(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t wait_link_timeout_us)2055 init_null_phy(
2056 lm_device_t *pdev,
2057 lm_medium_t req_medium,
2058 lm_flow_control_t flow_ctrl,
2059 u32_t wait_link_timeout_us)
2060 {
2061 DbgMessage(pdev, INFORM, "### init_null_phy\n");
2062
2063 if(GET_MEDIUM_TYPE(req_medium) != LM_MEDIUM_TYPE_NULL)
2064 {
2065 return LM_STATUS_INVALID_PARAMETER;
2066 }
2067
2068 /* Save current medium settings. */
2069 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_NULL);
2070 SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_1000MBPS);
2071 SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX);
2072
2073 pdev->vars.cable_is_attached = TRUE;
2074
2075 return LM_STATUS_SUCCESS;
2076 } /* init_null_phy */
2077
2078
2079
2080 /*******************************************************************************
2081 * Description:
2082 *
2083 * Return:
2084 ******************************************************************************/
2085 STATIC u32_t
netlink_pause_ad(lm_flow_control_t flow_ctrl)2086 netlink_pause_ad(
2087 lm_flow_control_t flow_ctrl)
2088 {
2089 u32_t pause_ad;
2090
2091 pause_ad = 0;
2092
2093 if((flow_ctrl == LM_FLOW_CONTROL_AUTO_PAUSE) ||
2094 ((flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
2095 (flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
2096 {
2097 pause_ad |= NETLINK_DRV_SET_LINK_FC_SYM_PAUSE |
2098 NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE;
2099 }
2100 else if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2101 {
2102 pause_ad |= NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE;
2103 }
2104 else if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
2105 {
2106 pause_ad |= NETLINK_DRV_SET_LINK_FC_SYM_PAUSE |
2107 NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE;
2108 }
2109
2110 return pause_ad;
2111 } /* netlink_pause_ad */
2112
2113
2114
2115 /*******************************************************************************
2116 * Description:
2117 *
2118 * Return:
2119 ******************************************************************************/
2120 STATIC u32_t
link_setting_to_netlink(lm_link_settings_t * link_settings,u32_t serdes)2121 link_setting_to_netlink(
2122 lm_link_settings_t *link_settings,
2123 u32_t serdes)
2124 {
2125 lm_medium_t duplex;
2126 lm_medium_t speed;
2127 u32_t netlink;
2128
2129 speed = GET_MEDIUM_SPEED(link_settings->req_medium);
2130 duplex = GET_MEDIUM_DUPLEX(link_settings->req_medium);
2131 netlink = 0;
2132
2133 switch(speed)
2134 {
2135 case LM_MEDIUM_SPEED_10MBPS:
2136 if(duplex == LM_MEDIUM_FULL_DUPLEX)
2137 {
2138 netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL;
2139
2140 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2141 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2142 {
2143 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2144 }
2145 }
2146 else
2147 {
2148 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2149 }
2150 break;
2151
2152 case LM_MEDIUM_SPEED_100MBPS:
2153 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2154 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2155 {
2156 netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL;
2157 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2158 }
2159
2160 if(duplex == LM_MEDIUM_FULL_DUPLEX)
2161 {
2162 netlink |= NETLINK_DRV_SET_LINK_SPEED_100FULL;
2163
2164 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2165 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2166 {
2167 netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF;
2168 }
2169 }
2170 else
2171 {
2172 netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF;
2173 }
2174 break;
2175
2176 case LM_MEDIUM_SPEED_1000MBPS:
2177 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2178 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2179 {
2180 netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL;
2181 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2182 netlink |= NETLINK_DRV_SET_LINK_SPEED_100FULL;
2183 netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF;
2184 }
2185
2186 if(duplex == LM_MEDIUM_FULL_DUPLEX)
2187 {
2188 netlink |= NETLINK_DRV_SET_LINK_SPEED_1GFULL;
2189
2190 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2191 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2192 {
2193 netlink |= NETLINK_DRV_SET_LINK_SPEED_1GHALF;
2194 }
2195 }
2196 else
2197 {
2198 netlink |= NETLINK_DRV_SET_LINK_SPEED_1GHALF;
2199 }
2200 break;
2201
2202 default:
2203 if (serdes)
2204 {
2205 netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG |
2206 NETLINK_DRV_SET_LINK_SPEED_1GHALF |
2207 NETLINK_DRV_SET_LINK_SPEED_1GFULL;
2208 }
2209 else
2210 {
2211 netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG |
2212 NETLINK_DRV_SET_LINK_SPEED_10HALF |
2213 NETLINK_DRV_SET_LINK_SPEED_10FULL |
2214 NETLINK_DRV_SET_LINK_SPEED_100HALF |
2215 NETLINK_DRV_SET_LINK_SPEED_100FULL |
2216 NETLINK_DRV_SET_LINK_SPEED_1GHALF |
2217 NETLINK_DRV_SET_LINK_SPEED_1GFULL;
2218 }
2219 break;
2220 }
2221
2222 netlink |= NETLINK_DRV_SET_LINK_PHY_RESET;
2223
2224 if(link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK)
2225 {
2226 netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG;
2227 }
2228
2229 if(link_settings->flag & LINK_FLAG_WIRE_SPEED)
2230 {
2231 netlink |= NETLINK_DRV_SET_LINK_ETH_AT_WIRESPEED_ENABLE;
2232 }
2233
2234 netlink |= netlink_pause_ad(link_settings->flow_ctrl);
2235
2236 return netlink;
2237 } /* link_settings_to_netlink */
2238
2239
2240
2241 /*******************************************************************************
2242 * Description:
2243 *
2244 * Return:
2245 ******************************************************************************/
2246 lm_status_t
lm_init_remote_phy(lm_device_t * pdev,lm_link_settings_t * serdes_link,lm_link_settings_t * rphy_link)2247 lm_init_remote_phy(
2248 lm_device_t *pdev,
2249 lm_link_settings_t *serdes_link,
2250 lm_link_settings_t *rphy_link)
2251 {
2252 u32_t serdes_netlink;
2253 u32_t rphy_netlink;
2254 u32_t set_link_arg;
2255 u32_t val;
2256
2257 DbgBreakIf(pdev->params.enable_remote_phy == FALSE);
2258
2259 serdes_netlink = link_setting_to_netlink(serdes_link, TRUE);
2260 rphy_netlink = link_setting_to_netlink(rphy_link, FALSE);
2261
2262 REG_WR_IND(
2263 pdev,
2264 pdev->hw_info.shmem_base +
2265 OFFSETOF(shmem_region_t, remotephy.serdes_link_pref),
2266 serdes_netlink);
2267
2268 REG_WR_IND(
2269 pdev,
2270 pdev->hw_info.shmem_base +
2271 OFFSETOF(shmem_region_t, remotephy.copper_phy_link_pref),
2272 rphy_netlink | NETLINK_DRV_SET_LINK_PHY_APP_REMOTE);
2273
2274 REG_RD_IND(
2275 pdev,
2276 pdev->hw_info.shmem_base +
2277 OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
2278 &val);
2279 if(val & NETLINK_GET_LINK_STATUS_SERDES_LINK)
2280 {
2281 set_link_arg = serdes_netlink;
2282 }
2283 else
2284 {
2285 set_link_arg = rphy_netlink | NETLINK_DRV_SET_LINK_PHY_APP_REMOTE;
2286 }
2287
2288 REG_WR_IND(
2289 pdev,
2290 pdev->hw_info.shmem_base +
2291 OFFSETOF(shmem_region_t, drv_fw_mb.mb_args[0]),
2292 set_link_arg);
2293
2294 (void) lm_submit_fw_cmd(pdev, DRV_MSG_CODE_CMD_SET_LINK);
2295
2296 return LM_STATUS_SUCCESS;
2297 } /* lm_init_remote_phy */
2298
2299
2300
2301 /*******************************************************************************
2302 * Description:
2303 *
2304 * Return:
2305 ******************************************************************************/
2306 lm_status_t
lm_init_phy(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wire_speed,u32_t wait_link_timeout_us)2307 lm_init_phy(
2308 lm_device_t *pdev,
2309 lm_medium_t req_medium,
2310 lm_flow_control_t flow_ctrl,
2311 u32_t selective_autoneg,
2312 u32_t wire_speed,
2313 u32_t wait_link_timeout_us)
2314 {
2315 lm_status_t lm_status;
2316
2317 DbgBreakIf(pdev->params.enable_remote_phy);
2318
2319 if(GET_MEDIUM_AUTONEG_MODE(req_medium) == LM_MEDIUM_SELECTIVE_AUTONEG)
2320 {
2321 selective_autoneg = TRUE;
2322 }
2323
2324 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_AUTO_DETECT)
2325 {
2326 if(CHIP_REV(pdev) == CHIP_REV_IKOS)
2327 {
2328 req_medium = LM_MEDIUM_TYPE_NULL;
2329 }
2330 else if(CHIP_REV(pdev) == CHIP_REV_FPGA)
2331 {
2332 selective_autoneg = TRUE;
2333 req_medium = LM_MEDIUM_TYPE_UTP |
2334 LM_MEDIUM_SPEED_10MBPS |
2335 LM_MEDIUM_FULL_DUPLEX;
2336 }
2337 else if(lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
2338 {
2339 if(req_medium == LM_MEDIUM_AUTO_DETECT)
2340 {
2341 req_medium = LM_MEDIUM_TYPE_FIBER;
2342 }
2343 else
2344 {
2345 SET_MEDIUM_TYPE(req_medium, LM_MEDIUM_TYPE_FIBER);
2346 }
2347 }
2348 else
2349 {
2350 if(req_medium == LM_MEDIUM_AUTO_DETECT)
2351 {
2352 req_medium = LM_MEDIUM_TYPE_UTP;
2353 }
2354 else
2355 {
2356 SET_MEDIUM_TYPE(req_medium, LM_MEDIUM_TYPE_UTP);
2357 }
2358 }
2359 }
2360
2361 switch(GET_MEDIUM_TYPE(req_medium))
2362 {
2363 case LM_MEDIUM_TYPE_UTP:
2364 lm_status = init_utp(
2365 pdev,
2366 req_medium,
2367 flow_ctrl,
2368 selective_autoneg,
2369 wire_speed,
2370 wait_link_timeout_us);
2371 break;
2372
2373 case LM_MEDIUM_TYPE_FIBER:
2374 DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5706 &&
2375 CHIP_NUM(pdev) != CHIP_NUM_5708 &&
2376 CHIP_NUM(pdev) != CHIP_NUM_5709);
2377
2378 if(CHIP_NUM(pdev) == CHIP_NUM_5706)
2379 {
2380 lm_status = init_5706_serdes(
2381 pdev,
2382 req_medium,
2383 flow_ctrl,
2384 wait_link_timeout_us);
2385 }
2386 else if(CHIP_NUM(pdev) == CHIP_NUM_5708)
2387 {
2388 lm_status = init_5708_serdes(
2389 pdev,
2390 req_medium,
2391 flow_ctrl,
2392 selective_autoneg,
2393 wait_link_timeout_us);
2394 }
2395 else
2396 {
2397 lm_status = init_5709_serdes(
2398 pdev,
2399 req_medium,
2400 flow_ctrl,
2401 selective_autoneg,
2402 wait_link_timeout_us);
2403 }
2404
2405 break;
2406
2407 case LM_MEDIUM_TYPE_NULL:
2408 lm_status = init_null_phy(
2409 pdev,
2410 req_medium,
2411 flow_ctrl,
2412 wait_link_timeout_us);
2413 break;
2414
2415 case LM_MEDIUM_TYPE_PHY_LOOPBACK:
2416 case LM_MEDIUM_TYPE_MAC_LOOPBACK:
2417 lm_status = init_loopback_mac_link(
2418 pdev,
2419 req_medium,
2420 flow_ctrl);
2421 break;
2422
2423 default:
2424 lm_status = LM_STATUS_UNKNOWN_MEDIUM;
2425 break;
2426 }
2427
2428 return lm_status;
2429 } /* lm_init_phy */
2430
2431
2432
2433 /*******************************************************************************
2434 * Description:
2435 *
2436 * Return:
2437 ******************************************************************************/
2438 STATIC void
get_serdes_phy_ad(lm_device_t * pdev,u32_t * local_phy_ad,u32_t * remote_phy_ad)2439 get_serdes_phy_ad(
2440 lm_device_t *pdev,
2441 u32_t *local_phy_ad,
2442 u32_t *remote_phy_ad)
2443 {
2444 u32_t val;
2445
2446 *local_phy_ad = 0;
2447 *remote_phy_ad = 0;
2448
2449 if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
2450 {
2451 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, &val);
2452
2453 if(val & PHY_AN_AD_1000X_PAUSE_CAPABLE)
2454 {
2455 *local_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2456 }
2457
2458 if(val & PHY_AN_AD_1000X_ASYM_PAUSE)
2459 {
2460 *local_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2461 }
2462
2463 (void) lm_mread(pdev,pdev->params.phy_addr,PHY_LINK_PARTNER_ABILITY_REG,&val);
2464
2465 if(val & PHY_AN_AD_1000X_PAUSE_CAPABLE)
2466 {
2467 *remote_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2468 }
2469
2470 if(val & PHY_AN_AD_1000X_ASYM_PAUSE)
2471 {
2472 *remote_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2473 }
2474 }
2475 else
2476 {
2477 /* select combo ieee0 block. */
2478 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
2479
2480 /* local advertisement. */
2481 (void) lm_mread(pdev, pdev->params.phy_addr, 0x14, &val);
2482
2483 if(val & 0x80)
2484 {
2485 *local_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2486 }
2487
2488 if(val & 0x100)
2489 {
2490 *local_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2491 }
2492
2493 /* remote advertisement. */
2494 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &val);
2495
2496 if(val & 0x80)
2497 {
2498 *remote_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2499 }
2500
2501 if(val & 0x100)
2502 {
2503 *remote_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2504 }
2505 }
2506 } /* get_serdes_phy_ad */
2507
2508
2509
2510 /*******************************************************************************
2511 * Description:
2512 *
2513 * Return:
2514 ******************************************************************************/
2515 STATIC lm_flow_control_t
set_mac_flow_control(lm_device_t * pdev,lm_medium_t medium,lm_flow_control_t flow_control_cap)2516 set_mac_flow_control(
2517 lm_device_t *pdev,
2518 lm_medium_t medium,
2519 lm_flow_control_t flow_control_cap)
2520 {
2521 lm_flow_control_t flow_ctrl;
2522 u32_t remote_phy_link;
2523 u32_t remote_phy_ad;
2524 u32_t local_phy_ad;
2525 u32_t val;
2526 lm_rx_chain_t *rxq;
2527 u32_t idx;
2528
2529 if(pdev->params.enable_remote_phy)
2530 {
2531 local_phy_ad = 0;
2532
2533 if((flow_control_cap == LM_FLOW_CONTROL_AUTO_PAUSE) ||
2534 ((flow_control_cap & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
2535 (flow_control_cap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)) ||
2536 (flow_control_cap & LM_FLOW_CONTROL_RECEIVE_PAUSE))
2537 {
2538 local_phy_ad |= (PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE);
2539 }
2540 else if(flow_control_cap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2541 {
2542 local_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2543 }
2544
2545 remote_phy_ad = 0;
2546
2547 REG_RD_IND(
2548 pdev,
2549 pdev->hw_info.shmem_base +
2550 OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
2551 &remote_phy_link);
2552
2553 if(remote_phy_link & NETLINK_GET_LINK_STATUS_PARTNER_SYM_PAUSE_CAP)
2554 {
2555 remote_phy_ad |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
2556 }
2557
2558 if(remote_phy_link & NETLINK_GET_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP)
2559 {
2560 remote_phy_ad |= PHY_LINK_PARTNER_ASYM_PAUSE;
2561 }
2562 }
2563 else
2564 {
2565 if(GET_MEDIUM_TYPE(medium) == LM_MEDIUM_TYPE_FIBER)
2566 {
2567 get_serdes_phy_ad(pdev, &local_phy_ad, &remote_phy_ad);
2568 }
2569 else
2570 {
2571 (void) lm_mread(
2572 pdev,
2573 pdev->params.phy_addr,
2574 PHY_AN_AD_REG,
2575 &local_phy_ad);
2576
2577 (void) lm_mread(
2578 pdev,
2579 pdev->params.phy_addr,
2580 PHY_LINK_PARTNER_ABILITY_REG,
2581 &remote_phy_ad);
2582 }
2583 }
2584
2585 DbgMessage(pdev, INFORM, "Local flow control settings.\n");
2586
2587 if(local_phy_ad & PHY_AN_AD_PAUSE_CAPABLE)
2588 {
2589 DbgMessage(pdev, INFORM, " PAUSE capable.\n");
2590 }
2591
2592 if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE)
2593 {
2594 DbgMessage(pdev, INFORM, " ASYM_PAUSE capable.\n");
2595 }
2596
2597 DbgMessage(pdev, INFORM, "Remote flow control settings.\n");
2598
2599 if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
2600 {
2601 DbgMessage(pdev, INFORM, " PAUSE capable.\n");
2602 }
2603
2604 if(remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE)
2605 {
2606 DbgMessage(pdev, INFORM, " ASYM_PAUSE capable.\n");
2607 }
2608
2609 /* Resultant flow control setting. */
2610 flow_ctrl = LM_FLOW_CONTROL_NONE;
2611
2612 if((flow_control_cap & LM_FLOW_CONTROL_AUTO_PAUSE) ||
2613 pdev->params.flow_control_reporting_mode)
2614 {
2615 /* See Table 28B-3 of 802.3ab-1999 spec. */
2616 if(local_phy_ad & PHY_AN_AD_PAUSE_CAPABLE)
2617 {
2618 if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE)
2619 {
2620 if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
2621 {
2622 DbgMessage(pdev, INFORM, "FlowCap: tx/rx\n");
2623
2624 flow_ctrl =
2625 LM_FLOW_CONTROL_TRANSMIT_PAUSE |
2626 LM_FLOW_CONTROL_RECEIVE_PAUSE;
2627 }
2628 else if(remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE)
2629 {
2630 DbgMessage(pdev, INFORM, "FlowCap: rx PAUSE\n");
2631
2632 flow_ctrl = LM_FLOW_CONTROL_RECEIVE_PAUSE;
2633 }
2634 }
2635 else
2636 {
2637 if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
2638 {
2639 DbgMessage(pdev, INFORM, "FlowCap: tx/rx\n");
2640
2641 flow_ctrl =
2642 LM_FLOW_CONTROL_TRANSMIT_PAUSE |
2643 LM_FLOW_CONTROL_RECEIVE_PAUSE;
2644 }
2645 }
2646 }
2647 else if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE)
2648 {
2649 if((remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE) &&
2650 (remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE))
2651 {
2652 DbgMessage(pdev, INFORM, "FlowCap: tx PAUSE\n");
2653
2654 flow_ctrl = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
2655 }
2656 }
2657 }
2658 else
2659 {
2660 flow_ctrl = flow_control_cap;
2661 }
2662
2663 DbgMessage(pdev, INFORM, "Flow control capabilities.\n");
2664
2665 if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2666 {
2667 DbgMessage(pdev, INFORM, " tx PAUSE\n");
2668 }
2669
2670 if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
2671 {
2672 DbgMessage(pdev, INFORM, " rx PAUSE\n");
2673 }
2674
2675 if(flow_ctrl == LM_FLOW_CONTROL_NONE)
2676 {
2677 DbgMessage(pdev, INFORM, " none.\n");
2678 }
2679
2680 /* Enable/disable rx PAUSE. */
2681 REG_RD(pdev, emac.emac_rx_mode, &val);
2682 val &= ~EMAC_RX_MODE_FLOW_EN;
2683
2684 if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
2685 {
2686 val |= EMAC_RX_MODE_FLOW_EN;
2687 DbgMessage(pdev, INFORM, "Enable rx PAUSE.\n");
2688 }
2689 REG_WR(pdev, emac.emac_rx_mode, val);
2690
2691 /* Enable/disable tx PAUSE. */
2692 REG_RD(pdev, emac.emac_tx_mode, &val);
2693 val &= ~EMAC_TX_MODE_FLOW_EN;
2694
2695 if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2696 {
2697 val |= EMAC_TX_MODE_FLOW_EN;
2698 DbgMessage(pdev, INFORM, "Enable tx PAUSE.\n");
2699 }
2700 REG_WR(pdev, emac.emac_tx_mode, val);
2701
2702 for(idx = 0; idx < pdev->rx_info.num_rxq; idx++)
2703 {
2704 rxq = &pdev->rx_info.chain[idx];
2705 val = CTX_RD(
2706 pdev,
2707 rxq->cid_addr,
2708 WORD_ALIGNED_OFFSETOF(l2_bd_chain_context_t, l2ctx_ctx_type));
2709
2710 /* Enable/disable RV2P wait (i.e. watermark field) for buffer post based on flow control setting. */
2711 if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2712 {
2713 val |= 0xFF;
2714 }
2715 else
2716 {
2717 // RV2P is checking for non-zero in this byte field
2718 val &= ~0xFF;
2719 }
2720 CTX_WR(
2721 pdev,
2722 rxq->cid_addr,
2723 WORD_ALIGNED_OFFSETOF(l2_bd_chain_context_t, l2ctx_ctx_type),
2724 val);
2725 }
2726
2727 return flow_ctrl;
2728 } /* set_mac_flow_control */
2729
2730
2731
2732 /*******************************************************************************
2733 * Description:
2734 *
2735 * Return:
2736 ******************************************************************************/
2737 STATIC lm_status_t
get_copper_phy_link(lm_device_t * pdev,lm_medium_t * medium)2738 get_copper_phy_link(
2739 lm_device_t *pdev,
2740 lm_medium_t *medium)
2741 {
2742 lm_medium_t duplex;
2743 lm_medium_t speed;
2744 lm_status_t link;
2745 u32_t phy_status;
2746 u32_t remote_adv;
2747 u32_t local_adv;
2748 u32_t phy_ctrl;
2749 u32_t val;
2750
2751 DbgMessage(pdev, INFORM, "### get_copper_phy_link\n");
2752
2753 *medium = LM_MEDIUM_TYPE_UTP |
2754 LM_MEDIUM_SPEED_UNKNOWN |
2755 LM_MEDIUM_FULL_DUPLEX;
2756
2757 pdev->vars.cable_is_attached = FALSE;
2758
2759 /* Check for link. The first read returns the latched value, the
2760 * second read returns the current value. */
2761 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status);
2762 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status);
2763 if((phy_status & PHY_STATUS_LINK_PASS) == 0)
2764 {
2765 DbgMessage(pdev, INFORM, "link down.\n");
2766
2767 if(CHIP_REV(pdev) != CHIP_REV_FPGA)
2768 {
2769 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
2770 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
2771 if(val & 0x20)
2772 {
2773 pdev->vars.cable_is_attached = TRUE;
2774 }
2775 }
2776
2777 return LM_STATUS_LINK_DOWN;
2778 }
2779
2780 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
2781
2782 /* Make sure the PHY control register is valid. */
2783 DbgBreakIf(phy_ctrl & (
2784 PHY_CTRL_COLLISION_TEST_ENABLE |
2785 PHY_CTRL_RESTART_AUTO_NEG |
2786 PHY_CTRL_ISOLATE_PHY |
2787 PHY_CTRL_LOOPBACK_MODE |
2788 PHY_CTRL_PHY_RESET));
2789
2790 link = LM_STATUS_LINK_ACTIVE;
2791 pdev->vars.cable_is_attached = TRUE;
2792
2793 /* Determine duplex mode. Link is present also means autoneg is done. */
2794 if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE)
2795 {
2796 /* Autonegotiation is enabled. And since we have link, we know
2797 * autonegotiation has completed.
2798 *
2799 * Infer the link speed by figuring out the highest common speed
2800 * between us and our link partner. */
2801
2802 /* Get local and remote 1000BASET advertisement. */
2803 (void) lm_mread(
2804 pdev,
2805 pdev->params.phy_addr,
2806 PHY_1000BASET_CTRL_REG,
2807 &local_adv);
2808 (void) lm_mread(
2809 pdev,
2810 pdev->params.phy_addr,
2811 PHY_1000BASET_STATUS_REG,
2812 &remote_adv);
2813
2814 val = local_adv & (remote_adv >> 2);
2815 if(val & PHY_AN_AD_1000BASET_FULL)
2816 {
2817 DbgMessage(pdev, INFORM, "detected 1gb full autoneg.\n");
2818
2819 speed = LM_MEDIUM_SPEED_1000MBPS;
2820 duplex = LM_MEDIUM_FULL_DUPLEX;
2821 }
2822 else if(val & PHY_AN_AD_1000BASET_HALF)
2823 {
2824 DbgMessage(pdev, INFORM, "detected 1gb half autoneg.\n");
2825
2826 speed = LM_MEDIUM_SPEED_1000MBPS;
2827 duplex = LM_MEDIUM_HALF_DUPLEX;
2828 }
2829 else
2830 {
2831 /* Get local and remote 10/100 mb advertisement. */
2832 (void) lm_mread(
2833 pdev,
2834 pdev->params.phy_addr,
2835 PHY_AN_AD_REG,
2836 &local_adv);
2837
2838 (void) lm_mread(
2839 pdev,
2840 pdev->params.phy_addr,
2841 PHY_LINK_PARTNER_ABILITY_REG,
2842 &remote_adv);
2843
2844 val = local_adv & remote_adv;
2845 if(val & PHY_AN_AD_100BASETX_FULL)
2846 {
2847 DbgMessage(pdev, INFORM, "detected 100mb full autoneg.\n");
2848
2849 speed = LM_MEDIUM_SPEED_100MBPS;
2850 duplex = LM_MEDIUM_FULL_DUPLEX;
2851 }
2852 else if(val & PHY_AN_AD_100BASETX_HALF)
2853 {
2854 DbgMessage(pdev, INFORM, "detected 100mb half autoneg.\n");
2855
2856 speed = LM_MEDIUM_SPEED_100MBPS;
2857 duplex = LM_MEDIUM_HALF_DUPLEX;
2858 }
2859 else if(val & PHY_AN_AD_10BASET_FULL)
2860 {
2861 DbgMessage(pdev, INFORM, "detected 10mb full autoneg.\n");
2862
2863 speed = LM_MEDIUM_SPEED_10MBPS;
2864 duplex = LM_MEDIUM_FULL_DUPLEX;
2865 }
2866 else if(val & PHY_AN_AD_10BASET_HALF)
2867 {
2868 DbgMessage(pdev, INFORM, "detected 10mb half autoneg.\n");
2869
2870 speed = LM_MEDIUM_SPEED_10MBPS;
2871 duplex = LM_MEDIUM_HALF_DUPLEX;
2872 }
2873 else
2874 {
2875 DbgBreakMsg("unable to determine autoneg speed.\n");
2876
2877 speed = LM_MEDIUM_SPEED_UNKNOWN;
2878 duplex = LM_MEDIUM_FULL_DUPLEX;
2879 link = LM_STATUS_LINK_DOWN;
2880 }
2881 }
2882 }
2883 else
2884 {
2885 /* The link speed speed and duplex mode are forced. Get the forced
2886 * line settings from the PHY control register. */
2887 if(phy_ctrl & PHY_CTRL_SPEED_SELECT_100MBPS)
2888 {
2889 DbgMessage(pdev, INFORM, "PHY forced to 100mb.\n");
2890 speed = LM_MEDIUM_SPEED_100MBPS;
2891 }
2892 else if(phy_ctrl & PHY_CTRL_SPEED_SELECT_1000MBPS)
2893 {
2894 DbgMessage(pdev, INFORM, "PHY forced to 1gb.\n");
2895
2896 speed = LM_MEDIUM_SPEED_1000MBPS;
2897 }
2898 else
2899 {
2900 DbgMessage(pdev, INFORM, "PHY forced to 10mb.\n");
2901
2902 speed = LM_MEDIUM_SPEED_10MBPS;
2903 }
2904
2905 if(phy_ctrl & PHY_CTRL_FULL_DUPLEX_MODE)
2906 {
2907 DbgMessage(pdev, INFORM, "PHY forced to full duplex.\n");
2908
2909 duplex = LM_MEDIUM_FULL_DUPLEX;
2910 }
2911 else
2912 {
2913 DbgMessage(pdev, INFORM, "PHY forced to half duplex.\n");
2914
2915 duplex = LM_MEDIUM_HALF_DUPLEX;
2916 }
2917 }
2918
2919 *medium = LM_MEDIUM_TYPE_UTP | speed | duplex;
2920
2921 return link;
2922 } /* get_copper_phy_link */
2923
2924
2925
2926 /*******************************************************************************
2927 * Description:
2928 *
2929 * Return:
2930 ******************************************************************************/
2931 STATIC void
init_mac_link(lm_device_t * pdev,lm_status_t link,lm_medium_t medium,lm_flow_control_t flow_ctrl)2932 init_mac_link(
2933 lm_device_t *pdev,
2934 lm_status_t link,
2935 lm_medium_t medium,
2936 lm_flow_control_t flow_ctrl)
2937 {
2938 u32_t val;
2939
2940 /* Configure slot time, IPG, and 802.3 flow control. */
2941 REG_WR(pdev, emac.emac_tx_lengths, 0x2620);
2942 if(link == LM_STATUS_LINK_ACTIVE)
2943 {
2944 if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_1000MBPS &&
2945 GET_MEDIUM_DUPLEX(medium) == LM_MEDIUM_HALF_DUPLEX)
2946 {
2947 REG_WR(pdev, emac.emac_tx_lengths, 0x26ff);
2948 }
2949
2950 pdev->vars.flow_control = set_mac_flow_control(pdev, medium, flow_ctrl);
2951 }
2952
2953 /* Configure the EMAC mode register. */
2954 REG_RD(pdev, emac.emac_mode, &val);
2955
2956 val &= ~(EMAC_MODE_PORT | EMAC_MODE_FORCE_LINK);
2957
2958 if(link == LM_STATUS_LINK_ACTIVE)
2959 {
2960 if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_10MBPS)
2961 {
2962 if(CHIP_NUM(pdev) == CHIP_NUM_5706)
2963 {
2964 val |= EMAC_MODE_PORT_MII;
2965 }
2966 else
2967 {
2968 /* 5708 setting. */
2969 val |= EMAC_MODE_PORT_MII_10M;
2970 }
2971 }
2972 else if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_100MBPS)
2973 {
2974 val |= EMAC_MODE_PORT_MII;
2975 }
2976 else
2977 {
2978 val |= EMAC_MODE_PORT_GMII;
2979 }
2980
2981 if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_2500MBPS)
2982 {
2983 val |= EMAC_MODE_25G_MODE;
2984 }
2985
2986 /* We need to set the port mode to GMII when we are running in
2987 * the FPGA mode, regardless of the actual line speed. */
2988 if(CHIP_REV(pdev) == CHIP_REV_FPGA)
2989 {
2990 val &= ~EMAC_MODE_PORT;
2991 val |= EMAC_MODE_PORT_GMII;
2992 }
2993 }
2994 else
2995 {
2996 val |= EMAC_MODE_PORT_GMII;
2997 }
2998
2999 if(GET_MEDIUM_TYPE(medium) == LM_MEDIUM_TYPE_NULL)
3000 {
3001 val |= EMAC_MODE_FORCE_LINK;
3002 }
3003
3004 /* Set the MAC to operate in the appropriate duplex mode. */
3005 val &= ~EMAC_MODE_HALF_DUPLEX;
3006 if(GET_MEDIUM_DUPLEX(medium) == LM_MEDIUM_HALF_DUPLEX)
3007 {
3008 val |= EMAC_MODE_HALF_DUPLEX;
3009 }
3010 REG_WR(pdev, emac.emac_mode, val);
3011
3012 /* Acknowledge the interrupt. */
3013 REG_WR(pdev, emac.emac_status, EMAC_STATUS_LINK_CHANGE);
3014
3015 /* Enable phy link change attention. */
3016 if(pdev->params.phy_int_mode == PHY_INT_MODE_MI_INTERRUPT)
3017 {
3018 REG_WR(pdev, emac.emac_attention_ena, EMAC_ATTENTION_ENA_MI_INT);
3019 }
3020 else
3021 {
3022 REG_WR(pdev, emac.emac_attention_ena, EMAC_ATTENTION_ENA_LINK);
3023 }
3024
3025 /* Enable status block link attention. */
3026 REG_RD(pdev, hc.hc_attn_bits_enable, &val);
3027 val &= ~STATUS_ATTN_BITS_LINK_STATE;
3028 if(pdev->params.link_chng_mode == LINK_CHNG_MODE_USE_STATUS_BLOCK)
3029 {
3030 val |= STATUS_ATTN_BITS_LINK_STATE;
3031 }
3032 REG_WR(pdev, hc.hc_attn_bits_enable, val);
3033
3034 pdev->vars.medium = medium;
3035 pdev->vars.link_status = link;
3036 } /* init_mac_link */
3037
3038
3039
3040 /*******************************************************************************
3041 * Description:
3042 *
3043 * Return:
3044 ******************************************************************************/
3045 STATIC lm_status_t
serdes_fallback(lm_device_t * pdev,u8_t fallback_select)3046 serdes_fallback(
3047 lm_device_t *pdev,
3048 u8_t fallback_select)
3049 {
3050 u32_t intr_exp_status;
3051 u8_t fallback_to;
3052 u32_t phy_status;
3053 u32_t phy_ctrl;
3054 u32_t val;
3055 u32_t cnt;
3056
3057 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE;
3058
3059 if(fallback_select == SERDES_FALLBACK_NONE)
3060 {
3061 return LM_STATUS_LINK_DOWN;
3062 }
3063
3064 /* See if the cable is connected. */
3065 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
3066 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
3067
3068 /* We think the cable is not attached, set up the serdes to
3069 * autoneg as the default. */
3070 if(!(val & 0x10)) /* SIG_DETECT */
3071 {
3072 DbgMessage(pdev, INFORM, "no cable, default to autoneg.\n");
3073
3074 (void) lm_mwrite(
3075 pdev,
3076 pdev->params.phy_addr,
3077 PHY_CTRL_REG,
3078 PHY_CTRL_AUTO_NEG_ENABLE);
3079
3080 return LM_STATUS_LINK_DOWN;
3081 }
3082
3083 /* Read the interrupt expansion register to see if rudi_c is set.
3084 * rudi_c is set when we are receiving config words which means
3085 * the link partner is attempting to autonegotiate.
3086 *
3087 * When the link partner is attempting to autonegotiate and we
3088 * are not able to get linke, it could mean our transmit cable
3089 * is not plugged in. In this case we don't want to fallback
3090 * to the force mode. We want to remain in autonegotiation mode. */
3091 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x0f01);
3092 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &intr_exp_status);
3093 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &intr_exp_status);
3094
3095 /* See if autoneg is enabled and the remote is not sending us
3096 * configs. If this is the case and link is currently down, we
3097 * will switch to the force mode and disable autonegotiation.
3098 *
3099 * If we are current in the forced mode or the link partner is
3100 * sending use configs, we'll enable autoneg and restart it. */
3101 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
3102 if((phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE) && !(intr_exp_status & 0x20))
3103 {
3104 DbgMessage(pdev, INFORM, "switch to force mode - 1G full\n");
3105
3106 (void) lm_mwrite(
3107 pdev,
3108 pdev->params.phy_addr,
3109 PHY_CTRL_REG,
3110 PHY_CTRL_SPEED_SELECT_1000MBPS | PHY_CTRL_FULL_DUPLEX_MODE);
3111
3112 fallback_to = SERDES_FALLBACK_1G;
3113 }
3114 else
3115 {
3116 DbgMessage(pdev, INFORM, "switch to autoneg mode - 1G full\n");
3117
3118 /* Switch to autoneg mode. */
3119 (void) lm_mwrite(
3120 pdev,
3121 pdev->params.phy_addr,
3122 PHY_CTRL_REG,
3123 PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG);
3124
3125 fallback_to = SERDES_FALLBACK_NONE;
3126 }
3127
3128 for(cnt = 0; cnt < 100; cnt++)
3129 {
3130 mm_wait(pdev, 10);
3131 }
3132
3133 phy_status = mii_get_serdes_link_status(pdev);
3134
3135 if(phy_status & PHY_STATUS_LINK_PASS)
3136 {
3137 pdev->vars.serdes_fallback_status = fallback_to;
3138
3139 return LM_STATUS_LINK_ACTIVE;
3140 }
3141
3142 return LM_STATUS_LINK_DOWN;
3143 } /* serdes_fallback */
3144
3145
3146
3147 /*******************************************************************************
3148 * Description:
3149 *
3150 * Return:
3151 ******************************************************************************/
3152 STATIC lm_status_t
get_5708_serdes_link(lm_device_t * pdev,lm_medium_t * medium)3153 get_5708_serdes_link(
3154 lm_device_t *pdev,
3155 lm_medium_t *medium)
3156 {
3157 u8_t restarted_autoneg;
3158 lm_medium_t duplex;
3159 lm_medium_t speed;
3160 lm_status_t link;
3161 u32_t val;
3162 u32_t idx;
3163
3164 *medium = LM_MEDIUM_TYPE_FIBER |
3165 LM_MEDIUM_SPEED_UNKNOWN |
3166 LM_MEDIUM_FULL_DUPLEX;
3167
3168 pdev->vars.cable_is_attached = FALSE;
3169
3170 /* Check for link. The first read returns the latched value, the
3171 * second read returns the current value. */
3172 (void) lm_mread(
3173 pdev,
3174 pdev->params.phy_addr,
3175 MII_REG(serdes_reg_t, mii_status),
3176 &val);
3177 (void) lm_mread(
3178 pdev,
3179 pdev->params.phy_addr,
3180 MII_REG(serdes_reg_t, mii_status),
3181 &val);
3182
3183 /* CQ#23742 - Link status in the status block and the link status
3184 * in the mii_status are not consistent. mii_status appears to
3185 * return invalid value. Added a workaround here. */
3186 for(idx = 0; idx < 10 && val == 0; idx++)
3187 {
3188 mm_wait(pdev, 10);
3189
3190 (void) lm_mread(
3191 pdev,
3192 pdev->params.phy_addr,
3193 MII_REG(serdes_reg_t, mii_status),
3194 &val);
3195 }
3196
3197 if((val & MII_STAT_LINK_STATUS) == 0)
3198 {
3199 DbgMessage(pdev, INFORM, "serdes link down.\n");
3200
3201 pdev->vars.cable_is_attached = FALSE;
3202
3203 return LM_STATUS_LINK_DOWN;
3204 }
3205
3206 link = LM_STATUS_LINK_ACTIVE;
3207 pdev->vars.cable_is_attached = TRUE;
3208
3209 /* Determine duplex mode. Link is present also means autoneg is done. */
3210 (void) lm_mread(
3211 pdev,
3212 pdev->params.phy_addr,
3213 MII_REG(serdes_reg_t, mii_ctrl),
3214 &val);
3215 if(val & MII_CTRL_ANEG_ENA)
3216 {
3217 /* Select Bank 0. */
3218 (void) lm_mwrite(
3219 pdev,
3220 pdev->params.phy_addr,
3221 MII_REG(serdes_reg_t, mii_block_addr),
3222 MII_BLK_ADDR_DIGITAL);
3223
3224 /* Get the negotiated speed and duplex mode. */
3225 (void) lm_mread(
3226 pdev,
3227 pdev->params.phy_addr,
3228 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_stat1),
3229 &val);
3230 switch(val & MII_1000X_STAT1_SPEED)
3231 {
3232 case MII_1000X_STAT1_SPEED_2G5:
3233 DbgMessage(pdev, INFORM, "serdes autoneg to 2.5gb.\n");
3234 speed = LM_MEDIUM_SPEED_2500MBPS;
3235 break;
3236
3237 case MII_1000X_STAT1_SPEED_1G:
3238 DbgMessage(pdev, INFORM, "serdes autoneg to 1gb.\n");
3239 speed = LM_MEDIUM_SPEED_1000MBPS;
3240 break;
3241
3242 case MII_1000X_STAT1_SPEED_100:
3243 DbgMessage(pdev, INFORM, "serdes autoneg to 100mb.\n");
3244 speed = LM_MEDIUM_SPEED_100MBPS;
3245 break;
3246
3247 case MII_1000X_STAT1_SPEED_10:
3248 default:
3249 DbgMessage(pdev, INFORM, "serdes autoneg to 10mb.\n");
3250 speed = LM_MEDIUM_SPEED_10MBPS;
3251 break;
3252 }
3253
3254 /* Get the duplex mode. */
3255 duplex = LM_MEDIUM_FULL_DUPLEX;
3256 if(val & MII_1000X_STAT1_DUPLEX)
3257 {
3258 DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n");
3259 }
3260 else
3261 {
3262 (void) lm_mread(
3263 pdev,
3264 pdev->params.phy_addr,
3265 MII_REG(serdes_reg_t, mii_status),
3266 &val);
3267 if(val & MII_STAT_ANEG_CMPL)
3268 {
3269 duplex = LM_MEDIUM_HALF_DUPLEX;
3270 DbgMessage(pdev, INFORM, "serdes autoneg to half duplex.\n");
3271 }
3272 else
3273 {
3274 DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n");
3275 }
3276 }
3277
3278 /* Set up pre-emphasis for a backplane application. */
3279 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP)
3280 {
3281 restarted_autoneg = set_5708_serdes_pre_emphasis(
3282 pdev,
3283 pdev->params.serdes_pre_emphasis);
3284
3285 if(restarted_autoneg)
3286 {
3287 speed = LM_MEDIUM_SPEED_UNKNOWN;
3288 duplex = LM_MEDIUM_FULL_DUPLEX;
3289 link = LM_STATUS_LINK_DOWN;
3290 }
3291 }
3292 }
3293 else
3294 {
3295 /* Determine the forced link settings. */
3296 if(val & MII_CTRL_MANUAL_FORCE_2500)
3297 {
3298 DbgMessage(pdev, INFORM, "serdes forced to 2.5gb.\n");
3299 speed = LM_MEDIUM_SPEED_2500MBPS;
3300 }
3301 else if(val & MII_CTRL_MANUAL_SPD1)
3302 {
3303 DbgMessage(pdev, INFORM, "serdes forced to 1gb.\n");
3304 speed = LM_MEDIUM_SPEED_1000MBPS;
3305 }
3306 else if(val & MII_CTRL_MANUAL_SPD0)
3307 {
3308 DbgMessage(pdev, INFORM, "serdes forced to 100mb.\n");
3309 speed = LM_MEDIUM_SPEED_100MBPS;
3310 }
3311 else
3312 {
3313 DbgMessage(pdev, INFORM, "serdes forced to 10mb.\n");
3314 speed = LM_MEDIUM_SPEED_10MBPS;
3315 }
3316
3317 if(val & MII_CTRL_DUPLEX_MODE)
3318 {
3319 DbgMessage(pdev, INFORM, "serdes forced to full duplex.\n");
3320 duplex = LM_MEDIUM_FULL_DUPLEX;
3321 }
3322 else
3323 {
3324 DbgMessage(pdev, INFORM, "serdes forced to half duplex.\n");
3325 duplex = LM_MEDIUM_HALF_DUPLEX;
3326 }
3327 }
3328
3329 *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex;
3330
3331 return link;
3332 } /* get_5708_serdes_link */
3333
3334
3335
3336 /*******************************************************************************
3337 * Description:
3338 *
3339 * Return:
3340 ******************************************************************************/
3341 STATIC lm_status_t
get_5709_serdes_link(lm_device_t * pdev,lm_medium_t * medium)3342 get_5709_serdes_link(
3343 lm_device_t *pdev,
3344 lm_medium_t *medium)
3345 {
3346 lm_medium_t duplex = LM_MEDIUM_FULL_DUPLEX;
3347 lm_medium_t speed = LM_MEDIUM_SPEED_UNKNOWN;
3348 lm_status_t link = LM_STATUS_LINK_UNKNOWN;
3349 u32_t mac_status;
3350 u32_t val;
3351
3352 *medium = LM_MEDIUM_TYPE_FIBER |
3353 LM_MEDIUM_SPEED_UNKNOWN |
3354 LM_MEDIUM_FULL_DUPLEX;
3355
3356 pdev->vars.cable_is_attached = FALSE;
3357
3358 /* select gp_status block. */
3359 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8120);
3360
3361 /* get status. */
3362 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val);
3363 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val); /* is this needed? */
3364
3365 /* sometimes when we get a link event, mii register 0x1b does not
3366 * reflect the current link status but mac_status does reflect the
3367 * correct link status. */
3368 REG_RD(pdev, emac.emac_status, &mac_status);
3369
3370 /* link down. */
3371 if((val & 0x4) == 0 && (mac_status & EMAC_STATUS_LINK) == 0)
3372 {
3373 return LM_STATUS_LINK_DOWN;
3374 }
3375
3376 link = LM_STATUS_LINK_ACTIVE;
3377 pdev->vars.cable_is_attached = TRUE;
3378
3379 /* select combo ieee0 block. */
3380 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
3381
3382 /* phy_ctrl register. */
3383 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
3384
3385 if(val & 0x1000)
3386 {
3387 /* select gp_status block. */
3388 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8120);
3389
3390 /* get status. */
3391 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val);
3392
3393 /* duplex mode. */
3394 if(val & 0x8)
3395 {
3396 duplex = LM_MEDIUM_FULL_DUPLEX;
3397 }
3398 else
3399 {
3400 duplex = LM_MEDIUM_HALF_DUPLEX;
3401 }
3402
3403 /* Determine autoneg speed. */
3404 val = (val >> 8) & 0x3f;
3405 if(val == 0)
3406 {
3407 speed = LM_MEDIUM_SPEED_10MBPS;
3408 }
3409 else if(val == 1)
3410 {
3411 speed = LM_MEDIUM_SPEED_100MBPS;
3412 }
3413 else if(val == 2 || val == 13)
3414 {
3415 speed = LM_MEDIUM_SPEED_1000MBPS;
3416 }
3417 else if(val == 3)
3418 {
3419 speed = LM_MEDIUM_SPEED_2500MBPS;
3420 }
3421 else
3422 {
3423 DbgBreakMsg("unknown link speed status.\n");
3424 }
3425 }
3426 else
3427 {
3428 /* get forced duplex mode. */
3429 if(val & 0x100)
3430 {
3431 duplex = LM_MEDIUM_FULL_DUPLEX;
3432 }
3433 else
3434 {
3435 duplex = LM_MEDIUM_HALF_DUPLEX;
3436 }
3437
3438 /* get forced speed. */
3439 if(val & 0x20)
3440 {
3441 speed = LM_MEDIUM_SPEED_2500MBPS;
3442 }
3443 else if((val & 0x2040) == 0)
3444 {
3445 speed = LM_MEDIUM_SPEED_10MBPS;
3446 }
3447 else if((val & 0x2040) == 0x2000)
3448 {
3449 speed = LM_MEDIUM_SPEED_100MBPS;
3450 }
3451 else if((val & 0x2040) == 0x40)
3452 {
3453 speed = LM_MEDIUM_SPEED_1000MBPS;
3454 }
3455 else
3456 {
3457 DbgBreakMsg("unknown speed.\n");
3458 }
3459 }
3460
3461 *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex;
3462
3463 return link;
3464 } /* get_5709_serdes_link */
3465
3466
3467
3468 /*******************************************************************************
3469 * Description:
3470 *
3471 * Return:
3472 ******************************************************************************/
3473 STATIC lm_status_t
get_5706_serdes_link(lm_device_t * pdev,lm_medium_t * medium)3474 get_5706_serdes_link(
3475 lm_device_t *pdev,
3476 lm_medium_t *medium)
3477 {
3478 lm_status_t link;
3479 u32_t phy_status;
3480 u32_t remote_adv;
3481 u32_t local_adv;
3482 u32_t phy_ctrl;
3483 u32_t val;
3484
3485 *medium = LM_MEDIUM_TYPE_FIBER;
3486
3487 phy_status = mii_get_serdes_link_status(pdev);
3488
3489 if(phy_status & PHY_STATUS_LINK_PASS)
3490 {
3491 DbgMessage(pdev, INFORM, "serdes link up.\n");
3492
3493 link = LM_STATUS_LINK_ACTIVE;
3494 *medium |= LM_MEDIUM_SPEED_1000MBPS;
3495
3496 /* Determine duplex mode. Link is present also means
3497 * autoneg is done. */
3498 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
3499 if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE)
3500 {
3501 (void) lm_mread(
3502 pdev,
3503 pdev->params.phy_addr,
3504 PHY_AN_AD_REG,
3505 &local_adv);
3506 (void) lm_mread(
3507 pdev,
3508 pdev->params.phy_addr,
3509 PHY_LINK_PARTNER_ABILITY_REG,
3510 &remote_adv);
3511
3512 val = local_adv & remote_adv;
3513 if(val & PHY_AN_AD_1000X_FULL_DUPLEX)
3514 {
3515 DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n");
3516
3517 *medium |= LM_MEDIUM_FULL_DUPLEX;
3518 }
3519 else
3520 {
3521 DbgMessage(pdev, INFORM, "serdes autoneg to half duplex.\n");
3522
3523 *medium |= LM_MEDIUM_HALF_DUPLEX;
3524 }
3525
3526 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE;
3527 }
3528 else
3529 {
3530 if(phy_ctrl & PHY_CTRL_FULL_DUPLEX_MODE)
3531 {
3532 DbgMessage(pdev, INFORM, "serdes forced to full duplex.\n");
3533
3534 *medium |= LM_MEDIUM_FULL_DUPLEX;
3535 }
3536 else
3537 {
3538 DbgMessage(pdev, INFORM, "serdes forced to half duplex.\n");
3539
3540 *medium |= LM_MEDIUM_HALF_DUPLEX;
3541 }
3542
3543 if(pdev->vars.serdes_fallback_select)
3544 {
3545 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_1G;
3546 }
3547 }
3548 }
3549 else
3550 {
3551 DbgMessage(pdev, INFORM, "serdes link down.\n");
3552
3553 /* This routine is called only when the link is down. */
3554 link = serdes_fallback(pdev, pdev->vars.serdes_fallback_select);
3555 }
3556
3557 /* cq#30504 - restore the tx driver current so we can get link. */
3558 if(pdev->vars.bcm5706s_tx_drv_cur)
3559 {
3560 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x0f03);
3561
3562 (void) lm_mwrite(
3563 pdev,
3564 pdev->params.phy_addr,
3565 0x15,
3566 pdev->vars.bcm5706s_tx_drv_cur);
3567
3568 pdev->vars.bcm5706s_tx_drv_cur = 0;
3569 }
3570
3571 pdev->vars.cable_is_attached = TRUE;
3572
3573 if(link == LM_STATUS_LINK_DOWN)
3574 {
3575 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
3576 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
3577 if(!(val & 0x10))
3578 {
3579 pdev->vars.cable_is_attached = FALSE;
3580 }
3581 }
3582
3583 return link;
3584 } /* get_5706_serdes_link */
3585
3586
3587
3588 /*******************************************************************************
3589 * Description:
3590 *
3591 * Return:
3592 ******************************************************************************/
3593 STATIC lm_status_t
get_remote_phy_link(lm_device_t * pdev,lm_medium_t * medium)3594 get_remote_phy_link(
3595 lm_device_t *pdev,
3596 lm_medium_t *medium)
3597 {
3598 u32_t remote_phy_link;
3599 lm_medium_t duplex;
3600 lm_medium_t speed;
3601 lm_status_t link;
3602
3603 DbgBreakIf(pdev->params.enable_remote_phy == FALSE);
3604
3605 *medium = LM_MEDIUM_TYPE_FIBER |
3606 LM_MEDIUM_SPEED_UNKNOWN |
3607 LM_MEDIUM_FULL_DUPLEX;
3608
3609 pdev->vars.cable_is_attached = FALSE;
3610
3611 REG_RD_IND(
3612 pdev,
3613 pdev->hw_info.shmem_base +
3614 OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
3615 &remote_phy_link);
3616
3617 pdev->vars.rphy_status = 0;
3618
3619 if((remote_phy_link & NETLINK_GET_LINK_STATUS_SERDES_LINK) == 0)
3620 {
3621 pdev->vars.rphy_status |= RPHY_STATUS_ACTIVE;
3622 }
3623
3624 if((remote_phy_link & NETLINK_GET_LINK_STATUS_NO_MEDIA_DETECTED) == 0)
3625 {
3626 pdev->vars.rphy_status |= RPHY_STATUS_MODULE_PRESENT;
3627 }
3628
3629 if((remote_phy_link & NETLINK_GET_LINK_STATUS_LINK_UP) == 0)
3630 {
3631 return LM_STATUS_LINK_DOWN;
3632 }
3633
3634 link = LM_STATUS_LINK_ACTIVE;
3635 pdev->vars.cable_is_attached = TRUE;
3636
3637 switch(remote_phy_link & NETLINK_GET_LINK_STATUS_SPEED_MASK)
3638 {
3639 case NETLINK_GET_LINK_STATUS_10HALF:
3640 speed = LM_MEDIUM_SPEED_10MBPS;
3641 duplex = LM_MEDIUM_HALF_DUPLEX;
3642 break;
3643
3644 case NETLINK_GET_LINK_STATUS_10FULL:
3645 speed = LM_MEDIUM_SPEED_10MBPS;
3646 duplex = LM_MEDIUM_FULL_DUPLEX;
3647 break;
3648
3649 case NETLINK_GET_LINK_STATUS_100HALF:
3650 speed = LM_MEDIUM_SPEED_100MBPS;
3651 duplex = LM_MEDIUM_HALF_DUPLEX;
3652 break;
3653
3654 case NETLINK_GET_LINK_STATUS_100FULL:
3655 speed = LM_MEDIUM_SPEED_100MBPS;
3656 duplex = LM_MEDIUM_FULL_DUPLEX;
3657 break;
3658
3659 case NETLINK_GET_LINK_STATUS_1000HALF:
3660 speed = LM_MEDIUM_SPEED_1000MBPS;
3661 duplex = LM_MEDIUM_HALF_DUPLEX;
3662 break;
3663
3664 case NETLINK_GET_LINK_STATUS_1000FULL:
3665 speed = LM_MEDIUM_SPEED_1000MBPS;
3666 duplex = LM_MEDIUM_FULL_DUPLEX;
3667 break;
3668
3669 case NETLINK_GET_LINK_STATUS_2500HALF:
3670 speed = LM_MEDIUM_SPEED_2500MBPS;
3671 duplex = LM_MEDIUM_HALF_DUPLEX;
3672 break;
3673
3674 case NETLINK_GET_LINK_STATUS_2500FULL:
3675 speed = LM_MEDIUM_SPEED_2500MBPS;
3676 duplex = LM_MEDIUM_FULL_DUPLEX;
3677 break;
3678
3679 default:
3680 speed = LM_MEDIUM_SPEED_UNKNOWN;
3681 duplex = LM_MEDIUM_FULL_DUPLEX;
3682 break;
3683 }
3684
3685 *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex;
3686
3687 return link;
3688 } /* get_remote_phy_link */
3689
3690
3691
3692 /*******************************************************************************
3693 * Description:
3694 *
3695 * Return:
3696 ******************************************************************************/
3697 lm_status_t
lm_init_mac_link(lm_device_t * pdev)3698 lm_init_mac_link(
3699 lm_device_t *pdev)
3700 {
3701 lm_status_t lm_status;
3702 lm_medium_t medium;
3703 lm_status_t link;
3704 u32_t val, phy_ctrl, phy_status;
3705
3706 if(pdev->params.enable_remote_phy)
3707 {
3708 link = get_remote_phy_link(pdev, &medium);
3709 init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap);
3710
3711 return LM_STATUS_SUCCESS;
3712 }
3713
3714 switch(GET_MEDIUM_TYPE(pdev->vars.medium))
3715 {
3716 case LM_MEDIUM_TYPE_UTP:
3717 link = get_copper_phy_link(pdev, &medium);
3718 init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap);
3719
3720 lm_status = LM_STATUS_SUCCESS;
3721 break;
3722
3723 case LM_MEDIUM_TYPE_FIBER:
3724 DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5706 &&
3725 CHIP_NUM(pdev) != CHIP_NUM_5708 &&
3726 CHIP_NUM(pdev) != CHIP_NUM_5709);
3727
3728 if(CHIP_NUM(pdev) == CHIP_NUM_5706)
3729 {
3730 link = get_5706_serdes_link(pdev, &medium);
3731 }
3732 else if(CHIP_NUM(pdev) == CHIP_NUM_5708)
3733 {
3734 link = get_5708_serdes_link(pdev, &medium);
3735 }
3736 else
3737 {
3738 link = get_5709_serdes_link(pdev, &medium);
3739 }
3740
3741 init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap);
3742
3743 lm_status = LM_STATUS_SUCCESS;
3744 break;
3745
3746 case LM_MEDIUM_TYPE_PHY_LOOPBACK:
3747 case LM_MEDIUM_TYPE_MAC_LOOPBACK:
3748 lm_status = init_loopback_mac_link(
3749 pdev,
3750 pdev->params.req_medium,
3751 pdev->params.flow_ctrl_cap);
3752 break;
3753
3754 case LM_MEDIUM_TYPE_NULL:
3755 init_mac_link(
3756 pdev,
3757 LM_STATUS_LINK_ACTIVE,
3758 LM_MEDIUM_TYPE_NULL |
3759 LM_MEDIUM_SPEED_1000MBPS |
3760 LM_MEDIUM_FULL_DUPLEX,
3761 pdev->params.flow_ctrl_cap);
3762
3763 lm_status = LM_STATUS_SUCCESS;
3764 break;
3765
3766 default:
3767 lm_status = LM_STATUS_UNKNOWN_MEDIUM;
3768 break;
3769 }
3770
3771 /* Report the currnet link status to the management firmware. */
3772 val = 0;
3773
3774 if(pdev->vars.link_status == LM_STATUS_LINK_ACTIVE)
3775 {
3776 val |= NETLINK_GET_LINK_STATUS_LINK_UP;
3777
3778 if(lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
3779 {
3780 val |= NETLINK_GET_LINK_STATUS_SERDES_LINK;
3781 }
3782 }
3783
3784 switch(GET_MEDIUM_SPEED(pdev->vars.medium))
3785 {
3786 case LM_MEDIUM_SPEED_10MBPS:
3787 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3788 {
3789 val |= NETLINK_GET_LINK_STATUS_10FULL;
3790 }
3791 else
3792 {
3793 val |= NETLINK_GET_LINK_STATUS_10HALF;
3794 }
3795 break;
3796
3797 case LM_MEDIUM_SPEED_100MBPS:
3798 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3799 {
3800 val |= NETLINK_GET_LINK_STATUS_100FULL;
3801 }
3802 else
3803 {
3804 val |= NETLINK_GET_LINK_STATUS_100HALF;
3805 }
3806 break;
3807
3808 case LM_MEDIUM_SPEED_1000MBPS:
3809 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3810 {
3811 val |= NETLINK_GET_LINK_STATUS_1000FULL;
3812 }
3813 else
3814 {
3815 val |= NETLINK_GET_LINK_STATUS_1000HALF;
3816 }
3817 break;
3818
3819 case LM_MEDIUM_SPEED_2500MBPS:
3820 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3821 {
3822 val |= NETLINK_GET_LINK_STATUS_2500FULL;
3823 }
3824 else
3825 {
3826 val |= NETLINK_GET_LINK_STATUS_2500HALF;
3827 }
3828 break;
3829 }
3830
3831 // read PHY_CTRL_REG to see if auto-negotiation is enabled/completed
3832 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
3833
3834 if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE)
3835 {
3836 val |= NETLINK_GET_LINK_STATUS_AN_ENABLED;
3837 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status);
3838 if(phy_status & PHY_STATUS_AUTO_NEG_COMPLETE)
3839 {
3840 val |= NETLINK_GET_LINK_STATUS_AN_COMPLETE;
3841 // Following bits are valid for copper (i.e. SerDes flag == 0)
3842 if ((val & NETLINK_GET_LINK_STATUS_SERDES_LINK) == 0)
3843 {
3844 u32_t remote_phy_ad;
3845 (void) lm_mread(
3846 pdev,
3847 pdev->params.phy_addr,
3848 PHY_1000BASET_STATUS_REG,
3849 &remote_phy_ad);
3850
3851 if(remote_phy_ad & PHY_LINK_PARTNER_1000BASET_FULL)
3852 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_1000FULL;
3853 if(remote_phy_ad & PHY_LINK_PARTNER_1000BASET_HALF)
3854 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_1000HALF;
3855
3856 (void) lm_mread(
3857 pdev,
3858 pdev->params.phy_addr,
3859 PHY_LINK_PARTNER_ABILITY_REG,
3860 &remote_phy_ad);
3861 if (remote_phy_ad & PHY_LINK_PARTNER_10BASET_HALF)
3862 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_10HALF;
3863 if (remote_phy_ad & PHY_LINK_PARTNER_10BASET_FULL)
3864 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_10FULL;
3865 if (remote_phy_ad & PHY_LINK_PARTNER_100BASETX_HALF)
3866 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_100HALF;
3867 if (remote_phy_ad & PHY_LINK_PARTNER_100BASETX_FULL)
3868 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_100FULL;
3869 if (remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
3870 val |= NETLINK_GET_LINK_STATUS_PARTNER_SYM_PAUSE_CAP;
3871 if (remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE)
3872 val |= NETLINK_GET_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP;
3873 // Read PHY_AN_EXPANSION_REG to see if Link partner support auto
3874 // negotiation
3875 (void) lm_mread(
3876 pdev,
3877 pdev->params.phy_addr,
3878 PHY_AN_EXPANSION_REG,
3879 &remote_phy_ad);
3880 // If Link partner does not support auto negotiation, we assume
3881 // parallel detection was used to get link.
3882 if ((remote_phy_ad & PHY_LINK_PARTNER_AUTONEG_ABILITY) == 0)
3883 val |= NETLINK_GET_LINK_STATUS_PARALLEL_DET;
3884 }
3885 }
3886 }
3887 if(pdev->vars.flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
3888 {
3889 val |= NETLINK_GET_LINK_STATUS_TX_FC_ENABLED;
3890 }
3891 if(pdev->vars.flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE)
3892 {
3893 val |= NETLINK_GET_LINK_STATUS_RX_FC_ENABLED;
3894 }
3895 // Following bits are not supported yet
3896 // NETLINK_GET_LINK_STATUS_NO_MEDIA_DETECTED;
3897 // NETLINK_GET_LINK_STATUS_CABLESENSE;
3898 // NETLINK_GET_LINK_STATUS_SW_TIMER_EVENT;
3899 REG_WR_IND(
3900 pdev,
3901 pdev->hw_info.shmem_base +
3902 OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
3903 val);
3904
3905 return lm_status;
3906 } /* lm_init_mac_link */
3907
3908
3909
3910 /*******************************************************************************
3911 * Description:
3912 *
3913 * Return:
3914 ******************************************************************************/
3915 void
lm_service_phy_int(lm_device_t * pdev,u32_t force_service_int)3916 lm_service_phy_int(
3917 lm_device_t *pdev,
3918 u32_t force_service_int)
3919 {
3920 u32_t deasserted_attns;
3921 u32_t asserted_attns;
3922 u32_t link_chng;
3923 u32_t val;
3924
3925 link_chng = FALSE;
3926
3927 if(pdev->params.link_chng_mode == LINK_CHNG_MODE_USE_STATUS_REG)
3928 {
3929 REG_RD(pdev, emac.emac_status, &val);
3930 if(pdev->params.phy_int_mode == PHY_INT_MODE_MI_INTERRUPT)
3931 {
3932 if(val & EMAC_STATUS_MI_INT)
3933 {
3934 link_chng = TRUE;
3935 }
3936 }
3937 else if(val & EMAC_STATUS_LINK_CHANGE)
3938 {
3939 link_chng = TRUE;
3940 }
3941 }
3942 else
3943 {
3944 link_chng = FALSE;
3945
3946 GET_ATTN_CHNG_BITS(pdev, &asserted_attns, &deasserted_attns);
3947
3948 asserted_attns &= STATUS_ATTN_BITS_LINK_STATE;
3949 deasserted_attns &= STATUS_ATTN_BITS_LINK_STATE;
3950
3951 if(asserted_attns)
3952 {
3953 link_chng = TRUE;
3954
3955 REG_WR(
3956 pdev,
3957 pci_config.pcicfg_status_bit_set_cmd,
3958 asserted_attns);
3959 }
3960 else if(deasserted_attns)
3961 {
3962 link_chng = TRUE;
3963
3964 REG_WR(
3965 pdev,
3966 pci_config.pcicfg_status_bit_clear_cmd,
3967 deasserted_attns);
3968 }
3969 }
3970
3971 if(link_chng || force_service_int || pdev->params.enable_remote_phy)
3972 {
3973 (void) lm_init_mac_link(pdev);
3974
3975 mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium);
3976 }
3977 } /* lm_service_phy_int */
3978
3979
3980
3981 /*******************************************************************************
3982 * Description:
3983 *
3984 * Return:
3985 ******************************************************************************/
3986 lm_medium_t
lm_get_medium(lm_device_t * pdev)3987 lm_get_medium(
3988 lm_device_t *pdev)
3989 {
3990 u32_t decode;
3991 u32_t val;
3992
3993 if(CHIP_REV(pdev) == CHIP_REV_IKOS)
3994 {
3995 return LM_MEDIUM_TYPE_NULL;
3996 }
3997
3998 if(CHIP_REV(pdev) == CHIP_REV_FPGA)
3999 {
4000 return LM_MEDIUM_TYPE_UTP;
4001 }
4002
4003 if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
4004 {
4005 if(CHIP_BOND_ID(pdev) & CHIP_BOND_ID_SERDES_BIT)
4006 {
4007 return LM_MEDIUM_TYPE_FIBER;
4008 }
4009
4010 return LM_MEDIUM_TYPE_UTP;
4011 }
4012
4013 if(CHIP_NUM(pdev) == CHIP_NUM_5709)
4014 {
4015 REG_RD(pdev, misc.misc_dual_media_ctrl, &val);
4016
4017 if((val & MISC_DUAL_MEDIA_CTRL_BOND_ID) ==
4018 MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
4019 {
4020 return LM_MEDIUM_TYPE_UTP;
4021 }
4022
4023 if((val & MISC_DUAL_MEDIA_CTRL_BOND_ID) ==
4024 MISC_DUAL_MEDIA_CTRL_BOND_ID_S)
4025 {
4026 return LM_MEDIUM_TYPE_FIBER;
4027 }
4028
4029 /* mac to phy/serdes decode.
4030 * swap strap mac0 mac1
4031 * ==== ===== ==== ====
4032 * 0 000 phy0 phy1
4033 * 0 001 phy0 ser0
4034 * 0 010 phy0 ser1
4035 * 0 110 ser0 phy0
4036 * 0 101 ser0 phy1
4037 * 0 100 ser0 ser1
4038 *
4039 * 1 000 phy1 phy0
4040 * 1 001 phy1 ser1
4041 * 1 010 phy1 ser0
4042 * 1 110 ser1 phy1
4043 * 1 101 ser1 phy0
4044 * 1 100 ser1 ser0 */
4045 if(val & MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE)
4046 {
4047 decode = (val & MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
4048
4049 if(val & MISC_DUAL_MEDIA_CTRL_PORT_SWAP)
4050 {
4051 decode |= 0x8;
4052 }
4053 }
4054 else
4055 {
4056 decode = (val & MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
4057
4058 if(val & MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN)
4059 {
4060 decode |= 0x8;
4061 }
4062 }
4063
4064 decode |= pdev->hw_info.mac_id << 4;
4065
4066 /* mac:4, swap:3, strap:2-0. */
4067 switch(decode)
4068 {
4069 case 0x00: /* 00000 - mac0, phy0 */
4070 case 0x01: /* 00001 - mac0, phy0 */
4071 case 0x02: /* 00010 - mac0, phy0 */
4072 case 0x08: /* 01000 - mac0, phy1 */
4073 case 0x09: /* 01001 - mac0, phy1 */
4074 case 0x0a: /* 01010 - mac0, phy1 */
4075 case 0x10: /* 10000 - mac1, phy1 */
4076 case 0x15: /* 10101 - mac1, phy1 */
4077 case 0x16: /* 10110 - mac1, phy0 */
4078 case 0x18: /* 11000 - mac1, phy0 */
4079 case 0x1d: /* 11101 - mac1, phy0 */
4080 case 0x1e: /* 11110 - mac1, phy1 */
4081 return LM_MEDIUM_TYPE_UTP;
4082
4083 case 0x04: /* 00100 - mac0, ser0 */
4084 case 0x05: /* 00101 - mac0, ser0 */
4085 case 0x06: /* 00110 - mac0, ser0 */
4086 case 0x0c: /* 01100 - mac0, ser1 */
4087 case 0x0d: /* 01101 - mac0, ser1 */
4088 case 0x0e: /* 01110 - mac0, ser1 */
4089 case 0x11: /* 10001 - mac1, ser0 */
4090 case 0x12: /* 10010 - mac1, ser1 */
4091 case 0x14: /* 10100 - mac1, ser1 */
4092 case 0x19: /* 11001 - mac1, ser1 */
4093 case 0x1a: /* 11010 - mac1, ser0 */
4094 case 0x1c: /* 11100 - mac1, ser0 */
4095 return LM_MEDIUM_TYPE_FIBER;
4096 }
4097 }
4098
4099 return LM_MEDIUM_TYPE_NULL;
4100 } /* lm_get_medium */
4101