xref: /aosp_15_r20/external/coreboot/src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-cn81xx.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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