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