Based on kernel version 7.3. Page generated on 2026-10-19 13:17 EDT.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
.. SPDX-License-Identifier: GPL-2.0-only
.. Copyright (c) 2026 Free Mobile - Vincent Jardin <vjardin@free.fr>
Kernel driver mpq8646
=====================
Supported chips:
* MPS MPQ8646
Prefix: 'mpq8646'
Author:
- Vincent Jardin <vjardin@free.fr>
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
|