Bind through the tree-level PMBus framework and add a board-local
EVT_LAST_STAGE_INIT spy that prints the traces to the serial console.

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

 arch/arm/dts/fsl-lx2160a-nbxv3.dts  |  17 +++++
 board/nxp/lx2160a/Kconfig           |  11 +++
 board/nxp/lx2160a/nbxv3/Makefile    |   1 +
 board/nxp/lx2160a/nbxv3/mps_pmbus.c | 107 ++++++++++++++++++++++++++++
 4 files changed, 136 insertions(+)
 create mode 100644 board/nxp/lx2160a/nbxv3/mps_pmbus.c

diff --git a/arch/arm/dts/fsl-lx2160a-nbxv3.dts 
b/arch/arm/dts/fsl-lx2160a-nbxv3.dts
index 8caea051bed..8e336a622f3 100644
--- a/arch/arm/dts/fsl-lx2160a-nbxv3.dts
+++ b/arch/arm/dts/fsl-lx2160a-nbxv3.dts
@@ -40,3 +40,20 @@
        phy-connection-type = "rgmii-id";
        u-boot,nickname = "lanconsole0";
 };
+
+&i2c0 { /* IIC1: on module management bus */
+       status = "okay";
+
+       regulator@10 {
+               compatible = "mps,mpq8785";
+               reg = <0x10>;
+               regulator-name = "+0V8_VDD";
+               regulator-min-microvolt = < 600000>;
+               regulator-max-microvolt = <1100000>;
+               /* MPQ8785 datasheet rating: continuous 40 A output (IOUT). */
+               regulator-min-microamp = <       0>;
+               regulator-max-microamp = <40000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+};
diff --git a/board/nxp/lx2160a/Kconfig b/board/nxp/lx2160a/Kconfig
index 37e8f7ff717..e46223d1b43 100644
--- a/board/nxp/lx2160a/Kconfig
+++ b/board/nxp/lx2160a/Kconfig
@@ -65,4 +65,15 @@ config NBXV3_DM_EVENT
        default y
        select DM_EVENT
 
+config NBXV3_PMBUS
+       bool
+       default y
+       select PMBUS
+       select CMD_PMBUS
+       select DM_REGULATOR
+       select DM_REGULATOR_PMBUS_HELPER
+       select DM_REGULATOR_MPQ8785
+       select DM_REGULATOR_PMBUS_GENERIC
+       select CMD_REGULATOR
+
 endif
diff --git a/board/nxp/lx2160a/nbxv3/Makefile b/board/nxp/lx2160a/nbxv3/Makefile
index 90ef2734eec..e4aa5309804 100644
--- a/board/nxp/lx2160a/nbxv3/Makefile
+++ b/board/nxp/lx2160a/nbxv3/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-y += eth_nbxv3.o
+obj-y += mps_pmbus.o
diff --git a/board/nxp/lx2160a/nbxv3/mps_pmbus.c 
b/board/nxp/lx2160a/nbxv3/mps_pmbus.c
new file mode 100644
index 00000000000..15c0d0d0bc6
--- /dev/null
+++ b/board/nxp/lx2160a/nbxv3/mps_pmbus.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2026 Free Mobile, Vincent Jardin
+ *
+ * Boot time snapshot of the +0V8_VDD core regulator.
+ *
+ * The MPS MPQ8785 or MPQ8646 chips are bound through DT
+ * thanks to the per chip driver in
+ *   drivers/power/regulator/mpq8785.c.
+ *
+ * The only thing this file still does is the boot time event spy and logs:
+ *  - at `EVT_LAST_STAGE_INIT` it probes the regulator (which triggers
+ *    the chip driver's .probe),
+ *  - it seeds pmbus_active so the `pmbus` command works without the
+ *    operator typing `pmbus dev`,
+ *  - and then it prints a one shot rail snapshot to the serial console.
+ */
+
+#include <command.h>
+#include <dm.h>
+#include <event.h>
+#include <i2c.h>
+#include <log.h>
+#include <pmbus.h>
+#include <vsprintf.h>
+#include <power/regulator.h>
+
+#define NBXV3_VDD_REGULATOR_NAME       "+0V8_VDD"
+
+static void mps_pmbus_print_snapshot(struct udevice *reg)
+{
+       const struct pmbus_active_dev *act;
+       struct udevice *chip;
+       u16 raw, status_word = 0, prot_last = 0;
+       u8 vout_mode = 0;
+       int uV, en;
+
+       uV = regulator_get_value(reg);
+       en = regulator_get_enable(reg);
+
+       act = pmbus_active();
+       if (!act || pmbus_active_get_i2c(&chip)) {
+               printf("MPQ8785 (+0V8_VDD): VOUT=%d uV  enabled=%d  (no PMBus 
active dev)\n",
+                      uV, en);
+               return;
+       }
+
+       pmbus_read_byte(chip, PMBUS_VOUT_MODE, &vout_mode);
+       pmbus_read_word(chip, PMBUS_STATUS_WORD, &status_word);
+       pmbus_read_word(chip, 0xfb /* MPS_PROTECTION_LAST */, &prot_last);
+
+       {
+               u8 rev_byte = 0;
+
+               (void)pmbus_read_byte(chip, PMBUS_MFR_REVISION, &rev_byte);
+               printf("MPQ8785 @ i2c%d:0x%02x  MFR_ID=\"%s\" MODEL=\"%s\" 
REV=0x%02x VOUT_MODE=0x%02x\n",
+                      act->bus_seq, act->addr,
+                      act->mfr_id[0] ? act->mfr_id : "?",
+                      act->mfr_model[0] ? act->mfr_model : "?",
+                      rev_byte, vout_mode);
+       }
+       printf("  +0V8_VDD: VOUT=%d uV  enabled=%d\n", uV, en);
+
+       if (pmbus_read_word(chip, PMBUS_READ_VIN, &raw) == 0)
+               printf("            VIN  raw=0x%04x  =%lld uV\n", raw,
+                      (long long)pmbus_reg2data(act->info, PSC_VOLTAGE_IN,
+                                                raw, vout_mode));
+       if (pmbus_read_word(chip, PMBUS_READ_IOUT, &raw) == 0)
+               printf("            IOUT raw=0x%04x  =%lld uA\n", raw,
+                      (long long)pmbus_reg2data(act->info, PSC_CURRENT_OUT,
+                                                raw, vout_mode));
+       if (pmbus_read_word(chip, PMBUS_READ_TEMPERATURE_1, &raw) == 0)
+               printf("            TEMP raw=0x%04x  =%lld udegC\n", raw,
+                      (long long)pmbus_reg2data(act->info, PSC_TEMPERATURE,
+                                                raw & 0x00ff, vout_mode));
+
+       printf("  STATUS_WORD = 0x%04x  [", status_word);
+       pmbus_print_status_bits(PMBUS_STATUS_WORD, status_word,
+                               pmbus_status_word_bits,
+                               act->info ? act->info->status_overrides : NULL);
+       printf("]\n");
+       printf("  PROTECTION_LAST = 0x%04x (NVM)\n", prot_last);
+       printf("  Use `pmbus telemetry`, `pmbus status`, `pmbus mps last` for 
details.\n");
+}
+
+static int mps_pmbus_last_stage_init(void)
+{
+       struct udevice *reg = NULL;
+
+       if (regulator_get_by_platname(NBXV3_VDD_REGULATOR_NAME, &reg))
+               return 0;
+       if (!reg)
+               return 0;
+
+       {
+               int bus_seq;
+               u8 addr;
+
+               if (pmbus_resolve_by_name(NBXV3_VDD_REGULATOR_NAME,
+                                         &bus_seq, &addr) == 0)
+                       pmbus_set_active(bus_seq, addr);
+       }
+
+       mps_pmbus_print_snapshot(reg);
+       return 0;
+}
+EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, mps_pmbus_last_stage_init);
-- 
2.43.0

Reply via email to