.. SPDX-License-Identifier: GPL-2.0-only .. Copyright (c) 2026 Free Mobile - Vincent Jardin Kernel driver mpq8646 ===================== Supported chips: * MPS MPQ8646 Prefix: 'mpq8646' Author: - Vincent Jardin 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-/-/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-/-/protection_last (RO) /sys/kernel/debug/i2c/i2c-/-/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//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-/-/``. 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