aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c
diff options
context:
space:
mode:
authorDavid Hendricks <dhendricks@fb.com>2018-03-09 13:58:27 -0800
committerPatrick Georgi <pgeorgi@google.com>2018-04-06 06:48:11 +0000
commit2004b93aed993aa02bbc588b8d82c22418ac52ec (patch)
treecdd5e95a154e2e0139474288262835a7f5847665 /src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c
parent71cbd71eb5c0e8e13b25b5d5dd2f495e7d2967eb (diff)
soc/cavium: import raw BDK sources
This imports common BDK sources that will be used in subsequent patches. The BDK is licensed under BSD and will be reduced in size and optimized to compile under coreboot. Change-Id: Icb32ee670d9fa9e5c10f9abb298cebf616fa67ad Signed-off-by: David Hendricks <dhendricks@fb.com> Reviewed-on: https://review.coreboot.org/25524 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: David Hendricks <david.hendricks@gmail.com>
Diffstat (limited to 'src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c')
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c1946
1 files changed, 1946 insertions, 0 deletions
diff --git a/src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c b/src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c
new file mode 100644
index 0000000000..d4b412d439
--- /dev/null
+++ b/src/vendorcode/cavium/bdk/libbdk-hal/bdk-config.c
@@ -0,0 +1,1946 @@
+/***********************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 <stdarg.h>
+#include <libfdt.h>
+#include <unistd.h>
+#include "libbdk-arch/bdk-csrs-mio_fus.h"
+#include "libbdk-arch/bdk-csrs-fus.h"
+
+/* Set this define to override the trace the BDK uses. This is most
+ useful with trusted boot when the setup menus are not able to
+ configure the trace level. A possible example: */
+//#define BDK_TRACE_OVERRIDE (1ull << BDK_TRACE_ENABLE_INIT)
+#define BDK_TRACE_OVERRIDE 0
+
+typedef enum
+{
+ BDK_CONFIG_TYPE_INT,
+ BDK_CONFIG_TYPE_STR,
+ BDK_CONFIG_TYPE_STR_LIST,
+ BDK_CONFIG_TYPE_BINARY,
+} bdk_config_type_t;
+
+typedef struct
+{
+ const char *format; /* Printf style format string to create the item name */
+ const bdk_config_type_t ctype;/* Type of this item */
+ int64_t default_value; /* Default value when no present. String defaults are cast to pointers from this */
+ const int64_t min_value;/* Minimum valid value for INT parameters. Unused for Strings */
+ const int64_t max_value;/* Maximum valid value for INT parameters. Unused for Strings */
+} bdk_config_info_t;
+
+static void config_set_defaults(void);
+
+/* Tracing defaults to the level specified here before config files are loaded */
+uint64_t bdk_trace_enables = BDK_TRACE_OVERRIDE;
+
+/* Global variables that contain the config inside a FDT */
+static void *config_fdt;
+static int config_node;
+
+static bdk_config_info_t config_info[__BDK_CONFIG_END] = {
+ /* Board manufacturing data */
+ [BDK_CONFIG_BOARD_MODEL] = {
+ .format = "BOARD-MODEL", /* String, No parameters */
+ .ctype = BDK_CONFIG_TYPE_STR,
+ .default_value = (long)"unknown",
+ },
+ [BDK_CONFIG_BOARD_REVISION] = {
+ .format = "BOARD-REVISION", /* String, No parameters */
+ .ctype = BDK_CONFIG_TYPE_STR,
+ .default_value = (long)"unknown",
+ },
+ [BDK_CONFIG_BOARD_SERIAL] = {
+ .format = "BOARD-SERIAL", /* String, No parameters */
+ .ctype = BDK_CONFIG_TYPE_STR,
+ .default_value = (long)"unknown",
+ },
+ [BDK_CONFIG_MAC_ADDRESS] = {
+ .format = "BOARD-MAC-ADDRESS", /* Int64, No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Default updated at boot based on fuses */
+ .min_value = 0,
+ .max_value = 0xffffffffffffll,
+ },
+ [BDK_CONFIG_MAC_ADDRESS_NUM] = {
+ .format = "BOARD-MAC-ADDRESS-NUM", /* Int, No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 256,
+ },
+ [BDK_CONFIG_MAC_ADDRESS_NUM_OVERRIDE] = {
+ .format = "BOARD-MAC-ADDRESS-NUM-OVERRIDE", /* Int, No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1,
+ .min_value = -1,
+ .max_value = 256,
+ },
+
+ /* Board generic */
+ [BDK_CONFIG_BMC_TWSI] = {
+ .format = "BMC-TWSI", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* TWSI bus number, -1 = disabled */
+ .min_value = -1,
+ .max_value = 5,
+ },
+ [BDK_CONFIG_WATCHDOG_TIMEOUT] = {
+ .format = "WATCHDOG-TIMEOUT", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 0 = disabled */
+ .min_value = 0,
+ .max_value = 10000,
+ },
+ [BDK_CONFIG_TWSI_WRITE] = {
+ .format = "TWSI-WRITE", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_STR_LIST,
+ },
+ [BDK_CONFIG_MDIO_WRITE] = {
+ .format = "MDIO-WRITE", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_STR_LIST,
+ },
+
+ /* Board wiring of network ports and PHYs */
+ [BDK_CONFIG_PHY_ADDRESS] = {
+ .format = "PHY-ADDRESS.N%d.BGX%d.P%d", /* Parameters: Node, Interface, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Default to no PHY */
+ .min_value = -1,
+ .max_value = 0xffffffffll,
+ },
+ [BDK_CONFIG_BGX_ENABLE] = {
+ .format = "BGX-ENABLE.N%d.BGX%d.P%d", /* Parameters: Node, BGX, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1, /* 0 = disable, 1 = enable */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ /* Non-EBB specific SFF8104 board and alike */
+ [BDK_CONFIG_AQUANTIA_PHY] = {
+ .format = "AQUANTIA-PHY.N%d.BGX%d.P%d", /*Parameters: Node, BGX, Port */
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xffffll,
+ },
+
+
+ /* BDK Configuration params */
+ [BDK_CONFIG_VERSION] = {
+ .format = "BDK-VERSION",
+ .ctype = BDK_CONFIG_TYPE_STR,
+ },
+ [BDK_CONFIG_NUM_PACKET_BUFFERS] = {
+ .format = "BDK-NUM-PACKET-BUFFERS",
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Default updated at boot */
+ .min_value = 0,
+ .max_value = 1000000,
+ },
+ [BDK_CONFIG_PACKET_BUFFER_SIZE] = {
+ .format = "BDK-PACKET-BUFFER-SIZE",
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1024, /* bytes */
+ .min_value = 128,
+ .max_value = 32768,
+ },
+ [BDK_CONFIG_SHOW_LINK_STATUS] = {
+ .format = "BDK-SHOW-LINK-STATUS",
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1, /* 0 = off, 1 = on */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_COREMASK] = {
+ .format = "BDK-COREMASK",
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Zero means all cores */
+ .min_value = 0,
+ .max_value = 0xffffffffffffll,
+ },
+ [BDK_CONFIG_BOOT_MENU_TIMEOUT] = {
+ .format = "BDK-BOOT-MENU-TIMEOUT",
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 10, /* seconds */
+ .min_value = 0,
+ .max_value = 300,
+ },
+ [BDK_CONFIG_BOOT_PATH_OPTION] = {
+ .format = "BDK-BOOT-PATH-OPTION",
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 0 = normal, 1 = diagnostics */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_BOOT_NEXT_STAGE] = {
+ .format = "BDK-CONFIG-BOOT-NEXT-STAGE-%s",
+ .ctype = BDK_CONFIG_TYPE_STR,
+ },
+ [BDK_CONFIG_TRACE] = {
+ .format = "BDK-CONFIG-TRACE",
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* bitmask */
+ .min_value = 0,
+ .max_value = 0x7fffffffffffffffull,
+ },
+
+ /* Chip feature items */
+ [BDK_CONFIG_MULTI_NODE] = {
+ .format = "MULTI-NODE", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 2, /* 2 = Auto */
+ .min_value = 0,
+ .max_value = 2,
+ },
+ [BDK_CONFIG_PCIE_EA] = {
+ .format = "PCIE-ENHANCED-ALLOCATION", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1, /* 1 = EA supported, 0 = EA not supported */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_PCIE_ORDERING] = {
+ .format = "PCIE-ORDERING", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 1 = Wait for commit, 0 = Don't wait for commit */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_PCIE_PRESET_REQUEST_VECTOR] = {
+ .format = "PCIE-PRESET-REQUEST-VECTOR.N%d.PORT%d", /* Parameters: Node, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0x593, /* Value for PCIERCX_CFG554[PRV] */
+ .min_value = 0,
+ .max_value = 0xffff,
+ },
+ [BDK_CONFIG_PCIE_WIDTH] = {
+ .format = "PCIE-WIDTH.N%d.PORT%d", /* Parameters: Node, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Width override for PCIe links */
+ .min_value = -1,
+ .max_value = 16,
+ },
+ [BDK_CONFIG_PCIE_PHYSICAL_SLOT] = {
+ .format = "PCIE-PHYSICAL-SLOT.N%d.PORT%d", /* Parameters: Node, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Define which physical slot we connect to on the board */
+ .min_value = -1,
+ .max_value = 8191,
+ },
+ [BDK_CONFIG_PCIE_FLASH] = {
+ .format = "PCIE-FLASH.N%d.PORT%d", /* Parameters: Node, Port */
+ .ctype = BDK_CONFIG_TYPE_STR_LIST,
+ },
+ [BDK_CONFIG_CCPI_LANE_REVERSE] = {
+ .format = "CCPI-LANE-REVERSE", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 0 = No forced lane reversal, 1 = forced lane reversal */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_CHIP_SKU] = {
+ .format = "CHIP-SKU.NODE%d", /* Parameter: Node */
+ .ctype = BDK_CONFIG_TYPE_STR,
+ .default_value = (long)"TBD",
+ },
+ [BDK_CONFIG_CHIP_SERIAL] = {
+ .format = "CHIP-SERIAL.NODE%d", /* Parameter: Node */
+ .ctype = BDK_CONFIG_TYPE_STR,
+ .default_value = (long)"TBD",
+ },
+ [BDK_CONFIG_CHIP_UNIQUE_ID] = {
+ .format = "CHIP-UNIQUE-ID.NODE%d", /* Parameter: Node */
+ .ctype = BDK_CONFIG_TYPE_STR,
+ .default_value = (long)"TBD",
+ },
+
+ /* QLM related config */
+ [BDK_CONFIG_QLM_AUTO_CONFIG] = {
+ .format = "QLM-AUTO-CONFIG", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 0 = off, 1 = on */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ /* SFF8104 related QLM config */
+ [BDK_CONFIG_QLM_DIP_AUTO_CONFIG] = {
+ .format = "QLM-DIP-AUTO-CONFIG", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 0 = off, 1 = on */
+ .min_value = 0,
+ .max_value = 1,
+ },
+
+ [BDK_CONFIG_QLM_MODE] = {
+ .format = "QLM-MODE.N%d.QLM%d", /* Parameters: Node, QLM */
+ .ctype = BDK_CONFIG_TYPE_STR,
+ },
+ [BDK_CONFIG_QLM_FREQ] = {
+ .format = "QLM-FREQ.N%d.QLM%d", /* Parameters: Node, QLM */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Mhz */
+ .min_value = 0,
+ .max_value = 10312,
+ },
+ [BDK_CONFIG_QLM_CLK] = {
+ .format = "QLM-CLK.N%d.QLM%d", /* Parameters: Node, QLM */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 2, /* 2 = External */
+ .min_value = 0,
+ .max_value = 2,
+ },
+ [BDK_CONFIG_QLM_TUNING_TX_SWING] = {
+ .format = "QLM-TUNING-TX-SWING.N%d.QLM%d.LANE%d", /* Parameters: Node, QLM, Lane */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Default of no tuning */
+ .min_value = -1,
+ .max_value = 31,
+ },
+ [BDK_CONFIG_QLM_TUNING_TX_PREMPTAP] = {
+ .format = "QLM-TUNING-TX-PREMPTAP.N%d.QLM%d.LANE%d", /* Parameters: Node, QLM, Lane */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Default of no tuning */
+ .min_value = -1,
+ .max_value = 511,
+ },
+ [BDK_CONFIG_QLM_TUNING_TX_GAIN] = {
+ .format = "QLM-TUNING-TX-GAIN.N%d.QLM%d.LANE%d", /* Parameters: Node, QLM, Lane */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Default of no tuning */
+ .min_value = -1,
+ .max_value = 7,
+ },
+ [BDK_CONFIG_QLM_TUNING_TX_VBOOST] = {
+ .format = "QLM-TUNING-TX-VBOOST.N%d.QLM%d.LANE%d", /* Parameters: Node, QLM, Lane */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Default of no tuning */
+ .min_value = -1,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_QLM_CHANNEL_LOSS] = {
+ .format = "QLM-CHANNEL-LOSS.N%d.QLM%d", /* Parameters: Node, QLM */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Default will use Cavium defaults */
+ .min_value = -1,
+ .max_value = 40,
+ },
+
+ /* DRAM configuration options */
+ [BDK_CONFIG_DDR_SPEED] = {
+ .format = "DDR-SPEED.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* In MT/s */
+ .min_value = 0,
+ .max_value = 2400,
+ },
+ [BDK_CONFIG_DDR_ALT_REFCLK] = {
+ .format = "DDR-ALT-REFCLK.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Mhz */
+ .min_value = 0,
+ .max_value = 100,
+ },
+ [BDK_CONFIG_DDR_SPD_ADDR] = {
+ .format = "DDR-CONFIG-SPD-ADDR.DIMM%d.LMC%d.N%d", /* Parameters: DIMM, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xffff,
+ },
+ [BDK_CONFIG_DDR_SPD_DATA] = {
+ .format = "DDR-CONFIG-SPD-DATA.DIMM%d.LMC%d.N%d", /* Parameters: DIMM, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_BINARY,
+ },
+ [BDK_CONFIG_DDR_RANKS_DQX_CTL] = {
+ .format = "DDR-CONFIG-DQX-CTL.RANKS%d.DIMMS%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xf,
+ },
+ [BDK_CONFIG_DDR_RANKS_WODT_MASK] = {
+ .format = "DDR-CONFIG-WODT-MASK.RANKS%d.DIMMS%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xfffffff,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE1_PASR] = {
+ .format = "DDR-CONFIG-MODE1-PASR.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0x7,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE1_ASR] = {
+ .format = "DDR-CONFIG-MODE1-ASR.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE1_SRT] = {
+ .format = "DDR-CONFIG-MODE1-SRT.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR] = {
+ .format = "DDR-CONFIG-MODE1-RTT-WR.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT, // Split for extension bit
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0x7,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE1_DIC] = {
+ .format = "DDR-CONFIG-MODE1-DIC.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0x3,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM] = {
+ .format = "DDR-CONFIG-MODE1-RTT-NOM.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0x7,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE1_DB_OUTPUT_IMPEDANCE] = {
+ .format = "DDR-CONFIG-MODE1-DB-OUTPUT-IMPEDANCE.RANKS%d.DIMMS%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT, // Not per RANK, only one
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0x7,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK] = {
+ .format = "DDR-CONFIG-MODE2-RTT-PARK.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0x7,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE] = {
+ .format = "DDR-CONFIG-MODE2-VREF-VALUE.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0x3f,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE] = {
+ .format = "DDR-CONFIG-MODE2-VREF-RANGE.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, Rank, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_RANKS_MODE2_VREFDQ_TRAIN_EN] = {
+ .format = "DDR-CONFIG-MODE2-VREFDQ-TRAIN-EN.RANKS%d.DIMMS%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT, // Not per RANK, only one
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+
+ [BDK_CONFIG_DDR_RANKS_RODT_CTL] = {
+ .format = "DDR-CONFIG-RODT-CTL.RANKS%d.DIMMS%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xf,
+ },
+ [BDK_CONFIG_DDR_RANKS_RODT_MASK] = {
+ .format = "DDR-CONFIG-RODT-MASK.RANKS%d.DIMMS%d.LMC%d.N%d", /* Parameters: Num Ranks, Num DIMMs, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xfffffff,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MIN_RTT_NOM_IDX] = {
+ .format = "DDR-CONFIG-CUSTOM-MIN-RTT-NOM-IDX.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1,
+ .min_value = 0,
+ .max_value = 7,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MAX_RTT_NOM_IDX] = {
+ .format = "DDR-CONFIG-CUSTOM-MAX-RTT-NOM-IDX.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 5,
+ .min_value = 0,
+ .max_value = 7,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MIN_RODT_CTL] = {
+ .format = "DDR-CONFIG-CUSTOM-MIN-RODT-CTL.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1,
+ .min_value = 0,
+ .max_value = 7,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MAX_RODT_CTL] = {
+ .format = "DDR-CONFIG-CUSTOM-MAX-RODT-CTL.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 5,
+ .min_value = 0,
+ .max_value = 7,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_CK_CTL] = {
+ .format = "DDR-CONFIG-CUSTOM-CK-CTL.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xffff,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_CMD_CTL] = {
+ .format = "DDR-CONFIG-CUSTOM-CMD-CTL.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xffff,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_CTL_CTL] = {
+ .format = "DDR-CONFIG-CUSTOM-CTL-CTL.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xf,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MIN_CAS_LATENCY] = {
+ .format = "DDR-CONFIG-CUSTOM-MIN-CAS-LATENCY.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xffff,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_OFFSET_EN] = {
+ .format = "DDR-CONFIG-CUSTOM-OFFSET-EN.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_OFFSET] = {
+ .format = "DDR-CONFIG-CUSTOM-OFFSET.%s.LMC%d.N%d", /* Parameters: Type(UDIMM,RDIMM), LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT, // UDIMM or RDIMM
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xf,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMPUTE] = {
+ .format = "DDR-CONFIG-CUSTOM-RLEVEL-COMPUTE.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMP_OFFSET] = {
+ .format = "DDR-CONFIG-CUSTOM-RLEVEL-COMP-OFFSET.%s.LMC%d.N%d", /* Parameters: Type(UDIMM,RDIMM), LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT, // UDIMM or RDIMM
+ .default_value = 2,
+ .min_value = 0,
+ .max_value = 0xffff,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_DDR2T] = {
+ .format = "DDR-CONFIG-CUSTOM-DDR2T.%s.LMC%d.N%d", /* Parameters: Type(UDIMM,RDIMM), LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT, // UDIMM or RDIMM
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_DISABLE_SEQUENTIAL_DELAY_CHECK] = {
+ .format = "DDR-CONFIG-CUSTOM-DISABLE-SEQUENTIAL-DELAY-CHECK.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MAXIMUM_ADJACENT_RLEVEL_DELAY_INCREMENT] = {
+ .format = "DDR-CONFIG-CUSTOM-MAXIMUM-ADJACENT-RLEVEL-DELAY-INCREMENT.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xffff,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_PARITY] = {
+ .format = "DDR-CONFIG-CUSTOM-PARITY.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_FPRCH2] = {
+ .format = "DDR-CONFIG-CUSTOM-FPRCH2.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 0xf,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MODE32B] = {
+ .format = "DDR-CONFIG-CUSTOM-MODE32B.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_MEASURED_VREF] = {
+ .format = "DDR-CONFIG-CUSTOM-MEASURED-VREF.LMC%d.N%d", /* Parameters: LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_DLL_WRITE_OFFSET] = {
+ .format = "DDR-CONFIG-CUSTOM-DLL-WRITE-OFFSET.BYTE%d.LMC%d.N%d", /* Parameters: Byte, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = -63,
+ .max_value = 63,
+ },
+ [BDK_CONFIG_DDR_CUSTOM_DLL_READ_OFFSET] = {
+ .format = "DDR-CONFIG-CUSTOM-DLL-READ-OFFSET.BYTE%d.LMC%d.N%d", /* Parameters: Byte, LMC, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0,
+ .min_value = -63,
+ .max_value = 63,
+ },
+
+ /* High level DRAM options */
+ [BDK_CONFIG_DRAM_VERBOSE] = {
+ .format = "DDR-VERBOSE", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 0 = off */
+ .min_value = 0,
+ .max_value = 255,
+ },
+ [BDK_CONFIG_DRAM_BOOT_TEST] = {
+ .format = "DDR-TEST-BOOT", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* 0 = off, 1 = on */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_DRAM_CONFIG_GPIO] = {
+ .format = "DDR-CONFIG-GPIO", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* -1 = disabled, otherwise GPIO number */
+ .min_value = -1,
+ .max_value = 63,
+ },
+ [BDK_CONFIG_DRAM_SCRAMBLE] = {
+ .format = "DDR-CONFIG-SCRAMBLE", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 2, /* 0=off, 1=on, 2=trust on, non-trust off */
+ .min_value = 0,
+ .max_value = 2,
+ },
+
+ /* USB */
+ [BDK_CONFIG_USB_PWR_GPIO] = {
+ .format = "USB-PWR-GPIO.N%d.PORT%d", /* Parameters: Node, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* GPIO number, or -1 for none */
+ .min_value = -1,
+ .max_value = 49,
+ },
+ [BDK_CONFIG_USB_PWR_GPIO_POLARITY] = {
+ .format = "USB-PWR-GPIO-POLARITY.N%d.PORT%d", /* Parameters: Node, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 1, /* GPIO polarity: 1=high, 0=low */
+ .min_value = 0,
+ .max_value = 1,
+ },
+ [BDK_CONFIG_USB_REFCLK_SRC] = {
+ .format = "USB-REFCLK-SRC.N%d.PORT%d", /* Parameters: Node, Port */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Clock Source (SS:HS)
+ ** 0 - SS(USB_REF_CLK) HS(USB_REF_CLK)
+ ** 1 - SS(DLMC_REF_CLK0) HS(DLMC_REF_CLK0)
+ ** 2 - SS(DLMC_REF_CLK1) HS(DLMC_REF_CLK1)
+ ** 3 - SS(USB_REF_CLK) HS(PLL_REF_CLK)
+ ** 4 - SS(DLMC_REF_CLK0) HS(PLL_REF_CLK)
+ ** 5 - SS(DLMC_REF_CLK1) HS(PLL_REF_CLK)
+ */
+ .min_value = 0,
+ .max_value = 5,
+ },
+
+ /* Nitrox reset - For CN88XX SC and SNT part. High drives Nitrox DC_OK high */
+ [BDK_CONFIG_NITROX_GPIO] = {
+ .format = "NITROX-GPIO.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* GPIO number, or -1 for none */
+ .min_value = -1,
+ .max_value = 49,
+ },
+
+ /* How EYE diagrams are captured from a QLM */
+ [BDK_CONFIG_EYE_ZEROS] = {
+ .format = "QLM-EYE-NUM-ZEROS", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 2,
+ .min_value = 1,
+ .max_value = 63,
+ },
+ [BDK_CONFIG_EYE_SAMPLE_TIME] = {
+ .format = "QLM-EYE-SAMPLE-TIME", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 400, /* us */
+ .min_value = 20, /* us */
+ .max_value = 10000000, /* us */
+ },
+ [BDK_CONFIG_EYE_SETTLE_TIME] = {
+ .format = "QLM-EYE-SETTLE-TIME", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 50, /* us */
+ .min_value = 20, /* us */
+ .max_value = 100000, /* us */
+ },
+
+ /* SGPIO */
+ [BDK_CONFIG_SGPIO_SCLOCK_FREQ] = {
+ .format = "SGPIO-SCLOCK-FREQ.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 10000, /* Hz */
+ .min_value = 128, /* Hz */
+ .max_value = 100000, /* Hz */
+ },
+ [BDK_CONFIG_SGPIO_PIN_POWER] = {
+ .format = "SGPIO-PIN-POWER.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* GPIO number, or -1 for none */
+ .min_value = -1,
+ .max_value = 50,
+ },
+ [BDK_CONFIG_SGPIO_PIN_SCLOCK] = {
+ .format = "SGPIO-PIN-SCLOCK.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* GPIO number, or -1 for none */
+ .min_value = -1,
+ .max_value = 50,
+ },
+ [BDK_CONFIG_SGPIO_PIN_SLOAD] = {
+ .format = "SGPIO-PIN-SLOAD.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* GPIO number, or -1 for none */
+ .min_value = -1,
+ .max_value = 50,
+ },
+ [BDK_CONFIG_SGPIO_PIN_SDATAOUT] = {
+ .format = "SGPIO-PIN-SDATAOUT.N%d.D%d", /* Parameters: Node, Dataline */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* GPIO number, or -1 for none */
+ .min_value = -1,
+ .max_value = 50,
+ },
+
+ /* VRM temperature throttling */
+ [BDK_CONFIG_VRM_TEMP_TRIP] = {
+ .format = "VRM-TEMP-TRIP.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 110, /* Degrees C */
+ .min_value = 0, /* Degrees C */
+ .max_value = 110, /* Degrees C. Max die temp plus 5 for uncertainty of measurement */
+ },
+ [BDK_CONFIG_VRM_TEMP_HIGH] = {
+ .format = "VRM-TEMP-HIGH.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 110, /* Degrees C */
+ .min_value = 0, /* Degrees C */
+ .max_value = 110, /* Degrees C. Max die temp plus 5 for uncertainty of measurement */
+ },
+ [BDK_CONFIG_VRM_TEMP_LOW] = {
+ .format = "VRM-TEMP-LOW.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 100, /* Degrees C */
+ .min_value = 0, /* Degrees C */
+ .max_value = 110, /* Degrees C. Max die temp plus 5 for uncertainty of measurement */
+ },
+ [BDK_CONFIG_VRM_THROTTLE_NORMAL] = {
+ .format = "VRM-THROTTLE-NORMAL.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 65, /* Percentage */
+ .min_value = 1, /* Percentage */
+ .max_value = 100, /* Percentage */
+ },
+ [BDK_CONFIG_VRM_THROTTLE_THERM] = {
+ .format = "VRM-THROTTLE-THERM.N%d", /* Parameters: Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 15, /* Percentage */
+ .min_value = 1, /* Percentage */
+ .max_value = 100, /* Percentage */
+ },
+
+ /* Generic GPIO, unrelated to a specific block */
+ [BDK_CONFIG_GPIO_PIN_SELECT] = {
+ .format = "GPIO-PIN-SELECT-GPIO%d.N%d", /* Parameters: GPIO, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = -1, /* Hardware default, normal GPIO pin */
+ .min_value = 0, /* GPIO_PIN_SEL_E enumeration */
+ .max_value = 65535, /* GPIO_PIN_SEL_E enumeration */
+ },
+ [BDK_CONFIG_GPIO_POLARITY] = {
+ .format = "GPIO-POLARITY-GPIO%d.N%d", /* Parameters: GPIO, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Hardware default, not inverted */
+ .min_value = 0, /* Not inverted */
+ .max_value = 1, /* Inverted */
+ },
+
+ /* PBUS */
+ [BDK_CONFIG_PBUS_CFG] = {
+ .format = "PBUS-CFG.REGION%d.N%d", /* Parameters: Region, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Hardware default */
+ .min_value = 0, /* No change */
+ .max_value = 0x0000ffffffffffffll, /* PBUS_REGX_CFG value */
+ },
+ [BDK_CONFIG_PBUS_TIM] = {
+ .format = "PBUS-TIM.REGION%d.N%d", /* Parameters: Region, Node */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Hardware default, not inverted */
+ .min_value = 0x8000000000000000ll, /* PBUS_REGX_TIM value, zero is no change */
+ .max_value = 0x7fffffffffffffffll, /* PBUS_REGX_TIM value */
+ },
+
+ /* Trusted boot information */
+ [BDK_CONFIG_TRUST_CSIB] = {
+ .format = "TRUST-CSIB", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_BINARY,
+ .default_value = 0, /* Hardware default */
+ },
+ [BDK_CONFIG_TRUST_ROT_ADDR] = {
+ .format = "TRUST-ROT-ADDR", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* Non-trusted */
+ .min_value = 0, /* No key */
+ .max_value = 0x0000ffffffffffffll, /* Address in key memory */
+ },
+ [BDK_CONFIG_TRUST_BSSK_ADDR] = {
+ .format = "TRUST-BSSK-ADDR", /* No parameters */
+ .ctype = BDK_CONFIG_TYPE_INT,
+ .default_value = 0, /* No HUK, so no BSSK */
+ .min_value = 0, /* No HUK, so no BSSK */
+ .max_value = 0x0000ffffffffffffll, /* Address in key memory */
+ },
+};
+
+/**
+ * Look up a configuration item in the environment.
+ *
+ * @param name
+ *
+ * @return
+ */
+static const char *get_value(const char *name, int *blob_size)
+{
+ if (!config_fdt)
+ {
+ bdk_error("bdk-config asked for %s before configuration loaded\n", name);
+ return NULL;
+ }
+
+ char n[64];
+ strncpy(n, name, sizeof(n));
+ n[sizeof(n)-1] = '\0';
+
+ while (*n)
+ {
+ const char *val = fdt_getprop(config_fdt, config_node, n, blob_size);
+ if (val)
+ return val;
+
+ char *p = strrchr(n, '.');
+ if (p)
+ *p = '\0';
+ else
+ break;
+ }
+ return NULL;
+}
+
+/**
+ * Get an integer configuration item
+ *
+ * @param cfg_item Config item to get. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ *
+ * @return The value of the configuration item, or def_value if the item is not set
+ */
+int64_t bdk_config_get_int(bdk_config_t cfg_item, ...)
+{
+ /* Make sure the correct access function was called */
+ if (config_info[cfg_item].ctype != BDK_CONFIG_TYPE_INT)
+ bdk_fatal("bdk_config_get_int() called for %s, not an int\n",
+ config_info[cfg_item].format);
+
+ char name[64];
+ va_list args;
+ va_start(args, cfg_item);
+ vsnprintf(name, sizeof(name)-1, config_info[cfg_item].format, args);
+ va_end(args);
+
+ const char *val = get_value(name, NULL);
+ if (val)
+ {
+ int count;
+ int64_t tmp;
+ if ((val[0] == '0') && (val[1] == 'x'))
+ count = sscanf(val + 2, "%lx", &tmp);
+ else
+ count = sscanf(val, "%li", &tmp);
+ if (count == 1)
+ {
+ if ((tmp < config_info[cfg_item].min_value) || (tmp > config_info[cfg_item].max_value))
+ {
+ bdk_warn("Out of range for %s = \"%s\", using default\n", name, val);
+ return config_info[cfg_item].default_value;
+ }
+ return tmp;
+ }
+ else
+ {
+ bdk_warn("Failed to parse %s = \"%s\", using default\n", name, val);
+ return config_info[cfg_item].default_value;
+ }
+ }
+ else
+ return config_info[cfg_item].default_value;
+}
+
+/**
+ * Get a string configuration item
+ *
+ * @param cfg_item Config item to get. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ *
+ * @return The value of the configuration item, or def_value if the item is not set
+ */
+const char *bdk_config_get_str(bdk_config_t cfg_item, ...)
+{
+ /* Make sure the correct access function was called */
+ if (config_info[cfg_item].ctype != BDK_CONFIG_TYPE_STR)
+ bdk_fatal("bdk_config_get_str() called for %s, not a str\n",
+ config_info[cfg_item].format);
+
+ char name[64];
+ va_list args;
+ va_start(args, cfg_item);
+ vsnprintf(name, sizeof(name)-1, config_info[cfg_item].format, args);
+
+ if (BDK_CONFIG_QLM_MODE == cfg_item)
+ {
+ char name2[64];
+ vsnprintf(name2, sizeof(name2)-1,"QLM-MODE.N%d.DLM%d" , args);
+ const char *val = get_value(name2, NULL);
+ if (val)
+ bdk_warn("%s: QLM-MODE.N%%d.DLM%%d format depricated. Please use QLM-MODE.N%%d.QLM%%d instead\n", name2);
+
+ }
+ va_end(args);
+
+ const char *val = get_value(name, NULL);
+ if (val)
+ return val;
+ else
+ return (const char *)config_info[cfg_item].default_value;
+}
+
+/**
+ * Get a binary blob
+ *
+ * @param blob_size Integer to receive the size of the blob
+ * @param cfg_item Config item to get. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ *
+ * @return The value of the configuration item, or def_value if the item is not set
+ */
+const void* bdk_config_get_blob(int *blob_size, bdk_config_t cfg_item, ...)
+{
+ char name[64];
+ va_list args;
+ va_start(args, cfg_item);
+ vsnprintf(name, sizeof(name)-1, config_info[cfg_item].format, args);
+ va_end(args);
+
+ const void *val = get_value(name, blob_size);
+ if (val)
+ return val;
+ else
+ return (const void *)config_info[cfg_item].default_value;
+}
+
+/**
+ * Set an integer configuration item. Note this only sets the item in memory,
+ * persistent storage is not updated. The optional parameters for the setting are
+ * not supplied, meaning this function only changes the global default.
+ *
+ * @param value Configuration item value
+ * @param cfg_item Config item to set. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ */
+void bdk_config_set_int_no_param(int64_t value, bdk_config_t cfg_item)
+{
+ /* Make sure the correct access function was called */
+ if (config_info[cfg_item].ctype != BDK_CONFIG_TYPE_INT)
+ bdk_fatal("bdk_config_set_int_no_param() called for %s, not an int\n",
+ config_info[cfg_item].format);
+
+ char name[64];
+ char valstr[20];
+ /* Create a name without the optional parameters */
+ strncpy(name, config_info[cfg_item].format, sizeof(name) - 1);
+ name[sizeof(name) - 1] = 0;
+ char *ptr = strchr(name, '.');
+ if (ptr)
+ *ptr = 0;
+
+ if (!config_fdt)
+ {
+ bdk_error("bdk-config set %s before configuration loaded\n", name);
+ return;
+ }
+ if ((value < config_info[cfg_item].min_value) || (value > config_info[cfg_item].max_value))
+ {
+ bdk_error("Set out of range for %s = \"0x%lx\", ignoring\n", name, value);
+ return;
+ }
+
+ if (value < 10)
+ snprintf(valstr, sizeof(valstr), "%ld", value);
+ else
+ snprintf(valstr, sizeof(valstr), "0x%lx", value);
+
+ int status = fdt_setprop_string(config_fdt, config_node, name, valstr);
+ if (status < 0)
+ bdk_fatal("Failed to set %s=%s in FDT\n", name, valstr);
+}
+
+/**
+ * Set an integer configuration item. Note this only sets the item in memory,
+ * persistent storage is not updated.
+ *
+ * @param value Configuration item value
+ * @param cfg_item Config item to set. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ */
+void bdk_config_set_int(int64_t value, bdk_config_t cfg_item, ...)
+{
+ /* Make sure the correct access function was called */
+ if (config_info[cfg_item].ctype != BDK_CONFIG_TYPE_INT)
+ bdk_fatal("bdk_config_set_int() called for %s, not an int\n",
+ config_info[cfg_item].format);
+
+ char name[64];
+ char valstr[20];
+ va_list args;
+ va_start(args, cfg_item);
+ vsnprintf(name, sizeof(name)-1, config_info[cfg_item].format, args);
+ va_end(args);
+
+ if (!config_fdt)
+ {
+ bdk_error("bdk-config set %s before configuration loaded\n", name);
+ return;
+ }
+ if ((value < config_info[cfg_item].min_value) || (value > config_info[cfg_item].max_value))
+ {
+ bdk_error("Set out of range for %s = \"0x%lx\", ignoring\n", name, value);
+ return;
+ }
+
+ if (value < 10)
+ snprintf(valstr, sizeof(valstr), "%ld", value);
+ else
+ snprintf(valstr, sizeof(valstr), "0x%lx", value);
+
+ int status = fdt_setprop_string(config_fdt, config_node, name, valstr);
+ if (status < 0)
+ bdk_fatal("Failed to set %s=%s in FDT\n", name, valstr);
+}
+
+/**
+ * Set an integer configuration item. Note this only sets the item in memory,
+ * persistent storage is not updated.
+ *
+ * @param value Configuration item value
+ * @param cfg_item Config item to set. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ */
+void bdk_config_set_str(const char *value, bdk_config_t cfg_item, ...)
+{
+ /* Make sure the correct access function was called */
+ if (config_info[cfg_item].ctype != BDK_CONFIG_TYPE_STR)
+ bdk_fatal("bdk_config_set_str() called for %s, not a str\n",
+ config_info[cfg_item].format);
+
+ char name[64];
+ va_list args;
+
+ va_start(args, cfg_item);
+ vsnprintf(name, sizeof(name)-1, config_info[cfg_item].format, args);
+ va_end(args);
+
+ if (!config_fdt)
+ {
+ bdk_error("bdk-config set %s before configuration loaded\n", name);
+ return;
+ }
+
+ int status;
+ if (value)
+ status = fdt_setprop_string(config_fdt, config_node, name, value);
+ else
+ status = fdt_delprop(config_fdt, config_node, name);
+
+ if ((status < 0) && (status != -FDT_ERR_NOTFOUND))
+ bdk_fatal("Failed to set %s=%s in FDT\n", name, value);
+}
+
+/**
+ * Set a blob configuration item. Note this only sets the
+ * item in memory, persistent storage is not updated. The optional
+ * parameters for the setting are not supplied, meaning this function
+ * only changes the global default.
+ *
+ * @param size Size of the item in bytes. A size of zero removes the device tree field
+ * @param value Configuration item value
+ * @param cfg_item Config item to set. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ */
+void bdk_config_set_blob_no_param(int size, const void *value, bdk_config_t cfg_item)
+{
+ /* Make sure the correct access function was called */
+ if ((config_info[cfg_item].ctype != BDK_CONFIG_TYPE_BINARY) &&
+ (config_info[cfg_item].ctype != BDK_CONFIG_TYPE_STR_LIST))
+ bdk_fatal("bdk_config_set_blob() called for %s, not binary\n",
+ config_info[cfg_item].format);
+
+ char name[64];
+ /* Create a name without the optional parameters */
+ strncpy(name, config_info[cfg_item].format, sizeof(name) - 1);
+ name[sizeof(name) - 1] = 0;
+ char *ptr = strchr(name, '.');
+ if (ptr)
+ *ptr = 0;
+
+ if (!config_fdt)
+ {
+ bdk_error("bdk-config set %s before configuration loaded\n", name);
+ return;
+ }
+
+ int status;
+ if (size)
+ status = fdt_setprop(config_fdt, config_node, name, value, size);
+ else
+ status = fdt_delprop(config_fdt, config_node, name);
+
+ if ((status < 0) && (status != -FDT_ERR_NOTFOUND))
+ bdk_fatal("Failed to set %s in FDT\n", name);
+}
+
+/**
+ * Set a blob configuration item. Note this only sets the
+ * item in memory, persistent storage is not updated.
+ *
+ * @param size Size of the item in bytes. A size of zero removes the device tree field
+ * @param value Configuration item value
+ * @param cfg_item Config item to set. If the item takes parameters (see bdk_config_t), then the
+ * parameters are listed following cfg_item.
+ */
+void bdk_config_set_blob(int size, const void *value, bdk_config_t cfg_item, ...)
+{
+ /* Make sure the correct access function was called */
+ if ((config_info[cfg_item].ctype != BDK_CONFIG_TYPE_BINARY) &&
+ (config_info[cfg_item].ctype != BDK_CONFIG_TYPE_STR_LIST))
+ bdk_fatal("bdk_config_set_blob() called for %s, not binary\n",
+ config_info[cfg_item].format);
+
+ char name[64];
+ va_list args;
+
+ va_start(args, cfg_item);
+ vsnprintf(name, sizeof(name)-1, config_info[cfg_item].format, args);
+ va_end(args);
+
+ if (!config_fdt)
+ {
+ bdk_error("bdk-config set %s before configuration loaded\n", name);
+ return;
+ }
+
+ int status;
+ if (size)
+ status = fdt_setprop(config_fdt, config_node, name, value, size);
+ else
+ status = fdt_delprop(config_fdt, config_node, name);
+
+ if ((status < 0) && (status != -FDT_ERR_NOTFOUND))
+ bdk_fatal("Failed to set %s in FDT\n", name);
+}
+
+/**
+ * Multiple functions need to display the config item help string in a format
+ * suitable for inclusion in a device tree. This function displays the help
+ * message properly indented and such.
+ *
+ * @param cfg Config item to display help for
+ */
+static void display_help(bdk_config_t cfg)
+{
+ /* Print the help text as a comment before the entry */
+ /* Indent with tabs like Linux requires */
+ printf("\n");
+ printf("\t/* ");
+ const char *ptr = bdk_config_get_help(cfg);
+ while (*ptr)
+ {
+ putchar(*ptr);
+ if (*ptr == '\n')
+ putchar('\t');
+ ptr++;
+ }
+ printf(" */\n");
+ /* Print the parameter and its default value a comment. This will be
+ a reference that is easy for the user to change */
+ printf("\t//%s = ", config_info[cfg].format);
+ switch (config_info[cfg].ctype)
+ {
+ case BDK_CONFIG_TYPE_INT:
+ if (config_info[cfg].default_value < 10)
+ printf("\"%ld\"", config_info[cfg].default_value);
+ else
+ printf("\"0x%lx\"", config_info[cfg].default_value);
+ break;
+ case BDK_CONFIG_TYPE_STR:
+ case BDK_CONFIG_TYPE_STR_LIST:
+ if (config_info[cfg].default_value)
+ printf("\"%s\"", (const char *)config_info[cfg].default_value);
+ else
+ printf("\"\"");
+ break;
+ case BDK_CONFIG_TYPE_BINARY:
+ printf("[]");
+ break;
+ }
+ printf(";\n");
+}
+
+/**
+ * Display the active configuration as a valid device tree
+ */
+void bdk_config_show(void)
+{
+ /* Output the standard DTS headers */
+ printf("/dts-v1/;\n");
+ printf("\n");
+ printf("/ {\n");
+ printf("cavium,bdk {\n");
+ for (bdk_config_t cfg = 0; cfg < __BDK_CONFIG_END; cfg++)
+ {
+ /* Show the help message */
+ display_help(cfg);
+
+ /* Figure out how much of the config item is fixed versus
+ the optional parameters */
+ const char *format = config_info[cfg].format;
+ const char *format_param = strchr(format, '.');
+ int format_length = 0;
+ if (format_param)
+ format_length = format_param - format;
+
+ /* Loop through all device tree entries displaying the ones that
+ match this format */
+ int offset = fdt_first_property_offset(config_fdt, config_node);
+ while (offset >= 0)
+ {
+ /* Get the device tree item */
+ const char *name = NULL;
+ int data_size = 0;
+ const char *data = fdt_getprop_by_offset(config_fdt, offset, &name, &data_size);
+ const char *data_end = data + data_size;
+ /* Find the first param */
+ const char *name_param = strchr(name, '.');
+ int name_length = 0;
+ if (name_param)
+ {
+ /* We want to compare up to the first param */
+ name_length = name_param - name;
+ /* If the lengths are different not including the parameters,
+ then we force a full matchn which will always fail */
+ if (name_length != format_length)
+ name_length = 0;
+ }
+ else /* No params, match base of format */
+ name_length = format_length;
+
+ /* Check if it matches the current config format */
+ int match;
+ if (name_length)
+ {
+ /* Check the prefix */
+ match = strncmp(name, format, name_length);
+ if (match == 0)
+ {
+ /* Prefix matched. We only really match if the next
+ character is the end of the string or a '.' */
+ if ((name[name_length] != 0) && (name[name_length] != '.'))
+ match = 1;
+ }
+ }
+ else
+ match = strcmp(name, format);
+ /* Print matching entries */
+ if (match == 0)
+ {
+ if (config_info[cfg].ctype == BDK_CONFIG_TYPE_BINARY)
+ {
+ printf("\t%s = [", name);
+ const char *ptr = data;
+ while (ptr < data_end)
+ {
+ printf(" %02x", (int)*ptr);
+ ptr++;
+ }
+ printf(" ]");
+ }
+ else
+ {
+ printf("\t%s = \"%s\"", name, data);
+ data += strlen(data) + 1;
+ while (data < data_end)
+ {
+ printf(",\n\t\t\"%s\"", data);
+ data += strlen(data) + 1;
+ }
+ }
+ printf(";\n");
+ }
+ offset = fdt_next_property_offset(config_fdt, offset);
+ }
+ }
+ /* Output the standard DTS footers */
+ printf("}; /* cavium,bdk */\n");
+ printf("}; /* / */\n");
+}
+
+/**
+ * Display a list of all possible config items with help text
+ */
+void bdk_config_help(void)
+{
+ /* Write out formatted as part of a device tree source (dts) file */
+ printf("/dts-v1/;\n");
+ printf("\n");
+ printf("/ {\n");
+ printf("cavium,bdk {\n");
+ for (bdk_config_t cfg = 0; cfg < __BDK_CONFIG_END; cfg++)
+ display_help(cfg);
+ printf("}; /* cavium,bdk */\n");
+ printf("}; /* / */\n");
+}
+
+
+/**
+ * Save the current configuration to flash
+ *
+ * @return Zero on success, negative on failure
+ */
+int bdk_config_save(void)
+{
+ /* Pack the FDT so it uses less space */
+ int status = fdt_pack(config_fdt);
+ if (status < 0)
+ {
+ bdk_error("FDT error %d: %s\n", status, fdt_strerror(status));
+ return -1;
+ }
+
+ /* Calculate a CRC32 of the FDT */
+ int fdt_size = fdt_totalsize(config_fdt);
+ uint32_t crc32 = bdk_crc32(config_fdt, fdt_size, 0);
+
+ /* Open the output file */
+ FILE *outf = fopen("/fatfs/default.dtb", "wb");
+ if (!outf)
+ {
+ bdk_error("Failed to open flash");
+ return -1;
+ }
+
+ /* Write the FDT */
+ if (fwrite(config_fdt, fdt_size, 1, outf) != 1)
+ {
+ bdk_error("Failed to write FDT");
+ fclose(outf);
+ return -1;
+ }
+
+ /* Save the CRC32 in the same endianness as the FDT */
+ crc32 = cpu_to_fdt32(crc32);
+ if (fwrite(&crc32, sizeof(crc32), 1, outf) != 1)
+ {
+ bdk_error("Failed to write FDT CRC32");
+ fclose(outf);
+ return -1;
+ }
+
+ fclose(outf);
+ return 0;
+}
+
+/**
+ * Takes the current live device tree and exports it to a memory address suitable
+ * for passing to the next binary in register X1.
+ *
+ * @return Physical address of the device tree, or 0 on failure
+ */
+uint64_t __bdk_config_export_to_mem(void)
+{
+ void *end_ptr = sbrk(0);
+ bdk_node_t node = bdk_numa_master();
+ int fdt_size = fdt_totalsize(config_fdt);
+
+ /* Round size up to 4KB boundary, be sure to add 4 bytes for CRC32 */
+ int fdt_space = (fdt_size + 4 + 0xfff) & -4096;
+ /* First try 4MB - FDT size as this keeps the FDT in the 4MB secure space
+ setup by ATF */
+ void *fdt_ptr = bdk_phys_to_ptr(0x400000 - fdt_space);
+ if (!__bdk_is_dram_enabled(node))
+ {
+ /* Address must be in L2 */
+ int l2_size = bdk_l2c_get_cache_size_bytes(node);
+ void *l2_ptr = bdk_phys_to_ptr(l2_size - fdt_space);
+ if (l2_ptr < fdt_ptr)
+ fdt_ptr = l2_ptr;
+ if (fdt_ptr < end_ptr)
+ {
+ bdk_error("No room for FDT to pass to next binary\n");
+ return 0;
+ }
+ }
+ else
+ {
+ /* We have DRAM, make sure we're past the end of this image */
+ if (fdt_ptr < end_ptr)
+ fdt_ptr = end_ptr;
+ }
+ uint32_t crc32 = bdk_crc32(config_fdt, fdt_size, 0);
+ fdt_move(config_fdt, fdt_ptr, fdt_size);
+ /* CRC32 is stored in same endianness as FDT at the end */
+ *(uint32_t *)((const char *)fdt_ptr + fdt_size) = cpu_to_fdt32(crc32);
+ BDK_TRACE(FDT_OS, "Exported device tree to memory %p, size 0x%x, CRC32 %08x\n",
+ fdt_ptr, fdt_size, crc32);
+ return bdk_ptr_to_phys(fdt_ptr);
+}
+
+/**
+ * Return a pointer to the device tree used for configuration
+ *
+ * @return FDT or NULL on failure
+ */
+void* bdk_config_get_fdt(void)
+{
+ return config_fdt;
+}
+
+/**
+ * Set the device tree used for configuration
+ *
+ * @param fdt Device tree to use. Memory is assumed to be from malloc() and bdk_config takes
+ * over ownership on success
+ *
+ * @return Zero on success, negative on failure
+ */
+int bdk_config_set_fdt(void *fdt)
+{
+ int offset = fdt_path_offset(fdt, "/cavium,bdk"); /* Find our node */
+ if (offset < 0)
+ return -1;
+ free(config_fdt);
+ config_fdt = fdt;
+ config_node = offset;
+ return 0;
+}
+
+/**
+ * Write all default values to a FDT. Missing config items get defaults in the
+ * BDK config, this function adds those defaults to the FDT. This way other code
+ * gets the default value without needing special code.
+ *
+ * @param fdt FDT structure to fill defaults into
+ *
+ * @return Zero on success, negative on failure
+ */
+int bdk_config_expand_defaults(void *fdt)
+{
+ const struct fdt_property *prop;
+
+ /* The best defaults may have changed while this image was running if DRAM
+ is setup. Update the defaults before expanding them */
+ config_set_defaults();
+
+ int fdt_node = fdt_path_offset(fdt, "/cavium,bdk"); /* Find our node */
+ if (fdt_node < 0)
+ {
+ bdk_error("Failed to find top node, FDT error %d: %s\n",
+ fdt_node, fdt_strerror(fdt_node));
+ return -1;
+ }
+
+ /* Loop through all configuration items */
+ for (bdk_config_t cfg = 0; cfg < __BDK_CONFIG_END; cfg++)
+ {
+ /* Figure out the base name without and dot parameters */
+ const char *name = config_info[cfg].format;
+ const char *name_end = strchr(name, '.');
+ int name_len;
+ if (name_end)
+ name_len = name_end - name;
+ else
+ name_len = strlen(name);
+ /* Try and find the base name in the FDT */
+ prop = fdt_get_property_namelen(fdt, fdt_node, name, name_len, NULL);
+ /* If it wasn't found, then we need to add the default */
+ if (prop == NULL)
+ {
+ /* Create a copy of the name for use in FDT calls */
+ char temp_name[name_len + 1];
+ memcpy(temp_name, name, name_len);
+ temp_name[name_len] = 0;
+ /* Call the correct FDT call based on the type */
+ int status = 0;
+ switch (config_info[cfg].ctype)
+ {
+ case BDK_CONFIG_TYPE_INT:
+ {
+ char temp_value[20];
+ if (config_info[cfg].default_value < 10)
+ snprintf(temp_value, sizeof(temp_value), "%ld", config_info[cfg].default_value);
+ else
+ snprintf(temp_value, sizeof(temp_value), "0x%lx", config_info[cfg].default_value);
+ /* Store the default int value */
+ status = fdt_setprop_string(fdt, fdt_node, temp_name, temp_value);
+ break;
+ }
+ case BDK_CONFIG_TYPE_STR:
+ /* Store the default string value, if present */
+ if (config_info[cfg].default_value)
+ {
+ status = fdt_setprop_string(fdt, fdt_node, temp_name,
+ (const char *)config_info[cfg].default_value);
+ }
+ break;
+ case BDK_CONFIG_TYPE_STR_LIST:
+ /* Do nothing, string list default to empty */
+ break;
+ case BDK_CONFIG_TYPE_BINARY:
+ /* Do nothing, binary defaults to empty */
+ break;
+ }
+ if (status < 0)
+ {
+ bdk_error("Failed to set default for %s, FDT error %d: %s\n",
+ temp_name, status, fdt_strerror(status));
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Some of the default config values can vary based on runtime parameters. This
+ * function sets those default parameters. It must be run before anyone calls
+ * bdk_config_get_*().
+ */
+static void config_set_defaults(void)
+{
+ bool isEmulation = bdk_is_platform(BDK_PLATFORM_EMULATOR);
+ /* This is Cavium's OUI with the local admin bit. We will use this as a
+ default as it won't collide with official addresses, but is sort of
+ part of the Cavium range. The lower three bytes will be updated with
+ the wafer info */
+ uint64_t mac_address = 0x020fb7000000ull;
+ /* Set the lower MAC address bits based on the chip manufacturing
+ information. This should give reasonable MAC address defaults
+ for production parts */
+ if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
+ {
+ BDK_CSR_INIT(fus_dat0, bdk_numa_local(), BDK_MIO_FUS_DAT0);
+ mac_address |= fus_dat0.u & 0xffffff;
+ }
+ else
+ {
+ mac_address |= bdk_fuse_read_range(bdk_numa_local(), BDK_FUS_FUSE_NUM_E_MFG_INFOX(0), 24);
+ }
+ config_info[BDK_CONFIG_MAC_ADDRESS].default_value = mac_address;
+
+ /* Set the number of packet buffers */
+ int num_packet_buffers = 4096;
+ /* If DRAM is setup, allocate 8K buffers for 8 ports plus some slop */
+ if (__bdk_is_dram_enabled(bdk_numa_master()))
+ num_packet_buffers = 8192 * 16 + 1024;
+ else if (isEmulation) {
+ if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
+ num_packet_buffers = 4096 * 4;
+ }
+ config_info[BDK_CONFIG_NUM_PACKET_BUFFERS].default_value = num_packet_buffers;
+ config_info[BDK_CONFIG_PACKET_BUFFER_SIZE].default_value = 1024;
+
+ /* Asim doesn't scale to 48 cores well. Limit to 4 */
+ if (bdk_is_platform(BDK_PLATFORM_ASIM))
+ config_info[BDK_CONFIG_COREMASK].default_value = 0xf;
+ /* CN88XX pass 1.x doesn't support EA */
+ if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
+ config_info[BDK_CONFIG_PCIE_EA].default_value = 0;
+ /* Emulator only supports 4 cores */
+ if (isEmulation)
+ config_info[BDK_CONFIG_COREMASK].default_value = 0xf;
+}
+
+/**
+ * BDK configuration items are stored in a device tree so thay can be passed to
+ * other software later. This function creates the initial empty device tree
+ * used for BDK configuration items. The values will be populated as configuration
+ * files are read from flash.
+ */
+static void config_setup_fdt(void)
+{
+ const int FDT_SIZE = 0x10000;
+ config_fdt = calloc(1, FDT_SIZE);
+ if (!config_fdt)
+ bdk_fatal("Unable to allocate memory for config FDT\n");
+ if (fdt_create_empty_tree(config_fdt, FDT_SIZE) < 0)
+ bdk_fatal("Unable to create FDT for config\n");
+ config_node = fdt_add_subnode(config_fdt, 0, "cavium,bdk");
+ if (config_node < 0)
+ bdk_fatal("Unable to create cavium,bdk node in FDT\n");
+}
+
+/**
+ * Parse a FDT and copy its properties to our configuration FDT
+ *
+ * @param fdt FDT to parse
+ */
+static int config_parse_fdt(const void *fdt, const char *base_path)
+{
+ /* Check the FDT header */
+ int result = fdt_check_header(fdt);
+ if (result)
+ goto fail;
+
+ /* Find our node */
+ result = fdt_path_offset(fdt, base_path);
+ if (result < 0)
+ goto fail;
+
+ /* Copy all parameters to our in memory FDT */
+ int offset = fdt_first_property_offset(fdt, result);
+ while (offset >= 0)
+ {
+ const char *name = NULL;
+ int blob_size = 0;
+ const char *data = fdt_getprop_by_offset(fdt, offset, &name, &blob_size);
+ result = fdt_setprop(config_fdt, config_node, name, data, blob_size);
+ offset = fdt_next_property_offset(fdt, offset);
+ }
+ return 0;
+fail:
+ bdk_error("FDT error %d: %s\n", result, fdt_strerror(result));
+ return -1;
+}
+
+/**
+ * Load a FDT from a file and pull in its configuration properties
+ *
+ * @param filename File to read from
+ * @param offset Offset into the file to read from
+ *
+ * @return Zero on success, negative on failure
+ */
+static int config_load_file(const char *filename, uint64_t offset)
+{
+ uint64_t ftd_size = 0;
+ bdk_signed_flags_t sign_flags = BDK_SIGNED_FLAG_NONE;
+ if (offset)
+ sign_flags = BDK_SIGNED_FLAG_ALLOW_UNSIGNED | BDK_SIGNED_FLAG_NOT_ENCRYPTED;
+ void *fdt = bdk_signed_load(filename, offset, BDK_SIGNED_DTS, sign_flags, &ftd_size);
+ if (!fdt)
+ return -1;
+
+ /* Make sure the read succeeded */
+ if (ftd_size < (int)sizeof(struct fdt_header))
+ {
+ bdk_error("Invalid device tee %s\n", filename);
+ free(fdt);
+ return -1;
+ }
+
+ if (fdt_check_header(fdt))
+ {
+ bdk_error("Invalid FDT header read from %s\n", filename);
+ free(fdt);
+ return -1;
+ }
+
+ /* Make sure we read enough data to contain the FDT */
+ int correct_size = fdt_totalsize(fdt);
+ if ((int)ftd_size < correct_size)
+ {
+ bdk_error("Unable to read FDT from %s\n", filename);
+ free(fdt);
+ return -1;
+ }
+
+ /* Check if a CRC32 was added on the end of the FDT */
+ if ((int)ftd_size >= correct_size + 4)
+ {
+ uint32_t crc32 = bdk_crc32(fdt, correct_size, 0);
+ uint32_t correct_crc32 = *(uint32_t *)((const char *)fdt + correct_size);
+ /* CRC32 is stored in same endianness as FDT */
+ correct_crc32 = fdt32_to_cpu(correct_crc32);
+ if (crc32 != correct_crc32)
+ {
+ bdk_error("FDT failed CRC32 verification (%s)\n", filename);
+ free(fdt);
+ return -1;
+ }
+ //printf("PASS: FDT CRC32 verification (%s)\n", filename);
+ }
+
+ /* Parse the device tree, adding its configuration to ours */
+ if (config_parse_fdt(fdt, "/cavium,bdk"))
+ {
+ free(fdt);
+ return -1;
+ }
+
+ free(fdt);
+ return 0;
+}
+
+/**
+ * Internal BDK function to initialize the config system. Must be called before
+ * any configuration functions are called
+ */
+void __bdk_config_init(void)
+{
+ bool done_trust_init = false;
+ /* Set default that can vary dynamically at runtime */
+ config_set_defaults();
+
+ /* Regsiter X1 is expected to be a device tree when we boot. Check that
+ the physical address seems correct, then load the device tree */
+ if ((__bdk_init_reg_x1 > 0) && /* Not zero */
+ (__bdk_init_reg_x1 < 0x1000000) && /* In the lower 16MB */
+ ((__bdk_init_reg_x1 & 0xfff) == 0)) /* Aligned on a 4KB boundary */
+ {
+ const void *fdt = (const void *)__bdk_init_reg_x1;
+ /* Check the FDT header */
+ int result = fdt_check_header(fdt);
+ if (result)
+ result = -1; /* Invalid tree */
+ else
+ {
+ int fdt_size = fdt_totalsize(fdt);
+ uint32_t crc32 = bdk_crc32(fdt, fdt_size, 0);
+ uint32_t correct_crc32 = *(uint32_t *)((const char *)fdt + fdt_size);
+ /* CRC32 is stored in same endianness as FDT */
+ correct_crc32 = fdt32_to_cpu(correct_crc32);
+ if (crc32 == correct_crc32)
+ {
+ //printf("Previous image FDT passed CRC32 verification(%p, size 0x%x, CRC32 %08x)\n", fdt, fdt_size, crc32);
+ result = fdt_path_offset(fdt, "/cavium,bdk"); /* Find our node */
+ }
+ else
+ {
+ bdk_error("Previous image FDT failed CRC32 verification(%p, size 0x%x)\n", fdt, fdt_size);
+ result = -1; /* Invalid tree */
+ }
+ }
+ /* If tree is valid so far, attempt to move it into our memory space */
+ if (result > 0)
+ {
+ /* 4KB extra room for growth */
+ const int fdt_size = fdt_totalsize(fdt) + 4096;
+ config_fdt = calloc(1, fdt_size);
+ if (config_fdt)
+ {
+ int result = fdt_move(fdt, config_fdt, fdt_size);
+ if (result == 0)
+ {
+ /* Find our node */
+ config_node = fdt_path_offset(config_fdt, "/cavium,bdk");
+ if (config_node > 0)
+ {
+ printf("Using configuration from previous image\n");
+ goto done;
+ }
+ else
+ {
+ bdk_error("Unable to find BDK node after move\n");
+ free(config_fdt);
+ config_node = 0;
+ config_fdt = NULL;
+ }
+ }
+ else
+ {
+ bdk_error("Unable to move passed device tree\n");
+ free(config_fdt);
+ config_fdt = NULL;
+ }
+ }
+ else
+ bdk_error("Failed to allocate memory for passed device tree (%d bytes)\n", fdt_size);
+ }
+ }
+
+ /* Create the global device tree used to store config items */
+ config_setup_fdt();
+ /* Setup trust level so reading device trees works */
+ __bdk_trust_init();
+ done_trust_init = true;
+
+ if (bdk_is_platform(BDK_PLATFORM_ASIM))
+ {
+ if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
+ bdk_config_set_str("ASIM-CN88XX", BDK_CONFIG_BOARD_MODEL);
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
+ bdk_config_set_str("ASIM-CN83XX", BDK_CONFIG_BOARD_MODEL);
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
+ bdk_config_set_str("ASIM-CN81XX", BDK_CONFIG_BOARD_MODEL);
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN93XX))
+ bdk_config_set_str("ASIM-CN93XX", BDK_CONFIG_BOARD_MODEL);
+ }
+ else if (bdk_is_platform(BDK_PLATFORM_EMULATOR))
+ {
+ if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
+ bdk_config_set_str("EMUL-CN88XX", BDK_CONFIG_BOARD_MODEL);
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
+ bdk_config_set_str("EMUL-CN83XX", BDK_CONFIG_BOARD_MODEL);
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
+ bdk_config_set_str("EMUL-CN81XX", BDK_CONFIG_BOARD_MODEL);
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN93XX))
+ bdk_config_set_str("EMUL-CN93XX", BDK_CONFIG_BOARD_MODEL);
+ }
+ else if (config_load_file("/rom/boardcfg.dtb", 0) == 0)
+ {
+ printf("Board manufacturing information loaded from ROM-FS\n");
+ }
+ /* Load manufacturing data from the top 64KB of flash */
+ else if (config_load_file("/boot", BDK_CONFIG_MANUFACTURING_ADDRESS) != 0)
+ {
+ printf("\33[1m"); /* Bold */
+ bdk_warn("\n");
+ bdk_warn("********************************************************\n");
+ bdk_warn("* Board manufacturing information not found. Program\n");
+ bdk_warn("* the board manufacturing information in the Setup menu.\n");
+ bdk_warn("********************************************************\n");
+ bdk_warn("\n");
+ printf("\33[0m"); /* Normal */
+ goto done;
+ }
+
+ const char *model = bdk_config_get_str(BDK_CONFIG_BOARD_MODEL);
+ const char *revision = bdk_config_get_str(BDK_CONFIG_BOARD_REVISION);
+
+ /* Load BOARD-REVISION.cfg if it is on ROM-FS */
+ if (model && revision)
+ {
+ char filename[64];
+ snprintf(filename, sizeof(filename), "/rom/%s-%s.dtb", model, revision);
+ if (config_load_file(filename, 0) == 0)
+ goto done;
+ }
+
+ /* Load BOARD.cfg if it is on ROM-FS */
+ if (model)
+ {
+ char filename[64];
+ snprintf(filename, sizeof(filename), "/rom/%s.dtb", model);
+ if (config_load_file(filename, 0) == 0)
+ goto done;
+ }
+
+ /* Load default.dtb if it is there */
+ if (config_load_file("/fatfs/default.dtb", 0) == 0)
+ goto done;
+
+ /* Load BOARD-REVISION.cfg if it is there */
+ if (model && revision)
+ {
+ char filename[64];
+ snprintf(filename, sizeof(filename), "/fatfs/%s-%s.dtb", model, revision);
+ if (config_load_file(filename, 0) == 0)
+ goto done;
+ }
+
+ /* Load BOARD.cfg if it is there */
+ if (model)
+ {
+ char filename[64];
+ snprintf(filename, sizeof(filename), "/fatfs/%s.dtb", model);
+ if (config_load_file(filename, 0) == 0)
+ goto done;
+ }
+
+ /* No board specific configuration was found. Warn the user */
+ printf("\33[1m"); /* Bold */
+ bdk_warn("\n");
+ bdk_warn("********************************************************\n");
+ bdk_warn("* Board configuration file not found. Either the board\n");
+ bdk_warn("* model is incorrect, or factory settings are not\n");
+ bdk_warn("* available. DTB file not found for board \"%s\".\n", model);
+ bdk_warn("********************************************************\n");
+ bdk_warn("\n");
+ printf("\33[0m"); /* Normal */
+
+done:
+ bdk_config_set_str(bdk_version_string(), BDK_CONFIG_VERSION);
+ /* Load the tracing level */
+ bdk_trace_enables = bdk_config_get_int(BDK_CONFIG_TRACE);
+ if (BDK_TRACE_OVERRIDE)
+ bdk_trace_enables = BDK_TRACE_OVERRIDE;
+ if (!done_trust_init)
+ __bdk_trust_init();
+}