Derive the mode from ${carrier}:
nbv32 100g4x25g 1x 100GE + 4x 25G
nbv32-40g 2x40g 2x 40GE
nbv32-40g-4x10g 40g4x10g 1x 40GE + 4x 10G
nbv32-100g-4x10g 100g4x10g 1x 100GE + 4x 10G
so that "setenv carrier <name>" alone selects the lanes and the data
path that describes them.
Signed-off-by: Vincent Jardin <[email protected]>
---
board/nxp/lx2160a/nbxv3/carrier.c | 97 +++++++++++++++++++++++++++++
board/nxp/lx2160a/nbxv3/carrier.h | 6 ++
board/nxp/lx2160a/nbxv3/eth_nbxv3.c | 4 +-
doc/board/nxp/nbxv3.rst | 22 +++++++
4 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/board/nxp/lx2160a/nbxv3/carrier.c
b/board/nxp/lx2160a/nbxv3/carrier.c
index 06a54bed0eb..26b079a1d3a 100644
--- a/board/nxp/lx2160a/nbxv3/carrier.c
+++ b/board/nxp/lx2160a/nbxv3/carrier.c
@@ -23,16 +23,20 @@
*/
#include <env.h>
+#include <hwconfig.h>
+#include <malloc.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <vsprintf.h>
#include <asm/io.h>
#include <asm/arch/immap_lsch3.h>
#include <asm/arch/soc.h>
#include "carrier.h"
+#include "../serdes_split.h"
#ifndef NBXV3_CARRIER_DEFAULT
#define NBXV3_CARRIER_DEFAULT "nbv30"
@@ -148,3 +152,96 @@ void nbxv3_carrier_env_init(void)
printf("Carrier: %s (%s, not saved; setenv carrier <name> &&
saveenv to pin)\n",
carrier, origin);
}
+
+/*
+ * serdes 1 lane grouping of each carrier, as a hwconfig serdes1:<mode>
+ * of board/nxp/lx2160a/serdes_split.c. A carrier without an entry
+ * keeps what the RCW provides.
+ *
+ * nbv32-40g used to need an RCW at serdes 1 protocol 20. serdes1:2x40g
+ * builds the same grouping from the protocol 13 RCW, and it is void
+ * for a protocol 20 one.
+ */
+static const struct {
+ const char *carrier;
+ const char *mode;
+} nbxv3_serdes1_modes[] = {
+ { .carrier = "nbv32", .mode = "100g4x25g" },
+ { .carrier = "nbv32-40g", .mode = "2x40g" },
+ { .carrier = "nbv32-40g-4x10g", .mode = "40g4x10g" },
+ { .carrier = "nbv32-100g-4x10g", .mode = "100g4x10g" },
+};
+
+/* Is ${hwconfig} serdes1:@mode ? */
+static bool nbxv3_serdes1_is(const char *mode)
+{
+ const char *arg;
+ size_t len;
+
+ arg = hwconfig_arg("serdes1", &len);
+
+ return arg && len == strlen(mode) && !strncmp(arg, mode, len);
+}
+
+/* Does ${hwconfig} name a SerDes 1 mode ? */
+static bool nbxv3_serdes1_named(void)
+{
+ int i;
+
+ if (nbxv3_serdes1_is("2x100g"))
+ return true;
+
+ for (i = 0; i < ARRAY_SIZE(nbxv3_serdes1_modes); i++)
+ if (nbxv3_serdes1_is(nbxv3_serdes1_modes[i].mode))
+ return true;
+
+ return false;
+}
+
+void nbxv3_serdes1_apply(void)
+{
+ const char *carrier = env_get("carrier");
+ const char *mode = NULL;
+ const char *cur;
+ char *saved = NULL;
+ char *hw = NULL;
+ bool set = false;
+ int i;
+
+ for (i = 0; carrier && i < ARRAY_SIZE(nbxv3_serdes1_modes); i++)
+ if (!strcmp(carrier, nbxv3_serdes1_modes[i].carrier))
+ mode = nbxv3_serdes1_modes[i].mode;
+
+ /* Put serdes1:<mode> in front of ${hwconfig} */
+ if (mode && !nbxv3_serdes1_named()) {
+ if (hwconfig("serdes1"))
+ printf("Carrier: ${hwconfig} serdes1 names no
mode, serdes1:%s of %s used\n",
+ mode, carrier);
+ cur = env_get("hwconfig");
+ if (cur && *cur)
+ saved = strdup(cur);
+ hw = malloc(sizeof("serdes1:") + strlen(mode) +
+ (saved ? strlen(saved) + 1 : 0));
+ if (hw && (saved || !cur || !*cur)) {
+ sprintf(hw, "serdes1:%s%s%s", mode, saved ? ";" : "",
+ saved ? saved : "");
+ set = !env_set("hwconfig", hw);
+ }
+ if (!set)
+ printf("Carrier: WARNING: cannot add serdes1:%s
to ${hwconfig}\n",
+ mode);
+ }
+
+ lx2160a_serdes_apply_hwconfig();
+
+ /* The DS250 retimers do not follow the SerDes on their own */
+ if (nbxv3_serdes1_is("100g4x10g"))
+ printf("Carrier: serdes1:100g4x10g mixes 25.78125 and
10.3125 Gbd lanes, set each retimer CDR to the rate of its lane\n");
+
+ /* Put ${hwconfig} back; NULL deletes it again if it was not set */
+ if (set && env_set("hwconfig", saved))
+ printf("Carrier: WARNING: cannot restore ${hwconfig}\n");
+
+ free(hw);
+ free(saved);
+}
diff --git a/board/nxp/lx2160a/nbxv3/carrier.h
b/board/nxp/lx2160a/nbxv3/carrier.h
index 44b2ce1f047..063765821eb 100644
--- a/board/nxp/lx2160a/nbxv3/carrier.h
+++ b/board/nxp/lx2160a/nbxv3/carrier.h
@@ -15,4 +15,10 @@
*/
void nbxv3_carrier_env_init(void);
+/*
+ * Apply the serdes 1 lane of ${carrier}, unless ${hwconfig}
+ * names a serdes1:<mode>
+ */
+void nbxv3_serdes1_apply(void);
+
#endif /* __NBXV3_CARRIER_H */
diff --git a/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
b/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
index 69873909733..6dd05b5fe23 100644
--- a/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
+++ b/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
@@ -15,7 +15,6 @@
#include <fsl-mc/fsl_mc.h>
#include "carrier.h"
-#include "../serdes_split.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -35,7 +34,8 @@ void reset_phy(void)
*/
nbxv3_carrier_env_init();
- lx2160a_serdes_apply_hwconfig();
+ /* Then SerDes 1, from ${hwconfig} or else from ${carrier} */
+ nbxv3_serdes1_apply();
if (IS_ENABLED(CONFIG_FSL_MC_ENET))
mc_env_boot();
diff --git a/doc/board/nxp/nbxv3.rst b/doc/board/nxp/nbxv3.rst
index 8259ca85095..0e3578b5742 100644
--- a/doc/board/nxp/nbxv3.rst
+++ b/doc/board/nxp/nbxv3.rst
@@ -121,6 +121,28 @@ no data path for the MC to manage and starting it hangs
the boot.
U-Boot clears ``mcinitcmd`` for that boot, whatever ``${carrier}`` is,
and does not save it.
+SerDes 1 per carrier
+^^^^^^^^^^^^^^^^^^^^
+
+Before the MC starts, U-Boot should set the serdes 1 lane grouping
+that the MC's DPC and the DPL of ``${carrier}`` expect, using
+the ``serdes1`` hwconfig option. It can be used to
+override the RCW's protocol grouping for SerDes 1.
+
+==================== ================= ==============================
+``${carrier}`` serdes1 mode SerDes 1
+==================== ================= ==============================
+nbv30 (none) as built by the RCW
+nbv32 100g4x25g 1x 100GE + 4x 25G
+nbv32-40g 2x40g 2x 40GE
+nbv32-40g-4x10g 40g4x10g 1x 40GE + 4x 10G
+nbv32-100g-4x10g 100g4x10g 1x 100GE + 4x 10G
+==================== ================= ==============================
+
+Example to switch an NBV32 to 1x40GE + 4x10G::
+
+ => setenv carrier nbv32-40g-4x10g && saveenv && reset
+
Boot flow
---------
--
2.43.0