blob: 18d9081922c4c7add7e4b0899521312225bfdce8 [file] [log] [blame]
David Hendricks7d48ac52018-03-09 14:30:38 -08001/***********************license start***********************************
2* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
3* reserved.
4*
5*
6* Redistribution and use in source and binary forms, with or without
7* modification, are permitted provided that the following conditions are
8* met:
9*
10* * Redistributions of source code must retain the above copyright
11* notice, this list of conditions and the following disclaimer.
12*
13* * Redistributions in binary form must reproduce the above
14* copyright notice, this list of conditions and the following
15* disclaimer in the documentation and/or other materials provided
16* with the distribution.
17*
18* * Neither the name of Cavium Inc. nor the names of
19* its contributors may be used to endorse or promote products
20* derived from this software without specific prior written
21* permission.
22*
23* This Software, including technical data, may be subject to U.S. export
24* control laws, including the U.S. Export Administration Act and its
25* associated regulations, and may be subject to export or import
26* regulations in other countries.
27*
28* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
31* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
32* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
33* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
34* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
35* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
36* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
37* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38***********************license end**************************************/
39#include <bdk.h>
Elyes HAOUAS39179042019-11-30 19:06:14 +010040#include <stdlib.h>
David Hendricks7d48ac52018-03-09 14:30:38 -080041#include <string.h>
42#include "libbdk-arch/bdk-csrs-gser.h"
43#include "libbdk-arch/bdk-csrs-gsern.h"
44#include "libbdk-hal/if/bdk-if.h"
45#include "libbdk-hal/bdk-qlm.h"
46#include "libbdk-hal/qlm/bdk-qlm-common.h"
47
48/* This code is an optional part of the BDK. It is only linked in
49 if BDK_REQUIRE() needs it */
50BDK_REQUIRE_DEFINE(QLM);
51
52/**
53 * Convert a mode into a configuration variable string value
54 *
55 * @param mode Mode to convert
56 *
57 * @return configuration value string
58 */
59const char *bdk_qlm_mode_to_cfg_str(bdk_qlm_modes_t mode)
60{
61#define MODE_CASE(m) case m: return #m+13
62 switch (mode)
63 {
64 MODE_CASE(BDK_QLM_MODE_DISABLED);
65 MODE_CASE(BDK_QLM_MODE_PCIE_1X1);
66 MODE_CASE(BDK_QLM_MODE_PCIE_2X1);
67 MODE_CASE(BDK_QLM_MODE_PCIE_1X2);
68 MODE_CASE(BDK_QLM_MODE_PCIE_1X4);
69 MODE_CASE(BDK_QLM_MODE_PCIE_1X8);
70 MODE_CASE(BDK_QLM_MODE_PCIE_1X16);
71
72 MODE_CASE(BDK_QLM_MODE_SATA_4X1);
73 MODE_CASE(BDK_QLM_MODE_SATA_2X1);
74
75 MODE_CASE(BDK_QLM_MODE_ILK);
76 MODE_CASE(BDK_QLM_MODE_SGMII_4X1);
77 MODE_CASE(BDK_QLM_MODE_SGMII_2X1);
78 MODE_CASE(BDK_QLM_MODE_SGMII_1X1);
79 MODE_CASE(BDK_QLM_MODE_XAUI_1X4);
80 MODE_CASE(BDK_QLM_MODE_RXAUI_2X2);
81 MODE_CASE(BDK_QLM_MODE_RXAUI_1X2);
82 MODE_CASE(BDK_QLM_MODE_OCI);
83 MODE_CASE(BDK_QLM_MODE_XFI_4X1);
84 MODE_CASE(BDK_QLM_MODE_XFI_2X1);
85 MODE_CASE(BDK_QLM_MODE_XFI_1X1);
86 MODE_CASE(BDK_QLM_MODE_XLAUI_1X4);
87 MODE_CASE(BDK_QLM_MODE_10G_KR_4X1);
88 MODE_CASE(BDK_QLM_MODE_10G_KR_2X1);
89 MODE_CASE(BDK_QLM_MODE_10G_KR_1X1);
90 MODE_CASE(BDK_QLM_MODE_40G_KR4_1X4);
91 MODE_CASE(BDK_QLM_MODE_QSGMII_4X1);
92 MODE_CASE(BDK_QLM_MODE_25G_4X1);
93 MODE_CASE(BDK_QLM_MODE_25G_2X1);
94 MODE_CASE(BDK_QLM_MODE_50G_2X2);
95 MODE_CASE(BDK_QLM_MODE_50G_1X2);
96 MODE_CASE(BDK_QLM_MODE_100G_1X4);
97 MODE_CASE(BDK_QLM_MODE_25G_KR_4X1);
98 MODE_CASE(BDK_QLM_MODE_25G_KR_2X1);
99 MODE_CASE(BDK_QLM_MODE_50G_KR_2X2);
100 MODE_CASE(BDK_QLM_MODE_50G_KR_1X2);
101 MODE_CASE(BDK_QLM_MODE_100G_KR4_1X4);
102 MODE_CASE(BDK_QLM_MODE_USXGMII_4X1);
103 MODE_CASE(BDK_QLM_MODE_USXGMII_2X1);
104
105 case BDK_QLM_MODE_LAST: break; /* fall through error */
106 }
107 return "INVALID_QLM_MODE_VALUE";
108}
109
110/**
111 * Convert a configuration variable value string into a mode
112 *
113 * @param val Configuration variable value
114 *
115 * @return mode
116 */
117bdk_qlm_modes_t bdk_qlm_cfg_string_to_mode(const char *val)
118{
119 bdk_qlm_modes_t mode;
120
121 for (mode = 0; mode < BDK_QLM_MODE_LAST; mode++)
122 {
123 if (0 == strcmp(val, bdk_qlm_mode_to_cfg_str(mode)))
124 {
125 return mode;
126 }
127 }
128 return -1;
129}
130
131/**
132 * Convert a mode into a human understandable string
133 *
134 * @param mode Mode to convert
135 *
136 * @return Easy to read string
137 */
138const char *bdk_qlm_mode_tostring(bdk_qlm_modes_t mode)
139{
140 const char *result = "Unknown, update bdk_qlm_mode_tostring()";
141 switch (mode)
142 {
143 case BDK_QLM_MODE_DISABLED:
144 result = "Disabled";
145 break;
146 case BDK_QLM_MODE_PCIE_1X1:
147 result = "1 PCIe, 1 lane";
148 break;
149 case BDK_QLM_MODE_PCIE_2X1:
150 result = "2 PCIe, 1 lane each";
151 break;
152 case BDK_QLM_MODE_PCIE_1X2:
153 result = "1 PCIe, 2 lanes";
154 break;
155 case BDK_QLM_MODE_PCIE_1X4:
156 result = "1 PCIe, 4 lanes";
157 break;
158 case BDK_QLM_MODE_PCIE_1X8:
159 result = "1 PCIe, 8 lanes";
160 break;
161 case BDK_QLM_MODE_PCIE_1X16:
162 result = "1 PCIe, 16 lanes";
163 break;
164
165 case BDK_QLM_MODE_SATA_4X1:
166 result = "4 SATA, one lane each";
167 break;
168 case BDK_QLM_MODE_SATA_2X1:
169 result = "2 SATA, one lane each";
170 break;
171
172 case BDK_QLM_MODE_ILK:
173 result = "Interlaken";
174 break;
175 case BDK_QLM_MODE_SGMII_4X1:
176 result = "4 SGMII, 1 lane each";
177 break;
178 case BDK_QLM_MODE_SGMII_2X1:
179 result = "2 SGMII, 1 lane each";
180 break;
181 case BDK_QLM_MODE_SGMII_1X1:
182 result = "1 SGMII, 1 lane";
183 break;
184 case BDK_QLM_MODE_XAUI_1X4:
185 result = "1 XAUI, 4 lanes";
186 break;
187 case BDK_QLM_MODE_RXAUI_2X2:
188 result = "2 RXAUI, 2 lanes each";
189 break;
190 case BDK_QLM_MODE_RXAUI_1X2:
191 result = "1 RXAUI, 2 lanes each";
192 break;
193 case BDK_QLM_MODE_OCI:
194 result = "Cavium Coherent Processor Interconnect";
195 break;
196 case BDK_QLM_MODE_XFI_4X1:
197 result = "4 XFI, 1 lane each";
198 break;
199 case BDK_QLM_MODE_XFI_2X1:
200 result = "2 XFI, 1 lane each";
201 break;
202 case BDK_QLM_MODE_XFI_1X1:
203 result = "1 XFI, 1 lane";
204 break;
205 case BDK_QLM_MODE_XLAUI_1X4:
206 result = "1 XLAUI, 4 lanes";
207 break;
208 case BDK_QLM_MODE_10G_KR_4X1:
209 result = "4 10GBASE-KR, 1 lane each";
210 break;
211 case BDK_QLM_MODE_10G_KR_2X1:
212 result = "2 10GBASE-KR, 1 lane each";
213 break;
214 case BDK_QLM_MODE_10G_KR_1X1:
215 result = "1 10GBASE-KR, 1 lane";
216 break;
217 case BDK_QLM_MODE_40G_KR4_1X4:
218 result = "1 40GBASE-KR4, 4 lanes";
219 break;
220 case BDK_QLM_MODE_QSGMII_4X1:
221 result = "4 QSGMII, 1 lane";
222 break;
223 case BDK_QLM_MODE_25G_4X1:
224 result = "4 25G, 1 lane each";
225 break;
226 case BDK_QLM_MODE_25G_2X1:
227 result = "2 25G, 1 lane each";
228 break;
229 case BDK_QLM_MODE_50G_2X2:
230 result = "2 50G, 2 lanes each";
231 break;
232 case BDK_QLM_MODE_50G_1X2:
233 result = "1 50G, 2 lanes";
234 break;
235 case BDK_QLM_MODE_100G_1X4:
236 result = "1 100G, 4 lanes";
237 break;
238 case BDK_QLM_MODE_25G_KR_4X1:
239 result = "4 25G, 1 lane each";
240 break;
241 case BDK_QLM_MODE_25G_KR_2X1:
242 result = "2 25G, 1 lane each";
243 break;
244 case BDK_QLM_MODE_50G_KR_2X2:
245 result = "2 50G, 2 lanes each";
246 break;
247 case BDK_QLM_MODE_50G_KR_1X2:
248 result = "1 50G, 2 lanes";
249 break;
250 case BDK_QLM_MODE_100G_KR4_1X4:
251 result = "1 100G, 4 lanes";
252 break;
253 case BDK_QLM_MODE_USXGMII_4X1:
254 result = "4 USXGMII, 1 lane each";
255 break;
256 case BDK_QLM_MODE_USXGMII_2X1:
257 result = "2 USXGMII, 1 lane each";
258 break;
259
260 case BDK_QLM_MODE_LAST:
261 break; /* fallthrough error */
262 }
263 return result;
264}
265
266int bdk_qlm_measure_clock(bdk_node_t node, int qlm)
267{
268 int ref_clock = __bdk_qlm_measure_refclock(node, qlm);
269 BDK_TRACE(QLM, "N%d.QLM%d: Ref clock %d Hz\n", node, qlm, ref_clock);
270
271 return ref_clock;
272}
273
274/**
275 * Set the QLM's clock source.
276 *
277 * @param node Node to use in a Numa setup
278 * @param qlm QLM to configure
279 * @param clk Clock source for QLM
280 *
281 * @return Zero on success, negative on failure
282 */
283int bdk_qlm_set_clock(bdk_node_t node, int qlm, bdk_qlm_clock_t clk)
284{
285 if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
286 {
287 int sel;
288 int com1;
289 switch (clk)
290 {
291 case BDK_QLM_CLK_COMMON_0:
292 sel = 1;
293 com1 = 0;
294 break;
295 case BDK_QLM_CLK_COMMON_1:
296 sel = 1;
297 com1 = 1;
298 break;
299 case BDK_QLM_CLK_EXTERNAL:
300 sel = 0;
301 com1 = 0;
302 break;
303 default:
304 bdk_warn("Unrecognized clock mode %d for QLM%d on node %d.\n",
305 clk, qlm, node);
306 return -1;
307 }
308
309 BDK_CSR_MODIFY(c, node, BDK_GSERX_REFCLK_SEL(qlm),
310 c.s.com_clk_sel = sel;
311 c.s.use_com1 = com1);
312 }
313 else
314 {
315 int cclksel;
316 switch (clk)
317 {
318 case BDK_QLM_CLK_COMMON_0:
319 cclksel = 0;
320 break;
321 case BDK_QLM_CLK_COMMON_1:
322 cclksel = 1;
323 break;
324 case BDK_QLM_CLK_COMMON_2:
325 cclksel = 2;
326 break;
327 case BDK_QLM_CLK_EXTERNAL:
328 cclksel = 3;
329 break;
330 default:
331 bdk_warn("Unrecognized clock mode %d for QLM%d on node %d.\n",
332 clk, qlm, node);
333 return -1;
334 }
335 BDK_CSR_MODIFY(c, node, BDK_GSERNX_COMMON_REFCLK_BCFG(qlm),
336 c.s.pwdn = (clk == BDK_QLM_CLK_EXTERNAL) ? 0 : 1;
337 c.s.cclksel = cclksel);
338 }
339 return 0;
340}
341
342/**
343 * Display an eye diagram for the given QLM lane. The eye data can be in "eye", or
344 * captured during the call if "eye" is NULL.
345 *
346 * @param node Node to use in numa setup
347 * @param qlm QLM to use
348 * @param qlm_lane Which lane
349 * @param format Display format. 0 = raw, 1 = Color ASCII
350 * @param eye Eye data to display, or NULL if the data should be captured.
351 *
352 * @return Zero on success, negative on failure
353 */
354int bdk_qlm_eye_display(bdk_node_t node, int qlm, int qlm_lane, int format, const bdk_qlm_eye_t *eye)
355{
356 int result;
357 int need_free = 0;
358 if (eye == NULL)
359 {
360 bdk_qlm_eye_t *eye_data = malloc(sizeof(bdk_qlm_eye_t));
361 if (eye_data == NULL)
362 {
363 bdk_error("Failed to allocate space for eye\n");
364 return -1;
365 }
Jacob Garber43d07f72019-07-26 12:17:53 -0600366 if (bdk_qlm_eye_capture(node, qlm, qlm_lane, eye_data)) {
367 free(eye_data);
368 return -1;
369 }
David Hendricks7d48ac52018-03-09 14:30:38 -0800370 eye = eye_data;
Jacob Garber43d07f72019-07-26 12:17:53 -0600371 need_free = 1;
David Hendricks7d48ac52018-03-09 14:30:38 -0800372 }
373
374 /* Calculate the max eye width */
David Hendricks7d48ac52018-03-09 14:30:38 -0800375 int eye_width = 0;
376 for (int y = 0; y < eye->height; y++)
377 {
378 int width = 0;
379 for (int x = 0; x < eye->width; x++)
380 {
381 if (eye->data[y][x] == 0)
382 {
383 width++;
David Hendricks7d48ac52018-03-09 14:30:38 -0800384 }
385 }
386 if (width > eye_width)
387 eye_width = width;
388 }
389
390 /* Calculate the max eye height */
391 int eye_height = 0;
392 for (int x = 0; x < eye->width; x++)
393 {
394 int height = 0;
395 for (int y = 0; y < eye->height; y++)
396 {
397 if (eye->data[y][x] == 0)
398 {
399 height++;
David Hendricks7d48ac52018-03-09 14:30:38 -0800400 }
401 }
402 if (height > eye_height)
403 eye_height = height;
404 }
405
406 printf("\nEye Diagram for Node %d, QLM %d, Lane %d\n", node, qlm, qlm_lane);
407
408 if (format == 0) /* Raw */
409 {
410 for (int y = 0; y < eye->height; y++)
411 {
412 for (int x = 0; x < eye->width; x++)
413 printf("%u\t", eye->data[y][x]);
414 printf("\n");
415 }
416 result = 0;
417 }
418 else
419 result = -1;
420
421 if (need_free)
422 free((void*)eye);
423 return result;
424}