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