1 /***********************license start***********************************
2 * Copyright (c) 2003-2017 Cavium Inc. ([email protected]). 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>
40 #include "libbdk-hal/bdk-qlm.h"
41 #include "libbdk-hal/qlm/bdk-qlm-common.h"
42 #include "libbdk-arch/bdk-csrs-bgx.h"
43 #include "libbdk-arch/bdk-csrs-gser.h"
44 #include "libbdk-arch/bdk-csrs-pem.h"
45 #include "libbdk-arch/bdk-csrs-sata.h"
46 #include "libbdk-arch/bdk-csrs-rst.h"
47 #include "libbdk-hal/bdk-config.h"
48 #include "libbdk-hal/qlm/bdk-qlm-errata-cn8xxx.h"
49 #include "libbdk-hal/bdk-gpio.h"
50
51 /**
52 * Return the number of QLMs supported for the chip
53 *
54 * @return Number of QLMs
55 */
bdk_qlm_get_num(bdk_node_t node)56 int bdk_qlm_get_num(bdk_node_t node)
57 {
58 return 4; /* 4 DLM */
59 }
60
61 /**
62 * Return the number of lanes in a QLM. QLMs normally contain
63 * 4 lanes, except for chips which only have half of a QLM.
64 *
65 * @param qlm QLM to get lanes number for
66 *
67 * @return Number of lanes on the QLM
68 */
bdk_qlm_get_lanes(bdk_node_t node,int qlm)69 int bdk_qlm_get_lanes(bdk_node_t node, int qlm)
70 {
71
72 if ((qlm < 2) && cavium_is_altpkg(CAVIUM_CN81XX))
73 return 1; /* DLM0 and DLM1 are a single lane on CN80XX */
74 else
75 return 2; /* DLMs */
76 }
77
78 /**
79 * Lookup the hardware QLM number for a given interface type and index. This
80 * function will fail with a fatal error if called on invalid interfaces for
81 * a chip. It returns the QLM number for an interface without checking to
82 * see if the QLM is in the correct mode.
83 *
84 * @param iftype Interface type
85 * @param interface Interface index number
86 *
87 * @return QLM number. Dies on a fatal error on failure.
88 */
bdk_qlm_get_qlm_num(bdk_node_t node,bdk_if_t iftype,int interface,int index)89 int bdk_qlm_get_qlm_num(bdk_node_t node, bdk_if_t iftype, int interface, int index)
90 {
91 switch (iftype)
92 {
93 case BDK_IF_BGX:
94 {
95 int qlm;
96 switch (interface)
97 {
98 case 0:
99 {
100 /* This BGX spans two DLMs. The index must be used to
101 figure out which DLM we are using */
102 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(0));
103 if (gserx_cfg.s.bgx)
104 {
105 if (gserx_cfg.s.bgx_quad) /* 4 lanes together */
106 qlm = 0;
107 else if (gserx_cfg.s.bgx_dual) /* 2 lanes together */
108 qlm = (index >= 1) ? 1 : 0;
109 else /* All lanes independent */
110 {
111 bdk_qlm_modes_t mode = bdk_qlm_get_mode(node, 0);
112 if (mode == BDK_QLM_MODE_QSGMII_4X1)
113 qlm = 0;
114 else if (mode <= BDK_QLM_MODE_PCIE_1X8)
115 qlm = 1;
116 else if (cavium_is_altpkg(CAVIUM_CN81XX))
117 {
118 bdk_qlm_modes_t mode1 = bdk_qlm_get_mode(node, 1);
119 if ((mode1 != BDK_QLM_MODE_QSGMII_4X1) && (index >= 2))
120 return -1;
121 qlm = (index >= 1) ? 1 : 0;
122 }
123 else
124 qlm = (index >= 2) ? 1 : 0;
125 }
126 }
127 else
128 qlm = 1;
129 break;
130 }
131 case 1:
132 {
133 /* This BGX spans two DLMs. The index must be used to
134 figure out which DLM we are using */
135 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(2));
136 if (gserx_cfg.s.bgx)
137 {
138 if (gserx_cfg.s.bgx_quad) /* 4 lanes together */
139 qlm = 2;
140 else if (gserx_cfg.s.bgx_dual) /* 2 lanes together */
141 qlm = (index >= 1) ? 3 : 2;
142 else /* All lanes independent */
143 {
144 bdk_qlm_modes_t mode = bdk_qlm_get_mode(node, 2);
145 if (mode == BDK_QLM_MODE_QSGMII_4X1)
146 qlm = 2;
147 else if (mode <= BDK_QLM_MODE_PCIE_1X8)
148 qlm = 1;
149 else
150 qlm = (index >= 2) ? 3 : 2;
151 }
152 }
153 else
154 qlm = 3;
155 break;
156 }
157 default:
158 return -1;
159 }
160 /* Make sure the QLM is powered up and out of reset */
161 BDK_CSR_INIT(phy_ctl, node, BDK_GSERX_PHY_CTL(qlm));
162 if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
163 return -1;
164 /* Make sure the QLM is in BGX mode */
165 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(qlm));
166 if (gserx_cfg.s.bgx)
167 return qlm;
168 else
169 return -1;
170 }
171 case BDK_IF_PCIE: /* PCIe */
172 {
173 switch (interface)
174 {
175 case 0: /* PEM0 */
176 {
177 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(0));
178 if (gserx_cfg.s.pcie)
179 return 0; /* PEM0 is on DLM0 */
180 else
181 return -1; /* PEM0 is disabled */
182 }
183 case 1: /* PEM1 */
184 {
185 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(2));
186 if (gserx_cfg.s.pcie)
187 return 2; /* PEM1 is on DLM2 */
188 else
189 return -1; /* PEM1 is disabled */
190 }
191 case 2: /* PEM2 */
192 {
193 BDK_CSR_INIT(pem1_cfg, node, BDK_PEMX_CFG(1));
194 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(3));
195 if (!pem1_cfg.cn81xx.lanes4 && gserx_cfg.s.pcie)
196 return 3; /* PEM2 is on DLM3 */
197 else
198 return -1; /* PEM2 is disabled */
199 }
200 default: /* Max of 3 PEMs, 0-2 */
201 return -1;
202 }
203 }
204 default: /* Not supported by CN81XX */
205 return -1;
206 }
207 }
208
209 /**
210 * Get the mode of a QLM as a human readable string
211 *
212 * @param qlm QLM to examine
213 *
214 * @return String mode
215 */
bdk_qlm_get_mode(bdk_node_t node,int qlm)216 bdk_qlm_modes_t bdk_qlm_get_mode(bdk_node_t node, int qlm)
217 {
218 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(qlm));
219 if (gserx_cfg.s.pcie)
220 {
221 switch (qlm)
222 {
223 case 0: /* PEM0 */
224 {
225 BDK_CSR_INIT(pemx_cfg, node, BDK_PEMX_CFG(0));
226 if (cavium_is_altpkg(CAVIUM_CN81XX))
227 return BDK_QLM_MODE_PCIE_1X1; /* PEM0 x1 */
228 else if (pemx_cfg.cn81xx.lanes4)
229 return BDK_QLM_MODE_PCIE_1X4; /* PEM0 x4 */
230 else
231 return BDK_QLM_MODE_PCIE_1X2; /* PEM0 x2 */
232 }
233 case 1: /* PEM0 second two lanes */
234 return BDK_QLM_MODE_PCIE_1X4; /* PEM0 x4 */
235 case 2: /* Either PEM1 x4 or PEM1 x2 */
236 {
237 BDK_CSR_INIT(pemx_cfg, node, BDK_PEMX_CFG(1));
238 if (pemx_cfg.cn81xx.lanes4)
239 return BDK_QLM_MODE_PCIE_1X4; /* PEM1 x4 */
240 else
241 return BDK_QLM_MODE_PCIE_1X2; /* PEM1 x2 */
242 }
243 case 3: /* Either PEM1 x4 or PEM2 x2 */
244 {
245 /* Can be last 2 lanes of PEM1 */
246 BDK_CSR_INIT(pem1_cfg, node, BDK_PEMX_CFG(1));
247 if (pem1_cfg.cn81xx.lanes4)
248 return BDK_QLM_MODE_PCIE_1X4; /* PEM1 x4 */
249 /* Can be 2 lanes of PEM2 */
250 return BDK_QLM_MODE_PCIE_1X2; /* PEM2 x2 */
251 }
252 default:
253 return BDK_QLM_MODE_DISABLED;
254 }
255 }
256 else if (gserx_cfg.s.bgx)
257 {
258 int bgx;
259 int bgx_index;
260 switch (qlm)
261 {
262 case 0:
263 {
264 bgx = 0;
265 bgx_index = 0;
266 break;
267 }
268 case 1:
269 bgx = 0;
270 bgx_index = 2;
271 break;
272 case 2:
273 {
274 bgx = 1;
275 bgx_index = 0;
276 break;
277 }
278 case 3:
279 bgx = 1;
280 bgx_index = 2;
281 break;
282 default:
283 return BDK_QLM_MODE_DISABLED;
284 }
285 BDK_CSR_INIT(cmrx_config, node, BDK_BGXX_CMRX_CONFIG(bgx, bgx_index));
286 bool is_kr = __bdk_qlm_is_lane_kr(node, qlm, 0);
287 switch (cmrx_config.s.lmac_type)
288 {
289 case BDK_BGX_LMAC_TYPES_E_SGMII:
290 if (cavium_is_altpkg(CAVIUM_CN81XX) && (qlm < 2))
291 return BDK_QLM_MODE_SGMII_1X1;
292 else
293 return BDK_QLM_MODE_SGMII_2X1;
294 case BDK_BGX_LMAC_TYPES_E_XAUI: return BDK_QLM_MODE_XAUI_1X4; /* Doesn't differntiate between XAUI and DXAUI */
295 case BDK_BGX_LMAC_TYPES_E_RXAUI: return BDK_QLM_MODE_RXAUI_1X2;
296 case BDK_BGX_LMAC_TYPES_E_TENG_R:
297 if (is_kr)
298 return (cavium_is_altpkg(CAVIUM_CN81XX) && (qlm < 2)) ? BDK_QLM_MODE_10G_KR_1X1 : BDK_QLM_MODE_10G_KR_2X1;
299 else
300 return (cavium_is_altpkg(CAVIUM_CN81XX) && (qlm < 2)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_XFI_2X1;
301 case BDK_BGX_LMAC_TYPES_E_FORTYG_R:
302 if (is_kr)
303 return BDK_QLM_MODE_40G_KR4_1X4;
304 else
305 return BDK_QLM_MODE_XLAUI_1X4;
306 case BDK_BGX_LMAC_TYPES_E_QSGMII: return BDK_QLM_MODE_QSGMII_4X1;
307 default: return BDK_QLM_MODE_DISABLED;
308 }
309 }
310 else if (gserx_cfg.s.sata)
311 return BDK_QLM_MODE_SATA_2X1;
312 else
313 return BDK_QLM_MODE_DISABLED;
314 }
315
qlm_set_sata(bdk_node_t node,int qlm,bdk_qlm_modes_t mode,int baud_mhz,bdk_qlm_mode_flags_t flags)316 static int qlm_set_sata(bdk_node_t node, int qlm, bdk_qlm_modes_t mode, int baud_mhz, bdk_qlm_mode_flags_t flags)
317 {
318 /* SATA has a fixed mapping for ports on CN81XX */
319 int sata_port;
320 switch (qlm)
321 {
322 case 3: /* SATA 0-1 = DLM3 lanes 0-1 */
323 sata_port = 0;
324 break;
325 default:
326 bdk_error("Attempted to configure SATA on QLM that doesn't support it\n");
327 return -1;
328 }
329 return __bdk_qlm_set_sata_cn8xxx(node, qlm, baud_mhz, sata_port, sata_port + 1);
330 }
331
332 /**
333 * For chips that don't use pin strapping, this function programs
334 * the QLM to the specified mode
335 *
336 * @param node Node to use in a Numa setup
337 * @param qlm QLM to configure
338 * @param mode Desired mode
339 * @param baud_mhz Desired speed
340 * @param flags Flags to specify mode specific options
341 *
342 * @return Zero on success, negative on failure
343 */
bdk_qlm_set_mode(bdk_node_t node,int qlm,bdk_qlm_modes_t mode,int baud_mhz,bdk_qlm_mode_flags_t flags)344 int bdk_qlm_set_mode(bdk_node_t node, int qlm, bdk_qlm_modes_t mode, int baud_mhz, bdk_qlm_mode_flags_t flags)
345 {
346 int lane_mode = 0xf;
347 int lmac_type = -1;
348 int is_pcie = 0;
349 int is_sata = 0;
350 int is_ilk = 0;
351 int is_bgx = 0;
352 int bgx_block;
353 int bgx_index;
354
355 switch (qlm)
356 {
357 case 0:
358 bgx_block = 0;
359 bgx_index = 0;
360 break;
361 case 1:
362 bgx_block = 0;
363 bgx_index = 2;
364 break;
365 case 2:
366 bgx_block = 1;
367 bgx_index = 0;
368 break;
369 case 3:
370 bgx_block = 1;
371 bgx_index = 2;
372 break;
373 default:
374 bgx_block = -1;
375 bgx_index = -1;
376 break;
377 }
378
379 int measured_ref = bdk_qlm_measure_clock(node, qlm);
380 int ref_clk = (mode == BDK_QLM_MODE_DISABLED) ? 0 : __bdk_qlm_round_refclock(node, qlm, measured_ref);
381 int kr_mode = 0;
382
383 switch (mode)
384 {
385 case BDK_QLM_MODE_PCIE_1X1:
386 case BDK_QLM_MODE_PCIE_1X2:
387 case BDK_QLM_MODE_PCIE_1X4:
388 {
389 /* Note: PCIe ignores baud_mhz. Use the GEN 1/2/3 flags
390 to control speed */
391 is_pcie = 1;
392 if (ref_clk == REF_100MHZ)
393 {
394 BDK_CSR_MODIFY(c, node, BDK_GSERX_REFCLK_SEL(qlm),
395 c.s.pcie_refclk125 = 0);
396 if (baud_mhz == 2500)
397 lane_mode = BDK_GSER_LMODE_E_R_25G_REFCLK100;
398 else if (baud_mhz == 5000)
399 lane_mode = BDK_GSER_LMODE_E_R_5G_REFCLK100;
400 else
401 lane_mode = BDK_GSER_LMODE_E_R_8G_REFCLK100;
402 }
403 else if (ref_clk == REF_125MHZ)
404 {
405 BDK_CSR_MODIFY(c, node, BDK_GSERX_REFCLK_SEL(qlm),
406 c.s.pcie_refclk125 = 1);
407 if (baud_mhz == 2500)
408 lane_mode = BDK_GSER_LMODE_E_R_25G_REFCLK125;
409 else if (baud_mhz == 5000)
410 lane_mode = BDK_GSER_LMODE_E_R_5G_REFCLK125;
411 else
412 lane_mode = BDK_GSER_LMODE_E_R_8G_REFCLK125;
413 }
414 else
415 {
416 bdk_error("Invalid reference clock for PCIe on QLM%d\n", qlm);
417 return -1;
418 }
419 int cfg_md;
420 if (baud_mhz == 2500)
421 cfg_md = 0; /* Gen1 Speed */
422 else if (baud_mhz == 5000)
423 cfg_md = 1; /* Gen2 Speed */
424 else
425 cfg_md = 2; /* Gen3 Speed */
426 switch (qlm)
427 {
428 case 0: /* Either PEM0 x4 or PEM0 x2 or PEM0 x1 */
429 BDK_CSR_MODIFY(c, node, BDK_RST_SOFT_PRSTX(0),
430 c.s.soft_prst = !(flags & BDK_QLM_MODE_FLAG_ENDPOINT));
431 __bdk_qlm_setup_pem_reset(node, 0, flags & BDK_QLM_MODE_FLAG_ENDPOINT);
432 BDK_CSR_MODIFY(c, node, BDK_PEMX_CFG(0),
433 c.cn81xx.lanes4 = (mode == BDK_QLM_MODE_PCIE_1X4);
434 //c.cn81xx.hostmd = !(flags & BDK_QLM_MODE_FLAG_ENDPOINT);
435 c.cn81xx.md = cfg_md);
436 break;
437 case 1: /* Second two lanes for PEM0 x4 */
438 /* PEMX_CFG already setup */
439 break;
440 case 2: /* Either PEM1 x4 or PEM1 x2 */
441 BDK_CSR_MODIFY(c, node, BDK_RST_SOFT_PRSTX(1),
442 c.s.soft_prst = !(flags & BDK_QLM_MODE_FLAG_ENDPOINT));
443 __bdk_qlm_setup_pem_reset(node, 1, flags & BDK_QLM_MODE_FLAG_ENDPOINT);
444 BDK_CSR_MODIFY(c, node, BDK_PEMX_CFG(1),
445 c.cn81xx.lanes4 = (mode == BDK_QLM_MODE_PCIE_1X4);
446 //c.cn81xx.hostmd = !(flags & BDK_QLM_MODE_FLAG_ENDPOINT);
447 c.cn81xx.md = cfg_md);
448 break;
449 case 3: /* Either PEM1 x4 or PEM2 x2 */
450 if (mode == BDK_QLM_MODE_PCIE_1X4)
451 {
452 /* Last 2 lanes of PEM1 */
453 /* PEMX_CFG already setup */
454 }
455 else
456 {
457 /* Two lanes for PEM2 */
458 BDK_CSR_MODIFY(c, node, BDK_RST_SOFT_PRSTX(2),
459 c.s.soft_prst = !(flags & BDK_QLM_MODE_FLAG_ENDPOINT));
460 __bdk_qlm_setup_pem_reset(node, 2, flags & BDK_QLM_MODE_FLAG_ENDPOINT);
461 BDK_CSR_MODIFY(c, node, BDK_PEMX_CFG(2),
462 c.cn81xx.lanes4 = 0;
463 //c.cn81xx.hostmd = !(flags & BDK_QLM_MODE_FLAG_ENDPOINT);
464 c.cn81xx.md = cfg_md);
465 }
466 break;
467 default:
468 return -1;
469 }
470 break;
471 }
472 case BDK_QLM_MODE_SGMII_4X1:
473 case BDK_QLM_MODE_SGMII_2X1:
474 case BDK_QLM_MODE_SGMII_1X1:
475 /* Disable port BGX ports 2-3 on CN80XX */
476 if ((qlm < 2) && cavium_is_altpkg(CAVIUM_CN81XX))
477 {
478 BDK_CSR_WRITE(node, BDK_BGXX_CMRX_RX_DMAC_CTL(0, 2), 0);
479 BDK_CSR_WRITE(node, BDK_BGXX_CMRX_RX_DMAC_CTL(0, 3), 0);
480 }
481 lmac_type = BDK_BGX_LMAC_TYPES_E_SGMII; /* SGMII */
482 is_bgx = 1;
483 lane_mode = __bdk_qlm_get_lane_mode_for_speed_and_ref_clk("SGMII", qlm, ref_clk, baud_mhz);
484 if (lane_mode == -1)
485 return -1;
486 break;
487 case BDK_QLM_MODE_XAUI_1X4:
488 lmac_type = BDK_BGX_LMAC_TYPES_E_XAUI; /* XAUI */
489 is_bgx = 5;
490 lane_mode = __bdk_qlm_get_lane_mode_for_speed_and_ref_clk("XAUI", qlm, ref_clk, baud_mhz);
491 if (lane_mode == -1)
492 return -1;
493 break;
494 case BDK_QLM_MODE_RXAUI_2X2:
495 case BDK_QLM_MODE_RXAUI_1X2:
496 lmac_type = BDK_BGX_LMAC_TYPES_E_RXAUI; /* RXAUI */
497 is_bgx = 3;
498 lane_mode = __bdk_qlm_get_lane_mode_for_speed_and_ref_clk("RXAUI", qlm, ref_clk, baud_mhz);
499 if (lane_mode == -1)
500 return -1;
501 break;
502 case BDK_QLM_MODE_XFI_4X1:
503 case BDK_QLM_MODE_XFI_2X1:
504 case BDK_QLM_MODE_XFI_1X1:
505 /* Disable port BGX ports 2-3 on CN80XX */
506 if ((qlm < 2) && cavium_is_altpkg(CAVIUM_CN81XX))
507 {
508 BDK_CSR_WRITE(node, BDK_BGXX_CMRX_RX_DMAC_CTL(0, 2), 0);
509 BDK_CSR_WRITE(node, BDK_BGXX_CMRX_RX_DMAC_CTL(0, 3), 0);
510 }
511 lmac_type = BDK_BGX_LMAC_TYPES_E_TENG_R; /* 10G_R */
512 is_bgx = 1;
513 lane_mode = __bdk_qlm_get_lane_mode_for_speed_and_ref_clk("XFI", qlm, ref_clk, baud_mhz);
514 if (lane_mode == -1)
515 return -1;
516 break;
517 case BDK_QLM_MODE_XLAUI_1X4:
518 lmac_type = BDK_BGX_LMAC_TYPES_E_FORTYG_R; /* 40G_R */
519 is_bgx = 5;
520 lane_mode = __bdk_qlm_get_lane_mode_for_speed_and_ref_clk("XLAUI", qlm, ref_clk, baud_mhz);
521 if (lane_mode == -1)
522 return -1;
523 break;
524 case BDK_QLM_MODE_10G_KR_4X1:
525 case BDK_QLM_MODE_10G_KR_2X1:
526 case BDK_QLM_MODE_10G_KR_1X1:
527 /* Disable port BGX ports 2-3 on CN80XX */
528 if ((qlm < 2) && cavium_is_altpkg(CAVIUM_CN81XX))
529 {
530 BDK_CSR_WRITE(node, BDK_BGXX_CMRX_RX_DMAC_CTL(0, 2), 0);
531 BDK_CSR_WRITE(node, BDK_BGXX_CMRX_RX_DMAC_CTL(0, 3), 0);
532 }
533 lmac_type = BDK_BGX_LMAC_TYPES_E_TENG_R; /* 10G_R */
534 is_bgx = 1;
535 lane_mode = __bdk_qlm_get_lane_mode_for_speed_and_ref_clk("10G-KR", qlm, ref_clk, baud_mhz);
536 if (lane_mode == -1)
537 return -1;
538 kr_mode = 1;
539 break;
540 case BDK_QLM_MODE_40G_KR4_1X4:
541 lmac_type = BDK_BGX_LMAC_TYPES_E_FORTYG_R; /* 40G_R */
542 is_bgx = 5;
543 lane_mode = __bdk_qlm_get_lane_mode_for_speed_and_ref_clk("40G-KR", qlm, ref_clk, baud_mhz);
544 if (lane_mode == -1)
545 return -1;
546 kr_mode = 1;
547 break;
548 case BDK_QLM_MODE_QSGMII_4X1:
549 lmac_type = BDK_BGX_LMAC_TYPES_E_QSGMII; /* QSGMII */
550 is_bgx = 1;
551 lane_mode = BDK_GSER_LMODE_E_R_5G_REFCLK15625_QSGMII;
552 break;
553 case BDK_QLM_MODE_SATA_2X1:
554 BDK_CSR_MODIFY(c, node, BDK_GSERX_LANE_MODE(qlm), c.s.lmode = BDK_GSER_LMODE_E_R_8G_REFCLK100);
555 /* SATA initialization is different than BGX. Call its init function
556 and skip the rest of this routine */
557 return qlm_set_sata(node, qlm, mode, baud_mhz, flags);
558 case BDK_QLM_MODE_DISABLED:
559 /* Set gser for the interface mode */
560 BDK_CSR_MODIFY(c, node, BDK_GSERX_CFG(qlm),
561 c.u = 0);
562 /* Put the PHY in reset */
563 BDK_CSR_MODIFY(c, node, BDK_GSERX_PHY_CTL(qlm),
564 c.s.phy_reset = 1);
565 return 0;
566 default:
567 bdk_error("Unsupported QLM mode %d\n", mode);
568 return -1;
569 }
570
571 BDK_TRACE(QLM, "N%u.QLM%u: Power up...\n", node, qlm);
572
573 /* Power up phy, but keep it in reset */
574 BDK_CSR_MODIFY(c, node, BDK_GSERX_PHY_CTL(qlm),
575 c.s.phy_pd = 0;
576 c.s.phy_reset = 1);
577
578 /* Set gser for the interface mode */
579 BDK_CSR_MODIFY(c, node, BDK_GSERX_CFG(qlm),
580 c.s.sata = is_sata;
581 c.s.ila = is_ilk;
582 c.s.bgx = is_bgx & 1;
583 c.s.bgx_quad = (is_bgx >> 2) & 1;
584 c.s.bgx_dual = (is_bgx >> 1) & 1;
585 c.s.pcie = is_pcie);
586
587 /* Lane mode */
588 BDK_CSR_MODIFY(c, node, BDK_GSERX_LANE_MODE(qlm),
589 c.s.lmode = lane_mode);
590
591 /* LMAC type. We only program one port as the full setup is done in BGX */
592 if (lmac_type != -1)
593 {
594 BDK_CSR_MODIFY(c, node, BDK_BGXX_CMRX_CONFIG(bgx_block, bgx_index),
595 c.s.enable = 0;
596 c.s.lmac_type = lmac_type);
597 }
598
599 BDK_TRACE(QLM, "N%u.QLM%u: Deassert reset...\n", node, qlm);
600
601 /* Bring phy out of reset */
602 BDK_CSR_MODIFY(c, node, BDK_GSERX_PHY_CTL(qlm),
603 c.s.phy_reset = 0);
604
605 /* Wait 1us until the management interface is ready to accept
606 read/write commands.*/
607 bdk_wait_usec(1);
608
609 /* Configure the gser pll */
610 __bdk_qlm_init_mode_table(node, qlm, ref_clk);
611
612 /* Remember which lanes are using KR over BGX */
613 if (is_bgx)
614 {
615 int num_lanes = bdk_qlm_get_lanes(node, qlm);
616 for (int lane = 0; lane < num_lanes; lane++)
617 __bdk_qlm_set_lane_kr(node, qlm, lane, kr_mode);
618 }
619
620 /* Wait for reset to complete and the PLL to lock */
621 if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_GSERX_PLL_STAT(qlm), pll_lock, ==, 1, 10000))
622 {
623 bdk_error("QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\n", qlm);
624 return -1;
625 }
626
627 /* PCIe mode doesn't become ready until the PEM block attempts to bring
628 the interface up. Skip this check for PCIe */
629 if (!is_pcie && BDK_CSR_WAIT_FOR_FIELD(node, BDK_GSERX_QLM_STAT(qlm), rst_rdy, ==, 1, 10000))
630 {
631 bdk_error("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
632 return -1;
633 }
634
635 /* cdrlock will be checked in the BGX */
636
637 /* Errata (GSER-27140) SERDES temperature drift sensitivity in receiver */
638 int channel_loss = bdk_config_get_int(BDK_CONFIG_QLM_CHANNEL_LOSS, node, qlm);
639 __bdk_qlm_errata_gser_27140(node, qlm, baud_mhz, channel_loss);
640
641 /* Apply any custom tuning */
642 __bdk_qlm_tune(node, qlm, mode, baud_mhz);
643
644 /* Some modes require 4 lanes, which spans DLMs. For these modes, we need
645 to setup the second DLM at the same time we setup the first. The second
646 DLM also must use the same reference clock as the first */
647 bool paired_dlm = ((qlm & 1) == 0) && /* We're on the first (even) DLM */
648 ((mode == BDK_QLM_MODE_PCIE_1X4) || /* We're using a 4 lane mode */
649 (mode == BDK_QLM_MODE_XAUI_1X4) ||
650 (mode == BDK_QLM_MODE_XLAUI_1X4) ||
651 (mode == BDK_QLM_MODE_40G_KR4_1X4));
652 if (paired_dlm)
653 {
654 /* Use the same reference clock for the second QLM */
655 BDK_CSR_WRITE(node, BDK_GSERX_REFCLK_SEL(qlm + 1),
656 BDK_CSR_READ(node, BDK_GSERX_REFCLK_SEL(qlm)));
657 return bdk_qlm_set_mode(node, qlm + 1, mode, baud_mhz, flags);
658 }
659
660 return 0;
661 }
662
663 /**
664 * Get the speed (Gbaud) of the QLM in Mhz.
665 *
666 * @param qlm QLM to examine
667 *
668 * @return Speed in Mhz
669 */
bdk_qlm_get_gbaud_mhz(bdk_node_t node,int qlm)670 int bdk_qlm_get_gbaud_mhz(bdk_node_t node, int qlm)
671 {
672 BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(qlm));
673 if (gserx_cfg.u == 0)
674 return 0;
675 if (gserx_cfg.s.pcie)
676 {
677 /* QLMs in PCIe mode ignore LMODE and get their speed from
678 the PEM block that controls them */
679 int pem;
680 switch (qlm)
681 {
682 case 0: /* PEM0 */
683 case 1: /* PEM0 */
684 pem = 0;
685 break;
686 case 2: /* PEM1 */
687 pem = 1;
688 break;
689 case 3: /* PEM1 or PEM2 */
690 {
691 BDK_CSR_INIT(pemx_cfg, node, BDK_PEMX_CFG(1));
692 if (pemx_cfg.cn81xx.lanes4)
693 pem = 1;
694 else
695 pem = 2;
696 break;
697 }
698 default:
699 bdk_fatal("QLM%d: In PCIe mode, which shouldn't happen\n", qlm);
700 }
701 return __bdk_qlm_get_gbaud_mhz_pem(node, pem);
702 }
703 else if (gserx_cfg.s.sata)
704 {
705 int sata;
706 switch (qlm)
707 {
708 case 3:
709 sata = 0;
710 break;
711 default:
712 return 0;
713 }
714 BDK_CSR_INIT(sata_uctl_ctl, node, BDK_SATAX_UCTL_CTL(sata));
715 if (!sata_uctl_ctl.s.a_clk_en)
716 return 0;
717 BDK_CSR_INIT(sctl, node, BDK_SATAX_UAHC_P0_SCTL(sata));
718 switch (sctl.s.spd)
719 {
720 case 1: return 1500;
721 case 2: return 3000;
722 case 3: return 6000;
723 default: return 6000; /* No limit, assume 6G */
724 }
725 }
726 else
727 return __bdk_qlm_get_gbaud_mhz_lmode(node, qlm);
728 }
729
730 /**
731 * Initialize the QLM layer
732 */
bdk_qlm_init(bdk_node_t node)733 void bdk_qlm_init(bdk_node_t node)
734 {
735 /* Setup how each PEM drives the PERST lines */
736 for (int pem = 0; pem < 3; pem++)
737 {
738 BDK_CSR_INIT(rst_ctlx, node, BDK_RST_CTLX(pem));
739 __bdk_qlm_setup_pem_reset(node, pem, !rst_ctlx.s.host_mode);
740 }
741 }
742
__bdk_qlm_sff81xx_set_reference(bdk_node_t node,int qlm,int ref_clk)743 static void __bdk_qlm_sff81xx_set_reference(bdk_node_t node, int qlm, int ref_clk)
744 {
745 int use_clock;
746
747 if (CAVIUM_IS_MODEL(CAVIUM_CN88XX) || CAVIUM_IS_MODEL(CAVIUM_CN83XX) || CAVIUM_IS_MODEL(CAVIUM_CN81XX))
748 {
749 // Common clock 0 is 156MHz
750 // Common clock 1 is 100MHz
751 switch (qlm)
752 {
753 case 0:
754 use_clock = 1; /* DLMC_REF_CLK1 of 100MHz */
755 break;
756 case 1:
757 if (ref_clk == REF_100MHZ)
758 use_clock = 1; /* DLMC_REF_CLK1 of 100MHz */
759 else
760 use_clock = 2; /* DLM1_REF_CLK of 156MHz */
761 break;
762 case 2:
763 case 3:
764 default:
765 if (ref_clk == REF_100MHZ)
766 use_clock = 1; /* DLMC_REF_CLK1 of 100MHz */
767 else
768 use_clock = 2; /* DLM1_REF_CLK of 156MHz */
769 break;
770 }
771
772 BDK_TRACE(QLM, "Setting N%d.QLM%d to use ref clock %d\n", node, qlm, use_clock);
773 }
774 else
775 {
776 bdk_error("Update %s for qlm auto config of this chip\n",__func__);
777 return;
778 }
779 BDK_CSR_MODIFY(c, node, BDK_GSERX_REFCLK_SEL(qlm),
780 c.s.com_clk_sel = (use_clock != 2);
781 c.s.use_com1 = (use_clock == 1));
782 }
783
bdk_qlm_auto_config(bdk_node_t node)784 int bdk_qlm_auto_config(bdk_node_t node)
785 {
786 return -1;
787 }
788
789 /**
790 * For Cavium SFF board, query the DIP switches in GPIO o determine the QLM setup.
791 * Configure the GPIOs to read the DLM settings
792 * SW1.1 -> DLM0_SEL -> GPIO_26
793 * SW1.2 -> DLM1_SEL -> GPIO_25
794 * SW1.3 -> DLM2_SEL -> GPIO_31
795 * SW1.4 -> DLM3_SEL -> GPIO_4
796 *V1.x boards SW3.8 -> QSGMII/XFI SEL ->GPIO_9
797 *V2.x boards SW3.7 -> QSGMII/XFI SEL ->GPIO_36
798 */
bdk_qlm_dip_auto_config(bdk_node_t node)799 int bdk_qlm_dip_auto_config(bdk_node_t node)
800 {
801 bdk_qlm_modes_t dlm_mode[4];
802 int dlm_speed = 0;
803 int use_ref = 0;
804 bdk_qlm_mode_flags_t dlm_flags = 0;
805
806 unsigned int dlm_config, dlm3, dlm2, dlm1, dlm0;
807 uint64_t gpio = 0;
808
809 /* Configure the GPIOs to read the DLM settings */
810 /* SW1.1 -> DLM0_SEL -> GPIO_26 */
811 /* SW1.2 -> DLM1_SEL -> GPIO_25 */
812 /* SW1.3 -> DLM2_SEL -> GPIO_31 */
813 /* SW1.4 -> DLM3_SEL -> GPIO_4 */
814 //V1.x boards /* SW3.8 -> QSGMII/XFI SEL ->GPIO_9 */
815 //V2.x boards /* SW3.7 -> QSGMII/XFI SEL ->GPIO_36 */
816 /* Configure the GPIOs are input */
817 bdk_gpio_initialize(node, 26, 0, 0);
818 bdk_gpio_initialize(node, 25, 0, 0);
819 bdk_gpio_initialize(node, 31, 0, 0);
820 bdk_gpio_initialize(node, 4, 0, 0);
821 bdk_gpio_initialize(node, 36, 0, 0);
822
823
824 /* Read the GPIOs */
825 gpio = bdk_gpio_read(node, 0);
826
827 dlm3 = !!(gpio & (1ULL<<4));
828 dlm2 = !!(gpio & (1ULL<<31));
829 dlm1 = !!(gpio & (1ULL<<25));
830 dlm0 = !!(gpio & (1ULL<<26));
831
832
833 dlm_config = (dlm0<<3)| (dlm1<<2) | (dlm2<<1) | (dlm3);
834
835 BDK_TRACE(QLM, "DLM CONFIG:%d gpio36: %d\n", dlm_config, !!(gpio & (1ULL<<36)));
836
837 switch(dlm_config)
838 {
839 case 0:
840 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
841 dlm_mode[1] = BDK_QLM_MODE_DISABLED;
842 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
843 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
844 break;
845 case 1:
846 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
847 dlm_mode[1] = BDK_QLM_MODE_DISABLED;
848 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
849 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
850 break;
851 case 2:
852 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
853 dlm_mode[1] = BDK_QLM_MODE_DISABLED;
854 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
855 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
856 break;
857 case 3:
858 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
859 dlm_mode[1] = BDK_QLM_MODE_DISABLED;
860 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
861 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
862 break;
863 case 4:
864 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
865 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
866 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
867 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
868 break;
869 case 5:
870 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
871 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
872 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
873 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
874 break;
875 case 6:
876 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
877 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
878 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
879 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
880 break;
881 case 7:
882 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
883 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
884 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
885 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
886 break;
887 case 8:
888 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X4;
889 dlm_mode[1] = BDK_QLM_MODE_PCIE_1X4;
890 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
891 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
892 break;
893 case 9:
894 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X4;
895 dlm_mode[1] = BDK_QLM_MODE_PCIE_1X4;
896 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
897 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
898 break;
899 case 10:
900 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X4;
901 dlm_mode[1] = BDK_QLM_MODE_PCIE_1X4;
902 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
903 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
904 break;
905 case 11:
906 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X4;
907 dlm_mode[1] = BDK_QLM_MODE_PCIE_1X4;
908 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
909 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
910 break;
911 case 12:
912 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
913 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
914 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
915 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
916 break;
917 case 13:
918 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
919 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
920 dlm_mode[2] = BDK_QLM_MODE_PCIE_1X2;
921 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
922 break;
923 case 14:
924 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
925 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
926 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
927 dlm_mode[3] = BDK_QLM_MODE_PCIE_1X2;
928 break;
929 case 15:
930 dlm_mode[0] = BDK_QLM_MODE_PCIE_1X2;
931 dlm_mode[1] = (!!(gpio & (1ULL<<36)) ? BDK_QLM_MODE_XFI_1X1 : BDK_QLM_MODE_QSGMII_4X1);
932 dlm_mode[2] = BDK_QLM_MODE_XFI_2X1;
933 dlm_mode[3] = BDK_QLM_MODE_SATA_2X1;
934 break;
935 default:
936 return -1;
937 }
938
939 for(int dlm = 0; dlm < 4; dlm++)
940 {
941 const char *dlm_mode_str = bdk_qlm_mode_tostring(dlm_mode[dlm]);
942 switch(dlm_mode[dlm])
943 {
944 case BDK_QLM_MODE_DISABLED:
945 break;
946 case BDK_QLM_MODE_XFI_2X1:
947 case BDK_QLM_MODE_XFI_1X1:
948 use_ref = REF_156MHZ;
949 dlm_speed = 10312;
950 break;
951 case BDK_QLM_MODE_SATA_2X1:
952 dlm_speed = 6000;
953 use_ref = REF_100MHZ;
954 break;
955 case BDK_QLM_MODE_PCIE_1X2:
956 case BDK_QLM_MODE_PCIE_1X4:
957 dlm_speed = 8000;
958 use_ref =REF_100MHZ;
959 break;
960 case BDK_QLM_MODE_QSGMII_4X1:
961 use_ref = REF_100MHZ;
962 dlm_speed = 5000;
963 break;
964 default:
965 bdk_error("Unsupported N%d.QLM%d mode: %s(%d)",
966 node, dlm,
967 dlm_mode_str ? dlm_mode_str : "???",
968 dlm_mode[dlm]);
969 return -1;
970 }
971 if ((1 == dlm) && (dlm_mode[dlm] != BDK_QLM_MODE_QSGMII_4X1) && (dlm_mode[dlm] != BDK_QLM_MODE_DISABLED))
972 {
973 /* This code is specific to sff8104 board
974 ** QSGMII phy is wired to dlm1-gser lane 2
975 ** AQR-107 phy is wired to dlm1-gser lane 3
976 ** bdk always uses bgx0.port0 on that board
977 */
978 // If dlm1 is in XFI mode, change PHY address to mdio of aquantia phy
979 unsigned mdio_bus = 1;
980 unsigned mdio_addr = 0;
981 int phy_cfg = 0xff<<24 | ((mdio_bus& 0xf)<<8) | (mdio_addr & 0xff);
982 bdk_config_set_int((uint32_t) phy_cfg,BDK_CONFIG_PHY_ADDRESS, node, 0, 0);
983 /* Indicate serdes lane 3 , aquantia phy active */
984 int aq_phy = (0x3<<8) | 1;
985 bdk_config_set_int(aq_phy, BDK_CONFIG_AQUANTIA_PHY,node,0,0);
986 BDK_TRACE(QLM,"Disabling phys 0.1,0.2,0.3\n");
987 for (int i = 1; i<4; i++) {
988 bdk_config_set_int(-1,BDK_CONFIG_PHY_ADDRESS, node, 0, i);
989 bdk_config_set_int(0,BDK_CONFIG_BGX_ENABLE,node,0,i);
990 }
991 }
992
993 BDK_TRACE(QLM, "Setting N%d.QLM%d mode %s(%d), speed %d, flags 0x%x\n",
994 node, dlm, dlm_mode_str, dlm_mode[dlm], dlm_speed, dlm_flags);
995
996 /* Set the reference clock for this QLM */
997 __bdk_qlm_sff81xx_set_reference(node, dlm, use_ref);
998
999 if (bdk_qlm_set_mode(node, dlm, dlm_mode[dlm], dlm_speed, dlm_flags))
1000 return -1;
1001 }
1002 return 0;
1003 }
1004