Reuses the shared
  pmbus_print_telemetry() / pmbus_print_status_word() helpers,
for the 48V->12V Flex PSU reports.

The PSU is a carrier device: its DT node
  compatible = "pmbus",
  regulator-name = "psu-48v",
  pmbus,num-pages = <2>

sits behind the carrier SMBus mux tree, described with the I2C buses
later in this series. Until then no generic PMBus regulator is bound
and the hook prints nothing.

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

 board/nxp/lx2160a/nbxv3/Makefile    |  1 +
 board/nxp/lx2160a/nbxv3/psu_pmbus.c | 80 +++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)
 create mode 100644 board/nxp/lx2160a/nbxv3/psu_pmbus.c

diff --git a/board/nxp/lx2160a/nbxv3/Makefile b/board/nxp/lx2160a/nbxv3/Makefile
index e4aa5309804..24874138833 100644
--- a/board/nxp/lx2160a/nbxv3/Makefile
+++ b/board/nxp/lx2160a/nbxv3/Makefile
@@ -4,3 +4,4 @@
 
 obj-y += eth_nbxv3.o
 obj-y += mps_pmbus.o
+obj-y += psu_pmbus.o
diff --git a/board/nxp/lx2160a/nbxv3/psu_pmbus.c 
b/board/nxp/lx2160a/nbxv3/psu_pmbus.c
new file mode 100644
index 00000000000..33cd0b1f5ed
--- /dev/null
+++ b/board/nxp/lx2160a/nbxv3/psu_pmbus.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2026 Free Mobile - Vincent Jardin
+ *
+ * Nodebox v3 boot-time snapshot of the carrier PMBus PSU(s).
+ *
+ * Companion to mps_pmbus.c, which snapshots the on-module MPS MPQ8646
+ * core regulator (+0V8_VDD) at boot.
+ *
+ * This file covers the other class of PMBus device the board carries:
+ * spec-compliant PSU bricks with no per-chip driver, bound to the generic
+ * `pmbus_generic_regulator` (compatible = "pmbus").
+ *
+ * On nbxv3 that is the Flex 48 V -> 12 V PSU.
+ */
+
+#include <dm.h>
+#include <event.h>
+#include <i2c.h>
+#include <pmbus.h>
+#include <dm/uclass.h>
+#include <power/regulator.h>
+
+#define NBXV3_GENERIC_PMBUS_DRIVER     "pmbus_generic_regulator"
+
+static void nbxv3_psu_snapshot_one(struct udevice *reg)
+{
+       struct udevice *parent = dev_get_parent(reg);
+       struct udevice *chip;
+       int bus_seq, addr;
+       const struct pmbus_active_dev *act;
+
+       if (!parent || device_get_uclass_id(parent) != UCLASS_I2C)
+               return;
+       bus_seq = dev_seq(parent);
+       addr = dev_read_addr(reg);
+       if (addr < 0 || addr > 0x7f)
+               return;
+
+       /* Select the device: caches MFR_* + reuses the generic info. */
+       if (pmbus_set_active(bus_seq, (u8)addr))
+               return;
+       act = pmbus_active();
+       if (!act)
+               return;
+       if (pmbus_active_get_i2c(&chip))
+               return;
+
+       printf("PMBus PSU @ i2c%d:0x%02x", act->bus_seq, act->addr);
+       if (act->name[0])
+               printf("  rail=\"%s\"", act->name);
+       if (act->mfr_id[0])
+               printf("  MFR_ID=\"%s\"", act->mfr_id);
+       if (act->mfr_model[0])
+               printf("  MODEL=\"%s\"", act->mfr_model);
+       printf("\n");
+
+       pmbus_print_telemetry(chip);
+
+       pmbus_print_status_word(chip);
+}
+
+static int nbxv3_psu_pmbus_last_stage_init(void)
+{
+       struct udevice *reg;
+       struct uclass *uc;
+
+       if (uclass_get(UCLASS_REGULATOR, &uc))
+               return 0;
+
+       uclass_foreach_dev(reg, uc) {
+               if (!reg->driver || !reg->driver->name)
+                       continue;
+               if (strcmp(reg->driver->name, NBXV3_GENERIC_PMBUS_DRIVER))
+                       continue;
+               nbxv3_psu_snapshot_one(reg);
+       }
+       return 0;
+}
+EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, nbxv3_psu_pmbus_last_stage_init);
-- 
2.43.0

Reply via email to