1 /***********************license start***************
2 * Author: Cavium Networks
3 *
4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK
6 *
7 * Copyright (c) 2003-2008 Cavium Networks
8 *
9 * This file is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, Version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This file is distributed in the hope that it will be useful, but
14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16 * NONINFRINGEMENT. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this file; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * or visit http://www.gnu.org/licenses/.
23 *
24 * This file may also be available under a different license from Cavium.
25 * Contact Cavium Networks for more information
26 ***********************license end**************************************/
27
28 /*
29 *
30 * Helper functions for common, but complicated tasks.
31 *
32 */
33 #include <linux/bug.h>
34 #include <asm/octeon/octeon.h>
35
36 #include <asm/octeon/cvmx-config.h>
37
38 #include <asm/octeon/cvmx-fpa.h>
39 #include <asm/octeon/cvmx-pip.h>
40 #include <asm/octeon/cvmx-pko.h>
41 #include <asm/octeon/cvmx-ipd.h>
42 #include <asm/octeon/cvmx-spi.h>
43 #include <asm/octeon/cvmx-helper.h>
44 #include <asm/octeon/cvmx-helper-board.h>
45
46 #include <asm/octeon/cvmx-pip-defs.h>
47 #include <asm/octeon/cvmx-asxx-defs.h>
48
49 /* Port count per interface */
50 static int interface_port_count[9];
51
52 /**
53 * Return the number of interfaces the chip has. Each interface
54 * may have multiple ports. Most chips support two interfaces,
55 * but the CNX0XX and CNX1XX are exceptions. These only support
56 * one interface.
57 *
58 * Returns Number of interfaces on chip
59 */
cvmx_helper_get_number_of_interfaces(void)60 int cvmx_helper_get_number_of_interfaces(void)
61 {
62 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
63 return 9;
64 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
65 return 4;
66 if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
67 return 5;
68 else
69 return 3;
70 }
71 EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
72
73 /**
74 * Return the number of ports on an interface. Depending on the
75 * chip and configuration, this can be 1-16. A value of 0
76 * specifies that the interface doesn't exist or isn't usable.
77 *
78 * @interface: Interface to get the port count for
79 *
80 * Returns Number of ports on interface. Can be Zero.
81 */
cvmx_helper_ports_on_interface(int interface)82 int cvmx_helper_ports_on_interface(int interface)
83 {
84 return interface_port_count[interface];
85 }
86 EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
87
88 /**
89 * @INTERNAL
90 * Return interface mode for CN68xx.
91 */
__cvmx_get_mode_cn68xx(int interface)92 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
93 {
94 union cvmx_mio_qlmx_cfg qlm_cfg;
95 switch (interface) {
96 case 0:
97 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
98 /* QLM is disabled when QLM SPD is 15. */
99 if (qlm_cfg.s.qlm_spd == 15)
100 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
101
102 if (qlm_cfg.s.qlm_cfg == 2)
103 return CVMX_HELPER_INTERFACE_MODE_SGMII;
104 else if (qlm_cfg.s.qlm_cfg == 3)
105 return CVMX_HELPER_INTERFACE_MODE_XAUI;
106 else
107 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
108 case 2:
109 case 3:
110 case 4:
111 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
112 /* QLM is disabled when QLM SPD is 15. */
113 if (qlm_cfg.s.qlm_spd == 15)
114 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
115
116 if (qlm_cfg.s.qlm_cfg == 2)
117 return CVMX_HELPER_INTERFACE_MODE_SGMII;
118 else if (qlm_cfg.s.qlm_cfg == 3)
119 return CVMX_HELPER_INTERFACE_MODE_XAUI;
120 else
121 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
122 case 7:
123 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
124 /* QLM is disabled when QLM SPD is 15. */
125 if (qlm_cfg.s.qlm_spd == 15) {
126 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
127 } else if (qlm_cfg.s.qlm_cfg != 0) {
128 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
129 if (qlm_cfg.s.qlm_cfg != 0)
130 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
131 }
132 return CVMX_HELPER_INTERFACE_MODE_NPI;
133 case 8:
134 return CVMX_HELPER_INTERFACE_MODE_LOOP;
135 default:
136 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
137 }
138 }
139
140 /**
141 * @INTERNAL
142 * Return interface mode for an Octeon II
143 */
__cvmx_get_mode_octeon2(int interface)144 static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
145 {
146 union cvmx_gmxx_inf_mode mode;
147
148 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
149 return __cvmx_get_mode_cn68xx(interface);
150
151 if (interface == 2)
152 return CVMX_HELPER_INTERFACE_MODE_NPI;
153
154 if (interface == 3)
155 return CVMX_HELPER_INTERFACE_MODE_LOOP;
156
157 /* Only present in CN63XX & CN66XX Octeon model */
158 if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
159 (interface == 4 || interface == 5)) ||
160 (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
161 interface >= 4 && interface <= 7)) {
162 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
163 }
164
165 if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
166 union cvmx_mio_qlmx_cfg mio_qlm_cfg;
167
168 /* QLM2 is SGMII0 and QLM1 is SGMII1 */
169 if (interface == 0)
170 mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
171 else if (interface == 1)
172 mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
173 else
174 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
175
176 if (mio_qlm_cfg.s.qlm_spd == 15)
177 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
178
179 if (mio_qlm_cfg.s.qlm_cfg == 9)
180 return CVMX_HELPER_INTERFACE_MODE_SGMII;
181 else if (mio_qlm_cfg.s.qlm_cfg == 11)
182 return CVMX_HELPER_INTERFACE_MODE_XAUI;
183 else
184 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
185 } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
186 union cvmx_mio_qlmx_cfg qlm_cfg;
187
188 if (interface == 0) {
189 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
190 if (qlm_cfg.s.qlm_cfg == 2)
191 return CVMX_HELPER_INTERFACE_MODE_SGMII;
192 else if (qlm_cfg.s.qlm_cfg == 3)
193 return CVMX_HELPER_INTERFACE_MODE_XAUI;
194 else
195 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
196 } else if (interface == 1) {
197 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
198 if (qlm_cfg.s.qlm_cfg == 2)
199 return CVMX_HELPER_INTERFACE_MODE_SGMII;
200 else if (qlm_cfg.s.qlm_cfg == 3)
201 return CVMX_HELPER_INTERFACE_MODE_XAUI;
202 else
203 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
204 }
205 } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
206 if (interface == 0) {
207 union cvmx_mio_qlmx_cfg qlm_cfg;
208 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
209 if (qlm_cfg.s.qlm_cfg == 2)
210 return CVMX_HELPER_INTERFACE_MODE_SGMII;
211 }
212 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
213 }
214
215 if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
216 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
217
218 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
219
220 if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
221 switch (mode.cn61xx.mode) {
222 case 0:
223 return CVMX_HELPER_INTERFACE_MODE_SGMII;
224 case 1:
225 return CVMX_HELPER_INTERFACE_MODE_XAUI;
226 default:
227 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
228 }
229 } else {
230 if (!mode.s.en)
231 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
232
233 if (mode.s.type)
234 return CVMX_HELPER_INTERFACE_MODE_GMII;
235 else
236 return CVMX_HELPER_INTERFACE_MODE_RGMII;
237 }
238 }
239
240 /**
241 * @INTERNAL
242 * Return interface mode for CN7XXX.
243 */
__cvmx_get_mode_cn7xxx(int interface)244 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
245 {
246 union cvmx_gmxx_inf_mode mode;
247
248 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
249
250 switch (interface) {
251 case 0:
252 case 1:
253 switch (mode.cn68xx.mode) {
254 case 0:
255 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
256 case 1:
257 case 2:
258 return CVMX_HELPER_INTERFACE_MODE_SGMII;
259 case 3:
260 return CVMX_HELPER_INTERFACE_MODE_XAUI;
261 default:
262 return CVMX_HELPER_INTERFACE_MODE_SGMII;
263 }
264 case 2:
265 return CVMX_HELPER_INTERFACE_MODE_NPI;
266 case 3:
267 return CVMX_HELPER_INTERFACE_MODE_LOOP;
268 case 4:
269 /* TODO: Implement support for AGL (RGMII). */
270 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
271 default:
272 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
273 }
274 }
275
276 /**
277 * Get the operating mode of an interface. Depending on the Octeon
278 * chip and configuration, this function returns an enumeration
279 * of the type of packet I/O supported by an interface.
280 *
281 * @interface: Interface to probe
282 *
283 * Returns Mode of the interface. Unknown or unsupported interfaces return
284 * DISABLED.
285 */
cvmx_helper_interface_get_mode(int interface)286 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
287 {
288 union cvmx_gmxx_inf_mode mode;
289
290 if (interface < 0 ||
291 interface >= cvmx_helper_get_number_of_interfaces())
292 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
293
294 /*
295 * OCTEON III models
296 */
297 if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
298 return __cvmx_get_mode_cn7xxx(interface);
299
300 /*
301 * Octeon II models
302 */
303 if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
304 return __cvmx_get_mode_octeon2(interface);
305
306 /*
307 * Octeon and Octeon Plus models
308 */
309 if (interface == 2)
310 return CVMX_HELPER_INTERFACE_MODE_NPI;
311
312 if (interface == 3) {
313 if (OCTEON_IS_MODEL(OCTEON_CN56XX)
314 || OCTEON_IS_MODEL(OCTEON_CN52XX))
315 return CVMX_HELPER_INTERFACE_MODE_LOOP;
316 else
317 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
318 }
319
320 /* Interface 1 is always disabled on CN31XX and CN30XX */
321 if ((interface == 1)
322 && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
323 || OCTEON_IS_MODEL(OCTEON_CN50XX)
324 || OCTEON_IS_MODEL(OCTEON_CN52XX)))
325 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
326
327 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
328
329 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
330 switch (mode.cn52xx.mode) {
331 case 0:
332 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
333 case 1:
334 return CVMX_HELPER_INTERFACE_MODE_XAUI;
335 case 2:
336 return CVMX_HELPER_INTERFACE_MODE_SGMII;
337 case 3:
338 return CVMX_HELPER_INTERFACE_MODE_PICMG;
339 default:
340 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
341 }
342 } else {
343 if (!mode.s.en)
344 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
345
346 if (mode.s.type) {
347 if (OCTEON_IS_MODEL(OCTEON_CN38XX)
348 || OCTEON_IS_MODEL(OCTEON_CN58XX))
349 return CVMX_HELPER_INTERFACE_MODE_SPI;
350 else
351 return CVMX_HELPER_INTERFACE_MODE_GMII;
352 } else
353 return CVMX_HELPER_INTERFACE_MODE_RGMII;
354 }
355 }
356 EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
357
358 /**
359 * Configure the IPD/PIP tagging and QoS options for a specific
360 * port. This function determines the POW work queue entry
361 * contents for a port. The setup performed here is controlled by
362 * the defines in executive-config.h.
363 *
364 * @ipd_port: Port to configure. This follows the IPD numbering, not the
365 * per interface numbering
366 *
367 * Returns Zero on success, negative on failure
368 */
__cvmx_helper_port_setup_ipd(int ipd_port)369 static int __cvmx_helper_port_setup_ipd(int ipd_port)
370 {
371 union cvmx_pip_prt_cfgx port_config;
372 union cvmx_pip_prt_tagx tag_config;
373
374 port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
375 tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
376
377 /* Have each port go to a different POW queue */
378 port_config.s.qos = ipd_port & 0x7;
379
380 /* Process the headers and place the IP header in the work queue */
381 port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
382
383 tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
384 tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
385 tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
386 tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
387 tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
388 tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
389 tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
390 tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
391 tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
392 tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
393 tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
394 tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
395 tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
396 tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
397 tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
398 tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
399 /* Put all packets in group 0. Other groups can be used by the app */
400 tag_config.s.grp = 0;
401
402 cvmx_pip_config_port(ipd_port, port_config, tag_config);
403
404 return 0;
405 }
406
407 /**
408 * This function sets the interface_port_count[interface] correctly,
409 * without modifying any hardware configuration. Hardware setup of
410 * the ports will be performed later.
411 *
412 * @interface: Interface to probe
413 *
414 * Returns Zero on success, negative on failure
415 */
cvmx_helper_interface_enumerate(int interface)416 int cvmx_helper_interface_enumerate(int interface)
417 {
418 switch (cvmx_helper_interface_get_mode(interface)) {
419 /* These types don't support ports to IPD/PKO */
420 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
421 case CVMX_HELPER_INTERFACE_MODE_PCIE:
422 interface_port_count[interface] = 0;
423 break;
424 /* XAUI is a single high speed port */
425 case CVMX_HELPER_INTERFACE_MODE_XAUI:
426 interface_port_count[interface] =
427 __cvmx_helper_xaui_enumerate(interface);
428 break;
429 /*
430 * RGMII/GMII/MII are all treated about the same. Most
431 * functions refer to these ports as RGMII.
432 */
433 case CVMX_HELPER_INTERFACE_MODE_RGMII:
434 case CVMX_HELPER_INTERFACE_MODE_GMII:
435 interface_port_count[interface] =
436 __cvmx_helper_rgmii_enumerate(interface);
437 break;
438 /*
439 * SPI4 can have 1-16 ports depending on the device at
440 * the other end.
441 */
442 case CVMX_HELPER_INTERFACE_MODE_SPI:
443 interface_port_count[interface] =
444 __cvmx_helper_spi_enumerate(interface);
445 break;
446 /*
447 * SGMII can have 1-4 ports depending on how many are
448 * hooked up.
449 */
450 case CVMX_HELPER_INTERFACE_MODE_SGMII:
451 case CVMX_HELPER_INTERFACE_MODE_PICMG:
452 interface_port_count[interface] =
453 __cvmx_helper_sgmii_enumerate(interface);
454 break;
455 /* PCI target Network Packet Interface */
456 case CVMX_HELPER_INTERFACE_MODE_NPI:
457 interface_port_count[interface] =
458 __cvmx_helper_npi_enumerate(interface);
459 break;
460 /*
461 * Special loopback only ports. These are not the same
462 * as other ports in loopback mode.
463 */
464 case CVMX_HELPER_INTERFACE_MODE_LOOP:
465 interface_port_count[interface] =
466 __cvmx_helper_loop_enumerate(interface);
467 break;
468 }
469
470 interface_port_count[interface] =
471 __cvmx_helper_board_interface_probe(interface,
472 interface_port_count
473 [interface]);
474
475 /* Make sure all global variables propagate to other cores */
476 CVMX_SYNCWS;
477
478 return 0;
479 }
480
481 /**
482 * This function probes an interface to determine the actual
483 * number of hardware ports connected to it. It doesn't setup the
484 * ports or enable them. The main goal here is to set the global
485 * interface_port_count[interface] correctly. Hardware setup of the
486 * ports will be performed later.
487 *
488 * @interface: Interface to probe
489 *
490 * Returns Zero on success, negative on failure
491 */
cvmx_helper_interface_probe(int interface)492 int cvmx_helper_interface_probe(int interface)
493 {
494 cvmx_helper_interface_enumerate(interface);
495 /* At this stage in the game we don't want packets to be moving yet.
496 The following probe calls should perform hardware setup
497 needed to determine port counts. Receive must still be disabled */
498 switch (cvmx_helper_interface_get_mode(interface)) {
499 /* These types don't support ports to IPD/PKO */
500 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
501 case CVMX_HELPER_INTERFACE_MODE_PCIE:
502 break;
503 /* XAUI is a single high speed port */
504 case CVMX_HELPER_INTERFACE_MODE_XAUI:
505 __cvmx_helper_xaui_probe(interface);
506 break;
507 /*
508 * RGMII/GMII/MII are all treated about the same. Most
509 * functions refer to these ports as RGMII.
510 */
511 case CVMX_HELPER_INTERFACE_MODE_RGMII:
512 case CVMX_HELPER_INTERFACE_MODE_GMII:
513 __cvmx_helper_rgmii_probe(interface);
514 break;
515 /*
516 * SPI4 can have 1-16 ports depending on the device at
517 * the other end.
518 */
519 case CVMX_HELPER_INTERFACE_MODE_SPI:
520 __cvmx_helper_spi_probe(interface);
521 break;
522 /*
523 * SGMII can have 1-4 ports depending on how many are
524 * hooked up.
525 */
526 case CVMX_HELPER_INTERFACE_MODE_SGMII:
527 case CVMX_HELPER_INTERFACE_MODE_PICMG:
528 __cvmx_helper_sgmii_probe(interface);
529 break;
530 /* PCI target Network Packet Interface */
531 case CVMX_HELPER_INTERFACE_MODE_NPI:
532 __cvmx_helper_npi_probe(interface);
533 break;
534 /*
535 * Special loopback only ports. These are not the same
536 * as other ports in loopback mode.
537 */
538 case CVMX_HELPER_INTERFACE_MODE_LOOP:
539 __cvmx_helper_loop_probe(interface);
540 break;
541 }
542
543 /* Make sure all global variables propagate to other cores */
544 CVMX_SYNCWS;
545
546 return 0;
547 }
548
549 /**
550 * Setup the IPD/PIP for the ports on an interface. Packet
551 * classification and tagging are set for every port on the
552 * interface. The number of ports on the interface must already
553 * have been probed.
554 *
555 * @interface: Interface to setup IPD/PIP for
556 *
557 * Returns Zero on success, negative on failure
558 */
__cvmx_helper_interface_setup_ipd(int interface)559 static int __cvmx_helper_interface_setup_ipd(int interface)
560 {
561 int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
562 int num_ports = interface_port_count[interface];
563
564 while (num_ports--) {
565 __cvmx_helper_port_setup_ipd(ipd_port);
566 ipd_port++;
567 }
568 return 0;
569 }
570
571 /**
572 * Setup global setting for IPD/PIP not related to a specific
573 * interface or port. This must be called before IPD is enabled.
574 *
575 * Returns Zero on success, negative on failure.
576 */
__cvmx_helper_global_setup_ipd(void)577 static int __cvmx_helper_global_setup_ipd(void)
578 {
579 /* Setup the global packet input options */
580 cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
581 CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
582 CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
583 /* The +8 is to account for the next ptr */
584 (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
585 /* The +8 is to account for the next ptr */
586 (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
587 CVMX_FPA_WQE_POOL,
588 CVMX_IPD_OPC_MODE_STT,
589 CVMX_HELPER_ENABLE_BACK_PRESSURE);
590 return 0;
591 }
592
593 /**
594 * Setup the PKO for the ports on an interface. The number of
595 * queues per port and the priority of each PKO output queue
596 * is set here. PKO must be disabled when this function is called.
597 *
598 * @interface: Interface to setup PKO for
599 *
600 * Returns Zero on success, negative on failure
601 */
__cvmx_helper_interface_setup_pko(int interface)602 static int __cvmx_helper_interface_setup_pko(int interface)
603 {
604 /*
605 * Each packet output queue has an associated priority. The
606 * higher the priority, the more often it can send a packet. A
607 * priority of 8 means it can send in all 8 rounds of
608 * contention. We're going to make each queue one less than
609 * the last. The vector of priorities has been extended to
610 * support CN5xxx CPUs, where up to 16 queues can be
611 * associated to a port. To keep backward compatibility we
612 * don't change the initial 8 priorities and replicate them in
613 * the second half. With per-core PKO queues (PKO lockless
614 * operation) all queues have the same priority.
615 */
616 uint64_t priorities[16] =
617 { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
618
619 /*
620 * Setup the IPD/PIP and PKO for the ports discovered
621 * above. Here packet classification, tagging and output
622 * priorities are set.
623 */
624 int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
625 int num_ports = interface_port_count[interface];
626 while (num_ports--) {
627 cvmx_pko_config_port(ipd_port,
628 cvmx_pko_get_base_queue_per_core(ipd_port,
629 0),
630 cvmx_pko_get_num_queues(ipd_port),
631 priorities);
632 ipd_port++;
633 }
634 return 0;
635 }
636
637 /**
638 * Setup global setting for PKO not related to a specific
639 * interface or port. This must be called before PKO is enabled.
640 *
641 * Returns Zero on success, negative on failure.
642 */
__cvmx_helper_global_setup_pko(void)643 static int __cvmx_helper_global_setup_pko(void)
644 {
645 /*
646 * Disable tagwait FAU timeout. This needs to be done before
647 * anyone might start packet output using tags.
648 */
649 union cvmx_iob_fau_timeout fau_to;
650 fau_to.u64 = 0;
651 fau_to.s.tout_val = 0xfff;
652 fau_to.s.tout_enb = 0;
653 cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
654
655 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
656 union cvmx_pko_reg_min_pkt min_pkt;
657
658 min_pkt.u64 = 0;
659 min_pkt.s.size1 = 59;
660 min_pkt.s.size2 = 59;
661 min_pkt.s.size3 = 59;
662 min_pkt.s.size4 = 59;
663 min_pkt.s.size5 = 59;
664 min_pkt.s.size6 = 59;
665 min_pkt.s.size7 = 59;
666 cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
667 }
668
669 return 0;
670 }
671
672 /**
673 * Setup global backpressure setting.
674 *
675 * Returns Zero on success, negative on failure
676 */
__cvmx_helper_global_setup_backpressure(void)677 static int __cvmx_helper_global_setup_backpressure(void)
678 {
679 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
680 /* Disable backpressure if configured to do so */
681 /* Disable backpressure (pause frame) generation */
682 int num_interfaces = cvmx_helper_get_number_of_interfaces();
683 int interface;
684 for (interface = 0; interface < num_interfaces; interface++) {
685 switch (cvmx_helper_interface_get_mode(interface)) {
686 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
687 case CVMX_HELPER_INTERFACE_MODE_PCIE:
688 case CVMX_HELPER_INTERFACE_MODE_NPI:
689 case CVMX_HELPER_INTERFACE_MODE_LOOP:
690 case CVMX_HELPER_INTERFACE_MODE_XAUI:
691 break;
692 case CVMX_HELPER_INTERFACE_MODE_RGMII:
693 case CVMX_HELPER_INTERFACE_MODE_GMII:
694 case CVMX_HELPER_INTERFACE_MODE_SPI:
695 case CVMX_HELPER_INTERFACE_MODE_SGMII:
696 case CVMX_HELPER_INTERFACE_MODE_PICMG:
697 cvmx_gmx_set_backpressure_override(interface, 0xf);
698 break;
699 }
700 }
701 #endif
702
703 return 0;
704 }
705
706 /**
707 * Enable packet input/output from the hardware. This function is
708 * called after all internal setup is complete and IPD is enabled.
709 * After this function completes, packets will be accepted from the
710 * hardware ports. PKO should still be disabled to make sure packets
711 * aren't sent out partially setup hardware.
712 *
713 * @interface: Interface to enable
714 *
715 * Returns Zero on success, negative on failure
716 */
__cvmx_helper_packet_hardware_enable(int interface)717 static int __cvmx_helper_packet_hardware_enable(int interface)
718 {
719 int result = 0;
720 switch (cvmx_helper_interface_get_mode(interface)) {
721 /* These types don't support ports to IPD/PKO */
722 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
723 case CVMX_HELPER_INTERFACE_MODE_PCIE:
724 /* Nothing to do */
725 break;
726 /* XAUI is a single high speed port */
727 case CVMX_HELPER_INTERFACE_MODE_XAUI:
728 result = __cvmx_helper_xaui_enable(interface);
729 break;
730 /*
731 * RGMII/GMII/MII are all treated about the same. Most
732 * functions refer to these ports as RGMII
733 */
734 case CVMX_HELPER_INTERFACE_MODE_RGMII:
735 case CVMX_HELPER_INTERFACE_MODE_GMII:
736 result = __cvmx_helper_rgmii_enable(interface);
737 break;
738 /*
739 * SPI4 can have 1-16 ports depending on the device at
740 * the other end
741 */
742 case CVMX_HELPER_INTERFACE_MODE_SPI:
743 result = __cvmx_helper_spi_enable(interface);
744 break;
745 /*
746 * SGMII can have 1-4 ports depending on how many are
747 * hooked up
748 */
749 case CVMX_HELPER_INTERFACE_MODE_SGMII:
750 case CVMX_HELPER_INTERFACE_MODE_PICMG:
751 result = __cvmx_helper_sgmii_enable(interface);
752 break;
753 /* PCI target Network Packet Interface */
754 case CVMX_HELPER_INTERFACE_MODE_NPI:
755 result = __cvmx_helper_npi_enable(interface);
756 break;
757 /*
758 * Special loopback only ports. These are not the same
759 * as other ports in loopback mode
760 */
761 case CVMX_HELPER_INTERFACE_MODE_LOOP:
762 result = __cvmx_helper_loop_enable(interface);
763 break;
764 }
765 return result;
766 }
767
768 /**
769 * Function to adjust internal IPD pointer alignments
770 *
771 * Returns 0 on success
772 * !0 on failure
773 */
__cvmx_helper_errata_fix_ipd_ptr_alignment(void)774 static int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
775 {
776 #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
777 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
778 #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
779 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
780 #define FIX_IPD_OUTPORT 0
781 /* Ports 0-15 are interface 0, 16-31 are interface 1 */
782 #define INTERFACE(port) (port >> 4)
783 #define INDEX(port) (port & 0xf)
784 uint64_t *p64;
785 union cvmx_pko_command_word0 pko_command;
786 union cvmx_buf_ptr g_buffer, pkt_buffer;
787 struct cvmx_wqe *work;
788 int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
789 union cvmx_gmxx_prtx_cfg gmx_cfg;
790 int retry_cnt;
791 int retry_loop_cnt;
792 int i;
793
794 /* Save values for restore at end */
795 uint64_t prtx_cfg =
796 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
797 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
798 uint64_t tx_ptr_en =
799 cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
800 uint64_t rx_ptr_en =
801 cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
802 uint64_t rxx_jabber =
803 cvmx_read_csr(CVMX_GMXX_RXX_JABBER
804 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
805 uint64_t frame_max =
806 cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
807 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
808
809 /* Configure port to gig FDX as required for loopback mode */
810 cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
811
812 /*
813 * Disable reception on all ports so if traffic is present it
814 * will not interfere.
815 */
816 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
817
818 __delay(100000000ull);
819
820 for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
821 retry_cnt = 100000;
822 wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
823 pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
824 wqe_pcnt &= 0x7f;
825
826 num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
827
828 if (num_segs == 0)
829 goto fix_ipd_exit;
830
831 num_segs += 1;
832
833 size =
834 FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
835 ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
836 (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
837
838 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
839 1 << INDEX(FIX_IPD_OUTPORT));
840 CVMX_SYNC;
841
842 g_buffer.u64 = 0;
843 g_buffer.s.addr =
844 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
845 if (g_buffer.s.addr == 0) {
846 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
847 "buffer allocation failure.\n");
848 goto fix_ipd_exit;
849 }
850
851 g_buffer.s.pool = CVMX_FPA_WQE_POOL;
852 g_buffer.s.size = num_segs;
853
854 pkt_buffer.u64 = 0;
855 pkt_buffer.s.addr =
856 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
857 if (pkt_buffer.s.addr == 0) {
858 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
859 "buffer allocation failure.\n");
860 goto fix_ipd_exit;
861 }
862 pkt_buffer.s.i = 1;
863 pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
864 pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
865
866 p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
867 p64[0] = 0xffffffffffff0000ull;
868 p64[1] = 0x08004510ull;
869 p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
870 p64[3] = 0x3a5fc0a81073c0a8ull;
871
872 for (i = 0; i < num_segs; i++) {
873 if (i > 0)
874 pkt_buffer.s.size =
875 FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
876
877 if (i == (num_segs - 1))
878 pkt_buffer.s.i = 0;
879
880 *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
881 8 * i) = pkt_buffer.u64;
882 }
883
884 /* Build the PKO command */
885 pko_command.u64 = 0;
886 pko_command.s.segs = num_segs;
887 pko_command.s.total_bytes = size;
888 pko_command.s.dontfree = 0;
889 pko_command.s.gather = 1;
890
891 gmx_cfg.u64 =
892 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
893 (INDEX(FIX_IPD_OUTPORT),
894 INTERFACE(FIX_IPD_OUTPORT)));
895 gmx_cfg.s.en = 1;
896 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
897 (INDEX(FIX_IPD_OUTPORT),
898 INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
899 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
900 1 << INDEX(FIX_IPD_OUTPORT));
901 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
902 1 << INDEX(FIX_IPD_OUTPORT));
903
904 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
905 (INDEX(FIX_IPD_OUTPORT),
906 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
907 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
908 (INDEX(FIX_IPD_OUTPORT),
909 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
910
911 cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
912 cvmx_pko_get_base_queue
913 (FIX_IPD_OUTPORT),
914 CVMX_PKO_LOCK_CMD_QUEUE);
915 cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
916 cvmx_pko_get_base_queue
917 (FIX_IPD_OUTPORT), pko_command,
918 g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
919
920 CVMX_SYNC;
921
922 do {
923 work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
924 retry_cnt--;
925 } while ((work == NULL) && (retry_cnt > 0));
926
927 if (!retry_cnt)
928 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
929 "get_work() timeout occurred.\n");
930
931 /* Free packet */
932 if (work)
933 cvmx_helper_free_packet_data(work);
934 }
935
936 fix_ipd_exit:
937
938 /* Return CSR configs to saved values */
939 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
940 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
941 prtx_cfg);
942 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
943 tx_ptr_en);
944 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
945 rx_ptr_en);
946 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
947 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
948 rxx_jabber);
949 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
950 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
951 frame_max);
952 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
953
954 CVMX_SYNC;
955 if (num_segs)
956 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
957
958 return !!num_segs;
959
960 }
961
962 /**
963 * Called after all internal packet IO paths are setup. This
964 * function enables IPD/PIP and begins packet input and output.
965 *
966 * Returns Zero on success, negative on failure
967 */
cvmx_helper_ipd_and_packet_input_enable(void)968 int cvmx_helper_ipd_and_packet_input_enable(void)
969 {
970 int num_interfaces;
971 int interface;
972
973 /* Enable IPD */
974 cvmx_ipd_enable();
975
976 /*
977 * Time to enable hardware ports packet input and output. Note
978 * that at this point IPD/PIP must be fully functional and PKO
979 * must be disabled
980 */
981 num_interfaces = cvmx_helper_get_number_of_interfaces();
982 for (interface = 0; interface < num_interfaces; interface++) {
983 if (cvmx_helper_ports_on_interface(interface) > 0)
984 __cvmx_helper_packet_hardware_enable(interface);
985 }
986
987 /* Finally enable PKO now that the entire path is up and running */
988 cvmx_pko_enable();
989
990 if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
991 || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
992 && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
993 __cvmx_helper_errata_fix_ipd_ptr_alignment();
994 return 0;
995 }
996 EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
997
998 /**
999 * Initialize the PIP, IPD, and PKO hardware to support
1000 * simple priority based queues for the ethernet ports. Each
1001 * port is configured with a number of priority queues based
1002 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
1003 * priority than the previous.
1004 *
1005 * Returns Zero on success, non-zero on failure
1006 */
cvmx_helper_initialize_packet_io_global(void)1007 int cvmx_helper_initialize_packet_io_global(void)
1008 {
1009 int result = 0;
1010 int interface;
1011 union cvmx_l2c_cfg l2c_cfg;
1012 const int num_interfaces = cvmx_helper_get_number_of_interfaces();
1013
1014 /*
1015 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
1016 * be disabled.
1017 */
1018 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
1019 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
1020
1021 /*
1022 * Tell L2 to give the IOB statically higher priority compared
1023 * to the cores. This avoids conditions where IO blocks might
1024 * be starved under very high L2 loads.
1025 */
1026 l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
1027 l2c_cfg.s.lrf_arb_mode = 0;
1028 l2c_cfg.s.rfb_arb_mode = 0;
1029 cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
1030
1031 cvmx_pko_initialize_global();
1032 for (interface = 0; interface < num_interfaces; interface++) {
1033 result |= cvmx_helper_interface_probe(interface);
1034 if (cvmx_helper_ports_on_interface(interface) > 0)
1035 cvmx_dprintf("Interface %d has %d ports (%s)\n",
1036 interface,
1037 cvmx_helper_ports_on_interface(interface),
1038 cvmx_helper_interface_mode_to_string
1039 (cvmx_helper_interface_get_mode
1040 (interface)));
1041 result |= __cvmx_helper_interface_setup_ipd(interface);
1042 result |= __cvmx_helper_interface_setup_pko(interface);
1043 }
1044
1045 result |= __cvmx_helper_global_setup_ipd();
1046 result |= __cvmx_helper_global_setup_pko();
1047
1048 /* Enable any flow control and backpressure */
1049 result |= __cvmx_helper_global_setup_backpressure();
1050
1051 #if CVMX_HELPER_ENABLE_IPD
1052 result |= cvmx_helper_ipd_and_packet_input_enable();
1053 #endif
1054 return result;
1055 }
1056 EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
1057
1058 /**
1059 * Does core local initialization for packet io
1060 *
1061 * Returns Zero on success, non-zero on failure
1062 */
cvmx_helper_initialize_packet_io_local(void)1063 int cvmx_helper_initialize_packet_io_local(void)
1064 {
1065 return cvmx_pko_initialize_local();
1066 }
1067
1068 /**
1069 * Return the link state of an IPD/PKO port as returned by
1070 * auto negotiation. The result of this function may not match
1071 * Octeon's link config if auto negotiation has changed since
1072 * the last call to cvmx_helper_link_set().
1073 *
1074 * @ipd_port: IPD/PKO port to query
1075 *
1076 * Returns Link state
1077 */
cvmx_helper_link_get(int ipd_port)1078 union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)
1079 {
1080 union cvmx_helper_link_info result;
1081 int interface = cvmx_helper_get_interface_num(ipd_port);
1082 int index = cvmx_helper_get_interface_index_num(ipd_port);
1083
1084 /* The default result will be a down link unless the code below
1085 changes it */
1086 result.u64 = 0;
1087
1088 if (index >= cvmx_helper_ports_on_interface(interface))
1089 return result;
1090
1091 switch (cvmx_helper_interface_get_mode(interface)) {
1092 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1093 case CVMX_HELPER_INTERFACE_MODE_PCIE:
1094 /* Network links are not supported */
1095 break;
1096 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1097 result = __cvmx_helper_xaui_link_get(ipd_port);
1098 break;
1099 case CVMX_HELPER_INTERFACE_MODE_GMII:
1100 if (index == 0)
1101 result = __cvmx_helper_rgmii_link_get(ipd_port);
1102 else {
1103 WARN_ONCE(1, "Using deprecated link status - please update your DT");
1104 result.s.full_duplex = 1;
1105 result.s.link_up = 1;
1106 result.s.speed = 1000;
1107 }
1108 break;
1109 case CVMX_HELPER_INTERFACE_MODE_RGMII:
1110 result = __cvmx_helper_rgmii_link_get(ipd_port);
1111 break;
1112 case CVMX_HELPER_INTERFACE_MODE_SPI:
1113 result = __cvmx_helper_spi_link_get(ipd_port);
1114 break;
1115 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1116 case CVMX_HELPER_INTERFACE_MODE_PICMG:
1117 result = __cvmx_helper_sgmii_link_get(ipd_port);
1118 break;
1119 case CVMX_HELPER_INTERFACE_MODE_NPI:
1120 case CVMX_HELPER_INTERFACE_MODE_LOOP:
1121 /* Network links are not supported */
1122 break;
1123 }
1124 return result;
1125 }
1126 EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
1127
1128 /**
1129 * Configure an IPD/PKO port for the specified link state. This
1130 * function does not influence auto negotiation at the PHY level.
1131 * The passed link state must always match the link state returned
1132 * by cvmx_helper_link_get().
1133 *
1134 * @ipd_port: IPD/PKO port to configure
1135 * @link_info: The new link state
1136 *
1137 * Returns Zero on success, negative on failure
1138 */
cvmx_helper_link_set(int ipd_port,union cvmx_helper_link_info link_info)1139 int cvmx_helper_link_set(int ipd_port, union cvmx_helper_link_info link_info)
1140 {
1141 int result = -1;
1142 int interface = cvmx_helper_get_interface_num(ipd_port);
1143 int index = cvmx_helper_get_interface_index_num(ipd_port);
1144
1145 if (index >= cvmx_helper_ports_on_interface(interface))
1146 return -1;
1147
1148 switch (cvmx_helper_interface_get_mode(interface)) {
1149 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1150 case CVMX_HELPER_INTERFACE_MODE_PCIE:
1151 break;
1152 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1153 result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1154 break;
1155 /*
1156 * RGMII/GMII/MII are all treated about the same. Most
1157 * functions refer to these ports as RGMII.
1158 */
1159 case CVMX_HELPER_INTERFACE_MODE_RGMII:
1160 case CVMX_HELPER_INTERFACE_MODE_GMII:
1161 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1162 break;
1163 case CVMX_HELPER_INTERFACE_MODE_SPI:
1164 result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1165 break;
1166 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1167 case CVMX_HELPER_INTERFACE_MODE_PICMG:
1168 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1169 break;
1170 case CVMX_HELPER_INTERFACE_MODE_NPI:
1171 case CVMX_HELPER_INTERFACE_MODE_LOOP:
1172 break;
1173 }
1174 return result;
1175 }
1176 EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1177