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