1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <asm/octeon/octeon.h>
35#include <asm/octeon/cvmx-bootinfo.h>
36
37#include "cvmx-config.h"
38
39#include "cvmx-mdio.h"
40
41#include "cvmx-helper.h"
42#include "cvmx-helper-util.h"
43#include "cvmx-helper-board.h"
44
45#include "cvmx-gmxx-defs.h"
46#include "cvmx-asxx-defs.h"
47
48
49
50
51
52
53
54
55
56cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port) =
57 NULL;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75int cvmx_helper_board_get_mii_address(int ipd_port)
76{
77 switch (cvmx_sysinfo_get()->board_type) {
78 case CVMX_BOARD_TYPE_SIM:
79
80 return -1;
81 case CVMX_BOARD_TYPE_EBT3000:
82 case CVMX_BOARD_TYPE_EBT5800:
83 case CVMX_BOARD_TYPE_THUNDER:
84 case CVMX_BOARD_TYPE_NICPRO2:
85
86 if ((ipd_port >= 16) && (ipd_port < 20))
87 return ipd_port - 16;
88 else
89 return -1;
90 case CVMX_BOARD_TYPE_KODAMA:
91 case CVMX_BOARD_TYPE_EBH3100:
92 case CVMX_BOARD_TYPE_HIKARI:
93 case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
94 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
95 case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
96
97
98
99
100 if (ipd_port == 0)
101 return 4;
102 else if (ipd_port == 1)
103 return 9;
104 else
105 return -1;
106 case CVMX_BOARD_TYPE_NAC38:
107
108 if ((ipd_port >= 0) && (ipd_port < 4))
109 return ipd_port;
110 else if ((ipd_port >= 16) && (ipd_port < 20))
111 return ipd_port - 16 + 4;
112 else
113 return -1;
114 case CVMX_BOARD_TYPE_EBH3000:
115
116 return -1;
117 case CVMX_BOARD_TYPE_EBH5200:
118 case CVMX_BOARD_TYPE_EBH5201:
119 case CVMX_BOARD_TYPE_EBT5200:
120
121
122
123
124 if ((ipd_port >= 0) && (ipd_port < 4))
125 return ipd_port + 2;
126 else
127 return -1;
128 case CVMX_BOARD_TYPE_EBH5600:
129 case CVMX_BOARD_TYPE_EBH5601:
130 case CVMX_BOARD_TYPE_EBH5610:
131
132
133
134
135 if ((ipd_port >= 0) && (ipd_port < 4))
136 return ipd_port + 1;
137 else
138 return -1;
139 case CVMX_BOARD_TYPE_CUST_NB5:
140 if (ipd_port == 2)
141 return 4;
142 else
143 return -1;
144 case CVMX_BOARD_TYPE_NIC_XLE_4G:
145
146 if ((ipd_port >= 16) && (ipd_port < 20))
147 return ipd_port - 16 + 1;
148 else
149 return -1;
150 case CVMX_BOARD_TYPE_BBGW_REF:
151
152
153
154
155 return -1;
156
157 case CVMX_BOARD_TYPE_CUST_WSX16:
158 if (ipd_port >= 0 && ipd_port <= 3)
159 return ipd_port;
160 else if (ipd_port >= 16 && ipd_port <= 19)
161 return ipd_port - 16 + 4;
162 else
163 return -1;
164 }
165
166
167 cvmx_dprintf
168 ("cvmx_helper_board_get_mii_address: Unknown board type %d\n",
169 cvmx_sysinfo_get()->board_type);
170 return -1;
171}
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
192{
193 cvmx_helper_link_info_t result;
194 int phy_addr;
195 int is_broadcom_phy = 0;
196
197
198 if (cvmx_override_board_link_get)
199 return cvmx_override_board_link_get(ipd_port);
200
201
202 result.u64 = 0;
203
204
205
206
207
208 switch (cvmx_sysinfo_get()->board_type) {
209 case CVMX_BOARD_TYPE_SIM:
210
211 result.s.link_up = 1;
212 result.s.full_duplex = 1;
213 result.s.speed = 1000;
214 return result;
215 case CVMX_BOARD_TYPE_EBH3100:
216 case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
217 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
218 case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
219
220 if (ipd_port == 1) {
221 result.s.link_up = 1;
222 result.s.full_duplex = 1;
223 result.s.speed = 1000;
224 return result;
225 }
226
227 break;
228 case CVMX_BOARD_TYPE_CUST_NB5:
229
230 if (ipd_port == 1) {
231 result.s.link_up = 1;
232 result.s.full_duplex = 1;
233 result.s.speed = 1000;
234 return result;
235 } else
236 is_broadcom_phy = 1;
237 break;
238 case CVMX_BOARD_TYPE_BBGW_REF:
239
240 if (ipd_port == 2) {
241
242 result.u64 = 0;
243 return result;
244 } else {
245
246 result.s.link_up = 1;
247 result.s.full_duplex = 1;
248 result.s.speed = 1000;
249 return result;
250 }
251 break;
252 }
253
254 phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
255 if (phy_addr != -1) {
256 if (is_broadcom_phy) {
257
258
259
260
261
262 int phy_status =
263 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
264 0x19);
265 switch ((phy_status >> 8) & 0x7) {
266 case 0:
267 result.u64 = 0;
268 break;
269 case 1:
270 result.s.link_up = 1;
271 result.s.full_duplex = 0;
272 result.s.speed = 10;
273 break;
274 case 2:
275 result.s.link_up = 1;
276 result.s.full_duplex = 1;
277 result.s.speed = 10;
278 break;
279 case 3:
280 result.s.link_up = 1;
281 result.s.full_duplex = 0;
282 result.s.speed = 100;
283 break;
284 case 4:
285 result.s.link_up = 1;
286 result.s.full_duplex = 1;
287 result.s.speed = 100;
288 break;
289 case 5:
290 result.s.link_up = 1;
291 result.s.full_duplex = 1;
292 result.s.speed = 100;
293 break;
294 case 6:
295 result.s.link_up = 1;
296 result.s.full_duplex = 0;
297 result.s.speed = 1000;
298 break;
299 case 7:
300 result.s.link_up = 1;
301 result.s.full_duplex = 1;
302 result.s.speed = 1000;
303 break;
304 }
305 } else {
306
307
308
309
310
311
312
313
314 int phy_status =
315 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17);
316
317
318
319
320
321
322
323 if ((phy_status & (1 << 11)) == 0) {
324 int auto_status =
325 cvmx_mdio_read(phy_addr >> 8,
326 phy_addr & 0xff, 0);
327 if ((auto_status & (1 << 12)) == 0)
328 phy_status |= 1 << 11;
329 }
330
331
332
333
334
335
336 if (phy_status & (1 << 11)) {
337 result.s.link_up = 1;
338 result.s.full_duplex = ((phy_status >> 13) & 1);
339 switch ((phy_status >> 14) & 3) {
340 case 0:
341 result.s.speed = 10;
342 break;
343 case 1:
344 result.s.speed = 100;
345 break;
346 case 2:
347 result.s.speed = 1000;
348 break;
349 case 3:
350 result.u64 = 0;
351 break;
352 }
353 }
354 }
355 } else if (OCTEON_IS_MODEL(OCTEON_CN3XXX)
356 || OCTEON_IS_MODEL(OCTEON_CN58XX)
357 || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
358
359
360
361
362
363
364
365 union cvmx_gmxx_rxx_rx_inbnd inband_status;
366 int interface = cvmx_helper_get_interface_num(ipd_port);
367 int index = cvmx_helper_get_interface_index_num(ipd_port);
368 inband_status.u64 =
369 cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface));
370
371 result.s.link_up = inband_status.s.status;
372 result.s.full_duplex = inband_status.s.duplex;
373 switch (inband_status.s.speed) {
374 case 0:
375 result.s.speed = 10;
376 break;
377 case 1:
378 result.s.speed = 100;
379 break;
380 case 2:
381 result.s.speed = 1000;
382 break;
383 case 3:
384 result.u64 = 0;
385 break;
386 }
387 } else {
388
389
390
391
392
393
394 result.u64 = 0;
395 }
396
397
398 if (!result.s.link_up)
399 result.u64 = 0;
400
401 return result;
402}
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418int cvmx_helper_board_link_set_phy(int phy_addr,
419 cvmx_helper_board_set_phy_link_flags_types_t
420 link_flags,
421 cvmx_helper_link_info_t link_info)
422{
423
424
425 if ((link_flags & set_phy_link_flags_flow_control_mask) !=
426 set_phy_link_flags_flow_control_dont_touch) {
427 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
428 reg_autoneg_adver.u16 =
429 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
430 CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
431 reg_autoneg_adver.s.asymmetric_pause =
432 (link_flags & set_phy_link_flags_flow_control_mask) ==
433 set_phy_link_flags_flow_control_enable;
434 reg_autoneg_adver.s.pause =
435 (link_flags & set_phy_link_flags_flow_control_mask) ==
436 set_phy_link_flags_flow_control_enable;
437 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
438 CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
439 reg_autoneg_adver.u16);
440 }
441
442
443 if ((link_flags & set_phy_link_flags_autoneg)
444 && (link_info.s.speed == 0)) {
445 cvmx_mdio_phy_reg_control_t reg_control;
446 cvmx_mdio_phy_reg_status_t reg_status;
447 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
448 cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
449 cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
450
451 reg_status.u16 =
452 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
453 CVMX_MDIO_PHY_REG_STATUS);
454 reg_autoneg_adver.u16 =
455 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
456 CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
457 reg_autoneg_adver.s.advert_100base_t4 =
458 reg_status.s.capable_100base_t4;
459 reg_autoneg_adver.s.advert_10base_tx_full =
460 reg_status.s.capable_10_full;
461 reg_autoneg_adver.s.advert_10base_tx_half =
462 reg_status.s.capable_10_half;
463 reg_autoneg_adver.s.advert_100base_tx_full =
464 reg_status.s.capable_100base_x_full;
465 reg_autoneg_adver.s.advert_100base_tx_half =
466 reg_status.s.capable_100base_x_half;
467 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
468 CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
469 reg_autoneg_adver.u16);
470 if (reg_status.s.capable_extended_status) {
471 reg_extended_status.u16 =
472 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
473 CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
474 reg_control_1000.u16 =
475 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
476 CVMX_MDIO_PHY_REG_CONTROL_1000);
477 reg_control_1000.s.advert_1000base_t_full =
478 reg_extended_status.s.capable_1000base_t_full;
479 reg_control_1000.s.advert_1000base_t_half =
480 reg_extended_status.s.capable_1000base_t_half;
481 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
482 CVMX_MDIO_PHY_REG_CONTROL_1000,
483 reg_control_1000.u16);
484 }
485 reg_control.u16 =
486 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
487 CVMX_MDIO_PHY_REG_CONTROL);
488 reg_control.s.autoneg_enable = 1;
489 reg_control.s.restart_autoneg = 1;
490 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
491 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
492 } else if ((link_flags & set_phy_link_flags_autoneg)) {
493 cvmx_mdio_phy_reg_control_t reg_control;
494 cvmx_mdio_phy_reg_status_t reg_status;
495 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
496 cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
497 cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
498
499 reg_status.u16 =
500 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
501 CVMX_MDIO_PHY_REG_STATUS);
502 reg_autoneg_adver.u16 =
503 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
504 CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
505 reg_autoneg_adver.s.advert_100base_t4 = 0;
506 reg_autoneg_adver.s.advert_10base_tx_full = 0;
507 reg_autoneg_adver.s.advert_10base_tx_half = 0;
508 reg_autoneg_adver.s.advert_100base_tx_full = 0;
509 reg_autoneg_adver.s.advert_100base_tx_half = 0;
510 if (reg_status.s.capable_extended_status) {
511 reg_extended_status.u16 =
512 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
513 CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
514 reg_control_1000.u16 =
515 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
516 CVMX_MDIO_PHY_REG_CONTROL_1000);
517 reg_control_1000.s.advert_1000base_t_full = 0;
518 reg_control_1000.s.advert_1000base_t_half = 0;
519 }
520 switch (link_info.s.speed) {
521 case 10:
522 reg_autoneg_adver.s.advert_10base_tx_full =
523 link_info.s.full_duplex;
524 reg_autoneg_adver.s.advert_10base_tx_half =
525 !link_info.s.full_duplex;
526 break;
527 case 100:
528 reg_autoneg_adver.s.advert_100base_tx_full =
529 link_info.s.full_duplex;
530 reg_autoneg_adver.s.advert_100base_tx_half =
531 !link_info.s.full_duplex;
532 break;
533 case 1000:
534 reg_control_1000.s.advert_1000base_t_full =
535 link_info.s.full_duplex;
536 reg_control_1000.s.advert_1000base_t_half =
537 !link_info.s.full_duplex;
538 break;
539 }
540 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
541 CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
542 reg_autoneg_adver.u16);
543 if (reg_status.s.capable_extended_status)
544 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
545 CVMX_MDIO_PHY_REG_CONTROL_1000,
546 reg_control_1000.u16);
547 reg_control.u16 =
548 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
549 CVMX_MDIO_PHY_REG_CONTROL);
550 reg_control.s.autoneg_enable = 1;
551 reg_control.s.restart_autoneg = 1;
552 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
553 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
554 } else {
555 cvmx_mdio_phy_reg_control_t reg_control;
556 reg_control.u16 =
557 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
558 CVMX_MDIO_PHY_REG_CONTROL);
559 reg_control.s.autoneg_enable = 0;
560 reg_control.s.restart_autoneg = 1;
561 reg_control.s.duplex = link_info.s.full_duplex;
562 if (link_info.s.speed == 1000) {
563 reg_control.s.speed_msb = 1;
564 reg_control.s.speed_lsb = 0;
565 } else if (link_info.s.speed == 100) {
566 reg_control.s.speed_msb = 0;
567 reg_control.s.speed_lsb = 1;
568 } else if (link_info.s.speed == 10) {
569 reg_control.s.speed_msb = 0;
570 reg_control.s.speed_lsb = 0;
571 }
572 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
573 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
574 }
575 return 0;
576}
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599int __cvmx_helper_board_interface_probe(int interface, int supported_ports)
600{
601 switch (cvmx_sysinfo_get()->board_type) {
602 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
603 if (interface == 0)
604 return 2;
605 break;
606 case CVMX_BOARD_TYPE_BBGW_REF:
607 if (interface == 0)
608 return 2;
609 break;
610 case CVMX_BOARD_TYPE_NIC_XLE_4G:
611 if (interface == 0)
612 return 0;
613 break;
614
615
616 case CVMX_BOARD_TYPE_EBH5600:
617 if (interface == 1)
618 return 0;
619 break;
620 }
621 return supported_ports;
622}
623
624
625
626
627
628
629
630
631
632
633
634int __cvmx_helper_board_hardware_enable(int interface)
635{
636 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) {
637 if (interface == 0) {
638
639 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0);
640 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0);
641
642
643
644
645
646 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface),
647 0xc);
648 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface),
649 0xc);
650 }
651 } else if (cvmx_sysinfo_get()->board_type ==
652 CVMX_BOARD_TYPE_CN3010_EVB_HS5) {
653
654
655
656
657
658
659 if (interface == 0) {
660
661
662
663
664
665
666
667
668 int phy_addr = cvmx_helper_board_get_mii_address(0);
669 if (phy_addr != -1) {
670 int phy_identifier =
671 cvmx_mdio_read(phy_addr >> 8,
672 phy_addr & 0xff, 0x2);
673
674 if (phy_identifier == 0x0143) {
675 cvmx_dprintf("\n");
676 cvmx_dprintf("ERROR:\n");
677 cvmx_dprintf
678 ("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n");
679 cvmx_dprintf
680 ("ERROR: The board type is mis-configured, and software malfunctions are likely.\n");
681 cvmx_dprintf
682 ("ERROR: All boards require a unique board type to identify them.\n");
683 cvmx_dprintf("ERROR:\n");
684 cvmx_dprintf("\n");
685 cvmx_wait(1000000000);
686 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX
687 (0, interface), 5);
688 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX
689 (0, interface), 5);
690 }
691 }
692 }
693 }
694 return 0;
695}
696