summaryrefslogtreecommitdiff
path: root/src/vendorcode/cavium/bdk/libbdk-boot
diff options
context:
space:
mode:
authorDavid Hendricks <dhendricks@fb.com>2018-03-09 14:30:38 -0800
committerPhilipp Deppenwiese <zaolin.daisuki@gmail.com>2018-07-03 15:53:32 +0000
commit7d48ac5c7dfb52fc470bbad1013b4d460bc6a1e0 (patch)
tree42002ba1e86627339ff4a6cf38efb4b3f00033bb /src/vendorcode/cavium/bdk/libbdk-boot
parentd837e660074e0621d63f59515f933c209441b653 (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')
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-gpio.c70
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-pcie.c68
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-qlm.c515
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-status.c2
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-usb.c62
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot.c98
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-boot/bdk-watchdog.c108
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;
-}
-