The Nodebox v3 CPU module runs on several carriers. They share one
kernel Image but they need different DTBs and different DPAA2 DPC/DPL,
so the kernel FIT carries every carrier's set as fdt-<c> / dpc-<c> /
dpl-<c> with a conf-<c> configuration each, and U-Boot picks one:
mcinitcmd imxtract ... dpc-${carrier} / dpl-${carrier}
mc_init bootm ${kernel_addr_r}#conf-${carrier}
Signed-off-by: Vincent Jardin <[email protected]>
---
(no changes since v1)
board/nxp/lx2160a/nbxv3/Makefile | 1 +
board/nxp/lx2160a/nbxv3/carrier.c | 64 +++++++++++++++++++++++++++++
board/nxp/lx2160a/nbxv3/carrier.h | 17 ++++++++
board/nxp/lx2160a/nbxv3/eth_nbxv3.c | 10 +++++
4 files changed, 92 insertions(+)
create mode 100644 board/nxp/lx2160a/nbxv3/carrier.c
create mode 100644 board/nxp/lx2160a/nbxv3/carrier.h
diff --git a/board/nxp/lx2160a/nbxv3/Makefile b/board/nxp/lx2160a/nbxv3/Makefile
index 68fab9bf18f..f6df35ed7c5 100644
--- a/board/nxp/lx2160a/nbxv3/Makefile
+++ b/board/nxp/lx2160a/nbxv3/Makefile
@@ -6,3 +6,4 @@ obj-y += eth_nbxv3.o
obj-y += mps_pmbus.o
obj-y += psu_pmbus.o
obj-y += vid_handoff.o
+obj-y += carrier.o
diff --git a/board/nxp/lx2160a/nbxv3/carrier.c
b/board/nxp/lx2160a/nbxv3/carrier.c
new file mode 100644
index 00000000000..c810fe01957
--- /dev/null
+++ b/board/nxp/lx2160a/nbxv3/carrier.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2026 Free Mobile - Vincent Jardin
+ *
+ * Nodebox v3 carrier selector.
+ *
+ * The CPU module is used on several carrier boards (nbv30, nbv32, ...).
+ * They share a same kernel Image but they need different DTBs and different
+ * DPAA2 DPC/DPL.
+ *
+ * images: fdt-<carrier>, dpc-<carrier>, dpl-<carrier>
+ * configurations: conf-<carrier>
+ *
+ * and then the boot env picks one with ${carrier}:
+ * 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
+ */
+
+#include <env.h>
+#include <linux/kernel.h>
+#include <vsprintf.h>
+
+#include "carrier.h"
+
+#ifndef NBXV3_CARRIER_DEFAULT
+#define NBXV3_CARRIER_DEFAULT "nbv30"
+#endif
+
+/*
+ * Placeholder for strap/EEPROM based identification.
+ * Returning NULL means "cannot tell".
+ */
+static const char *nbxv3_carrier_detect(void)
+{
+ /* TODO, not available yet */
+ return NULL;
+}
+
+void nbxv3_carrier_env_init(void)
+{
+ const char *carrier = env_get("carrier");
+ const char *detected;
+
+ if (carrier && *carrier) {
+ printf("Carrier: %s (from env)\n", carrier);
+ return;
+ }
+
+ detected = nbxv3_carrier_detect();
+ if (!detected)
+ detected = NBXV3_CARRIER_DEFAULT;
+
+ if (env_set("carrier", detected)) {
+ 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);
+}
diff --git a/board/nxp/lx2160a/nbxv3/carrier.h
b/board/nxp/lx2160a/nbxv3/carrier.h
new file mode 100644
index 00000000000..e7eb42265e4
--- /dev/null
+++ b/board/nxp/lx2160a/nbxv3/carrier.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2026 Free Mobile - Vincent Jardin
+ */
+
+#ifndef __NBXV3_CARRIER_H
+#define __NBXV3_CARRIER_H
+
+/*
+ * Ensure ${carrier} is set before anything consumes it.
+ * It is idempotent, and it never overrides a value already present
+ * in the uboot's environment.
+ * It shall run after initr_env and before ${mcinitcmd} is evaluated.
+ */
+void nbxv3_carrier_env_init(void);
+
+#endif /* __NBXV3_CARRIER_H */
diff --git a/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
b/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
index 8aec68c571f..a8d249c5cac 100644
--- a/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
+++ b/board/nxp/lx2160a/nbxv3/eth_nbxv3.c
@@ -14,6 +14,8 @@
#include <exports.h>
#include <fsl-mc/fsl_mc.h>
+#include "carrier.h"
+
DECLARE_GLOBAL_DATA_PTR;
int board_eth_init(struct bd_info *bis)
@@ -24,6 +26,14 @@ int board_eth_init(struct bd_info *bis)
#if defined(CONFIG_RESET_PHY_R)
void reset_phy(void)
{
+ /*
+ * MUST come first: mc_env_boot() evaluates ${mcinitcmd}, which
+ * imxtracts dpc-${carrier} / dpl-${carrier} out of the FIT. If
+ * ${carrier} is still unset a subimage named "dpc-" and the MC
+ * firmware never starts.
+ */
+ nbxv3_carrier_env_init();
+
if (IS_ENABLED(CONFIG_FSL_MC_ENET))
mc_env_boot();
}
--
2.43.0