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#include <asm/octeon/octeon.h>
34
35#include "cvmx-config.h"
36
37#include "cvmx-mdio.h"
38#include "cvmx-helper.h"
39#include "cvmx-helper-board.h"
40
41#include "cvmx-gmxx-defs.h"
42#include "cvmx-pcsx-defs.h"
43
44void __cvmx_interrupt_gmxx_enable(int interface);
45void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block);
46void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index);
47
48
49
50
51
52
53
54
55
56static int __cvmx_helper_sgmii_hardware_init_one_time(int interface, int index)
57{
58 const uint64_t clock_mhz = cvmx_sysinfo_get()->cpu_clock_hz / 1000000;
59 union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg;
60 union cvmx_pcsx_linkx_timer_count_reg pcsx_linkx_timer_count_reg;
61 union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
62
63
64 gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
65 gmxx_prtx_cfg.s.en = 0;
66 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
67
68
69
70
71
72
73 pcs_misc_ctl_reg.u64 =
74 cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
75 pcsx_linkx_timer_count_reg.u64 =
76 cvmx_read_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface));
77 if (pcs_misc_ctl_reg.s.mode) {
78
79 pcsx_linkx_timer_count_reg.s.count =
80 (10000ull * clock_mhz) >> 10;
81 } else {
82
83 pcsx_linkx_timer_count_reg.s.count =
84 (1600ull * clock_mhz) >> 10;
85 }
86 cvmx_write_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface),
87 pcsx_linkx_timer_count_reg.u64);
88
89
90
91
92
93
94
95
96
97
98 if (pcs_misc_ctl_reg.s.mode) {
99
100 union cvmx_pcsx_anx_adv_reg pcsx_anx_adv_reg;
101 pcsx_anx_adv_reg.u64 =
102 cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface));
103 pcsx_anx_adv_reg.s.rem_flt = 0;
104 pcsx_anx_adv_reg.s.pause = 3;
105 pcsx_anx_adv_reg.s.hfd = 1;
106 pcsx_anx_adv_reg.s.fd = 1;
107 cvmx_write_csr(CVMX_PCSX_ANX_ADV_REG(index, interface),
108 pcsx_anx_adv_reg.u64);
109 } else {
110 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
111 pcsx_miscx_ctl_reg.u64 =
112 cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
113 if (pcsx_miscx_ctl_reg.s.mac_phy) {
114
115 union cvmx_pcsx_sgmx_an_adv_reg pcsx_sgmx_an_adv_reg;
116 pcsx_sgmx_an_adv_reg.u64 =
117 cvmx_read_csr(CVMX_PCSX_SGMX_AN_ADV_REG
118 (index, interface));
119 pcsx_sgmx_an_adv_reg.s.link = 1;
120 pcsx_sgmx_an_adv_reg.s.dup = 1;
121 pcsx_sgmx_an_adv_reg.s.speed = 2;
122 cvmx_write_csr(CVMX_PCSX_SGMX_AN_ADV_REG
123 (index, interface),
124 pcsx_sgmx_an_adv_reg.u64);
125 } else {
126
127 }
128 }
129 return 0;
130}
131
132
133
134
135
136
137
138
139
140
141static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index)
142{
143 union cvmx_pcsx_mrx_control_reg control_reg;
144
145
146
147
148
149
150
151
152
153 control_reg.u64 =
154 cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
155 if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) {
156 control_reg.s.reset = 1;
157 cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
158 control_reg.u64);
159 if (CVMX_WAIT_FOR_FIELD64
160 (CVMX_PCSX_MRX_CONTROL_REG(index, interface),
161 union cvmx_pcsx_mrx_control_reg, reset, ==, 0, 10000)) {
162 cvmx_dprintf("SGMII%d: Timeout waiting for port %d "
163 "to finish reset\n",
164 interface, index);
165 return -1;
166 }
167 }
168
169
170
171
172
173 control_reg.s.rst_an = 1;
174 control_reg.s.an_en = 1;
175 control_reg.s.pwr_dn = 0;
176 cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
177 control_reg.u64);
178
179
180
181
182
183
184
185 if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
186 CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_STATUS_REG(index, interface),
187 union cvmx_pcsx_mrx_status_reg, an_cpt, ==, 1,
188 10000)) {
189
190 return -1;
191 }
192 return 0;
193}
194
195
196
197
198
199
200
201
202
203
204
205static int __cvmx_helper_sgmii_hardware_init_link_speed(int interface,
206 int index,
207 cvmx_helper_link_info_t
208 link_info)
209{
210 int is_enabled;
211 union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
212 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
213
214
215 gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
216 is_enabled = gmxx_prtx_cfg.s.en;
217 gmxx_prtx_cfg.s.en = 0;
218 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
219
220
221 if (CVMX_WAIT_FOR_FIELD64
222 (CVMX_GMXX_PRTX_CFG(index, interface), union cvmx_gmxx_prtx_cfg,
223 rx_idle, ==, 1, 10000)
224 || CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
225 union cvmx_gmxx_prtx_cfg, tx_idle, ==, 1,
226 10000)) {
227 cvmx_dprintf
228 ("SGMII%d: Timeout waiting for port %d to be idle\n",
229 interface, index);
230 return -1;
231 }
232
233
234 gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
235
236
237
238
239
240 pcsx_miscx_ctl_reg.u64 =
241 cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
242
243
244
245
246
247 pcsx_miscx_ctl_reg.s.gmxeno = !link_info.s.link_up;
248
249
250 if (link_info.s.link_up)
251 gmxx_prtx_cfg.s.duplex = link_info.s.full_duplex;
252
253
254 switch (link_info.s.speed) {
255 case 10:
256 gmxx_prtx_cfg.s.speed = 0;
257 gmxx_prtx_cfg.s.speed_msb = 1;
258 gmxx_prtx_cfg.s.slottime = 0;
259
260 pcsx_miscx_ctl_reg.s.samp_pt = 25;
261 cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
262 cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
263 break;
264 case 100:
265 gmxx_prtx_cfg.s.speed = 0;
266 gmxx_prtx_cfg.s.speed_msb = 0;
267 gmxx_prtx_cfg.s.slottime = 0;
268 pcsx_miscx_ctl_reg.s.samp_pt = 0x5;
269 cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
270 cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
271 break;
272 case 1000:
273 gmxx_prtx_cfg.s.speed = 1;
274 gmxx_prtx_cfg.s.speed_msb = 0;
275 gmxx_prtx_cfg.s.slottime = 1;
276 pcsx_miscx_ctl_reg.s.samp_pt = 1;
277 cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 512);
278 cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 8192);
279 break;
280 default:
281 break;
282 }
283
284
285 cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
286 pcsx_miscx_ctl_reg.u64);
287
288
289 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
290
291
292 gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
293
294
295 gmxx_prtx_cfg.s.en = is_enabled;
296 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
297
298 return 0;
299}
300
301
302
303
304
305
306
307
308
309
310
311static int __cvmx_helper_sgmii_hardware_init(int interface, int num_ports)
312{
313 int index;
314
315 __cvmx_helper_setup_gmx(interface, num_ports);
316
317 for (index = 0; index < num_ports; index++) {
318 int ipd_port = cvmx_helper_get_ipd_port(interface, index);
319 __cvmx_helper_sgmii_hardware_init_one_time(interface, index);
320 __cvmx_helper_sgmii_link_set(ipd_port,
321 __cvmx_helper_sgmii_link_get
322 (ipd_port));
323
324 }
325
326 return 0;
327}
328
329
330
331
332
333
334
335
336
337
338int __cvmx_helper_sgmii_probe(int interface)
339{
340 union cvmx_gmxx_inf_mode mode;
341
342
343
344
345
346
347 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
348 mode.s.en = 1;
349 cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
350 return 4;
351}
352
353
354
355
356
357
358
359
360
361
362int __cvmx_helper_sgmii_enable(int interface)
363{
364 int num_ports = cvmx_helper_ports_on_interface(interface);
365 int index;
366
367 __cvmx_helper_sgmii_hardware_init(interface, num_ports);
368
369 for (index = 0; index < num_ports; index++) {
370 union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
371 gmxx_prtx_cfg.u64 =
372 cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
373 gmxx_prtx_cfg.s.en = 1;
374 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface),
375 gmxx_prtx_cfg.u64);
376 __cvmx_interrupt_pcsx_intx_en_reg_enable(index, interface);
377 }
378 __cvmx_interrupt_pcsxx_int_en_reg_enable(interface);
379 __cvmx_interrupt_gmxx_enable(interface);
380 return 0;
381}
382
383
384
385
386
387
388
389
390
391
392
393cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port)
394{
395 cvmx_helper_link_info_t result;
396 union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg;
397 int interface = cvmx_helper_get_interface_num(ipd_port);
398 int index = cvmx_helper_get_interface_index_num(ipd_port);
399 union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
400
401 result.u64 = 0;
402
403 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) {
404
405 result.s.link_up = 1;
406 result.s.full_duplex = 1;
407 result.s.speed = 1000;
408 return result;
409 }
410
411 pcsx_mrx_control_reg.u64 =
412 cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
413 if (pcsx_mrx_control_reg.s.loopbck1) {
414
415 result.s.link_up = 1;
416 result.s.full_duplex = 1;
417 result.s.speed = 1000;
418 return result;
419 }
420
421 pcs_misc_ctl_reg.u64 =
422 cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
423 if (pcs_misc_ctl_reg.s.mode) {
424
425
426 } else {
427 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
428 pcsx_miscx_ctl_reg.u64 =
429 cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
430 if (pcsx_miscx_ctl_reg.s.mac_phy) {
431
432 union cvmx_pcsx_mrx_status_reg pcsx_mrx_status_reg;
433 union cvmx_pcsx_anx_results_reg pcsx_anx_results_reg;
434
435
436
437
438
439 pcsx_mrx_status_reg.u64 =
440 cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG
441 (index, interface));
442 if (pcsx_mrx_status_reg.s.lnk_st == 0) {
443 if (__cvmx_helper_sgmii_hardware_init_link
444 (interface, index) != 0)
445 return result;
446 }
447
448
449 pcsx_anx_results_reg.u64 =
450 cvmx_read_csr(CVMX_PCSX_ANX_RESULTS_REG
451 (index, interface));
452 if (pcsx_anx_results_reg.s.an_cpt) {
453
454
455
456
457 result.s.full_duplex =
458 pcsx_anx_results_reg.s.dup;
459 result.s.link_up =
460 pcsx_anx_results_reg.s.link_ok;
461 switch (pcsx_anx_results_reg.s.spd) {
462 case 0:
463 result.s.speed = 10;
464 break;
465 case 1:
466 result.s.speed = 100;
467 break;
468 case 2:
469 result.s.speed = 1000;
470 break;
471 default:
472 result.s.speed = 0;
473 result.s.link_up = 0;
474 break;
475 }
476 } else {
477
478
479
480
481 result.s.speed = 0;
482 result.s.link_up = 0;
483 }
484 } else {
485
486 result = __cvmx_helper_board_link_get(ipd_port);
487 }
488 }
489 return result;
490}
491
492
493
494
495
496
497
498
499
500
501
502
503
504int __cvmx_helper_sgmii_link_set(int ipd_port,
505 cvmx_helper_link_info_t link_info)
506{
507 int interface = cvmx_helper_get_interface_num(ipd_port);
508 int index = cvmx_helper_get_interface_index_num(ipd_port);
509 __cvmx_helper_sgmii_hardware_init_link(interface, index);
510 return __cvmx_helper_sgmii_hardware_init_link_speed(interface, index,
511 link_info);
512}
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528int __cvmx_helper_sgmii_configure_loopback(int ipd_port, int enable_internal,
529 int enable_external)
530{
531 int interface = cvmx_helper_get_interface_num(ipd_port);
532 int index = cvmx_helper_get_interface_index_num(ipd_port);
533 union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
534 union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
535
536 pcsx_mrx_control_reg.u64 =
537 cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
538 pcsx_mrx_control_reg.s.loopbck1 = enable_internal;
539 cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
540 pcsx_mrx_control_reg.u64);
541
542 pcsx_miscx_ctl_reg.u64 =
543 cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
544 pcsx_miscx_ctl_reg.s.loopbck2 = enable_external;
545 cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
546 pcsx_miscx_ctl_reg.u64);
547
548 __cvmx_helper_sgmii_hardware_init_link(interface, index);
549 return 0;
550}
551