${carrier} selects the kernel's DTS and the MC's the DPC + DPL
to beloaded from the FIT.

Into the FIT, they should have the following names:
  conf-, dpc-, dpl-${carrier}

The console shall display the selected carrier.

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

 board/nxp/lx2160a/nbxv3/carrier.c | 87 ++++++++++++++++++++++++++-----
 doc/board/nxp/nbxv3.rst           | 35 ++++++++++++-
 2 files changed, 106 insertions(+), 16 deletions(-)

diff --git a/board/nxp/lx2160a/nbxv3/carrier.c 
b/board/nxp/lx2160a/nbxv3/carrier.c
index c810fe01957..61bab54d5ef 100644
--- a/board/nxp/lx2160a/nbxv3/carrier.c
+++ b/board/nxp/lx2160a/nbxv3/carrier.c
@@ -15,13 +15,22 @@
  *   mcinitcmd  imxtract ... dpc-${carrier} / dpl-${carrier}
  *   mc_init    bootm ${kernel_addr_r}#conf-${carrier}
  *
- * For testing, we can enforce, change it from the prompt and make it 
persistent:
- *   setenv carrier nbv32 && saveenv && reset
+ * ${carrier} comes, first match wins, from:
+ *   1. the environment, e.g. a saved one:
+ *        setenv carrier nbv32 && saveenv && reset
+ *   2. the RCW build stamp in DCFG SCRATCHRW13, see below
+ *   3. NBXV3_CARRIER_DEFAULT
  */
 
 #include <env.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
 #include <linux/kernel.h>
 #include <vsprintf.h>
+#include <asm/io.h>
+#include <asm/arch/immap_lsch3.h>
+#include <asm/arch/soc.h>
 
 #include "carrier.h"
 
@@ -30,35 +39,85 @@
 #endif
 
 /*
- * Placeholder for strap/EEPROM based identification.
- * Returning NULL means "cannot tell".
+ * RCW build stamp. The RCW must already match the carrier, because it
+ * sets the SerDes protocols and the pinmux, so its PBI also writes the
+ * carrier it was built for into DCFG SCRATCHRW13:
+ *
+ *   31   28 27   24 23   16 15    8 7     0
+ *  +-------+-------+-------+-------+-------+
+ *  |CARRIER|  TAG  |  YY   |  MM   |  DD   |
+ *  +-------+-------+-------+-------+-------+
+ *
+ * TAG is 0xB. Any other TAG, including the reset value 0 of the
+ * register, means no stamp. YY MM DD is the RCW build date in BCD, for
+ * the operator only.
+ *
+ * CARRIER:
+ *   0     any nbv3 carrier: one RCW for all of them, it names none
+ *   1     NBV30 / NBV31
+ *   2     NBV32
+ *   3     NBV32 with SerDes 1 at protocol 20 (2x 40GE) in the RCW
+ *   4..F  unassigned, treated like 0
  */
-static const char *nbxv3_carrier_detect(void)
+#define NBXV3_STAMP_SCRATCHRW          12      /* SCRATCHRW13 */
+#define NBXV3_STAMP_CARRIER            GENMASK(31, 28)
+#define NBXV3_STAMP_TAG                        GENMASK(27, 24)
+#define NBXV3_STAMP_TAG_NBXV3          0xb
+
+/* CARRIER digit of the RCW build stamp, -ENOENT without a stamp */
+static int nbxv3_stamp_carrier(void)
 {
-       /* TODO, not available yet */
-       return NULL;
+       struct ccsr_gur __iomem *gur = (void __iomem *)CFG_SYS_FSL_GUTS_ADDR;
+       u32 stamp = gur_in32(&gur->scratchrw[NBXV3_STAMP_SCRATCHRW]);
+
+       if (FIELD_GET(NBXV3_STAMP_TAG, stamp) != NBXV3_STAMP_TAG_NBXV3)
+               return -ENOENT;
+
+       return FIELD_GET(NBXV3_STAMP_CARRIER, stamp);
+}
+
+/* NULL when the stamp names no carrier */
+static const char *nbxv3_carrier_detect(int digit)
+{
+       switch (digit) {
+       case 1:
+               return "nbv30";
+       case 2:
+               return "nbv32";
+       case 3:
+               return "nbv32-40g";
+       default:
+               return NULL;
+       }
 }
 
 void nbxv3_carrier_env_init(void)
 {
        const char *carrier = env_get("carrier");
-       const char *detected;
+       const char *origin;
+       int digit;
 
        if (carrier && *carrier) {
                printf("Carrier:       %s (from env)\n", carrier);
                return;
        }
 
-       detected = nbxv3_carrier_detect();
-       if (!detected)
-               detected = NBXV3_CARRIER_DEFAULT;
+       digit = nbxv3_stamp_carrier();
+       carrier = nbxv3_carrier_detect(digit);
+       if (carrier) {
+               origin = "RCW build stamp";
+       } else {
+               carrier = NBXV3_CARRIER_DEFAULT;
+               origin = digit < 0 ? "default, no RCW build stamp" :
+                                    "default, the RCW names no carrier";
+       }
 
-       if (env_set("carrier", detected)) {
+       if (env_set("carrier", carrier)) {
                printf("Carrier:       WARNING: cannot set ${carrier}\n");
                return;
        }
 
        /* Not saved on purpose: saveenv on every boot would burn the NOR */
-       printf("Carrier:       %s (default, not saved; setenv carrier <name> && 
saveenv to pin)\n",
-              detected);
+       printf("Carrier:       %s (%s, not saved; setenv carrier <name> && 
saveenv to pin)\n",
+              carrier, origin);
 }
diff --git a/doc/board/nxp/nbxv3.rst b/doc/board/nxp/nbxv3.rst
index 98d5cf9e17d..3eb87104a52 100644
--- a/doc/board/nxp/nbxv3.rst
+++ b/doc/board/nxp/nbxv3.rst
@@ -80,9 +80,40 @@ FIT image at NOR offset 0x1000000::
   /configurations/conf-<carrier>
 
 ``${carrier}`` selects the carrier set (``conf-<carrier>``, ``dpc-``,
-``dpl-``). It is set on every boot. For debug, to enforce another carrier::
+``dpl-``). It is set on every boot, from the first of:
 
-  => setenv carrier nbv32 && saveenv && reset
+1. the environment. For debug, to enforce another carrier::
+
+     => setenv carrier nbv32 && saveenv && reset
+
+2. the RCW build stamp, see below,
+
+3. ``nbv30``, the built-in default.
+
+RCW build stamp
+^^^^^^^^^^^^^^^
+
+The RCW sets the SerDes protocols and the pinmux.
+Its PBI writes the carrier it was built for into
+DCFG SCRATCHRW13 (0x01e00230)::
+
+   31   28 27   24 23   16 15    8 7     0
+  +-------+-------+-------+-------+-------+
+  |CARRIER|  TAG  |  YY   |  MM   |  DD   |
+  +-------+-------+-------+-------+-------+
+
+``TAG`` is 0xB; any other value, such as the reset value 0, means no
+stamp. ``YY MM DD`` is the RCW build date in BCD, for the operator only.
+
+======= ==================================================
+CARRIER ``${carrier}``
+======= ==================================================
+0       none: one RCW for every carrier, it names none
+1       ``nbv30`` (NBV30, NBV31)
+2       ``nbv32``
+3       ``nbv32-40g``: NBV32 with SerDes 1 protocol 20 (2x 40GE)
+4..F    unassigned, treated like 0
+======= ==================================================
 
 Boot flow
 ---------
-- 
2.43.0

Reply via email to