mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
The write cases of debugfs entries are provisioning and bench helpers. By designs the MPQ8646 powers the CPU core rail, so a wrong write can brown out the board or persist a bad setpoint into finite-cycle NVM. Said differently: some wrong register writes can and likely will physically damage or destroy the chip and/or the board. To be safe, it is disabled by default behind a CONFIG_SENSORS_MPQ8646_DEBUG_UNSAFE and we print an explicit warning banner at probe time when they are built in. Signed-off-by: Vincent Jardin <vjardin@free.fr> Link: https://lore.kernel.org/r/20260730-mpq8646_v0-v7-4-e7c7ad768d5d@free.fr Signed-off-by: Guenter Roeck <linux@roeck-us.net>
301 lines
12 KiB
ReStructuredText
301 lines
12 KiB
ReStructuredText
.. 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
|