summaryrefslogtreecommitdiffstats
path: root/board
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-04-24 19:39:14 -0400
committerTom Rini <trini@konsulko.com>2021-04-24 19:39:14 -0400
commit4dda435131251a94b29afd52f010cf1ec5a7ceb2 (patch)
tree16bda495e53e1e5d6afc58077f2ec8e6ca670d1c /board
parente1333435afbf0c6290b1d16bb446b57807f75502 (diff)
parentb1d9554e058e5e8510a9d22183ae8321290ee87b (diff)
downloadu-boot-4dda435131251a94b29afd52f010cf1ec5a7ceb2.tar.gz
u-boot-4dda435131251a94b29afd52f010cf1ec5a7ceb2.tar.xz
u-boot-4dda435131251a94b29afd52f010cf1ec5a7ceb2.zip
Merge tag 'mips-pull-2021-04-24' of https://source.denx.de/u-boot/custodians/u-boot-mips
- MIPS: octeon: fix minor bugs of initial merge - MIPS: octeon: add support for QLM and PCI-E controller - MIPS: octeon: add support for AHCI and SATA - MIPS: octeon: add E1000 ethernet support - MIPS: octeon: add Octeon III NIC23 board - ata/scsi: add support for Big Endian platforms
Diffstat (limited to 'board')
-rw-r--r--board/Marvell/octeon_ebb7304/board.c732
-rw-r--r--board/Marvell/octeon_nic23/Kconfig19
-rw-r--r--board/Marvell/octeon_nic23/MAINTAINERS7
-rw-r--r--board/Marvell/octeon_nic23/Makefile8
-rw-r--r--board/Marvell/octeon_nic23/board.c106
-rw-r--r--board/Marvell/octeon_nic23/board_ddr.h269
6 files changed, 1139 insertions, 2 deletions
diff --git a/board/Marvell/octeon_ebb7304/board.c b/board/Marvell/octeon_ebb7304/board.c
index 611b18fa6a..9aac5f0b09 100644
--- a/board/Marvell/octeon_ebb7304/board.c
+++ b/board/Marvell/octeon_ebb7304/board.c
@@ -3,20 +3,32 @@
* Copyright (C) 2020 Stefan Roese <sr@denx.de>
*/
-#include <common.h>
#include <dm.h>
+#include <fdt_support.h>
#include <ram.h>
+#include <asm/gpio.h>
#include <mach/octeon_ddr.h>
+#include <mach/cvmx-qlm.h>
+#include <mach/octeon_qlm.h>
+#include <mach/octeon_fdt.h>
+#include <mach/cvmx-helper.h>
+#include <mach/cvmx-helper-cfg.h>
+#include <mach/cvmx-helper-util.h>
+#include <mach/cvmx-bgxx-defs.h>
#include "board_ddr.h"
+#define MAX_MIX_ENV_VARS 4
+
#define EBB7304_DEF_DRAM_FREQ 800
static struct ddr_conf board_ddr_conf[] = {
- OCTEON_EBB7304_DDR_CONFIGURATION
+ OCTEON_EBB7304_DDR_CONFIGURATION
};
+static int no_phy[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
struct ddr_conf *octeon_ddr_conf_table_get(int *count, int *def_ddr_freq)
{
*count = ARRAY_SIZE(board_ddr_conf);
@@ -24,3 +36,719 @@ struct ddr_conf *octeon_ddr_conf_table_get(int *count, int *def_ddr_freq)
return board_ddr_conf;
}
+
+/*
+ * parse_env_var: Parse the environment variable ("bgx_for_mix%d") to
+ * extract the lmac it is set to.
+ *
+ * index: Index of environment variable to parse.
+ * environment variable.
+ * env_bgx: Updated with the bgx of the lmac in the environment
+ * variable.
+ * env_lmac: Updated with the index of lmac in the environment
+ * variable.
+ *
+ * returns: Zero on success, error otherwise.
+ */
+static int parse_env_var(int index, int *env_bgx, int *env_lmac)
+{
+ char env_var[20];
+ ulong xipd_port;
+
+ sprintf(env_var, "bgx_for_mix%d", index);
+ xipd_port = env_get_ulong(env_var, 0, 0xffff);
+ if (xipd_port != 0xffff) {
+ int xiface;
+ struct cvmx_xiface xi;
+ struct cvmx_xport xp;
+
+ /*
+ * The environemt variable is set to the xipd port. Convert the
+ * xipd port to numa node, bgx, and lmac.
+ */
+ xiface = cvmx_helper_get_interface_num(xipd_port);
+ xi = cvmx_helper_xiface_to_node_interface(xiface);
+ xp = cvmx_helper_ipd_port_to_xport(xipd_port);
+ *env_bgx = xi.interface;
+ *env_lmac = cvmx_helper_get_interface_index_num(xp.port);
+ return 0;
+ }
+
+ return -1;
+}
+
+/*
+ * get_lmac_fdt_node: Search the device tree for the node corresponding to
+ * a given bgx lmac.
+ *
+ * fdt: Pointer to flat device tree
+ * search_node: Numa node of the lmac to search for.
+ * search_bgx: Bgx of the lmac to search for.
+ * search_lmac: Lmac index to search for.
+ * compat: Compatible string to search for.
+
+ * returns: The device tree node of the lmac if found,
+ * or -1 otherwise.
+ */
+static int get_lmac_fdt_node(const void *fdt, int search_node, int search_bgx, int search_lmac,
+ const char *compat)
+{
+ int node;
+ const fdt32_t *reg;
+ u64 addr;
+ int fdt_node = -1;
+ int fdt_bgx = -1;
+ int fdt_lmac = -1;
+ int len;
+ int parent;
+
+ /* Iterate through all bgx ports */
+ node = -1;
+ while ((node = fdt_node_offset_by_compatible((void *)fdt, node,
+ compat)) >= 0) {
+ /* Get the node and bgx from the physical address */
+ parent = fdt_parent_offset(fdt, node);
+ reg = fdt_getprop(fdt, parent, "reg", &len);
+ if (parent < 0 || !reg)
+ continue;
+
+ addr = fdt_translate_address((void *)fdt, parent, reg);
+ fdt_node = (addr >> 36) & 0x7;
+ fdt_bgx = (addr >> 24) & 0xf;
+
+ /* Get the lmac index from the reg property */
+ reg = fdt_getprop(fdt, node, "reg", &len);
+ if (reg)
+ fdt_lmac = *reg;
+
+ /* Check for a match */
+ if (search_node == fdt_node && search_bgx == fdt_bgx &&
+ search_lmac == fdt_lmac)
+ return node;
+ }
+
+ return -1;
+}
+
+/*
+ * get_mix_fdt_node: Search the device tree for the node corresponding to
+ * a given mix.
+ *
+ * fdt: Pointer to flat device tree
+ * search_node: Mix numa node to search for.
+ * search_index: Mix index to search for.
+ *
+ * returns: The device tree node of the lmac if found,
+ * or -1 otherwise.
+ */
+static int get_mix_fdt_node(const void *fdt, int search_node, int search_index)
+{
+ int node;
+
+ /* Iterate through all the mix fdt nodes */
+ node = -1;
+ while ((node = fdt_node_offset_by_compatible((void *)fdt, node,
+ "cavium,octeon-7890-mix")) >= 0) {
+ int parent;
+ int len;
+ const char *name;
+ int mix_numa_node;
+ const fdt32_t *reg;
+ int mix_index = -1;
+ u64 addr;
+
+ /* Get the numa node of the mix from the parent node name */
+ parent = fdt_parent_offset(fdt, node);
+ if (parent < 0 ||
+ ((name = fdt_get_name(fdt, parent, &len)) == NULL) ||
+ ((name = strchr(name, '@')) == NULL))
+ continue;
+
+ name++;
+ mix_numa_node = simple_strtol(name, NULL, 0) ? 1 : 0;
+
+ /* Get the mix index from the reg property */
+ reg = fdt_getprop(fdt, node, "reg", &len);
+ if (reg) {
+ addr = fdt_translate_address((void *)fdt, parent, reg);
+ mix_index = (addr >> 11) & 1;
+ }
+
+ /* Check for a match */
+ if (mix_numa_node == search_node && mix_index == search_index)
+ return node;
+ }
+
+ return -1;
+}
+
+/*
+ * fdt_fix_mix: Fix the mix nodes in the device tree. Only the mix nodes
+ * configured by the user will be preserved. All other mix
+ * nodes will be trimmed.
+ *
+ * fdt: Pointer to flat device tree
+ *
+ * returns: Zero on success, error otherwise.
+ */
+static int fdt_fix_mix(const void *fdt)
+{
+ int node;
+ int next_node;
+ int len;
+ int i;
+
+ /* Parse all the mix port environment variables */
+ for (i = 0; i < MAX_MIX_ENV_VARS; i++) {
+ int env_node = 0;
+ int env_bgx = -1;
+ int env_lmac = -1;
+ int lmac_fdt_node = -1;
+ int mix_fdt_node = -1;
+ int lmac_phandle;
+ char *compat;
+
+ /* Get the lmac for this environment variable */
+ if (parse_env_var(i, &env_bgx, &env_lmac))
+ continue;
+
+ /* Get the fdt node for this lmac and add a phandle to it */
+ compat = "cavium,octeon-7890-bgx-port";
+ lmac_fdt_node = get_lmac_fdt_node(fdt, env_node, env_bgx,
+ env_lmac, compat);
+ if (lmac_fdt_node < 0) {
+ /* Must check for the xcv compatible string too */
+ compat = "cavium,octeon-7360-xcv";
+ lmac_fdt_node = get_lmac_fdt_node(fdt, env_node,
+ env_bgx, env_lmac,
+ compat);
+ if (lmac_fdt_node < 0) {
+ printf("WARNING: Failed to get lmac fdt node for %d%d%d\n",
+ env_node, env_bgx, env_lmac);
+ continue;
+ }
+ }
+
+ lmac_phandle = fdt_alloc_phandle((void *)fdt);
+ fdt_set_phandle((void *)fdt, lmac_fdt_node, lmac_phandle);
+
+ /* Get the fdt mix node corresponding to this lmac */
+ mix_fdt_node = get_mix_fdt_node(fdt, env_node, env_lmac);
+ if (mix_fdt_node < 0)
+ continue;
+
+ /* Point the mix to the lmac */
+ fdt_getprop(fdt, mix_fdt_node, "cavium,mac-handle", &len);
+ fdt_setprop_inplace((void *)fdt, mix_fdt_node,
+ "cavium,mac-handle", &lmac_phandle, len);
+ }
+
+ /* Trim unused mix'es from the device tree */
+ for (node = fdt_next_node(fdt, -1, NULL); node >= 0; node = next_node) {
+ const char *compat;
+ const fdt32_t *reg;
+
+ next_node = fdt_next_node(fdt, node, NULL);
+
+ compat = fdt_getprop(fdt, node, "compatible", &len);
+ if (compat) {
+ if (strcmp(compat, "cavium,octeon-7890-mix"))
+ continue;
+
+ reg = fdt_getprop(fdt, node, "cavium,mac-handle", &len);
+ if (reg) {
+ if (*reg == 0xffff)
+ fdt_nop_node((void *)fdt, node);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void kill_fdt_phy(void *fdt, int offset, void *arg)
+{
+ int len, phy_offset;
+ const fdt32_t *php;
+ u32 phandle;
+
+ php = fdt_getprop(fdt, offset, "phy-handle", &len);
+ if (php && len == sizeof(*php)) {
+ phandle = fdt32_to_cpu(*php);
+ fdt_nop_property(fdt, offset, "phy-handle");
+ phy_offset = fdt_node_offset_by_phandle(fdt, phandle);
+ if (phy_offset > 0)
+ fdt_nop_node(fdt, phy_offset);
+ }
+}
+
+void __fixup_xcv(void)
+{
+ unsigned long bgx = env_get_ulong("bgx_for_rgmii", 10,
+ (unsigned long)-1);
+ char fdt_key[16];
+ int i;
+
+ debug("%s: BGX %d\n", __func__, (int)bgx);
+
+ for (i = 0; i < 3; i++) {
+ snprintf(fdt_key, sizeof(fdt_key),
+ bgx == i ? "%d,xcv" : "%d,not-xcv", i);
+ debug("%s: trimming bgx %lu with key %s\n",
+ __func__, bgx, fdt_key);
+
+ octeon_fdt_patch_rename((void *)gd->fdt_blob, fdt_key,
+ "cavium,xcv-trim", true, NULL, NULL);
+ }
+}
+
+/* QLM0 - QLM6 */
+void __fixup_fdt(void)
+{
+ int qlm;
+ int speed = 0;
+
+ for (qlm = 0; qlm < 7; qlm++) {
+ enum cvmx_qlm_mode mode;
+ char fdt_key[16];
+ const char *type_str = "none";
+
+ mode = cvmx_qlm_get_mode(qlm);
+ switch (mode) {
+ case CVMX_QLM_MODE_SGMII:
+ case CVMX_QLM_MODE_RGMII_SGMII:
+ case CVMX_QLM_MODE_RGMII_SGMII_1X1:
+ type_str = "sgmii";
+ break;
+ case CVMX_QLM_MODE_XAUI:
+ case CVMX_QLM_MODE_RGMII_XAUI:
+ speed = (cvmx_qlm_get_gbaud_mhz(qlm) * 8 / 10) * 4;
+ if (speed == 10000)
+ type_str = "xaui";
+ else
+ type_str = "dxaui";
+ break;
+ case CVMX_QLM_MODE_RXAUI:
+ case CVMX_QLM_MODE_RGMII_RXAUI:
+ type_str = "rxaui";
+ break;
+ case CVMX_QLM_MODE_XLAUI:
+ case CVMX_QLM_MODE_RGMII_XLAUI:
+ type_str = "xlaui";
+ break;
+ case CVMX_QLM_MODE_XFI:
+ case CVMX_QLM_MODE_RGMII_XFI:
+ case CVMX_QLM_MODE_RGMII_XFI_1X1:
+ type_str = "xfi";
+ break;
+ case CVMX_QLM_MODE_10G_KR:
+ case CVMX_QLM_MODE_RGMII_10G_KR:
+ type_str = "10G_KR";
+ break;
+ case CVMX_QLM_MODE_40G_KR4:
+ case CVMX_QLM_MODE_RGMII_40G_KR4:
+ type_str = "40G_KR4";
+ break;
+ case CVMX_QLM_MODE_SATA_2X1:
+ type_str = "sata";
+ break;
+ case CVMX_QLM_MODE_SGMII_2X1:
+ case CVMX_QLM_MODE_XFI_1X2:
+ case CVMX_QLM_MODE_10G_KR_1X2:
+ case CVMX_QLM_MODE_RXAUI_1X2:
+ case CVMX_QLM_MODE_MIXED: // special for DLM5 & DLM6
+ {
+ cvmx_bgxx_cmrx_config_t cmr_config;
+ cvmx_bgxx_spux_br_pmd_control_t pmd_control;
+ int mux = cvmx_qlm_mux_interface(2);
+
+ if (mux == 2) { // only dlm6
+ cmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(2, 2));
+ pmd_control.u64 =
+ csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(2, 2));
+ } else {
+ if (qlm == 5) {
+ cmr_config.u64 =
+ csr_rd(CVMX_BGXX_CMRX_CONFIG(0, 2));
+ pmd_control.u64 =
+ csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(0, 2));
+ } else {
+ cmr_config.u64 =
+ csr_rd(CVMX_BGXX_CMRX_CONFIG(2, 2));
+ pmd_control.u64 =
+ csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(2, 2));
+ }
+ }
+ switch (cmr_config.s.lmac_type) {
+ case 0:
+ type_str = "sgmii";
+ break;
+ case 1:
+ type_str = "xaui";
+ break;
+ case 2:
+ type_str = "rxaui";
+ break;
+ case 3:
+ if (pmd_control.s.train_en)
+ type_str = "10G_KR";
+ else
+ type_str = "xfi";
+ break;
+ case 4:
+ if (pmd_control.s.train_en)
+ type_str = "40G_KR4";
+ else
+ type_str = "xlaui";
+ break;
+ default:
+ type_str = "none";
+ break;
+ }
+ break;
+ }
+ default:
+ type_str = "none";
+ break;
+ }
+ sprintf(fdt_key, "%d,%s", qlm, type_str);
+ debug("Patching qlm %d for %s for mode %d%s\n", qlm, fdt_key, mode,
+ no_phy[qlm] ? ", removing PHY" : "");
+ octeon_fdt_patch_rename((void *)gd->fdt_blob, fdt_key, NULL, true,
+ no_phy[qlm] ? kill_fdt_phy : NULL, NULL);
+ }
+}
+
+int board_fix_fdt(void)
+{
+ __fixup_fdt();
+ __fixup_xcv();
+
+ /* Fix the mix ports */
+ fdt_fix_mix(gd->fdt_blob);
+
+ return 0;
+}
+
+/*
+ * Here is the description of the parameters that are passed to QLM
+ * configuration:
+ *
+ * param0 : The QLM to configure
+ * param1 : Speed to configure the QLM at
+ * param2 : Mode the QLM to configure
+ * param3 : 1 = RC, 0 = EP
+ * param4 : 0 = GEN1, 1 = GEN2, 2 = GEN3
+ * param5 : ref clock select, 0 = 100Mhz, 1 = 125MHz, 2 = 156MHz
+ * param6 : ref clock input to use:
+ * 0 - external reference (QLMx_REF_CLK)
+ * 1 = common clock 0 (QLMC_REF_CLK0)
+ * 2 = common_clock 1 (QLMC_REF_CLK1)
+ */
+static void board_configure_qlms(void)
+{
+ int speed[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ int mode[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+ int pcie_rc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ int pcie_gen[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ int ref_clock_sel[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ int ref_clock_input[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ struct gpio_desc desc;
+ int rbgx, rqlm;
+ char env_var[16];
+ int qlm;
+ int ret;
+
+ /* RGMII PHY reset GPIO */
+ ret = dm_gpio_lookup_name("gpio-controllerA27", &desc);
+ if (ret)
+ debug("gpio ret=%d\n", ret);
+ ret = dm_gpio_request(&desc, "rgmii_phy_reset");
+ if (ret)
+ debug("gpio_request ret=%d\n", ret);
+ ret = dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT);
+ if (ret)
+ debug("gpio dir ret=%d\n", ret);
+
+ /* Put RGMII PHY in reset */
+ dm_gpio_set_value(&desc, 0);
+
+ octeon_init_qlm(0);
+
+ rbgx = env_get_ulong("bgx_for_rgmii", 10, (unsigned long)-1);
+ switch (rbgx) {
+ case 0:
+ rqlm = 2;
+ break;
+ case 1:
+ rqlm = 3;
+ break;
+ case 2:
+ rqlm = 5;
+ break;
+ default:
+ rqlm = -1;
+ break;
+ }
+
+ for (qlm = 0; qlm < 7; qlm++) {
+ const char *mode_str;
+ char spd_env[16];
+
+ mode[qlm] = CVMX_QLM_MODE_DISABLED;
+ sprintf(env_var, "qlm%d_mode", qlm);
+ mode_str = env_get(env_var);
+ if (!mode_str)
+ continue;
+
+ if (qlm == 4 && mode[4] != -1 &&
+ mode[4] != CVMX_QLM_MODE_SATA_2X1) {
+ printf("Error: DLM 4 can only be configured for SATA\n");
+ continue;
+ }
+
+ if (strstr(mode_str, ",no_phy"))
+ no_phy[qlm] = 1;
+
+ if (!strncmp(mode_str, "sgmii", 5)) {
+ bool rgmii = false;
+
+ speed[qlm] = 1250;
+ if (rqlm == qlm && qlm < 5) {
+ mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII;
+ rgmii = true;
+ } else if (qlm == 6 || qlm == 5) {
+ if (rqlm == qlm && qlm == 5) {
+ mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII_1X1;
+ rgmii = true;
+ } else if (rqlm == 5 && qlm == 6 &&
+ mode[5] != CVMX_QLM_MODE_RGMII_SGMII_1X1) {
+ mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII_2X1;
+ rgmii = true;
+ } else {
+ mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;
+ }
+ } else {
+ mode[qlm] = CVMX_QLM_MODE_SGMII;
+ }
+ ref_clock_sel[qlm] = 2;
+
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+
+ if (no_phy[qlm]) {
+ int i;
+ int start = 0, stop = 2;
+
+ rbgx = 0;
+ switch (qlm) {
+ case 3:
+ rbgx = 1;
+ case 2:
+ for (i = 0; i < 4; i++) {
+ printf("Ignoring PHY for interface: %d, port: %d\n",
+ rbgx, i);
+ cvmx_helper_set_port_force_link_up(rbgx, i, true);
+ }
+ break;
+ case 6:
+ start = 2;
+ stop = 4;
+ case 5:
+ for (i = start; i < stop; i++) {
+ printf("Ignoring PHY for interface: %d, port: %d\n",
+ 2, i);
+ cvmx_helper_set_port_force_link_up(2, i, true);
+ }
+ break;
+ default:
+ printf("SGMII not supported for QLM/DLM %d\n",
+ qlm);
+ break;
+ }
+ }
+ printf("QLM %d: SGMII%s\n",
+ qlm, rgmii ? ", RGMII" : "");
+ } else if (!strncmp(mode_str, "xaui", 4)) {
+ speed[qlm] = 3125;
+ mode[qlm] = CVMX_QLM_MODE_XAUI;
+ ref_clock_sel[qlm] = 2;
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+ printf("QLM %d: XAUI\n", qlm);
+ } else if (!strncmp(mode_str, "dxaui", 5)) {
+ speed[qlm] = 6250;
+ mode[qlm] = CVMX_QLM_MODE_XAUI;
+ ref_clock_sel[qlm] = 2;
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+ printf("QLM %d: DXAUI\n", qlm);
+ } else if (!strncmp(mode_str, "rxaui", 5)) {
+ bool rgmii = false;
+
+ speed[qlm] = 6250;
+ if (qlm == 5 || qlm == 6) {
+ if (rqlm == qlm && qlm == 5) {
+ mode[qlm] = CVMX_QLM_MODE_RGMII_RXAUI;
+ rgmii = true;
+ } else {
+ mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
+ }
+ } else {
+ mode[qlm] = CVMX_QLM_MODE_RXAUI;
+ }
+ ref_clock_sel[qlm] = 2;
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+ printf("QLM %d: RXAUI%s\n",
+ qlm, rgmii ? ", rgmii" : "");
+ } else if (!strncmp(mode_str, "xlaui", 5)) {
+ speed[qlm] = 103125;
+ mode[qlm] = CVMX_QLM_MODE_XLAUI;
+ ref_clock_sel[qlm] = 2;
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+ sprintf(spd_env, "qlm%d_speed", qlm);
+ if (env_get(spd_env)) {
+ int spd = env_get_ulong(spd_env, 0, 8);
+
+ if (spd)
+ speed[qlm] = spd;
+ else
+ speed[qlm] = 103125;
+ }
+ printf("QLM %d: XLAUI\n", qlm);
+ } else if (!strncmp(mode_str, "xfi", 3)) {
+ bool rgmii = false;
+
+ speed[qlm] = 103125;
+ if (rqlm == qlm) {
+ mode[qlm] = CVMX_QLM_MODE_RGMII_XFI;
+ rgmii = true;
+ } else if (qlm == 5 || qlm == 6) {
+ mode[qlm] = CVMX_QLM_MODE_XFI_1X2;
+ } else {
+ mode[qlm] = CVMX_QLM_MODE_XFI;
+ }
+ ref_clock_sel[qlm] = 2;
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+ printf("QLM %d: XFI%s\n", qlm, rgmii ? ", RGMII" : "");
+ } else if (!strncmp(mode_str, "10G_KR", 6)) {
+ speed[qlm] = 103125;
+ if (rqlm == qlm && qlm == 5)
+ mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR;
+ else if (qlm == 5 || qlm == 6)
+ mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;
+ else
+ mode[qlm] = CVMX_QLM_MODE_10G_KR;
+ ref_clock_sel[qlm] = 2;
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+ printf("QLM %d: 10G_KR\n", qlm);
+ } else if (!strncmp(mode_str, "40G_KR4", 7)) {
+ speed[qlm] = 103125;
+ mode[qlm] = CVMX_QLM_MODE_40G_KR4;
+ ref_clock_sel[qlm] = 2;
+ if (qlm == 5 || qlm == 6)
+ ref_clock_input[qlm] = 2; // use QLMC_REF_CLK1
+ printf("QLM %d: 40G_KR4\n", qlm);
+ } else if (!strcmp(mode_str, "pcie")) {
+ char *pmode;
+ int lanes = 0;
+
+ sprintf(env_var, "pcie%d_mode", qlm);
+ pmode = env_get(env_var);
+ if (pmode && !strcmp(pmode, "ep"))
+ pcie_rc[qlm] = 0;
+ else
+ pcie_rc[qlm] = 1;
+ sprintf(env_var, "pcie%d_gen", qlm);
+ pcie_gen[qlm] = env_get_ulong(env_var, 0, 3);
+ sprintf(env_var, "pcie%d_lanes", qlm);
+ lanes = env_get_ulong(env_var, 0, 8);
+ if (lanes == 8) {
+ mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
+ } else if (qlm == 5 || qlm == 6) {
+ if (lanes != 2) {
+ printf("QLM%d: Invalid lanes selected, defaulting to 2 lanes\n",
+ qlm);
+ }
+ mode[qlm] = CVMX_QLM_MODE_PCIE_1X2;
+ ref_clock_input[qlm] = 1; // use QLMC_REF_CLK0
+ } else {
+ mode[qlm] = CVMX_QLM_MODE_PCIE;
+ }
+ ref_clock_sel[qlm] = 0;
+ printf("QLM %d: PCIe gen%d %s, x%d lanes\n",
+ qlm, pcie_gen[qlm] + 1,
+ pcie_rc[qlm] ? "root complex" : "endpoint",
+ lanes);
+ } else if (!strcmp(mode_str, "sata")) {
+ mode[qlm] = CVMX_QLM_MODE_SATA_2X1;
+ ref_clock_sel[qlm] = 0;
+ ref_clock_input[qlm] = 1;
+ sprintf(spd_env, "qlm%d_speed", qlm);
+ if (env_get(spd_env)) {
+ int spd = env_get_ulong(spd_env, 0, 8);
+
+ if (spd == 1500 || spd == 3000 || spd == 3000)
+ speed[qlm] = spd;
+ else
+ speed[qlm] = 6000;
+ } else {
+ speed[qlm] = 6000;
+ }
+ } else {
+ printf("QLM %d: disabled\n", qlm);
+ }
+ }
+
+ for (qlm = 0; qlm < 7; qlm++) {
+ int rc;
+
+ if (mode[qlm] == -1)
+ continue;
+
+ debug("Configuring qlm%d with speed(%d), mode(%d), RC(%d), Gen(%d), REF_CLK(%d), CLK_SOURCE(%d)\n",
+ qlm, speed[qlm], mode[qlm], pcie_rc[qlm],
+ pcie_gen[qlm] + 1,
+ ref_clock_sel[qlm], ref_clock_input[qlm]);
+ rc = octeon_configure_qlm(qlm, speed[qlm], mode[qlm],
+ pcie_rc[qlm], pcie_gen[qlm],
+ ref_clock_sel[qlm],
+ ref_clock_input[qlm]);
+
+ if (speed[qlm] == 6250) {
+ if (mode[qlm] == CVMX_QLM_MODE_RXAUI) {
+ octeon_qlm_tune_v3(0, qlm, speed[qlm], 0x12,
+ 0xa0, -1, -1);
+ } else {
+ octeon_qlm_tune_v3(0, qlm, speed[qlm], 0xa,
+ 0xa0, -1, -1);
+ }
+ } else if (speed[qlm] == 103125) {
+ octeon_qlm_tune_v3(0, qlm, speed[qlm], 0xd, 0xd0,
+ -1, -1);
+ }
+
+ if (qlm == 4 && rc != 0)
+ /*
+ * There is a bug with SATA with 73xx. Until it's
+ * fixed we need to strip it from the device tree.
+ */
+ octeon_fdt_patch_rename((void *)gd->fdt_blob, "4,none",
+ NULL, true, NULL, NULL);
+ }
+
+ dm_gpio_set_value(&desc, 0); /* Put RGMII PHY in reset */
+ mdelay(10);
+ dm_gpio_set_value(&desc, 1); /* Take RGMII PHY out of reset */
+}
+
+int board_late_init(void)
+{
+ board_configure_qlms();
+
+ return 0;
+}
diff --git a/board/Marvell/octeon_nic23/Kconfig b/board/Marvell/octeon_nic23/Kconfig
new file mode 100644
index 0000000000..3c42e8acda
--- /dev/null
+++ b/board/Marvell/octeon_nic23/Kconfig
@@ -0,0 +1,19 @@
+if TARGET_OCTEON_NIC23
+
+config SYS_BOARD
+ string
+ default "octeon_nic23"
+
+config SYS_VENDOR
+ string
+ default "Marvell"
+
+config SYS_CONFIG_NAME
+ string
+ default "octeon_nic23"
+
+config DEFAULT_DEVICE_TREE
+ string
+ default "mrvl,octeon-nic23"
+
+endif
diff --git a/board/Marvell/octeon_nic23/MAINTAINERS b/board/Marvell/octeon_nic23/MAINTAINERS
new file mode 100644
index 0000000000..cd5148dcfe
--- /dev/null
+++ b/board/Marvell/octeon_nic23/MAINTAINERS
@@ -0,0 +1,7 @@
+OCTEON_NIC23 BOARD
+M: Aaron Williams <awilliams@marvell.com>
+S: Maintained
+F: board/Marvell/octeon_nic23/*
+F: configs/octeon_nic23_defconfig
+F: include/configs/octeon_nic23.h
+F: arch/mips/dts/mrvl,octeon-nic23.dts
diff --git a/board/Marvell/octeon_nic23/Makefile b/board/Marvell/octeon_nic23/Makefile
new file mode 100644
index 0000000000..a79b94ec6f
--- /dev/null
+++ b/board/Marvell/octeon_nic23/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2021 Stefan Roese <sr@denx.de>
+# Copyright (C) 2019-2020 Marvell International Ltd.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := board.o
diff --git a/board/Marvell/octeon_nic23/board.c b/board/Marvell/octeon_nic23/board.c
new file mode 100644
index 0000000000..9f5eb2e2a1
--- /dev/null
+++ b/board/Marvell/octeon_nic23/board.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Stefan Roese <sr@denx.de>
+ */
+
+#include <dm.h>
+#include <ram.h>
+
+#include <mach/octeon_ddr.h>
+#include <mach/cvmx-qlm.h>
+#include <mach/octeon_qlm.h>
+#include <mach/octeon_fdt.h>
+#include <mach/cvmx-helper.h>
+#include <mach/cvmx-helper-cfg.h>
+#include <mach/cvmx-helper-util.h>
+#include <mach/cvmx-bgxx-defs.h>
+
+#include "board_ddr.h"
+
+#define NIC23_DEF_DRAM_FREQ 800
+
+static u8 octeon_nic23_cfg0_spd_values[512] = {
+ OCTEON_NIC23_CFG0_SPD_VALUES
+};
+
+static struct ddr_conf board_ddr_conf[] = {
+ OCTEON_NIC23_DDR_CONFIGURATION
+};
+
+struct ddr_conf *octeon_ddr_conf_table_get(int *count, int *def_ddr_freq)
+{
+ *count = ARRAY_SIZE(board_ddr_conf);
+ *def_ddr_freq = NIC23_DEF_DRAM_FREQ;
+
+ return board_ddr_conf;
+}
+
+int board_fix_fdt(void *fdt)
+{
+ u32 range_data[5 * 8];
+ bool rev4;
+ int node;
+ int rc;
+
+ /*
+ * ToDo:
+ * Read rev4 info from EEPROM or where the original U-Boot does
+ * and don't hard-code it here.
+ */
+ rev4 = true;
+
+ debug("%s() rev4: %s\n", __func__, rev4 ? "true" : "false");
+ /* Patch the PHY configuration based on board revision */
+ rc = octeon_fdt_patch_rename(fdt,
+ rev4 ? "4,nor-flash" : "4,no-nor-flash",
+ "cavium,board-trim", false, NULL, NULL);
+ if (!rev4) {
+ /* Modify the ranges for CS 0 */
+ node = fdt_node_offset_by_compatible(fdt, -1,
+ "cavium,octeon-3860-bootbus");
+ if (node < 0) {
+ printf("%s: Error: cannot find boot bus in device tree!\n",
+ __func__);
+ return -1;
+ }
+
+ rc = fdtdec_get_int_array(fdt, node, "ranges",
+ range_data, 5 * 8);
+ if (rc) {
+ printf("%s: Error reading ranges from boot bus FDT\n",
+ __func__);
+ return -1;
+ }
+ range_data[2] = cpu_to_fdt32(0x10000);
+ range_data[3] = 0;
+ range_data[4] = 0;
+ rc = fdt_setprop(fdt, node, "ranges", range_data,
+ sizeof(range_data));
+ if (rc) {
+ printf("%s: Error updating boot bus ranges in fdt\n",
+ __func__);
+ }
+ }
+ return rc;
+}
+
+void board_configure_qlms(void)
+{
+ octeon_configure_qlm(4, 3000, CVMX_QLM_MODE_SATA_2X1, 0, 0, 0, 0);
+ octeon_configure_qlm(5, 103125, CVMX_QLM_MODE_XFI_1X2, 0, 0, 2, 0);
+ /* Apply amplitude tuning to 10G interface */
+ octeon_qlm_tune_v3(0, 4, 3000, -1, -1, 7, -1);
+ octeon_qlm_tune_v3(0, 5, 103125, 0x19, 0x0, -1, -1);
+ octeon_qlm_set_channel_v3(0, 5, 0);
+ octeon_qlm_dfe_disable(0, 5, -1, 103125, CVMX_QLM_MODE_XFI_1X2);
+ debug("QLM 4 reference clock: %d\n"
+ "DLM 5 reference clock: %d\n",
+ cvmx_qlm_measure_clock(4), cvmx_qlm_measure_clock(5));
+}
+
+int board_late_init(void)
+{
+ board_configure_qlms();
+
+ return 0;
+}
diff --git a/board/Marvell/octeon_nic23/board_ddr.h b/board/Marvell/octeon_nic23/board_ddr.h
new file mode 100644
index 0000000000..eac877faf8
--- /dev/null
+++ b/board/Marvell/octeon_nic23/board_ddr.h
@@ -0,0 +1,269 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ *
+ * https://spdx.org/licenses
+ */
+
+#ifndef __BOARD_DDR_H__
+#define __BOARD_DDR_H__
+
+#define OCTEON_NIC23_DRAM_SOCKET_CONFIGURATION0 \
+ { {0x0, 0x0}, {octeon_nic23_cfg0_spd_values, NULL} }
+
+#define NIC23_MTA8ATF51264AZ2G3_SPD_VALUES \
+ 0x23, 0x10, 0x0c, 0x02, 0x84, 0x19, 0x00, 0x08, \
+ 0x00, 0x00, 0x00, 0x03, 0x01, 0x0b, 0x80, 0x00, \
+ 0x00, 0x00, 0x08, 0x0c, 0xf4, 0x1b, 0x00, 0x00, \
+ 0x6c, 0x6c, 0x6c, 0x11, 0x08, 0x74, 0x20, 0x08, \
+ 0x00, 0x05, 0x70, 0x03, 0x00, 0xa8, 0x1e, 0x2b, \
+ 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x2c, 0x15, 0x35, \
+ 0x15, 0x35, 0x0b, 0x2c, 0x15, 0x35, 0x0b, 0x35, \
+ 0x0b, 0x2c, 0x0b, 0x35, 0x15, 0x36, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xb5, 0xce, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x30, 0x0e, \
+ 0x11, 0x11, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x2e, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x80, 0x2c, 0x0f, 0x14, 0x50, 0x0e, 0x08, 0x18, \
+ 0xc8, 0x31, 0x38, 0x41, 0x53, 0x46, 0x31, 0x47, \
+ 0x37, 0x32, 0x41, 0x5a, 0x2d, 0x32, 0x47, 0x31, \
+ 0x41, 0x31, 0x20, 0x20, 0x20, 0x31, 0x80, 0x2c, \
+ 0x41, 0x44, 0x50, 0x41, 0x45, 0x4e, 0x43, 0x39, \
+ 0x30, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define OCTEON_NIC23_CFG0_SPD_VALUES NIC23_MTA8ATF51264AZ2G3_SPD_VALUES
+
+#define OCTEON_NIC23_BOARD_EEPROM_TWSI_ADDR 0x56
+
+#define OCTEON_NIC23_MODEREG_PARAMS1_1RANK_1SLOT \
+{ \
+ .cn78xx = { \
+ .pasr_00 = 0, \
+ .asr_00 = 0, \
+ .srt_00 = 0, \
+ .rtt_wr_00 = ddr4_rttwr_80ohm & 3, \
+ .rtt_wr_00_ext = (ddr4_rttwr_80ohm >> 2) & 1, \
+ .dic_00 = ddr4_dic_34ohm, \
+ .rtt_nom_00 = 0, \
+ .pasr_01 = 0, \
+ .asr_01 = 0, \
+ .srt_01 = 0, \
+ .rtt_wr_01 = 0, \
+ .dic_01 = ddr4_dic_34ohm, \
+ .rtt_nom_01 = 0, \
+ .pasr_10 = 0, \
+ .asr_10 = 0, \
+ .srt_10 = 0, \
+ .rtt_wr_10 = 0, \
+ .dic_10 = ddr4_dic_34ohm, \
+ .rtt_nom_10 = 0, \
+ .pasr_11 = 0, \
+ .asr_11 = 0, \
+ .srt_11 = 0, \
+ .rtt_wr_11 = 0, \
+ .dic_11 = ddr4_dic_34ohm, \
+ .rtt_nom_11 = 0, \
+ } \
+ }
+
+#define OCTEON_NIC23_MODEREG_PARAMS1_1RANK_2SLOT \
+{ \
+ .cn78xx = { \
+ .pasr_00 = 0, \
+ .asr_00 = 0, \
+ .srt_00 = 0, \
+ .rtt_wr_00 = ddr4_rttwr_80ohm & 3, \
+ .rtt_wr_00_ext = (ddr4_rttwr_80ohm >> 2) & 1, \
+ .dic_00 = ddr4_dic_34ohm, \
+ .rtt_nom_00 = 0, \
+ .pasr_01 = 0, \
+ .asr_01 = 0, \
+ .srt_01 = 0, \
+ .rtt_wr_01 = 0, \
+ .dic_01 = ddr4_dic_34ohm, \
+ .rtt_nom_01 = 0, \
+ .pasr_10 = 0, \
+ .asr_10 = 0, \
+ .srt_10 = 0, \
+ .rtt_wr_10 = ddr4_rttwr_80ohm & 3, \
+ .rtt_wr_10_ext = (ddr4_rttwr_80ohm >> 2) & 1, \
+ .dic_10 = ddr4_dic_34ohm, \
+ .rtt_nom_10 = 0, \
+ .pasr_11 = 0, \
+ .asr_11 = 0, \
+ .srt_11 = 0, \
+ .rtt_wr_11 = 0, \
+ .dic_11 = ddr4_dic_34ohm, \
+ .rtt_nom_11 = 0 \
+ } \
+}
+
+#define OCTEON_NIC23_MODEREG_PARAMS2_1RANK_1SLOT \
+{ \
+ .cn78xx = { \
+ .rtt_park_00 = ddr4_rttpark_60ohm, \
+ .vref_value_00 = 0x22, \
+ .vref_range_00 = 0, \
+ .rtt_park_01 = 0, \
+ .vref_value_01 = 0, \
+ .vref_range_01 = 0, \
+ .rtt_park_10 = 0, \
+ .vref_value_10 = 0, \
+ .vref_range_10 = 0, \
+ .rtt_park_11 = 0, \
+ .vref_value_11 = 0, \
+ .vref_range_11 = 0 \
+ } \
+}
+
+#define OCTEON_NIC23_MODEREG_PARAMS2_1RANK_2SLOT \
+{ \
+ .cn78xx = { \
+ .rtt_park_00 = ddr4_rttpark_48ohm, \
+ .vref_value_00 = 0x1f, \
+ .vref_range_00 = 0, \
+ .rtt_park_01 = 0, \
+ .vref_value_01 = 0, \
+ .vref_range_01 = 0, \
+ .rtt_park_10 = ddr4_rttpark_48ohm, \
+ .vref_value_10 = 0x1f, \
+ .vref_range_10 = 0, \
+ .rtt_park_11 = 0, \
+ .vref_value_11 = 0, \
+ .vref_range_11 = 0 \
+ } \
+}
+
+#define OCTEON_NIC23_CN73XX_DRAM_ODT_1RANK_CONFIGURATION \
+ /* 1 */ \
+ { \
+ ddr4_dqx_driver_34_ohm, \
+ 0x00000000ULL, \
+ OCTEON_NIC23_MODEREG_PARAMS1_1RANK_1SLOT, \
+ OCTEON_NIC23_MODEREG_PARAMS2_1RANK_1SLOT, \
+ ddr4_rodt_ctl_48_ohm, \
+ 0x00000000ULL, \
+ 0 \
+ }, \
+ /* 2 */ \
+ { \
+ ddr4_dqx_driver_34_ohm, \
+ 0x00000000ULL, \
+ OCTEON_NIC23_MODEREG_PARAMS1_1RANK_2SLOT, \
+ OCTEON_NIC23_MODEREG_PARAMS2_1RANK_2SLOT, \
+ ddr4_rodt_ctl_80_ohm, \
+ 0x00000000ULL, \
+ 0 \
+ }
+
+/*
+ * Construct a static initializer for the ddr_configuration_t variable that
+ * holds (almost) all of the information required for DDR initialization.
+ */
+
+/*
+ * The parameters below make up the custom_lmc_config data structure.
+ * This structure is used to customize the way that the LMC DRAM
+ * Controller is configured for a particular board design.
+ *
+ * Refer to the file lib_octeon_board_table_entry.h for a description
+ * of the custom board settings. It is usually kept in the following
+ * location... arch/mips/include/asm/arch-octeon/
+ *
+ */
+
+#define OCTEON_NIC23_DDR_CONFIGURATION \
+/* Interface 0 */ \
+{ \
+ .custom_lmc_config = { \
+ .min_rtt_nom_idx = 2, \
+ .max_rtt_nom_idx = 5, \
+ .min_rodt_ctl = 2, \
+ .max_rodt_ctl = 4, \
+ .ck_ctl = ddr4_driver_34_ohm, \
+ .cmd_ctl = ddr4_driver_34_ohm, \
+ .ctl_ctl = ddr4_driver_34_ohm, \
+ .min_cas_latency = 7, \
+ .offset_en = 1, \
+ .offset_udimm = 2, \
+ .offset_rdimm = 2, \
+ .ddr_rtt_nom_auto = 0, \
+ .ddr_rodt_ctl_auto = 0, \
+ .rlevel_compute = 0, \
+ .ddr2t_udimm = 1, \
+ .ddr2t_rdimm = 1, \
+ .maximum_adjacent_rlevel_delay_increment = 2, \
+ .fprch2 = 2, \
+ .dll_write_offset = NULL, \
+ .dll_read_offset = NULL, \
+ .disable_sequential_delay_check = 1, \
+ .parity = 0 \
+ }, \
+ .dimm_config_table = { \
+ OCTEON_NIC23_DRAM_SOCKET_CONFIGURATION0, \
+ DIMM_CONFIG_TERMINATOR \
+ }, \
+ .unbuffered = { \
+ .ddr_board_delay = 0, \
+ .lmc_delay_clk = 0, \
+ .lmc_delay_cmd = 0, \
+ .lmc_delay_dq = 0 \
+ }, \
+ .registered = { \
+ .ddr_board_delay = 0, \
+ .lmc_delay_clk = 0, \
+ .lmc_delay_cmd = 0, \
+ .lmc_delay_dq = 0 \
+ }, \
+ .odt_1rank_config = { \
+ OCTEON_NIC23_CN73XX_DRAM_ODT_1RANK_CONFIGURATION \
+ }, \
+},
+
+#endif /* __BOARD_DDR_H__ */