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