diff options
author | David Hendricks <dhendricks@fb.com> | 2018-03-09 14:30:38 -0800 |
---|---|---|
committer | Philipp Deppenwiese <zaolin.daisuki@gmail.com> | 2018-07-03 15:53:32 +0000 |
commit | 7d48ac5c7dfb52fc470bbad1013b4d460bc6a1e0 (patch) | |
tree | 42002ba1e86627339ff4a6cf38efb4b3f00033bb /src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c | |
parent | d837e660074e0621d63f59515f933c209441b653 (diff) |
soc/cavium: Integrate BDK files into coreboot
* Make it compile.
* Fix whitespace errors.
* Fix printf formats.
* Add missing headers includes
* Guard headers with ifdefs
Compile DRAM init code in romstage.
Compile QLM, PCIe, RNG, PHY, GPIO, MDIO init code in ramstage.
Change-Id: I0a93219a14bfb6ebe41103a825d5032b11e7f2c6
Signed-off-by: David Hendricks <dhendricks@fb.com>
Reviewed-on: https://review.coreboot.org/25089
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c')
-rw-r--r-- | src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c b/src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c new file mode 100644 index 0000000000..f7d631fb5b --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c @@ -0,0 +1,423 @@ +/***********************license start*********************************** +* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights +* reserved. +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* +* * Neither the name of Cavium Inc. nor the names of +* its contributors may be used to endorse or promote products +* derived from this software without specific prior written +* permission. +* +* This Software, including technical data, may be subject to U.S. export +* control laws, including the U.S. Export Administration Act and its +* associated regulations, and may be subject to export or import +* regulations in other countries. +* +* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" +* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR +* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT +* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY +* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT +* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES +* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR +* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, +* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK +* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. +***********************license end**************************************/ +#include <bdk.h> +#include <string.h> +#include "libbdk-arch/bdk-csrs-gser.h" +#include "libbdk-arch/bdk-csrs-gsern.h" +#include "libbdk-hal/if/bdk-if.h" +#include "libbdk-hal/bdk-qlm.h" +#include "libbdk-hal/qlm/bdk-qlm-common.h" + +/* This code is an optional part of the BDK. It is only linked in + if BDK_REQUIRE() needs it */ +BDK_REQUIRE_DEFINE(QLM); + +/** + * Convert a mode into a configuration variable string value + * + * @param mode Mode to convert + * + * @return configuration value string + */ +const char *bdk_qlm_mode_to_cfg_str(bdk_qlm_modes_t mode) +{ +#define MODE_CASE(m) case m: return #m+13 + switch (mode) + { + MODE_CASE(BDK_QLM_MODE_DISABLED); + MODE_CASE(BDK_QLM_MODE_PCIE_1X1); + MODE_CASE(BDK_QLM_MODE_PCIE_2X1); + MODE_CASE(BDK_QLM_MODE_PCIE_1X2); + MODE_CASE(BDK_QLM_MODE_PCIE_1X4); + MODE_CASE(BDK_QLM_MODE_PCIE_1X8); + MODE_CASE(BDK_QLM_MODE_PCIE_1X16); + + MODE_CASE(BDK_QLM_MODE_SATA_4X1); + MODE_CASE(BDK_QLM_MODE_SATA_2X1); + + MODE_CASE(BDK_QLM_MODE_ILK); + MODE_CASE(BDK_QLM_MODE_SGMII_4X1); + MODE_CASE(BDK_QLM_MODE_SGMII_2X1); + MODE_CASE(BDK_QLM_MODE_SGMII_1X1); + MODE_CASE(BDK_QLM_MODE_XAUI_1X4); + MODE_CASE(BDK_QLM_MODE_RXAUI_2X2); + MODE_CASE(BDK_QLM_MODE_RXAUI_1X2); + MODE_CASE(BDK_QLM_MODE_OCI); + MODE_CASE(BDK_QLM_MODE_XFI_4X1); + MODE_CASE(BDK_QLM_MODE_XFI_2X1); + MODE_CASE(BDK_QLM_MODE_XFI_1X1); + MODE_CASE(BDK_QLM_MODE_XLAUI_1X4); + MODE_CASE(BDK_QLM_MODE_10G_KR_4X1); + MODE_CASE(BDK_QLM_MODE_10G_KR_2X1); + MODE_CASE(BDK_QLM_MODE_10G_KR_1X1); + MODE_CASE(BDK_QLM_MODE_40G_KR4_1X4); + MODE_CASE(BDK_QLM_MODE_QSGMII_4X1); + MODE_CASE(BDK_QLM_MODE_25G_4X1); + MODE_CASE(BDK_QLM_MODE_25G_2X1); + MODE_CASE(BDK_QLM_MODE_50G_2X2); + MODE_CASE(BDK_QLM_MODE_50G_1X2); + MODE_CASE(BDK_QLM_MODE_100G_1X4); + MODE_CASE(BDK_QLM_MODE_25G_KR_4X1); + MODE_CASE(BDK_QLM_MODE_25G_KR_2X1); + MODE_CASE(BDK_QLM_MODE_50G_KR_2X2); + MODE_CASE(BDK_QLM_MODE_50G_KR_1X2); + MODE_CASE(BDK_QLM_MODE_100G_KR4_1X4); + MODE_CASE(BDK_QLM_MODE_USXGMII_4X1); + MODE_CASE(BDK_QLM_MODE_USXGMII_2X1); + + case BDK_QLM_MODE_LAST: break; /* fall through error */ + } + return "INVALID_QLM_MODE_VALUE"; +} + +/** + * Convert a configuration variable value string into a mode + * + * @param val Configuration variable value + * + * @return mode + */ +bdk_qlm_modes_t bdk_qlm_cfg_string_to_mode(const char *val) +{ + bdk_qlm_modes_t mode; + + for (mode = 0; mode < BDK_QLM_MODE_LAST; mode++) + { + if (0 == strcmp(val, bdk_qlm_mode_to_cfg_str(mode))) + { + return mode; + } + } + return -1; +} + +/** + * Convert a mode into a human understandable string + * + * @param mode Mode to convert + * + * @return Easy to read string + */ +const char *bdk_qlm_mode_tostring(bdk_qlm_modes_t mode) +{ + const char *result = "Unknown, update bdk_qlm_mode_tostring()"; + switch (mode) + { + case BDK_QLM_MODE_DISABLED: + result = "Disabled"; + break; + case BDK_QLM_MODE_PCIE_1X1: + result = "1 PCIe, 1 lane"; + break; + case BDK_QLM_MODE_PCIE_2X1: + result = "2 PCIe, 1 lane each"; + break; + case BDK_QLM_MODE_PCIE_1X2: + result = "1 PCIe, 2 lanes"; + break; + case BDK_QLM_MODE_PCIE_1X4: + result = "1 PCIe, 4 lanes"; + break; + case BDK_QLM_MODE_PCIE_1X8: + result = "1 PCIe, 8 lanes"; + break; + case BDK_QLM_MODE_PCIE_1X16: + result = "1 PCIe, 16 lanes"; + break; + + case BDK_QLM_MODE_SATA_4X1: + result = "4 SATA, one lane each"; + break; + case BDK_QLM_MODE_SATA_2X1: + result = "2 SATA, one lane each"; + break; + + case BDK_QLM_MODE_ILK: + result = "Interlaken"; + break; + case BDK_QLM_MODE_SGMII_4X1: + result = "4 SGMII, 1 lane each"; + break; + case BDK_QLM_MODE_SGMII_2X1: + result = "2 SGMII, 1 lane each"; + break; + case BDK_QLM_MODE_SGMII_1X1: + result = "1 SGMII, 1 lane"; + break; + case BDK_QLM_MODE_XAUI_1X4: + result = "1 XAUI, 4 lanes"; + break; + case BDK_QLM_MODE_RXAUI_2X2: + result = "2 RXAUI, 2 lanes each"; + break; + case BDK_QLM_MODE_RXAUI_1X2: + result = "1 RXAUI, 2 lanes each"; + break; + case BDK_QLM_MODE_OCI: + result = "Cavium Coherent Processor Interconnect"; + break; + case BDK_QLM_MODE_XFI_4X1: + result = "4 XFI, 1 lane each"; + break; + case BDK_QLM_MODE_XFI_2X1: + result = "2 XFI, 1 lane each"; + break; + case BDK_QLM_MODE_XFI_1X1: + result = "1 XFI, 1 lane"; + break; + case BDK_QLM_MODE_XLAUI_1X4: + result = "1 XLAUI, 4 lanes"; + break; + case BDK_QLM_MODE_10G_KR_4X1: + result = "4 10GBASE-KR, 1 lane each"; + break; + case BDK_QLM_MODE_10G_KR_2X1: + result = "2 10GBASE-KR, 1 lane each"; + break; + case BDK_QLM_MODE_10G_KR_1X1: + result = "1 10GBASE-KR, 1 lane"; + break; + case BDK_QLM_MODE_40G_KR4_1X4: + result = "1 40GBASE-KR4, 4 lanes"; + break; + case BDK_QLM_MODE_QSGMII_4X1: + result = "4 QSGMII, 1 lane"; + break; + case BDK_QLM_MODE_25G_4X1: + result = "4 25G, 1 lane each"; + break; + case BDK_QLM_MODE_25G_2X1: + result = "2 25G, 1 lane each"; + break; + case BDK_QLM_MODE_50G_2X2: + result = "2 50G, 2 lanes each"; + break; + case BDK_QLM_MODE_50G_1X2: + result = "1 50G, 2 lanes"; + break; + case BDK_QLM_MODE_100G_1X4: + result = "1 100G, 4 lanes"; + break; + case BDK_QLM_MODE_25G_KR_4X1: + result = "4 25G, 1 lane each"; + break; + case BDK_QLM_MODE_25G_KR_2X1: + result = "2 25G, 1 lane each"; + break; + case BDK_QLM_MODE_50G_KR_2X2: + result = "2 50G, 2 lanes each"; + break; + case BDK_QLM_MODE_50G_KR_1X2: + result = "1 50G, 2 lanes"; + break; + case BDK_QLM_MODE_100G_KR4_1X4: + result = "1 100G, 4 lanes"; + break; + case BDK_QLM_MODE_USXGMII_4X1: + result = "4 USXGMII, 1 lane each"; + break; + case BDK_QLM_MODE_USXGMII_2X1: + result = "2 USXGMII, 1 lane each"; + break; + + case BDK_QLM_MODE_LAST: + break; /* fallthrough error */ + } + return result; +} + +int bdk_qlm_measure_clock(bdk_node_t node, int qlm) +{ + int ref_clock = __bdk_qlm_measure_refclock(node, qlm); + BDK_TRACE(QLM, "N%d.QLM%d: Ref clock %d Hz\n", node, qlm, ref_clock); + + return ref_clock; +} + +/** + * Set the QLM's clock source. + * + * @param node Node to use in a Numa setup + * @param qlm QLM to configure + * @param clk Clock source for QLM + * + * @return Zero on success, negative on failure + */ +int bdk_qlm_set_clock(bdk_node_t node, int qlm, bdk_qlm_clock_t clk) +{ + if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX)) + { + int sel; + int com1; + switch (clk) + { + case BDK_QLM_CLK_COMMON_0: + sel = 1; + com1 = 0; + break; + case BDK_QLM_CLK_COMMON_1: + sel = 1; + com1 = 1; + break; + case BDK_QLM_CLK_EXTERNAL: + sel = 0; + com1 = 0; + break; + default: + bdk_warn("Unrecognized clock mode %d for QLM%d on node %d.\n", + clk, qlm, node); + return -1; + } + + BDK_CSR_MODIFY(c, node, BDK_GSERX_REFCLK_SEL(qlm), + c.s.com_clk_sel = sel; + c.s.use_com1 = com1); + } + else + { + int cclksel; + switch (clk) + { + case BDK_QLM_CLK_COMMON_0: + cclksel = 0; + break; + case BDK_QLM_CLK_COMMON_1: + cclksel = 1; + break; + case BDK_QLM_CLK_COMMON_2: + cclksel = 2; + break; + case BDK_QLM_CLK_EXTERNAL: + cclksel = 3; + break; + default: + bdk_warn("Unrecognized clock mode %d for QLM%d on node %d.\n", + clk, qlm, node); + return -1; + } + BDK_CSR_MODIFY(c, node, BDK_GSERNX_COMMON_REFCLK_BCFG(qlm), + c.s.pwdn = (clk == BDK_QLM_CLK_EXTERNAL) ? 0 : 1; + c.s.cclksel = cclksel); + } + return 0; +} + +/** + * Display an eye diagram for the given QLM lane. The eye data can be in "eye", or + * captured during the call if "eye" is NULL. + * + * @param node Node to use in numa setup + * @param qlm QLM to use + * @param qlm_lane Which lane + * @param format Display format. 0 = raw, 1 = Color ASCII + * @param eye Eye data to display, or NULL if the data should be captured. + * + * @return Zero on success, negative on failure + */ +int bdk_qlm_eye_display(bdk_node_t node, int qlm, int qlm_lane, int format, const bdk_qlm_eye_t *eye) +{ + int result; + int need_free = 0; + if (eye == NULL) + { + bdk_qlm_eye_t *eye_data = malloc(sizeof(bdk_qlm_eye_t)); + if (eye_data == NULL) + { + bdk_error("Failed to allocate space for eye\n"); + return -1; + } + if (bdk_qlm_eye_capture(node, qlm, qlm_lane, eye_data)) + return -1; + eye = eye_data; + } + + /* Calculate the max eye width */ + int eye_area = 0; + int eye_width = 0; + for (int y = 0; y < eye->height; y++) + { + int width = 0; + for (int x = 0; x < eye->width; x++) + { + if (eye->data[y][x] == 0) + { + width++; + eye_area++; + } + } + if (width > eye_width) + eye_width = width; + } + + /* Calculate the max eye height */ + int eye_height = 0; + for (int x = 0; x < eye->width; x++) + { + int height = 0; + for (int y = 0; y < eye->height; y++) + { + if (eye->data[y][x] == 0) + { + height++; + eye_area++; + } + } + if (height > eye_height) + eye_height = height; + } + + printf("\nEye Diagram for Node %d, QLM %d, Lane %d\n", node, qlm, qlm_lane); + + if (format == 0) /* Raw */ + { + for (int y = 0; y < eye->height; y++) + { + for (int x = 0; x < eye->width; x++) + printf("%u\t", eye->data[y][x]); + printf("\n"); + } + result = 0; + } + else + result = -1; + + if (need_free) + free((void*)eye); + return result; +} |