[PATCH v1 04/23] board: nbxv3: add MPQ8785 PMBus traces + DT regulator
Vincent Jardin <[email protected]>
| Newsgroups | gmane.comp.boot-loaders.u-boot |
|---|---|
| Message-ID | <20260817153144.1951036-5-vjardin__7466.13516691781$1786980814$gmane$org@free.fr> |
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, ®)) + 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