1 #ifndef __CB_BDK_QLM_H__ 2 #define __CB_BDK_QLM_H__ 3 /***********************license start*********************************** 4 * Copyright (c) 2003-2017 Cavium Inc. ([email protected]). All rights 5 * reserved. 6 * 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * * Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided 18 * with the distribution. 19 * 20 * * Neither the name of Cavium Inc. nor the names of 21 * its contributors may be used to endorse or promote products 22 * derived from this software without specific prior written 23 * permission. 24 * 25 * This Software, including technical data, may be subject to U.S. export 26 * control laws, including the U.S. Export Administration Act and its 27 * associated regulations, and may be subject to export or import 28 * regulations in other countries. 29 * 30 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 31 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 32 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT 33 * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 34 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 35 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 36 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 37 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, 38 * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK 39 * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 40 ***********************license end**************************************/ 41 42 /** 43 * @file 44 * 45 * Function and structure definitions for QLM manipulation 46 * 47 * <hr>$Revision: 49448 $<hr> 48 * 49 * @addtogroup hal 50 * @{ 51 */ 52 #include <bdk.h> 53 #include <libbdk-hal/if/bdk-if.h> 54 55 typedef enum 56 { 57 BDK_QLM_MODE_DISABLED, /* QLM is disabled (all chips) */ 58 BDK_QLM_MODE_PCIE_1X1, /* 1 PCIe, 1 lane. Other lanes unused */ 59 BDK_QLM_MODE_PCIE_2X1, /* 2 PCIe, 1 lane each */ 60 BDK_QLM_MODE_PCIE_1X2, /* 1 PCIe, 2 lanes */ 61 BDK_QLM_MODE_PCIE_1X4, /* 1 PCIe, 4 lanes */ 62 BDK_QLM_MODE_PCIE_1X8, /* 1 PCIe, 8 lanes */ 63 BDK_QLM_MODE_PCIE_1X16, /* 1 PCIe, 16 lanes (CN93XX) */ 64 65 BDK_QLM_MODE_SATA_4X1, /* SATA, each lane independent (cn88xx) */ 66 BDK_QLM_MODE_SATA_2X1, /* SATA, each lane independent (cn83xx) */ 67 68 BDK_QLM_MODE_ILK, /* ILK 4 lanes (cn78xx) */ 69 BDK_QLM_MODE_SGMII_4X1, /* SGMII, each lane independent (cn88xx) */ 70 BDK_QLM_MODE_SGMII_2X1, /* SGMII, each lane independent (cn83xx) */ 71 BDK_QLM_MODE_SGMII_1X1, /* SGMII, single lane (cn80xx) */ 72 BDK_QLM_MODE_XAUI_1X4, /* 1 XAUI or DXAUI, 4 lanes (cn88xx), use gbaud to tell difference */ 73 BDK_QLM_MODE_RXAUI_2X2, /* 2 RXAUI, 2 lanes each (cn88xx) */ 74 BDK_QLM_MODE_RXAUI_1X2, /* 1 RXAUI, 2 lanes each (cn83xx) */ 75 BDK_QLM_MODE_OCI, /* OCI Multichip interconnect (cn88xx) */ 76 BDK_QLM_MODE_XFI_4X1, /* 4 XFI, 1 lane each (cn88xx) */ 77 BDK_QLM_MODE_XFI_2X1, /* 2 XFI, 1 lane each (cn83xx) */ 78 BDK_QLM_MODE_XFI_1X1, /* 1 XFI, single lane (cn80xx) */ 79 BDK_QLM_MODE_XLAUI_1X4, /* 1 XLAUI, 4 lanes each (cn88xx) */ 80 BDK_QLM_MODE_10G_KR_4X1, /* 4 10GBASE-KR, 1 lane each (cn88xx) */ 81 BDK_QLM_MODE_10G_KR_2X1, /* 2 10GBASE-KR, 1 lane each (cn83xx) */ 82 BDK_QLM_MODE_10G_KR_1X1, /* 1 10GBASE-KR, single lane (cn80xx) */ 83 BDK_QLM_MODE_40G_KR4_1X4, /* 1 40GBASE-KR4, 4 lanes each (cn88xx) */ 84 BDK_QLM_MODE_QSGMII_4X1, /* QSGMII is 4 SGMII on one lane (cn81xx, cn83xx) */ 85 BDK_QLM_MODE_25G_4X1, /* 25G, 1 lane each (CN93XX QLMs) */ 86 BDK_QLM_MODE_25G_2X1, /* 25G, 1 lane each (CN93XX DLMs) */ 87 BDK_QLM_MODE_50G_2X2, /* 50G, 2 lanes each (CN93XX QLMs) */ 88 BDK_QLM_MODE_50G_1X2, /* 50G, 2 lanes each (CN93XX DLMs) */ 89 BDK_QLM_MODE_100G_1X4, /* 100G, 4 lanes each (CN93XX) */ 90 BDK_QLM_MODE_25G_KR_4X1, /* 25G-KR, 1 lane each (CN93XX QLMs) */ 91 BDK_QLM_MODE_25G_KR_2X1, /* 25G-KR, 1 lane each (CN93XX DLMs) */ 92 BDK_QLM_MODE_50G_KR_2X2, /* 50G-KR, 2 lanes each (CN93XX QLMs) */ 93 BDK_QLM_MODE_50G_KR_1X2, /* 50G-KR, 2 lanes each (CN93XX DLMs) */ 94 BDK_QLM_MODE_100G_KR4_1X4, /* 100G-KR4, 4 lanes each (CN93XX) */ 95 BDK_QLM_MODE_USXGMII_4X1, /* USXGMII, 1 lane each, 10M, 100M, 1G, 2.5G, 5G, 10G, 20G (CN93XX QLMs) */ 96 BDK_QLM_MODE_USXGMII_2X1, /* USXGMII, 1 lane each, 10M, 100M, 1G, 2.5G, 5G, 10G, 20G (CN93XX QLMs) */ 97 BDK_QLM_MODE_LAST, 98 } bdk_qlm_modes_t; 99 100 typedef enum 101 { 102 BDK_QLM_CLK_COMMON_0, 103 BDK_QLM_CLK_COMMON_1, 104 BDK_QLM_CLK_EXTERNAL, 105 BDK_QLM_CLK_COMMON_2, /* Must be after EXTERNAL as device trees have hard coded values */ 106 BDK_QLM_CLK_LAST, 107 } bdk_qlm_clock_t; 108 109 typedef enum 110 { 111 BDK_QLM_MODE_FLAG_ENDPOINT = 1, /* PCIe in EP instead of RC */ 112 } bdk_qlm_mode_flags_t; 113 114 typedef enum 115 { 116 BDK_QLM_LOOP_DISABLED, /* No shallow loopback */ 117 } bdk_qlm_loop_t; 118 119 typedef enum 120 { 121 BDK_QLM_DIRECTION_TX = 1, 122 BDK_QLM_DIRECTION_RX = 2, 123 BDK_QLM_DIRECTION_BOTH = 3, 124 } bdk_qlm_direction_t; 125 126 /** 127 * Types of QLM margining supported 128 */ 129 typedef enum 130 { 131 BDK_QLM_MARGIN_VERTICAL, 132 BDK_QLM_MARGIN_HORIZONTAL, 133 } bdk_qlm_margin_t; 134 135 /** 136 * Eye diagram captures are stored in the following structure 137 */ 138 typedef struct 139 { 140 int width; /* Width in the x direction (time) */ 141 int height; /* Height in the y direction (voltage) */ 142 uint32_t data[64][128]; /* Error count at location, saturates as max */ 143 } bdk_qlm_eye_t; 144 145 /** 146 * Initialize the QLM layer 147 */ 148 extern void bdk_qlm_init(bdk_node_t node) BDK_WEAK; 149 150 /** 151 * Return the number of QLMs supported for the chip 152 * 153 * @return Number of QLMs 154 */ 155 extern int bdk_qlm_get_num(bdk_node_t node); 156 157 /** 158 * Return the number of lanes in a QLM. QLMs normally contain 159 * 4 lanes, except for chips which only have half of a QLM. 160 * 161 * @param node Node to use in a Numa setup. Can be an exact ID or a special 162 * value. 163 * @param qlm QLM to get lanes number for 164 * 165 * @return Number of lanes on the QLM 166 */ 167 extern int bdk_qlm_get_lanes(bdk_node_t node, int qlm); 168 169 /** 170 * Lookup the hardware QLM number for a given interface type and index. This 171 * function will fail with a fatal error if called on invalid interfaces for 172 * a chip. It returns the QLM number for an interface without checking to 173 * see if the QLM is in the correct mode. 174 * 175 * @param iftype Interface type 176 * @param interface Interface index number 177 * 178 * @return QLM number. Dies on a fatal error on failure. 179 */ 180 int bdk_qlm_get_qlm_num(bdk_node_t node, bdk_if_t iftype, int interface, int index); 181 182 /** 183 * Convert a mode into a configuration variable string value 184 * 185 * @param mode Mode to convert 186 * 187 * @return configuration value string 188 */ 189 extern const char *bdk_qlm_mode_to_cfg_str(bdk_qlm_modes_t mode); 190 191 /** 192 * Convert a mode into a human understandable string 193 * 194 * @param mode Mode to convert 195 * 196 * @return Easy to read string 197 */ 198 extern const char *bdk_qlm_mode_tostring(bdk_qlm_modes_t mode); 199 200 /** 201 * Convert a configuration variable value string into a mode 202 * 203 * @param val Configuration variable value 204 * 205 * @return mode 206 */ 207 extern bdk_qlm_modes_t bdk_qlm_cfg_string_to_mode(const char *val); 208 209 /** 210 * Get the mode of a QLM as a human readable string 211 * 212 * @param node Node to use in a Numa setup. Can be an exact ID or a special 213 * value. 214 * @param qlm QLM to examine 215 * 216 * @return String mode 217 */ 218 extern bdk_qlm_modes_t bdk_qlm_get_mode(bdk_node_t node, int qlm); 219 220 /** 221 * For chips that don't use pin strapping, this function programs 222 * the QLM to the specified mode 223 * 224 * @param node Node to use in a Numa setup 225 * @param qlm QLM to configure 226 * @param mode Desired mode 227 * @param baud_mhz Desired speed 228 * @param flags Flags to specify mode specific options 229 * 230 * @return Zero on success, negative on failure 231 */ 232 extern 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); 233 234 /** 235 * Set the QLM's clock source. 236 * 237 * @param node Node to use in a Numa setup 238 * @param qlm QLM to configure 239 * @param clk Clock source for QLM 240 * 241 * @return Zero on success, negative on failure 242 */ 243 extern int bdk_qlm_set_clock(bdk_node_t node, int qlm, bdk_qlm_clock_t clk); 244 245 /** 246 * Get the speed (Gbaud) of the QLM in Mhz. 247 * 248 * @param node Node to use in a Numa setup. Can be an exact ID or a special 249 * value. 250 * @param qlm QLM to examine 251 * 252 * @return Speed in Mhz 253 */ 254 extern int bdk_qlm_get_gbaud_mhz(bdk_node_t node, int qlm); 255 256 /** 257 * Measure the reference clock of a QLM 258 * 259 * @param node Node to use in a Numa setup. Can be an exact ID or a special 260 * value. 261 * @param qlm QLM to measure 262 * 263 * @return Clock rate in Hz 264 */ 265 extern int bdk_qlm_measure_clock(bdk_node_t node, int qlm); 266 267 /** 268 * Reset a QLM to its initial state 269 * 270 * @param node Node to use in a numa setup 271 * @param qlm QLM to use 272 * 273 * @return Zero on success, negative on failure 274 */ 275 extern int bdk_qlm_reset(bdk_node_t node, int qlm); 276 277 /** 278 * Enable PRBS on a QLM 279 * 280 * @param node Node to use in a numa setup 281 * @param qlm QLM to use 282 * @param prbs PRBS mode (31, etc) 283 * @param dir Directions to enable. This is so you can enable TX and later 284 * enable RX after TX has run for a time 285 * 286 * @return Zero on success, negative on failure 287 */ 288 extern int bdk_qlm_enable_prbs(bdk_node_t node, int qlm, int prbs, bdk_qlm_direction_t dir); 289 290 /** 291 * Disable PRBS on a QLM 292 * 293 * @param node Node to use in a numa setup 294 * @param qlm QLM to use 295 * 296 * @return Zero on success, negative on failure 297 */ 298 extern int bdk_qlm_disable_prbs(bdk_node_t node, int qlm); 299 300 /** 301 * Return the number of PRBS errors since PRBS started running 302 * 303 * @param node Node to use in numa setup 304 * @param qlm QLM to use 305 * @param lane Which lane 306 * @param clear Clear the counter after returning its value 307 * 308 * @return Number of errors 309 */ 310 extern uint64_t bdk_qlm_get_prbs_errors(bdk_node_t node, int qlm, int lane, int clear); 311 312 /** 313 * Inject an error into PRBS 314 * 315 * @param node Node to use in numa setup 316 * @param qlm QLM to use 317 * @param lane Which lane 318 */ 319 extern void bdk_qlm_inject_prbs_error(bdk_node_t node, int qlm, int lane); 320 321 /** 322 * Enable shallow loopback on a QLM 323 * 324 * @param node Node to use in a numa setup 325 * @param qlm QLM to use 326 * @param loop Type of loopback. Not all QLMs support all modes 327 * 328 * @return Zero on success, negative on failure 329 */ 330 extern int bdk_qlm_enable_loop(bdk_node_t node, int qlm, bdk_qlm_loop_t loop); 331 332 /** 333 * Configure the TX tuning parameters for a QLM lane. The tuning parameters can 334 * be specified as -1 to maintain their current value 335 * 336 * @param node Node to configure 337 * @param qlm QLM to configure 338 * @param lane Lane to configure 339 * @param tx_swing Transmit swing (coef 0) Range 0-31 340 * @param tx_pre Pre cursor emphasis (Coef -1). Range 0-15 341 * @param tx_post Post cursor emphasis (Coef +1). Range 0-31 342 * @param tx_gain Transmit gain. Range 0-7 343 * @param tx_vboost Transmit voltage boost. Range 0-1 344 * 345 * @return Zero on success, negative on failure 346 */ 347 extern int bdk_qlm_tune_lane_tx(bdk_node_t node, int qlm, int lane, int tx_swing, int tx_pre, int tx_post, int tx_gain, int tx_vboost); 348 349 /** 350 * Perform RX equalization on a QLM 351 * 352 * @param node Node the QLM is on 353 * @param qlm QLM to perform RX equalization on 354 * @param lane Lane to use, or -1 for all lanes 355 * 356 * @return Zero on success, negative if any lane failed RX equalization 357 */ 358 extern int bdk_qlm_rx_equalization(bdk_node_t node, int qlm, int lane); 359 360 /** 361 * Capture an eye diagram for the given QLM lane. The output data is written 362 * to "eye". 363 * 364 * @param node Node to use in numa setup 365 * @param qlm QLM to use 366 * @param qlm_lane Which lane 367 * @param eye Output eye data 368 * 369 * @return Zero on success, negative on failure 370 */ 371 extern int bdk_qlm_eye_capture(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_eye_t *eye); 372 373 /** 374 * Display an eye diagram for the given QLM lane. The eye data can be in "eye", or 375 * captured during the call if "eye" is NULL. 376 * 377 * @param node Node to use in numa setup 378 * @param qlm QLM to use 379 * @param qlm_lane Which lane 380 * @param format Display format. 0 = raw, 1 = Color ASCII 381 * @param eye Eye data to display, or NULL if the data should be captured. 382 * 383 * @return Zero on success, negative on failure 384 */ 385 extern int bdk_qlm_eye_display(bdk_node_t node, int qlm, int qlm_lane, int format, const bdk_qlm_eye_t *eye); 386 387 /** 388 * Call the board specific method of determining the required QLM configuration 389 * and automatically settign up the QLMs to match. For example, on the EBB8800 390 * this function queries the MCU for the current setup. 391 * 392 * @param node Node to configure 393 * 394 * @return Zero on success, negative on failure 395 */ 396 extern int bdk_qlm_auto_config(bdk_node_t node); 397 398 /** 399 * Get the current RX margining parameter 400 * 401 * @param node Node to read margin value from 402 * @param qlm QLM to read from 403 * @param qlm_lane Lane to read 404 * @param margin_type 405 * Type of margining parameter to read 406 * 407 * @return Current margining parameter value 408 */ 409 extern int64_t bdk_qlm_margin_rx_get(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type); 410 411 /** 412 * Get the current RX margining parameter minimum value 413 * 414 * @param node Node to read margin value from 415 * @param qlm QLM to read from 416 * @param qlm_lane Lane to read 417 * @param margin_type 418 * Type of margining parameter to read 419 * 420 * @return Current margining parameter minimum value 421 */ 422 extern int64_t bdk_qlm_margin_rx_get_min(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type); 423 424 /** 425 * Get the current RX margining parameter maximum value 426 * 427 * @param node Node to read margin value from 428 * @param qlm QLM to read from 429 * @param qlm_lane Lane to read 430 * @param margin_type 431 * Type of margining parameter to read 432 * 433 * @return Current margining parameter maximum value 434 */ 435 extern int64_t bdk_qlm_margin_rx_get_max(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type); 436 437 /** 438 * Set the current RX margining parameter value 439 * 440 * @param node Node to set margin value on 441 * @param qlm QLM to set 442 * @param qlm_lane Lane to set 443 * @param margin_type 444 * Type of margining parameter to set 445 * @param value Value of margining parameter 446 * 447 * @return Zero on success, negative on failure 448 */ 449 extern int bdk_qlm_margin_rx_set(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type, int value); 450 451 /** 452 * Restore the supplied RX margining parameter value as if it was never set. This 453 * disables any overrides in the SERDES need to perform margining 454 * 455 * @param node Node to restore margin value on 456 * @param qlm QLM to restore 457 * @param qlm_lane Lane to restore 458 * @param margin_type 459 * Type of margining parameter to restore 460 * @param value Value of margining parameter 461 * 462 * @return Zero on success, negative on failure 463 */ 464 extern int bdk_qlm_margin_rx_restore(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type, int value); 465 466 /** 467 * For Cavium SFF query the dip switches to determine the QLM setup. Applying 468 * any configuration found. 469 * 470 * @param node Node to configure 471 * 472 * @return Zero on success, negative on failure 473 */ 474 475 extern int bdk_qlm_dip_auto_config(bdk_node_t node); 476 477 #endif /* __CB_BDK_QLM_H__ */ 478 /** @} */ 479