Fix the commit
  035d68fc36b5 ("lx2160: add lx2160_serdes split and management")
which is in next.

It leads to the following commands which are more explicit:

  lx2160_sd1 100g4x25g
        CHANGES the SerDes 1 Ethernet mode: it re-groups SD1's
        eight lanes and re-points its protocol converters.

  lx2160_serdes status [1|2|3]
        only READS, any of the three SerDes, unchanged syntax.

In order to prepare the next commits, this mode should be:
  100g4x25g (1x 100G + 4x 25G),
instead of "split", same for its hwconfig key:

  setenv hwconfig serdes1:100g4x25g && saveenv

The follow-up patches will add more SerDes 1 modes under the lx2160_sd1.

The SerDes 3 and LX2160A-only branches use IS_ENABLED() instead of
preprocessor conditionals, and the header no longer wraps its
declarations in CONFIG_ARCH_LX2160A: the definitions stay guarded in
serdes_split.c.

Signed-off-by: Vincent Jardin <[email protected]>

---

Changes in v3:
- Incremental on top of next, where v1 is merged as 035d68fc36b5:
  v2 mistakenly re-sent the whole file as its patch 1 (reported by
  Vladimir Oltean). Patch 1 is now only the delta: the lx2160_sd1 /
  lx2160_serdes command split and the 100g4x25g naming.
- Patches 2-5 unchanged, rebased onto next

Changes in v2:
- The mode-changing command is lx2160_sd1, lx2160_serdes only reads
  (v1 had both behind one lx2160_serdes command)
- New patches 2-4: the runtime SD1 conversions for many cases of
  split (2x 100GE -> 2x 40GE, second 40GE port -> 4x 10G,
  1x 100GE + 4x 10G)
- New patch 5: hwconfig and README.soc documentation
- Mode names say what they produce: 100g4x25g (v1: split), 2x40g
  (was 40g), 40g4x10g (was 4x10g); 100g4x10g unchanged; same for the
  hwconfig serdes1: keys
- Rebased onto main

 board/nxp/lx2160a/eth_lx2160aqds.c |   2 +-
 board/nxp/lx2160a/serdes_split.c   | 119 ++++++++++++++++-------------
 board/nxp/lx2160a/serdes_split.h   |  11 +--
 3 files changed, 70 insertions(+), 62 deletions(-)

diff --git a/board/nxp/lx2160a/eth_lx2160aqds.c 
b/board/nxp/lx2160a/eth_lx2160aqds.c
index c1a060877cd..b13606354e0 100644
--- a/board/nxp/lx2160a/eth_lx2160aqds.c
+++ b/board/nxp/lx2160a/eth_lx2160aqds.c
@@ -18,7 +18,7 @@ void reset_phy(void)
 {
        /*
         * Before the MC boots: it latches the live protocol-converter
-        * configuration when it starts, so `hwconfig=serdes1:split` has to
+        * configuration when it starts, so `hwconfig=serdes1:100g4x25g` has to
         * be applied here and not later.
         */
        lx2160a_serdes_apply_hwconfig();
diff --git a/board/nxp/lx2160a/serdes_split.c b/board/nxp/lx2160a/serdes_split.c
index ca3d7228977..04339a71350 100644
--- a/board/nxp/lx2160a/serdes_split.c
+++ b/board/nxp/lx2160a/serdes_split.c
@@ -2,7 +2,7 @@
 /*
  * Copyright 2026 Free Mobile - Vincent Jardin
  *
- * LX2160A 28G-Lynx SerDes inspection (`lx2160_serdes`).
+ * LX2160A 28G-Lynx SerDes customization.
  */
 
 #include <command.h>
@@ -19,11 +19,8 @@
 
 #include "serdes_split.h"
 
-#if defined(CONFIG_SYS_NXP_SRDS_3)
-#define SRDS_COUNT             3
-#else
-#define SRDS_COUNT             2       /* LX2162A has no SerDes 3 */
-#endif
+/* LX2162A has no SerDes 3 */
+#define SRDS_COUNT             (IS_ENABLED(CONFIG_SYS_NXP_SRDS_3) ? 3 : 2)
 #define SRDS_LANES             8
 #define SRDS_BLOCK_STRIDE      0x10000
 #define SRDS_LANE_STRIDE       0x100
@@ -102,8 +99,9 @@ static void print_rstctl(const char *what, u32 v)
  * must be 0 only on the port's master lane, and 0 on every single-lane
  * port. So a run of lanes where exactly one has PORT_LN0_B=0 is one
  * multi-lane port, and a run where all of them are 0 is that many
- * one-lane ports. That is precisely what the 100G -> 4x 25G split
- * changes, and it is invisible in RCWSR.
+ * one-lane ports.
+ * That is precisely what the 100G -> 4x 25G split changes, and it is
+ * invisible in RCWSR.
  */
 static void print_lane(unsigned long base, int m)
 {
@@ -126,15 +124,14 @@ static void print_lane(unsigned long base, int m)
 
 /*
  * Summarise the port grouping, which is the one line that says whether a
- * split happened. With PORT_RST_LEFT=0 the port's master is
- * its right-most lane (towards LNH), with PORT_RST_LEFT=1 it is the
- * left-most: PORT_LN0_B=0 marks that master, and is also 0 on every
- * single-lane port. So a group is a run of PORT_LN0_B=1 lanes terminated
- * (or led) by a PORT_LN0_B=0 lane.
+ * split happened.
+ * With PORT_RST_LEFT=0 the port's master is its right-most lane (towards LNH)
+ * With PORT_RST_LEFT=1 it is the left-most: PORT_LN0_B=0 marks that master
+ * and is also 0 on every single-lane port. So a group is a run of PORT_LN0_B=1
+ * lanes terminated (or led) by a PORT_LN0_B=0 lane.
  *
- * Checked on board with the PBI split applied:
- *   [LNA-LND] [LNE] [LNF] [LNG] [LNH]   -- 1x 100G + 4x 25G
- * and without it lanes E-H would read as a second [LNE-LNH] group.
+ * Examples:
+ *   [LNA-LND] [LNE] [LNF] [LNG] [LNH]  1x 100G + 4x 25G
  */
 static void print_grouping(unsigned long base)
 {
@@ -152,7 +149,7 @@ static void print_grouping(unsigned long base)
                int s, e;
 
                if (gcr0[m] & GCR0_PORT_LN0_B)
-                       continue;               /* a follower, not a master */
+                       continue; /* a follower, not a master */
 
                s = m;
                e = m;
@@ -225,13 +222,13 @@ static void print_rcw_view(int sd)
                mask  = FSL_CHASSIS3_SRDS2_PRTCL_MASK;
                shift = FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
                break;
-#if defined(CONFIG_SYS_NXP_SRDS_3)
        case NXP_SRDS_3:
+               if (!IS_ENABLED(CONFIG_SYS_NXP_SRDS_3))
+                       return;
                regsr = FSL_CHASSIS3_SRDS3_REGSR;
                mask  = FSL_CHASSIS3_SRDS3_PRTCL_MASK;
                shift = FSL_CHASSIS3_SRDS3_PRTCL_SHIFT;
                break;
-#endif
        default:
                return;
        }
@@ -248,8 +245,7 @@ static void print_rcw_view(int sd)
 /*
  * The split itself.
  *
- * This is NXP's e100g1_split.rcw sequence, moved from the PBI into
- * U-Boot.
+ * This is NXP's e100g1_split.rcw sequence, adapted from the PBI into U-Boot
  */
 #define SPLIT_FIRST_LANE       4       /* LNE */
 #define SPLIT_LAST_LANE                7       /* LNH */
@@ -272,8 +268,10 @@ static bool srds1_split_state(unsigned long base)
        u32 pcce = in_le32((void __iomem *)SRDS_PCCE(base));
 
        return PCCE_E100GA_CFG(pcce) == 0 &&
-              PCCD_E25G_CFG(pccd, 0) && PCCD_E25G_CFG(pccd, 1) &&
-              PCCD_E25G_CFG(pccd, 2) && PCCD_E25G_CFG(pccd, 3);
+              PCCD_E25G_CFG(pccd, 0) &&
+              PCCD_E25G_CFG(pccd, 1) &&
+              PCCD_E25G_CFG(pccd, 2) &&
+              PCCD_E25G_CFG(pccd, 3);
 }
 
 bool lx2160a_serdes1_is_split(void)
@@ -286,15 +284,17 @@ static bool srds1_is_unsplit(unsigned long base)
        u32 pccd = in_le32((void __iomem *)SRDS_PCCD(base));
        u32 pcce = in_le32((void __iomem *)SRDS_PCCE(base));
 
-       return PCCE_E100GA_CFG(pcce) != 0 && PCCE_E100GB_CFG(pcce) != 0 &&
-              PCCD_E25G_CFG(pccd, 0) == 0 && PCCD_E25G_CFG(pccd, 1) == 0 &&
-              PCCD_E25G_CFG(pccd, 2) == 0 && PCCD_E25G_CFG(pccd, 3) == 0;
+       return PCCE_E100GA_CFG(pcce) != 0 &&
+              PCCE_E100GB_CFG(pcce) != 0 &&
+              PCCD_E25G_CFG(pccd, 0) == 0 &&
+              PCCD_E25G_CFG(pccd, 1) == 0 &&
+              PCCD_E25G_CFG(pccd, 2) == 0 &&
+              PCCD_E25G_CFG(pccd, 3) == 0;
 }
 
 /*
- * Wait for a self-clearing request bit. Per the doc, hardware
- * clears HLT_REQ when the halt completes and RST_REQ when the reset
- * completes.
+ * Wait for a self-clearing request bit. The CPU clears HLT_REQ
+ * when the halt completes and RST_REQ when the reset completes.
  */
 static int poll_clear(unsigned long reg, u32 bit)
 {
@@ -328,11 +328,11 @@ int lx2160a_serdes1_split(void)
 
        /*
         * Halt. "Halt only has meaning on the master source
-        * clock lane of a port (LNmGCR0[PORT_LN0_B]=0)". Lanes E-H are one
-        * 100G port at this point, so exactly one of them is the master and
-        * the other three requests are ignored. Issue all four anyway
-        * (that is what NXP's sequence does) but only wait on the lane
-        * where the bit can actually clear.
+        * clock lane of a port (LNmGCR0[PORT_LN0_B]=0)".
+        * Lanes E-H are one 100G port at this point, so exactly one of
+        * them is the master and the other three requests are ignored.
+        * Issue all four anyway but only wait on the lane where the bit
+        * can actually clear.
         */
        for (m = SPLIT_FIRST_LANE; m <= SPLIT_LAST_LANE; m++) {
                if (!(in_le32((void __iomem *)SRDS_LNmGCR0(base, m)) &
@@ -409,13 +409,13 @@ int lx2160a_serdes1_split(void)
 }
 
 /*
- *   setenv hwconfig serdes1:split
+ *   setenv hwconfig serdes1:100g4x25g
  *
  * Idempotent: a board whose PBI already split SD1 skip it too.
  */
 void lx2160a_serdes_apply_hwconfig(void)
 {
-       if (!hwconfig_sub("serdes1", "split"))
+       if (!hwconfig_sub("serdes1", "100g4x25g"))
                return;
 
        if (lx2160a_serdes1_is_split())
@@ -441,19 +441,17 @@ static int do_serdes_status(int sd)
        return CMD_RET_SUCCESS;
 }
 
-static int do_lx2160_serdes(struct cmd_tbl *cmdtp, int flag,
-                           int argc, char *const argv[])
+static int do_lx2160_sd1(struct cmd_tbl *cmdtp, int flag,
+                        int argc, char *const argv[])
 {
-       int sd;
-
        if (argc < 2)
                return CMD_RET_USAGE;
 
-       if (!strcmp(argv[1], "split")) {
-#if !defined(CONFIG_ARCH_LX2160A)
-               printf("no 100GE on SerDes 1 to split on this SoC\n");
-               return CMD_RET_FAILURE;
-#else
+       if (!strcmp(argv[1], "100g4x25g")) {
+               if (!IS_ENABLED(CONFIG_ARCH_LX2160A)) {
+                       printf("no 100GE on SerDes 1 to split on this SoC\n");
+                       return CMD_RET_FAILURE;
+               }
                if (argc != 2)
                        return CMD_RET_USAGE;
                if (lx2160a_serdes1_is_split()) {
@@ -463,9 +461,20 @@ static int do_lx2160_serdes(struct cmd_tbl *cmdtp, int 
flag,
                if (lx2160a_serdes1_split())
                        return CMD_RET_FAILURE;
                return CMD_RET_SUCCESS;
-#endif
        }
 
+       return CMD_RET_USAGE;
+}
+
+/* reads SD1, SD2 or SD3 */
+static int do_lx2160_serdes(struct cmd_tbl *cmdtp, int flag,
+                           int argc, char *const argv[])
+{
+       int sd;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
        if (strcmp(argv[1], "status"))
                return CMD_RET_USAGE;
 
@@ -488,15 +497,22 @@ static int do_lx2160_serdes(struct cmd_tbl *cmdtp, int 
flag,
 }
 
 #if defined(CONFIG_ARCH_LX2160A)
-#define SPLIT_CMD_HELP                                                 \
-       "lx2160_serdes split\n"                                         \
+#define SD1_CMD_HELP                                                   \
+       "100g4x25g\n"                                                   \
        "    - split Lynx 28G SD1 100GE.1 (lanes LNE-LNH) into 4x 25G.\n"       
\
        "      Runs before the MC starts. To make it permanent on a board\n"    
\
-       "      that needs it: setenv hwconfig serdes1:split && saveenv"
+       "      that needs it: setenv hwconfig serdes1:100g4x25g && saveenv"
 #else
-#define SPLIT_CMD_HELP ""
+#define SD1_CMD_HELP                                                   \
+       "    - no SerDes 1 Ethernet modes on this SoC"
 #endif
 
+U_BOOT_CMD(
+       lx2160_sd1, 3, 0, do_lx2160_sd1,
+       "select the LX2160A SerDes 1 Ethernet mode",
+       SD1_CMD_HELP
+);
+
 U_BOOT_CMD(
        lx2160_serdes, 3, 0, do_lx2160_serdes,
        "inspect the LX2160A 28G-Lynx SerDes protocol configuration",
@@ -504,6 +520,5 @@ U_BOOT_CMD(
        "    - print the live protocol converters (PCCC/PCCD/PCCE) and the\n"
        "      per-lane port grouping and protocol (LNmGCR0), next to the\n"
        "      protocol number the RCW latched.\n"
-       "      No argument prints all three SerDes."
-       SPLIT_CMD_HELP
+       "      No argument prints all CPU SerDes blocks."
 );
diff --git a/board/nxp/lx2160a/serdes_split.h b/board/nxp/lx2160a/serdes_split.h
index 67e8c4873a7..764eb640029 100644
--- a/board/nxp/lx2160a/serdes_split.h
+++ b/board/nxp/lx2160a/serdes_split.h
@@ -7,10 +7,9 @@
 #define __LX2160A_SERDES_SPLIT_H
 
 /*
- * The split is LX2160A only: LX2162A's SerDes 1 is four lanes with no
- * 100GE in its protocol table.
+ * The SerDes 1 modes are LX2160A only: LX2162A's SerDes 1 is four lanes
+ * without 100GE in its protocol table.
  */
-#if defined(CONFIG_ARCH_LX2160A)
 
 /* Is SerDes 1 already 1x 100G + 4x 25G? */
 bool lx2160a_serdes1_is_split(void);
@@ -24,12 +23,6 @@ bool lx2160a_serdes1_is_split(void);
  */
 int lx2160a_serdes1_split(void);
 
-/*
- * Apply `hwconfig=serdes1:split` if the board's environment asks for it.
- * Boards call this from reset_phy(), before mc_env_boot().
- */
 void lx2160a_serdes_apply_hwconfig(void);
 
-#endif /* CONFIG_ARCH_LX2160A */
-
 #endif /* __LX2160A_SERDES_SPLIT_H */
-- 
2.43.0

Reply via email to