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