Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / mips / cavium-octeon / executive / cvmx-helper.c
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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         cvmx_pko_command_word0_t pko_command;
786         union cvmx_buf_ptr g_buffer, pkt_buffer;
787         cvmx_wqe_t *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  */
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  */
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  */
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  */
1078 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
1079 {
1080         cvmx_helper_link_info_t 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(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  */
1139 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t 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);