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