1
2
3
4
5
6
7
8
9#include <time.h>
10#include <log.h>
11#include <linux/delay.h>
12
13#include <mach/cvmx-regs.h>
14#include <mach/cvmx-csr.h>
15#include <mach/cvmx-bootmem.h>
16#include <mach/octeon-model.h>
17#include <mach/cvmx-fuse.h>
18#include <mach/octeon-feature.h>
19#include <mach/cvmx-qlm.h>
20#include <mach/octeon_qlm.h>
21#include <mach/cvmx-pcie.h>
22#include <mach/cvmx-coremask.h>
23
24#include <mach/cvmx-agl-defs.h>
25#include <mach/cvmx-bgxx-defs.h>
26#include <mach/cvmx-ciu-defs.h>
27#include <mach/cvmx-gmxx-defs.h>
28#include <mach/cvmx-ipd-defs.h>
29#include <mach/cvmx-pcsx-defs.h>
30#include <mach/cvmx-pki-defs.h>
31#include <mach/cvmx-xcv-defs.h>
32
33#include <mach/cvmx-helper.h>
34#include <mach/cvmx-helper-board.h>
35#include <mach/cvmx-helper-cfg.h>
36
37
38
39
40
41
42
43
44
45
46static int __cvmx_helper_sgmii_hardware_init_one_time(int interface, int index)
47{
48 const u64 clock_mhz = 1200;
49 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
50 union cvmx_pcsx_linkx_timer_count_reg pcsx_linkx_timer_count_reg;
51 union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
52
53 if (!cvmx_helper_is_port_valid(interface, index))
54 return 0;
55
56
57 gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
58 gmxx_prtx_cfg.s.en = 0;
59 csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
60
61
62
63
64
65
66 pcsx_miscx_ctl_reg.u64 =
67 csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
68
69 pcsx_miscx_ctl_reg.s.mac_phy =
70 cvmx_helper_get_mac_phy_mode(interface, index);
71 pcsx_miscx_ctl_reg.s.mode =
72 cvmx_helper_get_1000x_mode(interface, index);
73 csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
74 pcsx_miscx_ctl_reg.u64);
75
76 pcsx_linkx_timer_count_reg.u64 =
77 csr_rd(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface));
78 if (pcsx_miscx_ctl_reg.s.mode)
79
80 pcsx_linkx_timer_count_reg.s.count =
81 (10000ull * clock_mhz) >> 10;
82 else
83
84 pcsx_linkx_timer_count_reg.s.count =
85 (1600ull * clock_mhz) >> 10;
86
87 csr_wr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface),
88 pcsx_linkx_timer_count_reg.u64);
89
90
91
92
93
94
95
96
97
98
99 if (pcsx_miscx_ctl_reg.s.mode) {
100
101 union cvmx_pcsx_anx_adv_reg pcsx_anx_adv_reg;
102
103 pcsx_anx_adv_reg.u64 =
104 csr_rd(CVMX_PCSX_ANX_ADV_REG(index, interface));
105 pcsx_anx_adv_reg.s.rem_flt = 0;
106 pcsx_anx_adv_reg.s.pause = 3;
107 pcsx_anx_adv_reg.s.hfd = 1;
108 pcsx_anx_adv_reg.s.fd = 1;
109 csr_wr(CVMX_PCSX_ANX_ADV_REG(index, interface),
110 pcsx_anx_adv_reg.u64);
111 } else {
112 if (pcsx_miscx_ctl_reg.s.mac_phy) {
113
114 union cvmx_pcsx_sgmx_an_adv_reg pcsx_sgmx_an_adv_reg;
115
116 pcsx_sgmx_an_adv_reg.u64 = csr_rd(
117 CVMX_PCSX_SGMX_AN_ADV_REG(index, interface));
118 pcsx_sgmx_an_adv_reg.s.dup = 1;
119 pcsx_sgmx_an_adv_reg.s.speed = 2;
120 csr_wr(CVMX_PCSX_SGMX_AN_ADV_REG(index, interface),
121 pcsx_sgmx_an_adv_reg.u64);
122 } else {
123
124 }
125 }
126 return 0;
127}
128
129static int __cvmx_helper_need_g15618(void)
130{
131 if (OCTEON_IS_MODEL(OCTEON_CN63XX) ||
132 OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X) ||
133 OCTEON_IS_MODEL(OCTEON_CN68XX))
134 return 1;
135 else
136 return 0;
137}
138
139
140
141
142
143
144
145
146
147
148
149static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index)
150{
151 union cvmx_pcsx_mrx_control_reg control_reg;
152 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
153 bool phy_mode;
154 bool an_disable;
155 bool mode_1000x;
156
157 if (!cvmx_helper_is_port_valid(interface, index))
158 return 0;
159
160
161
162
163
164
165
166
167
168 control_reg.u64 = csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
169
170
171
172
173
174 if (!__cvmx_helper_need_g15618()) {
175 control_reg.s.reset = 1;
176 csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
177 control_reg.u64);
178 if (CVMX_WAIT_FOR_FIELD64(
179 CVMX_PCSX_MRX_CONTROL_REG(index, interface),
180 cvmx_pcsx_mrx_control_reg_t, reset, ==, 0, 10000)) {
181 debug("SGMII%x: Timeout waiting for port %d to finish reset\n",
182 interface, index);
183 return -1;
184 }
185 }
186
187
188
189
190
191 phy_mode = cvmx_helper_get_mac_phy_mode(interface, index);
192 an_disable = (phy_mode ||
193 !cvmx_helper_get_port_autonegotiation(interface, index));
194
195 control_reg.s.an_en = !an_disable;
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 control_reg.s.pwr_dn = 1;
218 csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), control_reg.u64);
219 csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
220
221
222 mdelay(25);
223
224 control_reg.s.pwr_dn = 0;
225 csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), control_reg.u64);
226
227
228 mode_1000x = cvmx_helper_get_1000x_mode(interface, index);
229 pcsx_miscx_ctl_reg.u64 =
230 csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
231 pcsx_miscx_ctl_reg.s.mode = mode_1000x;
232 pcsx_miscx_ctl_reg.s.mac_phy = phy_mode;
233 csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
234 pcsx_miscx_ctl_reg.u64);
235 if (an_disable)
236
237
238
239 return 0;
240
241
242
243
244
245
246
247 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_STATUS_REG(index, interface),
248 union cvmx_pcsx_mrx_status_reg, an_cpt, ==, 1,
249 10000)) {
250 debug("SGMII%x: Port %d link timeout\n", interface, index);
251 return -1;
252 }
253 return 0;
254}
255
256
257
258
259
260
261
262
263
264
265
266
267static int
268__cvmx_helper_sgmii_hardware_init_link_speed(int interface, int index,
269 cvmx_helper_link_info_t link_info)
270{
271 int is_enabled;
272 union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
273 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
274
275 if (!cvmx_helper_is_port_valid(interface, index))
276 return 0;
277
278
279 gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
280 is_enabled = gmxx_prtx_cfg.s.en;
281 gmxx_prtx_cfg.s.en = 0;
282 csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
283
284
285 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
286 cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1,
287 10000) ||
288 CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
289 cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1,
290 10000)) {
291 debug("SGMII%d: Timeout waiting for port %d to be idle\n",
292 interface, index);
293 return -1;
294 }
295
296
297 gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
298
299
300
301
302
303 pcsx_miscx_ctl_reg.u64 =
304 csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
305
306
307
308
309
310 pcsx_miscx_ctl_reg.s.gmxeno = !link_info.s.link_up;
311
312
313 if (link_info.s.link_up)
314 gmxx_prtx_cfg.s.duplex = link_info.s.full_duplex;
315
316
317 switch (link_info.s.speed) {
318 case 10:
319 gmxx_prtx_cfg.s.speed = 0;
320 gmxx_prtx_cfg.s.speed_msb = 1;
321 gmxx_prtx_cfg.s.slottime = 0;
322
323 pcsx_miscx_ctl_reg.s.samp_pt = 25;
324 csr_wr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
325 csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 0);
326 break;
327 case 100:
328 gmxx_prtx_cfg.s.speed = 0;
329 gmxx_prtx_cfg.s.speed_msb = 0;
330 gmxx_prtx_cfg.s.slottime = 0;
331 pcsx_miscx_ctl_reg.s.samp_pt = 0x5;
332 csr_wr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
333 csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 0);
334 break;
335 case 1000:
336 gmxx_prtx_cfg.s.speed = 1;
337 gmxx_prtx_cfg.s.speed_msb = 0;
338 gmxx_prtx_cfg.s.slottime = 1;
339 pcsx_miscx_ctl_reg.s.samp_pt = 1;
340 csr_wr(CVMX_GMXX_TXX_SLOT(index, interface), 512);
341 if (gmxx_prtx_cfg.s.duplex)
342
343 csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 0);
344 else
345
346 csr_wr(CVMX_GMXX_TXX_BURST(index, interface), 8192);
347 break;
348 default:
349 break;
350 }
351
352
353 csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
354 pcsx_miscx_ctl_reg.u64);
355
356
357 csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
358
359
360 gmxx_prtx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
361
362
363 gmxx_prtx_cfg.s.en = is_enabled;
364 csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
365
366 return 0;
367}
368
369
370
371
372
373
374
375
376
377
378
379
380static int __cvmx_helper_sgmii_hardware_init(int interface, int num_ports)
381{
382 int index;
383 int do_link_set = 1;
384
385
386
387
388
389 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) {
390 union cvmx_ciu_qlm2 ciu_qlm;
391
392 ciu_qlm.u64 = csr_rd(CVMX_CIU_QLM2);
393 ciu_qlm.s.txbypass = 1;
394 ciu_qlm.s.txdeemph = 0xf;
395 ciu_qlm.s.txmargin = 0xd;
396 csr_wr(CVMX_CIU_QLM2, ciu_qlm.u64);
397 }
398
399
400
401
402
403 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X)) {
404
405 union cvmx_mio_rst_boot mio_rst_boot;
406
407 mio_rst_boot.u64 = csr_rd(CVMX_MIO_RST_BOOT);
408
409 if (mio_rst_boot.cn63xx.qlm2_spd == 4) {
410 union cvmx_ciu_qlm2 ciu_qlm;
411
412 ciu_qlm.u64 = csr_rd(CVMX_CIU_QLM2);
413 ciu_qlm.s.txbypass = 1;
414 ciu_qlm.s.txdeemph = 0x0;
415 ciu_qlm.s.txmargin = 0xf;
416 csr_wr(CVMX_CIU_QLM2, ciu_qlm.u64);
417 }
418 }
419
420 __cvmx_helper_setup_gmx(interface, num_ports);
421
422 for (index = 0; index < num_ports; index++) {
423 int ipd_port = cvmx_helper_get_ipd_port(interface, index);
424
425 if (!cvmx_helper_is_port_valid(interface, index))
426 continue;
427 __cvmx_helper_sgmii_hardware_init_one_time(interface, index);
428 if (do_link_set)
429 __cvmx_helper_sgmii_link_set(ipd_port,
430 __cvmx_helper_sgmii_link_get(ipd_port));
431 }
432
433 return 0;
434}
435
436int __cvmx_helper_sgmii_enumerate(int xiface)
437{
438 if (OCTEON_IS_MODEL(OCTEON_CNF71XX))
439 return 2;
440 if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {
441 struct cvmx_xiface xi =
442 cvmx_helper_xiface_to_node_interface(xiface);
443 enum cvmx_qlm_mode qlm_mode =
444 cvmx_qlm_get_dlm_mode(0, xi.interface);
445
446 if (qlm_mode == CVMX_QLM_MODE_SGMII)
447 return 1;
448 else if (qlm_mode == CVMX_QLM_MODE_QSGMII)
449 return 4;
450 return 0;
451 }
452 return 4;
453}
454
455
456
457
458
459
460
461
462
463
464
465int __cvmx_helper_sgmii_probe(int xiface)
466{
467 struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
468 int interface = xi.interface;
469 union cvmx_gmxx_inf_mode mode;
470 int ports;
471
472
473
474
475
476 if (OCTEON_IS_OCTEON2()) {
477 int qlm = cvmx_qlm_interface(xiface);
478
479 if (cvmx_qlm_get_mode(qlm) != CVMX_QLM_MODE_SGMII)
480 return 0;
481 }
482
483
484 ports = __cvmx_helper_sgmii_enumerate(xiface);
485
486 if (ports <= 0)
487 return 0;
488
489
490
491
492
493
494 mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(interface));
495 mode.s.en = 1;
496 csr_wr(CVMX_GMXX_INF_MODE(interface), mode.u64);
497
498 return ports;
499}
500
501
502
503
504
505
506
507
508
509
510
511int __cvmx_helper_sgmii_enable(int xiface)
512{
513 int num_ports = cvmx_helper_ports_on_interface(xiface);
514 struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
515 int interface = xi.interface;
516 int index;
517
518
519 if (octeon_has_feature(OCTEON_FEATURE_PKND)) {
520 for (index = 0; index < num_ports; index++) {
521 union cvmx_gmxx_bpid_msk bpid_msk;
522 union cvmx_gmxx_bpid_mapx bpid_map;
523 union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
524
525 if (!cvmx_helper_is_port_valid(interface, index))
526 continue;
527
528 gmxx_prtx_cfg.u64 =
529 csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
530 gmxx_prtx_cfg.s.pknd =
531 cvmx_helper_get_pknd(interface, index);
532 csr_wr(CVMX_GMXX_PRTX_CFG(index, interface),
533 gmxx_prtx_cfg.u64);
534
535
536 bpid_map.u64 =
537 csr_rd(CVMX_GMXX_BPID_MAPX(index, interface));
538 bpid_map.s.val = 1;
539 bpid_map.s.bpid =
540 cvmx_helper_get_bpid(interface, index);
541 csr_wr(CVMX_GMXX_BPID_MAPX(index, interface),
542 bpid_map.u64);
543
544 bpid_msk.u64 = csr_rd(CVMX_GMXX_BPID_MSK(interface));
545 bpid_msk.s.msk_or |= (1 << index);
546 bpid_msk.s.msk_and &= ~(1 << index);
547 csr_wr(CVMX_GMXX_BPID_MSK(interface), bpid_msk.u64);
548 }
549 }
550
551 __cvmx_helper_sgmii_hardware_init(interface, num_ports);
552
553
554 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
555 union cvmx_gmxx_txx_append gmxx_txx_append_cfg;
556
557 for (index = 0; index < num_ports; index++) {
558 if (!cvmx_helper_is_port_valid(interface, index))
559 continue;
560 gmxx_txx_append_cfg.u64 =
561 csr_rd(CVMX_GMXX_TXX_APPEND(index, interface));
562 gmxx_txx_append_cfg.s.fcs = 0;
563 gmxx_txx_append_cfg.s.pad = 0;
564 csr_wr(CVMX_GMXX_TXX_APPEND(index, interface),
565 gmxx_txx_append_cfg.u64);
566 }
567 }
568
569
570 if (OCTEON_IS_MODEL(OCTEON_CN70XX) && num_ports > 1) {
571 union cvmx_gmxx_qsgmii_ctl qsgmii_ctl;
572
573 qsgmii_ctl.u64 = 0;
574 qsgmii_ctl.s.disparity = 1;
575 csr_wr(CVMX_GMXX_QSGMII_CTL(interface), qsgmii_ctl.u64);
576 }
577
578 for (index = 0; index < num_ports; index++) {
579 union cvmx_gmxx_txx_append append_cfg;
580 union cvmx_gmxx_txx_sgmii_ctl sgmii_ctl;
581 union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
582
583 if (!cvmx_helper_is_port_valid(interface, index))
584 continue;
585
586
587
588
589 append_cfg.u64 = csr_rd(CVMX_GMXX_TXX_APPEND(index, interface));
590 sgmii_ctl.u64 =
591 csr_rd(CVMX_GMXX_TXX_SGMII_CTL(index, interface));
592 sgmii_ctl.s.align = append_cfg.s.preamble ? 0 : 1;
593 csr_wr(CVMX_GMXX_TXX_SGMII_CTL(index, interface),
594 sgmii_ctl.u64);
595
596 gmxx_prtx_cfg.u64 =
597 csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
598 gmxx_prtx_cfg.s.en = 1;
599 csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
600 }
601 return 0;
602}
603
604
605
606
607
608
609
610
611
612
613
614
615cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port)
616{
617 cvmx_helper_link_info_t result;
618 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
619 int interface = cvmx_helper_get_interface_num(ipd_port);
620 int index = cvmx_helper_get_interface_index_num(ipd_port);
621 union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
622 int speed = 1000;
623 int qlm;
624
625 result.u64 = 0;
626
627 if (!cvmx_helper_is_port_valid(interface, index))
628 return result;
629
630 if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
631 union cvmx_gmxx_inf_mode inf_mode;
632
633 inf_mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(interface));
634 if (inf_mode.s.rate & (1 << index))
635 speed = 2500;
636 else
637 speed = 1000;
638 } else if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
639 qlm = cvmx_qlm_interface(interface);
640 speed = cvmx_qlm_get_gbaud_mhz(qlm) * 8 / 10;
641 } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
642 speed = cvmx_qlm_get_gbaud_mhz(0) * 8 / 10;
643 } else if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {
644 speed = cvmx_qlm_get_gbaud_mhz(0) * 8 / 10;
645 if (cvmx_qlm_get_dlm_mode(0, interface) == CVMX_QLM_MODE_SGMII)
646 speed >>= 1;
647 else
648 speed >>= 2;
649 }
650
651 pcsx_mrx_control_reg.u64 =
652 csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
653 if (pcsx_mrx_control_reg.s.loopbck1) {
654
655 result.s.link_up = 1;
656 result.s.full_duplex = 1;
657 result.s.speed = speed;
658 return result;
659 }
660
661 pcsx_miscx_ctl_reg.u64 =
662 csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
663 if (pcsx_miscx_ctl_reg.s.mac_phy ||
664 cvmx_helper_get_port_force_link_up(interface, index)) {
665
666
667
668 result.s.speed = speed;
669 result.s.full_duplex = 1;
670 result.s.link_up = 1;
671 return result;
672 }
673
674
675 return __cvmx_helper_board_link_get(ipd_port);
676}
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691int __cvmx_helper_sgmii_link_set(int ipd_port,
692 cvmx_helper_link_info_t link_info)
693{
694 union cvmx_pcsx_mrx_control_reg control_reg;
695 int interface = cvmx_helper_get_interface_num(ipd_port);
696 int index = cvmx_helper_get_interface_index_num(ipd_port);
697
698 if (!cvmx_helper_is_port_valid(interface, index))
699 return 0;
700
701
702
703
704
705 if (link_info.s.link_up || !__cvmx_helper_need_g15618()) {
706 __cvmx_helper_sgmii_hardware_init_link(interface, index);
707 } else {
708 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
709
710 pcsx_miscx_ctl_reg.u64 =
711 csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
712
713
714
715
716 control_reg.u64 =
717 csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
718 if (pcsx_miscx_ctl_reg.s.mac_phy == 0 ||
719 !cvmx_helper_get_port_autonegotiation(interface, index)) {
720 control_reg.s.an_en = 0;
721 control_reg.s.spdmsb = 1;
722 control_reg.s.spdlsb = 0;
723 control_reg.s.dup = 1;
724 }
725 csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
726 control_reg.u64);
727 csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
728
729
730
731
732 pcsx_miscx_ctl_reg.s.gmxeno = 1;
733 csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
734 pcsx_miscx_ctl_reg.u64);
735 csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
736 return 0;
737 }
738 return __cvmx_helper_sgmii_hardware_init_link_speed(interface, index,
739 link_info);
740}
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756int __cvmx_helper_sgmii_configure_loopback(int ipd_port, int enable_internal,
757 int enable_external)
758{
759 int interface = cvmx_helper_get_interface_num(ipd_port);
760 int index = cvmx_helper_get_interface_index_num(ipd_port);
761 union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
762 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
763
764 if (!cvmx_helper_is_port_valid(interface, index))
765 return 0;
766
767 pcsx_mrx_control_reg.u64 =
768 csr_rd(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
769 pcsx_mrx_control_reg.s.loopbck1 = enable_internal;
770 csr_wr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
771 pcsx_mrx_control_reg.u64);
772
773 pcsx_miscx_ctl_reg.u64 =
774 csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
775 pcsx_miscx_ctl_reg.s.loopbck2 = enable_external;
776 csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
777 pcsx_miscx_ctl_reg.u64);
778
779 __cvmx_helper_sgmii_hardware_init_link(interface, index);
780 return 0;
781}
782