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