Kernel driver mpq8646

Supported chips:

  • MPS MPQ8646

    Prefix: ‘mpq8646’

Author:

Chip-identity

Support the boards that are designed with the MPS MPQ8646 probed thanks to``MFR_MODEL`` register.

This driver targets the MPQ8646 silicon specifically.

Description

The MPQ8646 is a fully integrated, PMBus-compatible, high-frequency, synchronous buck converter. It offers a compact solution that achieves up high Amps output current per phase, with excellent load and line regulation over a wide input supply range. The chip operates at high efficiency over a wide output current load range.

The PMBus interface provides converter configurations and key parameters monitoring.

The device adopts MPS’s proprietary multi-phase digital constant-on-time (MCOT) control, which provides fast transient response and eases loop stabilization. The MCOT scheme also allows multiple devices or channels to be connected in parallel with excellent current sharing and phase interleaving for high-current applications.

Fully integrated protection features include over-current protection (OCP), over-voltage protection (OVP), under-voltage protection (UVP), and over-temperature protection (OTP).

This device is compliant with:

  • PMBus rev 1.3 interface.

The driver exports the following attributes via the ‘sysfs’ files for input voltage:

  • in1_input

  • in1_label

  • in1_max

  • in1_max_alarm

  • in1_min

  • in1_min_alarm

  • in1_crit

  • in1_crit_alarm

The driver provides the following attributes for output voltage:

  • in2_input

  • in2_label

  • in2_alarm

  • in2_max

  • in2_max_alarm

  • in2_min

  • in2_min_alarm

  • in2_crit

  • in2_crit_alarm

  • in2_lcrit

  • in2_lcrit_alarm

The driver provides the following attributes for output current:

  • curr1_input

  • curr1_label

  • curr1_max

  • curr1_max_alarm

  • curr1_crit

  • curr1_crit_alarm

The driver provides the following attributes for temperature:

  • temp1_input

  • temp1_max

  • temp1_max_alarm

  • temp1_crit

  • temp1_crit_alarm

Alarm acknowledgment

The hwmon-class inX_alarm/currX_alarm/tempX_alarm files are read-only in pmbus_core. The driver exposes the standard PMBUS_VIRT_RESET_*_HISTORY virtual-register channel for fault acknowledgment: writing 1 to inX_reset_history / currX_reset_history / tempX_reset_history sends the chip a CLEAR_FAULTS (0x03) Send-Byte, which clears the latched STATUS_WORD / STATUS_VOUT / STATUS_IOUT / STATUS_INPUT / STATUS_TEMPERATURE bits the chip is currently exposing.

The MPS-specific NVM post-mortem register PROTECTION_LAST (0xFB) is not cleared by this path; it can be read (decoded) via the protection_last debugfs entry described below.

Regulator framework integration

When CONFIG_REGULATOR=y is set, the chip is exposed under /sys/class/regulator/ and accepts the standard regulator framework operations:

  • regulator_enable() / regulator_disable() -> OPERATION (0x01)

  • regulator_set_voltage() -> VOUT_COMMAND (0x21)

  • regulator_get_voltage() -> READ_VOUT (0x8B)

  • regulator_is_enabled() -> OPERATION bit-decode

The single regulator descriptor is named "vout" (page 0). For a multi-page configuration the descriptor table can be extended in the driver.

In-driver alarm-poll fallback

On boards where the chip’s SMBALERT# pin is unavailable to the SoC, pmbus_core::pmbus_irq_setup cannot deliver SMBALERT-driven poll(POLLPRI) wakes or udev change@... events on the inX_alarm files. The driver provides a delayed_work-based polling fallback that periodically invokes the pmbus core fault check, pmbus_check_and_notify_faults(), which sends the notifications and then clears the latched faults, exactly like the SMBALERT# interrupt path. The frequency of polling is tunable:

/sys/kernel/debug/i2c/i2c-<bus>/<bus>-<addr>/alarm_poll_interval_ms

The default is 1000 ms.

Set it to 0 to disable. The worker self-suppresses when client->irq != 0 (i.e. when DT supplies an interrupts = <...> property on the regulator node), so adding SMBALERT# wiring is a zero-driver-change uplift on a future board rev.

MPS post-mortem (PROTECTION_LAST)

The MPQ8646 silicon keeps a single 16-bit NVM-backed record of the last protection event in PROTECTION_LAST (0xFB). It survives chip power/reset. The following debugfs entries expose it:

/sys/kernel/debug/i2c/i2c-<bus>/<bus>-<addr>/protection_last     (RO)
/sys/kernel/debug/i2c/i2c-<bus>/<bus>-<addr>/status_decoded      (RO)

protection_last decodes the 16-bit value based on the datasheet fault names (INIT_FAULT, NVM_CRC_ERROR, NVM_FAULT, OC_PHASE_FAULT, OTP_SELF_FAULT, SWITCH_PRD_FAULT, VIN_OV_FAULT, VOUT_OV_FAULT, VOUT_UV_FAULT, OC_TOT_FAULT, VIN_UVLO_FAULT, DRMOS_OTP).

status_decoded reads STATUS_WORD (0x79) and renders the 16 bits with MPS-extension labels (bit12 = NVM_SUMMARY, bit8 = WATCH_DOG, bit0 = DRMOS_FAULT) instead of the PMBus 1.3 spec generic names.

NVMEM snapshot

When CONFIG_NVMEM=y is set, the chip’s NVM-backed observability registers are exposed as a single 16-byte read-only nvmem_device at /sys/bus/nvmem/devices/<i2c-name>/nvmem. Layout (little-endian for 16-bit fields, zero-fill on per-entry read failure and for the reserved tail):

offset 0..1   PROTECTION_LAST  (0xFB)  word
offset 2..3   MFR_RETRY_TIMES  (0xF4)  word
offset 4..5   MFR_CONFIG_ID    (0xC0)  word
offset 6..7   MFR_VBOOT_CFG    (0xFC)  word
offset 8      MFR_SILICON_REV  (0xC3)  byte
offset 9..15  reserved (zero)

Suitable for single-cat post-mortem capture by a fleet daemon.

Diagnostics and introspection

When CONFIG_DEBUG_FS=y is set, the driver adds a read-only decode surface to the client’s pmbus debugfs directory, /sys/kernel/debug/i2c/i2c-<bus>/<bus>-<addr>/. The driver intentionally exposes no raw register poke/peek debugfs; use i2c-dev (i2cget/i2cset/i2ctransfer) for that.

Identity / observability (read-only):

File

PMBus / MFR cmd

Description

mfr_config_id

0xC0 (word)

board / SKU NVM identifier

mfr_config_code_rev

0xC1 (word)

NVM image revision (PART_RECOG + config code rev fields)

mfr_silicon_rev

0xC3 (byte)

die revision

mfr_retry_times

0xF4 (word)

per-fault-class recovery-mode configuration (NOT a retry count). Four 4-bit fields [15:12]=OTP, [11:8]=VOUT_OV, [7:4]=VOUT_UV, [3:0]=OCP. Each field: 0x0=latch-off, 0x1..0xE=retry N times then latch off, 0xF=hiccup (retry indefinitely). The chip exposes no in-NVM retry-event counter; track transitions externally if needed (poll protection_last or watch inX_alarm / temp1_alarm poll(POLLPRI) wakes).

mfr_vboot_cfg

0xFC (word)

ADDR/VBOOT latched at POR

Timing / UVLO knobs (read-only):

File

PMBus cmd

Description

vin_on

0x35 (word)

UVLO turn-on threshold

vin_off

0x36 (word)

UVLO turn-off threshold

ton_delay

0x60 (word)

soft-start delay

ton_rise

0x61 (word)

soft-start ramp time

toff_delay

0x64 (word)

soft-stop delay

toff_fall

0x65 (word)

soft-stop ramp time

The only writable entry is alarm_poll_interval_ms (the alarm-poll worker cadence, see above), it is driver-local and never touches the chip.

Unsafe provisioning

Available only when CONFIG_SENSORS_MPQ8646_DEBUG_UNSAFE=y (default n, it is for boards bring up only). They WRITE to the regulator. On many designs the MPQ8646 powers the main CPU core rail, so a wrong write can brown out the board or persist a bad setpoint into finite-cycle NVM. WARNING: Some wrong register writes can and likely will physically damage or destroy the chip and/or the board. An explicit warning banner is printed at probe time when this option is enabled.

File

PMBus / MFR cmd

Description

store_all

0x15

STORE_USER_ALL Send-Byte (commit RAM config to NVM)

restore_all

0x16

RESTORE_USER_ALL Send-Byte (revert RAM to last-NVM image)

clear_protection_last

0x08

CLEAR_LAST_FAULT Send-Byte

clear_protection_last_force

--

gated CLEAR_LAST_FAULT, see below

on_off_config

0x02 (byte)

PMBus vs CTRL-pin on/off source + active polarity

vout_margin_high

0x25 (word)

margin-high VOUT setpoint

vout_margin_low

0x26 (word)

margin-low VOUT setpoint

mfr_pmbus_lock

0xEE (word)

programmable PMBus write-lock

mfr_product_rev_user

0xC2 (word)

user-programmable product revision

clear_protection_last writes CLEAR_LAST_FAULT (0x08) Send-Byte. The chip silently no-ops unless MFR_CFG_EXT (0xF5) bit[6] is set.

clear_protection_last_force performs the unlock with the following six-step dancing:

  1. read WRITE_PROTECT (0x10) and MFR_CFG_EXT (0xF5) for restore

  2. clear WRITE_PROTECT if set

  3. set MFR_CFG_EXT bit[6] = 1, preserving other bits

  4. send CLEAR_LAST_FAULT (0x08)

  5. restore MFR_CFG_EXT (with retry to handle the chip’s undocumented post-NVM-write busy window)

  6. restore WRITE_PROTECT

Devicetree

The driver uses compatible = "mps,mpq8646". There are some few optional properties:

  • mps,vout-fb-divider-ratio-permille : it writes VOUT_SCALE_LOOP (0x29) at probe to compensate for an external resistor divider in the VOUT feedback path. The valid range is 11-bit.

  • interrupts = <...> : if the board routes the chip’s SMBALERT# pin to a SoC GPIO, declaring it here lights up pmbus_core::pmbus_irq_setup and disables the in-driver alarm-poll fallback