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-boot | |
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-boot')
7 files changed, 815 insertions, 108 deletions
diff --git a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-gpio.c b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-gpio.c new file mode 100644 index 0000000000..330a23ba49 --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-gpio.c @@ -0,0 +1,70 @@ +/***********************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 "libbdk-arch/bdk-csrs-gpio.h" +#include "libbdk-hal/bdk-config.h" +#include "libbdk-hal/bdk-gpio.h" +#include "libbdk-boot/bdk-boot-gpio.h" + +/** + * Configure GPIO on all nodes as part of booting + */ +void bdk_boot_gpio(void) +{ + const int NUM_GPIO = bdk_gpio_get_num(); + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (bdk_numa_exists(n)) + { + for (int gpio = 0; gpio < NUM_GPIO; gpio++) + { + int pin_sel = bdk_config_get_int(BDK_CONFIG_GPIO_PIN_SELECT, gpio, n); + if (pin_sel >= 0) + { + BDK_TRACE(INIT, "Connecting N%d.GPIO%d to pin select 0x%x\n", + n, gpio, pin_sel); + bdk_gpio_select_pin(n, gpio, pin_sel); + } + int invert = bdk_config_get_int(BDK_CONFIG_GPIO_POLARITY, gpio, n); + if (invert) + BDK_CSR_MODIFY(c, n, BDK_GPIO_BIT_CFGX(gpio), c.s.pin_xor = 1); + } + } + } +} diff --git a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-pcie.c b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-pcie.c new file mode 100644 index 0000000000..b03c2e03ee --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-pcie.c @@ -0,0 +1,68 @@ +/***********************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-hal/if/bdk-if.h" +#include "libbdk-hal/bdk-qlm.h" +#include "libbdk-arch/bdk-csrs-pem.h" +#include "libbdk-boot/bdk-boot-pcie.h" +#include "libbdk-hal/bdk-pcie.h" + +/** + * Configure PCIe on all nodes as part of booting + */ +void bdk_boot_pcie(void) +{ + /* Initialize PCIe and bring up the link */ + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (bdk_numa_exists(n)) + { + for (int p = 0; p < bdk_pcie_get_num_ports(n); p++) + { + /* Only init PCIe that are attached to QLMs */ + if (bdk_qlm_get_qlm_num(n, BDK_IF_PCIE, p, 0) != -1) + { + BDK_TRACE(INIT, "Initializing PCIe%d on Node %d\n", p, n); + bdk_pcie_rc_initialize(n, p); + } + } + } + } +} diff --git a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-qlm.c b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-qlm.c new file mode 100644 index 0000000000..73bdca0363 --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-qlm.c @@ -0,0 +1,515 @@ +/***********************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-hal/if/bdk-if.h" +#include "libbdk-hal/bdk-qlm.h" +#include "libbdk-hal/bdk-utils.h" +#include "libbdk-boot/bdk-boot-qlm.h" +#include "libbdk-hal/bdk-config.h" +#include "libbdk-hal/bdk-twsi.h" + +static void boot_init_qlm_clk(void) +{ + /* Setup reference clocks */ + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (!bdk_numa_exists(n)) + continue; + + int num_qlms = bdk_qlm_get_num(n); + + BDK_TRACE(INIT, "Initializing QLM clocks on Node %d\n", n); + for (int qlm = 0; qlm < num_qlms; qlm++) + { + bdk_qlm_clock_t clk = bdk_config_get_int(BDK_CONFIG_QLM_CLK, n, qlm); + if (BDK_QLM_CLK_LAST == clk) /* no entry */ + continue; + + if (clk > BDK_QLM_CLK_LAST) + { + bdk_warn("Invalid clock source %d for QLM%d on node %d. Not configuring.\n", + clk, qlm, n); + continue; + } + + if (0 != bdk_qlm_set_clock(n, qlm, clk)) + { + bdk_error("Error setting clock source %d for QLM%d on node %d. Ignoring.\n", + clk, qlm, n); + } + } + } +} + +/** + * Given a node and DLM/QLM, return the possible BGX lanes connected to it. This + * is needed to determine which PHY address to use for SFP/SFP+ detection. + * + * @param node Node the DLM/QLM is on + * @param qlm DLM/QLM to find the BGX for + * @param bgx Output: The BGX instance number, or -1 on failure + * @param bgx_lane_mask + * Output: Which BGX indexes may be connected to this port + */ +static void find_bgx(int node, int qlm, int *bgx, int *bgx_lane_mask) +{ + *bgx = -1; + *bgx_lane_mask = 0; + + if (CAVIUM_IS_MODEL(CAVIUM_CN88XX)) + { + switch (qlm) + { + case 0: /* BGX0 -> QLM0 */ + case 1: /* BGX1 -> QLM1 */ + *bgx = qlm; + *bgx_lane_mask = 0xf; + return; + default: + BDK_TRACE(INIT, "N%d.QLM%d: No BGX for this QLM, illegal config\n", node, qlm); + return; + } + } + else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX)) + { + switch (qlm) + { + case 2: /* BGX0 -> QLM2 */ + *bgx = 0; + *bgx_lane_mask = 0xf; + return; + case 3: /* BGX1 -> QLM3 */ + *bgx = 1; + *bgx_lane_mask = 0xf; + return; + case 4: /* BGX3 -> DLM4 */ + *bgx = 3; + *bgx_lane_mask = 0x3; + return; + case 5: /* BGX2 -> DLM5 */ + *bgx = 2; + *bgx_lane_mask = 0x3; + return; + case 6: /* BGX2 -> DLM6 */ + *bgx = 2; + *bgx_lane_mask = 0xc; + return; + default: + BDK_TRACE(INIT, "N%d.QLM%d: No BGX for this QLM, illegal config\n", node, qlm); + return; + } + } + else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX)) + { + switch (qlm) + { + case 0: /* BGX0 -> DLM0 */ + *bgx = 0; + *bgx_lane_mask = 0x3; + return; + case 1: /* BGX0 -> DLM1 */ + *bgx = 0; + *bgx_lane_mask = 0xc; + return; + case 2: /* BGX1 -> DLM2 */ + *bgx = 1; + *bgx_lane_mask = 0x3; + return; + case 3: /* BGX1 -> DLM3 */ + *bgx = 1; + *bgx_lane_mask = 0xc; + return; + default: + BDK_TRACE(INIT, "N%d.QLM%d: No BGX for this QLM, illegal config\n", node, qlm); + return; + } + } + else + bdk_error("N%d.QLM%d: Unsupported chip, update %s()\n", node, qlm, __FUNCTION__); +} + +/** + * Determine the DLM/QLM mode based on a SFP/SFP+ connected to the port. Note that + * the CN8XXX parts can't control mode per lane, so all SFP/SFP+ on a DLM/QLM must + * be the same mode. This code is sloppy about finding the BGX PHY for the DLM/QLM + * because not all lanes may be used. + * + * @param node Node to determine mode for + * @param qlm DLM/QLM the SFP/SFP+ is connected to + * + * @return QLM mode or -1 on failure + */ +static int init_sfp(int node, int qlm) +{ + int mode = BDK_QLM_MODE_XFI_4X1; /* Default to XFI if detection fails */ + int bgx = -1; + int bgx_lane_mask = 0; + + find_bgx(node, qlm, &bgx, &bgx_lane_mask); + if (bgx == -1) + return mode; + + BDK_TRACE(INIT, "N%d.QLM%d: Checking for SFP/SFP+\n", node, qlm); + + for (int index = 0; index < 4; index++) + { + /* Skip BGX indexes that aren't applicable */ + if ((bgx_lane_mask & (1 << index)) == 0) + continue; + /* Lookup the PHY address for this BGX port */ + int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, node, bgx, index); + /* SFP/SFP+ are connected with TWSI, so only check ports with + PHYs connected with TWSI */ + if ((phy_addr & BDK_IF_PHY_TYPE_MASK) != BDK_IF_PHY_TWSI) + continue; + + /* For TWSI: + Bits[31:24]: Node ID, 0xff for device node + Bits[23:16]: TWSI internal address width in bytes (0-2) + Bits[15:12]: 2=TWSI + Bits[11:8]: TWSI bus number + Bits[7:0]: TWSI address */ + int n = (phy_addr >> 24) & 0xff; + int twsi_ia_width = (phy_addr >> 16) & 0xff; + int twsi_bus = (phy_addr >> 8) & 0xf; + int twsi_addr = 0x50; /* From SFP spec */ + if (n == 0xff) + n = node; + + /* Read bytes 0-3 from eeprom. Note read is big endian, so byte 0 is + bits 31:24 in the result */ + int64_t eeprom_00_03 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 0, 4, twsi_ia_width); + if (eeprom_00_03 == -1) + { + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index); + continue; + } + int64_t eeprom_04_07 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 4, 4, twsi_ia_width); + if (eeprom_04_07 == -1) + { + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index); + continue; + } + int64_t eeprom_08_11 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 8, 4, twsi_ia_width); + if (eeprom_08_11 == -1) + { + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index); + continue; + } + int64_t eeprom_12 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 12, 1, twsi_ia_width); + if (eeprom_12 == -1) + { + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index); + continue; + } + + /* Byte 0: Identifier, should be 0x03 for SFP/SFP+ + 0x03 = SFP of SFP+ + 0x0c = QSFP + 0x0d = QSFP+ */ + if (bdk_extract(eeprom_00_03, 24, 8) != 0x03) + { + /* Byte 0 of eeprom should be 0x03 for SFP/SFP+ */ + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ not detected\n", node, qlm, bgx, index); + continue; + } + /* Byte 1: Extended Identifier, should be 0x04 */ + if (bdk_extract(eeprom_00_03, 16, 8) != 0x04) + { + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ incorrect extended identifier\n", node, qlm, bgx, index); + continue; + } + /* Byte 2: Connector + Value Description of connector + 00h Unknown or unspecified + 01h SC + 02h Fibre Channel Style 1 copper connector + 03h Fibre Channel Style 2 copper connector + 04h BNC/TNC + 05h Fibre Channel coaxial headers + 06h FiberJack + 07h LC + 08h MT-RJ + 09h MU + 0Ah SG + 0Bh Optical pigtail + 0Ch MPO Parallel Optic + 0Dh-1Fh Reserved, Unallocated + 20h HSSDC II + 21h Copper Pigtail + 22h RJ45 + 23h-7Fh Reserved, Unallocated + 80-FFh Vendor specific */ + bool isOptical = false; + switch (bdk_extract(eeprom_00_03, 8, 8)) + { + case 0x01: /* SC - Short channel */ + case 0x07: /* LC - Long channel */ + case 0x0B: /* Optical pigtail */ + isOptical = true; + break; + } + BDK_TRACE(INIT, "N%d.QLM%d: SFP/SFP+ eeprom Bytes[0:3] 0x%0llx, Bytes[4:7] 0x%08llx, [8:11] 0x%08llx [12] 0x%02llx\n", + node, qlm, eeprom_00_03, eeprom_04_07, eeprom_08_11, eeprom_12); + /* Byte 3: Transceiver info first byte. See comments below */ + /* Byte 3, bits 4-7 correspond to 10G Ethernet speeds */ + /* 10G Ethernet Compliance Codes + Byte 3[7] 10G BASE-ER (Fiber - Extended Reach) + Byte 3[6] 10G BASE-LRM (Fiber - Long reach multi-mode) + Byte 3[5] 10G BASE-LR (Fiber - Long reach) + Byte 3[4] 10G BASE-SR (Fiber - Short reach) */ + bool isXFI = bdk_extract(eeprom_00_03, 0, 8) != 0; + /* Byte 6, bits 0-7 correspond to Gigabit Ethernet speeds */ + /* Gigabit Ethernet Compliance Codes + Byte 6[7] BASE-PX + Byte 6[6] BASE-BX10 + Byte 6[5] 100BASE-FX + Byte 6[4] 100BASE-LX/LX10 (Fiber) + Byte 6[3] 1000BASE-T (Twisted pair) + Byte 6[2] 1000BASE-CX (Shielded balanced copper) + Byte 6[1] 1000BASE-LX (Fiber) + Byte 6[0] 1000BASE-SX (Fiber) */ + bool isSGMII = bdk_extract(eeprom_04_07, 8, 8) != 0; + /* Byte 12 is the nominal bit rate, units of 100 MBits/sec. */ + int bit_rate = eeprom_12 * 100; + if (bit_rate) + { + BDK_TRACE(INIT, "N%d.QLM%d: Nominal bit rate %d MBits/sec\n", + node, qlm, bit_rate); + isXFI = (bit_rate >= 10000); + isSGMII = (bit_rate <= 2500); + } + + if (isXFI) + { + mode = BDK_QLM_MODE_XFI_4X1; + if (isOptical) + BDK_TRACE(INIT, "N%d.QLM%d: SFP+ selecting XFI Optical\n", node, qlm); + else + BDK_TRACE(INIT, "N%d.QLM%d: SFP+ selecting XFI Copper\n", node, qlm); + } + else if (isSGMII) + { + mode = BDK_QLM_MODE_SGMII_4X1; + if (isOptical) + { + /* This should be 1000BASE-X, gigabit over fiber */ + BDK_TRACE(INIT, "N%d.QLM%d: SFP selecting SGMII Optical\n", node, qlm); + } + else /* This should be SGMII, gigabit over copper */ + BDK_TRACE(INIT, "N%d.QLM%d: SFP selecting SGMII Copper\n", node, qlm); + } + } + return mode; +} + +/** + * Determine the DLM/QLM mode based on a QSFP/QSFP+ connected to + * the port. This code is sloppy about finding the BGX PHY for + * the DLM/QLM because not all lanes may be used. + * + * @param node Node to determine mode for + * @param qlm DLM/QLM the SFP/SFP+ is connected to + * + * @return QLM mode or -1 on failure + */ +static int init_qsfp(int node, int qlm) +{ + int mode = BDK_QLM_MODE_XLAUI_1X4; /* Default to XLAUI if detection fails */ + int bgx = -1; + int bgx_lane_mask = 0; + + find_bgx(node, qlm, &bgx, &bgx_lane_mask); + if (bgx == -1) + return mode; + + BDK_TRACE(INIT, "N%d.QLM%d: Checking for QSFP/QSFP+\n", node, qlm); + int index = 0; + + /* Lookup the PHY address for this BGX port */ + int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, node, bgx, index); + /* QSFP/QSFP+ are connected with TWSI, so only check ports with + PHYs connected with TWSI */ + if ((phy_addr & BDK_IF_PHY_TYPE_MASK) != BDK_IF_PHY_TWSI) + return mode; + + /* For TWSI: + Bits[31:24]: Node ID, 0xff for device node + Bits[23:16]: TWSI internal address width in bytes (0-2) + Bits[15:12]: 2=TWSI + Bits[11:8]: TWSI bus number + Bits[7:0]: TWSI address */ + int n = (phy_addr >> 24) & 0xff; + int twsi_ia_width = (phy_addr >> 16) & 0xff; + int twsi_bus = (phy_addr >> 8) & 0xf; + int twsi_addr = 0x50; /* From SFP spec */ + if (n == 0xff) + n = node; + + /* Byte 0: Identifier, should be 0x03 for SFP/SFP+ + 0x03 = SFP of SFP+ + 0x0c = QSFP + 0x0d = QSFP+ */ + int64_t eeprom_00 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 0, 1, twsi_ia_width); + switch (eeprom_00) + { + case 0x03: + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d QSFP/QSFP+ contains a SFP+\n", node, qlm, bgx); + mode = init_sfp(node, qlm); + break; + case 0x0c: + case 0x0d: + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d Found a QSFP/QSFP+, assuming 40G\n", node, qlm, bgx); + mode = BDK_QLM_MODE_XLAUI_1X4; + break; + default: + BDK_TRACE(INIT, "N%d.QLM%d: BGX%d QSFP/QSFP+ not detected\n", node, qlm, bgx); + break; + } + return mode; +} + +static void boot_init_qlm_mode(void) +{ + /* Check if QLM autoconfig is requested */ + int qlm_auto = bdk_config_get_int(BDK_CONFIG_QLM_AUTO_CONFIG); + if (qlm_auto) + { + /* Auto configuration of QLMs + */ + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (bdk_numa_exists(n)) + { + BDK_TRACE(INIT, "Initializing QLMs on Node %d\n", n); + bdk_qlm_auto_config(n); + } + } + } + /* + * Check if QLM autoconfig from DIP switch settings is requested + */ + else if (bdk_config_get_int(BDK_CONFIG_QLM_DIP_AUTO_CONFIG)) + { + BDK_TRACE(INIT, "Reading DIP Switch settings for QLM Auto configuration\n"); + + /* Auto configuration of QLMs + */ + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (bdk_numa_exists(n)) + { + BDK_TRACE(INIT, "Initializing QLMs on Node %d\n", n); + if (bdk_qlm_dip_auto_config(n)) + bdk_error("QLM Auto configuration failed!\n"); + } + } + + } + else + { + /* Initialize the QLMs based on configuration file settings + */ + + boot_init_qlm_clk(); + + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (!bdk_numa_exists(n)) + continue; + + int num_qlms = bdk_qlm_get_num(n); + + BDK_TRACE(INIT, "Initializing QLMs on Node %d\n", n); + for (int qlm = 0; qlm < num_qlms; qlm++) + { + const char *cfg_val; + + cfg_val = bdk_config_get_str(BDK_CONFIG_QLM_MODE, n, qlm); + if (!cfg_val) + continue; + + int mode; + int freq; + /* Check for special token telling us to configure the QLM + based on the SFP/SFP+/QSFP/QSFP+ plugged into the system. */ + if ((strcmp(cfg_val, "SFP+") == 0) || (strcmp(cfg_val, "QSFP+") == 0)) + { + if (strcmp(cfg_val, "SFP+") == 0) + mode = init_sfp(n, qlm); + else + mode = init_qsfp(n, qlm); + + if (mode == BDK_QLM_MODE_SGMII_4X1) + freq = 1250; + else + freq = 10321; + } + else + { + mode = bdk_qlm_cfg_string_to_mode(cfg_val); + freq = bdk_config_get_int(BDK_CONFIG_QLM_FREQ, n, qlm); + } + if (-1 == mode) + { + bdk_error("Invalid QLM mode string '%s' for QLM%d on node %d. " + "Not configuring.\n", cfg_val, qlm, n); + continue; + } + if (-1 == freq) + { + bdk_error("No frequency setting for QLM%d on node %d. " + "Not configuring.\n", qlm, n); + continue; + } + + bdk_qlm_set_mode(n, qlm, mode, freq, 0); + } + } + } +} + +/** + * Configure QLM on all nodes as part of booting + */ +void bdk_boot_qlm(void) +{ + boot_init_qlm_mode(); +} diff --git a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-status.c b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-status.c index 83ab14cbc7..c91f2dd1bb 100644 --- a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-status.c +++ b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-status.c @@ -38,6 +38,8 @@ ***********************license end**************************************/ #include <bdk.h> #include "libbdk-arch/bdk-csrs-mio_tws.h" +#include "libbdk-boot/bdk-boot-status.h" +#include <libbdk-hal/bdk-config.h> /** * Report boot status to the BMC or whomever might care. This function diff --git a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-usb.c b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-usb.c new file mode 100644 index 0000000000..70ed44af4f --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-usb.c @@ -0,0 +1,62 @@ +/***********************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 <libbdk-hal/bdk-usb.h> +#include <libbdk-hal/bdk-config.h> +#include <libbdk-boot/bdk-boot-usb.h> + +/** + * Configure USB on all nodes as part of booting + */ +void bdk_boot_usb(void) +{ + /* Initialize USB, ready for standard XHCI driver */ + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (bdk_numa_exists(n)) + { + for (int p = 0; p < 2; p++) + { + int usb_refclock = bdk_config_get_int(BDK_CONFIG_USB_REFCLK_SRC, n,p); + BDK_TRACE(INIT, "Initializing USB%d on Node %d clock type %d\n", p, n, usb_refclock); + bdk_usb_initialize(n, p, usb_refclock); + } + } + } +} diff --git a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot.c b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot.c new file mode 100644 index 0000000000..15bcf4aa8c --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot.c @@ -0,0 +1,98 @@ +/***********************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-hal/if/bdk-if.h" +#include "libbdk-arch/bdk-csrs-pem.h" +#include "libbdk-boot/bdk-boot-pcie.h" +#include "libbdk-boot/bdk-boot-qlm.h" +#include "libbdk-boot/bdk-boot-usb.h" +#include "libbdk-hal/bdk-pcie.h" +#include "libbdk-hal/bdk-mdio.h" +#include "libbdk-hal/bdk-qlm.h" +#include "libbdk-hal/bdk-ecam.h" +#include "libbdk-hal/bdk-rng.h" +#include "libbdk-boot/bdk-boot-gpio.h" +#include "libbdk-arch/bdk-csrs-iobn.h" +#include "libbdk-arch/bdk-csrs-dap.h" + +/** + * Configure hardware + */ +void bdk_boot(void) +{ + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (bdk_numa_exists(n)) + { + /* Allow CAP access from cores so we can read system registers through + memory mapped addresses. See bdk_sysreg_read() */ + BDK_CSR_MODIFY(c, n, BDK_DAP_IMP_DAR, c.s.caben = 1); + + /* Enable IOBN */ + if (CAVIUM_IS_MODEL(CAVIUM_CN88XX) || CAVIUM_IS_MODEL(CAVIUM_CN81XX)) + { + BDK_CSR_MODIFY(c, n, BDK_IOBNX_NCB0_HP(0), + c.s.hp = 1); + if (CAVIUM_IS_MODEL(CAVIUM_CN88XX)) + BDK_CSR_MODIFY(c, n, BDK_IOBNX_NCB0_HP(1), + c.s.hp = 0); + } + + bdk_ecam_scan_all(n); + bdk_mdio_init(n); + bdk_qlm_init(n); + bdk_rng_init(n); + } + } + + bdk_boot_gpio(); + bdk_boot_usb(); + bdk_boot_qlm(); + bdk_boot_pcie(); + + /* Initialize PHYs */ + for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++) + { + if (bdk_numa_exists(n)) + { + bdk_if_phy_setup(n); + } + } +} diff --git a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-watchdog.c b/src/vendorcode/cavium/bdk/libbdk-boot/bdk-watchdog.c deleted file mode 100644 index 48f955a7ef..0000000000 --- a/src/vendorcode/cavium/bdk/libbdk-boot/bdk-watchdog.c +++ /dev/null @@ -1,108 +0,0 @@ -/***********************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 "libbdk-arch/bdk-csrs-gti.h" - -/** - * Setup the watchdog to expire in timeout_ms milliseconds. When the watchdog - * expires, the chip three things happen: - * 1) Expire 1: interrupt that is ignored by the BDK - * 2) Expire 2: DEL3T interrupt, which is disabled and ignored - * 3) Expire 3: Soft reset of the chip - * - * Since we want a soft reset, we actually program the watchdog to expire at - * the timeout / 3. - * - * @param timeout_ms Timeout in milliseconds. If this is zero, the timeout is taken from the - * global configuration option BDK_BRD_CFG_WATCHDOG_TIMEOUT - */ -void bdk_watchdog_set(unsigned int timeout_ms) -{ - if (timeout_ms == 0) - timeout_ms = bdk_config_get_int(BDK_CONFIG_WATCHDOG_TIMEOUT); - - if (timeout_ms > 0) - { - uint64_t sclk = bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_SCLK); - uint64_t timeout_sclk = sclk * timeout_ms / 1000; - /* Per comment above, we want the watchdog to expire at 3x the rate specified */ - timeout_sclk /= 3; - /* Watchdog counts in 1024 cycle steps */ - uint64_t timeout_wdog = timeout_sclk >> 10; - /* We can only specify the upper 16 bits of a 24 bit value. Round up */ - timeout_wdog = (timeout_wdog + 0xff) >> 8; - /* If the timeout overflows the hardware limit, set max */ - if (timeout_wdog >= 0x10000) - timeout_wdog = 0xffff; - - BDK_TRACE(INIT, "Watchdog: Set to expire %lu SCLK cycles\n", timeout_wdog << 18); - BDK_CSR_MODIFY(c, bdk_numa_local(), BDK_GTI_CWD_WDOGX(bdk_get_core_num()), - c.s.len = timeout_wdog; - c.s.mode = 3); - } -} - -/** - * Signal the watchdog that we are still running - */ -void bdk_watchdog_poke(void) -{ - BDK_CSR_WRITE(bdk_numa_local(), BDK_GTI_CWD_POKEX(bdk_get_core_num()), 0); -} - -/** - * Disable the hardware watchdog - */ -void bdk_watchdog_disable(void) -{ - BDK_CSR_WRITE(bdk_numa_local(), BDK_GTI_CWD_WDOGX(bdk_get_core_num()), 0); - BDK_TRACE(INIT, "Watchdog: Disabled\n"); -} - -/** - * Return true if the watchdog is configured and running - * - * @return Non-zero if watchdog is running - */ -int bdk_watchdog_is_running(void) -{ - BDK_CSR_INIT(wdog, bdk_numa_local(), BDK_GTI_CWD_WDOGX(bdk_get_core_num())); - return wdog.s.mode != 0; -} - |