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 <asm/octeon/cvmx-config.h>
38
39#include <asm/octeon/cvmx-mdio.h>
40
41#include <asm/octeon/cvmx-helper.h>
42#include <asm/octeon/cvmx-helper-util.h>
43#include <asm/octeon/cvmx-helper-board.h>
44
45#include <asm/octeon/cvmx-gmxx-defs.h>
46#include <asm/octeon/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 if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) &&
122 (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)))
123 return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT;
124
125
126
127
128 if ((ipd_port >= 0) && (ipd_port < 4))
129 return ipd_port + 2;
130 else
131 return -1;
132 case CVMX_BOARD_TYPE_EBH5600:
133 case CVMX_BOARD_TYPE_EBH5601:
134 case CVMX_BOARD_TYPE_EBH5610:
135
136 if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
137 return 0;
138
139
140
141
142 if ((ipd_port >= 0) && (ipd_port < 4))
143 return ipd_port + 1;
144 else
145 return -1;
146 case CVMX_BOARD_TYPE_CUST_NB5:
147 if (ipd_port == 2)
148 return 4;
149 else
150 return -1;
151 case CVMX_BOARD_TYPE_NIC_XLE_4G:
152
153 if ((ipd_port >= 16) && (ipd_port < 20))
154 return ipd_port - 16 + 1;
155 else
156 return -1;
157 case CVMX_BOARD_TYPE_NIC_XLE_10G:
158 case CVMX_BOARD_TYPE_NIC10E:
159 return -1;
160 case CVMX_BOARD_TYPE_NIC4E:
161 if (ipd_port >= 0 && ipd_port <= 3)
162 return (ipd_port + 0x1f) & 0x1f;
163 else
164 return -1;
165 case CVMX_BOARD_TYPE_NIC2E:
166 if (ipd_port >= 0 && ipd_port <= 1)
167 return ipd_port + 1;
168 else
169 return -1;
170 case CVMX_BOARD_TYPE_BBGW_REF:
171
172
173
174
175 return -1;
176
177 case CVMX_BOARD_TYPE_CUST_WSX16:
178 if (ipd_port >= 0 && ipd_port <= 3)
179 return ipd_port;
180 else if (ipd_port >= 16 && ipd_port <= 19)
181 return ipd_port - 16 + 4;
182 else
183 return -1;
184 case CVMX_BOARD_TYPE_UBNT_E100:
185 if (ipd_port >= 0 && ipd_port <= 2)
186 return 7 - ipd_port;
187 else
188 return -1;
189 case CVMX_BOARD_TYPE_CUST_DSR1000N:
190
191
192
193
194 if (ipd_port == 2)
195 return 8;
196 else
197 return -1;
198 }
199
200
201 cvmx_dprintf
202 ("cvmx_helper_board_get_mii_address: Unknown board type %d\n",
203 cvmx_sysinfo_get()->board_type);
204 return -1;
205}
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
226{
227 cvmx_helper_link_info_t result;
228 int phy_addr;
229 int is_broadcom_phy = 0;
230
231
232 if (cvmx_override_board_link_get)
233 return cvmx_override_board_link_get(ipd_port);
234
235
236 result.u64 = 0;
237
238
239
240
241
242 switch (cvmx_sysinfo_get()->board_type) {
243 case CVMX_BOARD_TYPE_SIM:
244
245 result.s.link_up = 1;
246 result.s.full_duplex = 1;
247 result.s.speed = 1000;
248 return result;
249 case CVMX_BOARD_TYPE_EBH3100:
250 case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
251 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
252 case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
253
254 if (ipd_port == 1) {
255 result.s.link_up = 1;
256 result.s.full_duplex = 1;
257 result.s.speed = 1000;
258 return result;
259 }
260
261 break;
262 case CVMX_BOARD_TYPE_CUST_NB5:
263
264 if (ipd_port == 1) {
265 result.s.link_up = 1;
266 result.s.full_duplex = 1;
267 result.s.speed = 1000;
268 return result;
269 } else
270 is_broadcom_phy = 1;
271 break;
272 case CVMX_BOARD_TYPE_BBGW_REF:
273
274 if (ipd_port == 2) {
275
276 result.u64 = 0;
277 return result;
278 } else {
279
280 result.s.link_up = 1;
281 result.s.full_duplex = 1;
282 result.s.speed = 1000;
283 return result;
284 }
285 break;
286 case CVMX_BOARD_TYPE_CUST_DSR1000N:
287 if (ipd_port == 0 || ipd_port == 1) {
288
289 result.s.link_up = 1;
290 result.s.full_duplex = 1;
291 result.s.speed = 1000;
292 return result;
293 } else {
294
295 is_broadcom_phy = 1;
296 }
297 break;
298 }
299
300 phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
301 if (phy_addr != -1) {
302 if (is_broadcom_phy) {
303
304
305
306
307
308 int phy_status =
309 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
310 0x19);
311 switch ((phy_status >> 8) & 0x7) {
312 case 0:
313 result.u64 = 0;
314 break;
315 case 1:
316 result.s.link_up = 1;
317 result.s.full_duplex = 0;
318 result.s.speed = 10;
319 break;
320 case 2:
321 result.s.link_up = 1;
322 result.s.full_duplex = 1;
323 result.s.speed = 10;
324 break;
325 case 3:
326 result.s.link_up = 1;
327 result.s.full_duplex = 0;
328 result.s.speed = 100;
329 break;
330 case 4:
331 result.s.link_up = 1;
332 result.s.full_duplex = 1;
333 result.s.speed = 100;
334 break;
335 case 5:
336 result.s.link_up = 1;
337 result.s.full_duplex = 1;
338 result.s.speed = 100;
339 break;
340 case 6:
341 result.s.link_up = 1;
342 result.s.full_duplex = 0;
343 result.s.speed = 1000;
344 break;
345 case 7:
346 result.s.link_up = 1;
347 result.s.full_duplex = 1;
348 result.s.speed = 1000;
349 break;
350 }
351 } else {
352
353
354
355
356
357
358
359
360 int phy_status =
361 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17);
362
363
364
365
366
367
368
369 if ((phy_status & (1 << 11)) == 0) {
370 int auto_status =
371 cvmx_mdio_read(phy_addr >> 8,
372 phy_addr & 0xff, 0);
373 if ((auto_status & (1 << 12)) == 0)
374 phy_status |= 1 << 11;
375 }
376
377
378
379
380
381
382 if (phy_status & (1 << 11)) {
383 result.s.link_up = 1;
384 result.s.full_duplex = ((phy_status >> 13) & 1);
385 switch ((phy_status >> 14) & 3) {
386 case 0:
387 result.s.speed = 10;
388 break;
389 case 1:
390 result.s.speed = 100;
391 break;
392 case 2:
393 result.s.speed = 1000;
394 break;
395 case 3:
396 result.u64 = 0;
397 break;
398 }
399 }
400 }
401 } else if (OCTEON_IS_MODEL(OCTEON_CN3XXX)
402 || OCTEON_IS_MODEL(OCTEON_CN58XX)
403 || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
404
405
406
407
408
409
410
411 union cvmx_gmxx_rxx_rx_inbnd inband_status;
412 int interface = cvmx_helper_get_interface_num(ipd_port);
413 int index = cvmx_helper_get_interface_index_num(ipd_port);
414 inband_status.u64 =
415 cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface));
416
417 result.s.link_up = inband_status.s.status;
418 result.s.full_duplex = inband_status.s.duplex;
419 switch (inband_status.s.speed) {
420 case 0:
421 result.s.speed = 10;
422 break;
423 case 1:
424 result.s.speed = 100;
425 break;
426 case 2:
427 result.s.speed = 1000;
428 break;
429 case 3:
430 result.u64 = 0;
431 break;
432 }
433 } else {
434
435
436
437
438
439
440 result.u64 = 0;
441 }
442
443
444 if (!result.s.link_up)
445 result.u64 = 0;
446
447 return result;
448}
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464int cvmx_helper_board_link_set_phy(int phy_addr,
465 cvmx_helper_board_set_phy_link_flags_types_t
466 link_flags,
467 cvmx_helper_link_info_t link_info)
468{
469
470
471 if ((link_flags & set_phy_link_flags_flow_control_mask) !=
472 set_phy_link_flags_flow_control_dont_touch) {
473 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
474 reg_autoneg_adver.u16 =
475 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
476 CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
477 reg_autoneg_adver.s.asymmetric_pause =
478 (link_flags & set_phy_link_flags_flow_control_mask) ==
479 set_phy_link_flags_flow_control_enable;
480 reg_autoneg_adver.s.pause =
481 (link_flags & set_phy_link_flags_flow_control_mask) ==
482 set_phy_link_flags_flow_control_enable;
483 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
484 CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
485 reg_autoneg_adver.u16);
486 }
487
488
489 if ((link_flags & set_phy_link_flags_autoneg)
490 && (link_info.s.speed == 0)) {
491 cvmx_mdio_phy_reg_control_t reg_control;
492 cvmx_mdio_phy_reg_status_t reg_status;
493 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
494 cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
495 cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
496
497 reg_status.u16 =
498 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
499 CVMX_MDIO_PHY_REG_STATUS);
500 reg_autoneg_adver.u16 =
501 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
502 CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
503 reg_autoneg_adver.s.advert_100base_t4 =
504 reg_status.s.capable_100base_t4;
505 reg_autoneg_adver.s.advert_10base_tx_full =
506 reg_status.s.capable_10_full;
507 reg_autoneg_adver.s.advert_10base_tx_half =
508 reg_status.s.capable_10_half;
509 reg_autoneg_adver.s.advert_100base_tx_full =
510 reg_status.s.capable_100base_x_full;
511 reg_autoneg_adver.s.advert_100base_tx_half =
512 reg_status.s.capable_100base_x_half;
513 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
514 CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
515 reg_autoneg_adver.u16);
516 if (reg_status.s.capable_extended_status) {
517 reg_extended_status.u16 =
518 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
519 CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
520 reg_control_1000.u16 =
521 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
522 CVMX_MDIO_PHY_REG_CONTROL_1000);
523 reg_control_1000.s.advert_1000base_t_full =
524 reg_extended_status.s.capable_1000base_t_full;
525 reg_control_1000.s.advert_1000base_t_half =
526 reg_extended_status.s.capable_1000base_t_half;
527 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
528 CVMX_MDIO_PHY_REG_CONTROL_1000,
529 reg_control_1000.u16);
530 }
531 reg_control.u16 =
532 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
533 CVMX_MDIO_PHY_REG_CONTROL);
534 reg_control.s.autoneg_enable = 1;
535 reg_control.s.restart_autoneg = 1;
536 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
537 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
538 } else if ((link_flags & set_phy_link_flags_autoneg)) {
539 cvmx_mdio_phy_reg_control_t reg_control;
540 cvmx_mdio_phy_reg_status_t reg_status;
541 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
542 cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
543
544 reg_status.u16 =
545 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
546 CVMX_MDIO_PHY_REG_STATUS);
547 reg_autoneg_adver.u16 =
548 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
549 CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
550 reg_autoneg_adver.s.advert_100base_t4 = 0;
551 reg_autoneg_adver.s.advert_10base_tx_full = 0;
552 reg_autoneg_adver.s.advert_10base_tx_half = 0;
553 reg_autoneg_adver.s.advert_100base_tx_full = 0;
554 reg_autoneg_adver.s.advert_100base_tx_half = 0;
555 if (reg_status.s.capable_extended_status) {
556 reg_control_1000.u16 =
557 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
558 CVMX_MDIO_PHY_REG_CONTROL_1000);
559 reg_control_1000.s.advert_1000base_t_full = 0;
560 reg_control_1000.s.advert_1000base_t_half = 0;
561 }
562 switch (link_info.s.speed) {
563 case 10:
564 reg_autoneg_adver.s.advert_10base_tx_full =
565 link_info.s.full_duplex;
566 reg_autoneg_adver.s.advert_10base_tx_half =
567 !link_info.s.full_duplex;
568 break;
569 case 100:
570 reg_autoneg_adver.s.advert_100base_tx_full =
571 link_info.s.full_duplex;
572 reg_autoneg_adver.s.advert_100base_tx_half =
573 !link_info.s.full_duplex;
574 break;
575 case 1000:
576 reg_control_1000.s.advert_1000base_t_full =
577 link_info.s.full_duplex;
578 reg_control_1000.s.advert_1000base_t_half =
579 !link_info.s.full_duplex;
580 break;
581 }
582 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
583 CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
584 reg_autoneg_adver.u16);
585 if (reg_status.s.capable_extended_status)
586 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
587 CVMX_MDIO_PHY_REG_CONTROL_1000,
588 reg_control_1000.u16);
589 reg_control.u16 =
590 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
591 CVMX_MDIO_PHY_REG_CONTROL);
592 reg_control.s.autoneg_enable = 1;
593 reg_control.s.restart_autoneg = 1;
594 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
595 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
596 } else {
597 cvmx_mdio_phy_reg_control_t reg_control;
598 reg_control.u16 =
599 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
600 CVMX_MDIO_PHY_REG_CONTROL);
601 reg_control.s.autoneg_enable = 0;
602 reg_control.s.restart_autoneg = 1;
603 reg_control.s.duplex = link_info.s.full_duplex;
604 if (link_info.s.speed == 1000) {
605 reg_control.s.speed_msb = 1;
606 reg_control.s.speed_lsb = 0;
607 } else if (link_info.s.speed == 100) {
608 reg_control.s.speed_msb = 0;
609 reg_control.s.speed_lsb = 1;
610 } else if (link_info.s.speed == 10) {
611 reg_control.s.speed_msb = 0;
612 reg_control.s.speed_lsb = 0;
613 }
614 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
615 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
616 }
617 return 0;
618}
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641int __cvmx_helper_board_interface_probe(int interface, int supported_ports)
642{
643 switch (cvmx_sysinfo_get()->board_type) {
644 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
645 if (interface == 0)
646 return 2;
647 break;
648 case CVMX_BOARD_TYPE_BBGW_REF:
649 if (interface == 0)
650 return 2;
651 break;
652 case CVMX_BOARD_TYPE_NIC_XLE_4G:
653 if (interface == 0)
654 return 0;
655 break;
656
657
658 case CVMX_BOARD_TYPE_EBH5600:
659 if (interface == 1)
660 return 0;
661 break;
662 }
663 return supported_ports;
664}
665
666
667
668
669
670
671
672
673
674
675
676int __cvmx_helper_board_hardware_enable(int interface)
677{
678 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) {
679 if (interface == 0) {
680
681 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0);
682 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0);
683
684
685
686
687
688 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface),
689 0xc);
690 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface),
691 0xc);
692 }
693 } else if (cvmx_sysinfo_get()->board_type ==
694 CVMX_BOARD_TYPE_CN3010_EVB_HS5) {
695
696
697
698
699
700
701 if (interface == 0) {
702
703
704
705
706
707
708
709
710 int phy_addr = cvmx_helper_board_get_mii_address(0);
711 if (phy_addr != -1) {
712 int phy_identifier =
713 cvmx_mdio_read(phy_addr >> 8,
714 phy_addr & 0xff, 0x2);
715
716 if (phy_identifier == 0x0143) {
717 cvmx_dprintf("\n");
718 cvmx_dprintf("ERROR:\n");
719 cvmx_dprintf
720 ("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n");
721 cvmx_dprintf
722 ("ERROR: The board type is mis-configured, and software malfunctions are likely.\n");
723 cvmx_dprintf
724 ("ERROR: All boards require a unique board type to identify them.\n");
725 cvmx_dprintf("ERROR:\n");
726 cvmx_dprintf("\n");
727 cvmx_wait(1000000000);
728 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX
729 (0, interface), 5);
730 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX
731 (0, interface), 5);
732 }
733 }
734 }
735 } else if (cvmx_sysinfo_get()->board_type ==
736 CVMX_BOARD_TYPE_UBNT_E100) {
737 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0);
738 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0x10);
739 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0);
740 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0x10);
741 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(2, interface), 0);
742 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(2, interface), 0x10);
743 }
744 return 0;
745}
746
747
748
749
750
751
752
753enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(void)
754{
755 switch (cvmx_sysinfo_get()->board_type) {
756 case CVMX_BOARD_TYPE_BBGW_REF:
757 case CVMX_BOARD_TYPE_LANAI2_A:
758 case CVMX_BOARD_TYPE_LANAI2_U:
759 case CVMX_BOARD_TYPE_LANAI2_G:
760 case CVMX_BOARD_TYPE_NIC10E_66:
761 case CVMX_BOARD_TYPE_UBNT_E100:
762 case CVMX_BOARD_TYPE_CUST_DSR1000N:
763 return USB_CLOCK_TYPE_CRYSTAL_12;
764 case CVMX_BOARD_TYPE_NIC10E:
765 return USB_CLOCK_TYPE_REF_12;
766 default:
767 break;
768 }
769
770 if (OCTEON_IS_OCTEON2())
771 return USB_CLOCK_TYPE_CRYSTAL_12;
772 return USB_CLOCK_TYPE_REF_48;
773}
774