summaryrefslogtreecommitdiff
path: root/doc/develop/pmbus.rst
blob: f5550541e83fd878c8577b595bf6ac495c781d0c (plain)
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
.. SPDX-License-Identifier: GPL-2.0+

PMBus support in U-Boot
=======================

This document describes U-Boot's PMBus 1.x support: what it is for,
how it is structured, and how to add support for a new PMBus chipn
either from scratch from a chip datasheet or by porting an existing
Linux ``drivers/hwmon/pmbus/`` driver.

.. contents::
   :local:
   :depth: 2

Intent and scope
----------------

U-Boot's PMBus layer is not a hardware monitoring (hwmon) clone of
the Linux kernel's ``drivers/hwmon/pmbus/`` subsystem. Linux owns the
runtime side: continuous polling, sysfs publication, alert IRQ
handling, fan control loops. U-Boot owns the boot time side. Concretely
the U-Boot PMBus support exists to:

* Identify the PMBus regulator(s) a board carries at boot:
  ``MFR_ID``, ``MFR_MODEL``, ``MFR_REVISION`` reads, plus a quick
  ``STATUS_WORD`` sanity check.
* Print telemetry so an operator can confirm rail voltages, input
  current, and temperature before handing off to the kernel. One shot
  reads, on demand, via the ``pmbus`` and ``regulator`` U-Boot
  commands (``pmbus dev <name>; pmbus telemetry``,
  ``regulator dev <name>; regulator value``).
* Decode chip alerts when a rail trips an over/under voltage,
  over current, or thermal threshold; so a boot log shows why the
  previous boot failed, before the kernel even comes up.
* Optionally trim a critical rail (typically the SoC core) before
  the kernel takes over; "set the voltage prior to a kernel boot
  to better protect the board". This is the existing
  ``board/nxp/common/vid.c`` AVS path and any future per board
  speed binning trim.

Out of scope, by design:

* No periodic polling. No worker thread. No background updates.
* No sysfs / procfs / userspace surface. U-Boot has none.
* No fan speed control loop. The kernel runs that.
* No long tail of virtual sensor registers (``PMBUS_VIRT_*``).
* No sensor caching / update timestamps.

If you find yourself wanting any of those, the answer is "wait until
Linux comes up". Keep U-Boot's PMBus surface minimal.

Architecture overview
---------------------

The framework is split into four layers (layer 3 comes in two
flavours, 3a and 3b),

::

    +----------------------------------------+
    |     Layer 1: include/pmbus.h           |
    |     Standard PMBus 1.x command codes,  |
    |     numeric format enum, sensor class  |
    |     enum, struct pmbus_driver_info,    |
    |     decoder + transport prototypes,    |
    |     STATUS_WORD bit names.             |
    +----------------------------------------+
    |     Layer 2: lib/pmbus.c               |
    |     Format decoders (LINEAR11/LINEAR16/|
    |     DIRECT) and encoder (LINEAR16),    |
    |     two stage SMBus block read helper, |
    |     STATUS_*-bit print tables, generic |
    |     dispatcher pmbus_reg2data().       |
    +----------------------------------------+
    |     Layer 3a: drivers/power/regulator/ |
    |               <chip>.c                 |
    |     UCLASS_REGULATOR per chip drivers  |
    |    ; one struct pmbus_driver_info    |
    |     plus regulator set_value/get_value |
    |     ops. Optional: per chip identify() |
    |     hook to refine format from the     |
    |     chip's own VOUT_MODE.              |
    +----------------------------------------+
    |     Layer 3b: drivers/power/regulator/ |
    |               pmbus_generic.c          |
    |     Catch all driver matching          |
    |     compatible = "pmbus".              |
    |     Auto detects format via VOUT_MODE  |
    |     and PMBUS_QUERY where supported.   |
    |     Use for compliant chips with no    |
    |     per chip driver yet; ship        |
    |     telemetry today, write a per chip  |
    |     driver later only if quirks demand |
    |     it.                                |
    +----------------------------------------+
    |     Layer 4: board/<vendor>/<board>/   |
    |              <chip>_diag.c             |
    |     Diagnostic commands only:          |
    |       <chip>_info / <chip>_raw         |
    |     Reads via regulator_get_value()    |
    |     and lib/pmbus.c helpers. LINEAR /  |
    |     DIRECT math NOT here.              |
    +----------------------------------------+

Generic vs. board specific separation rule. Layer 1, 2, and 3
files are tree level and platform agnostic. Their comments may
reference only:

* the PMBus 1.x specification, and
* chip manufacturer datasheets.

Never a specific board, SoC, or product. Board-specific quirks
(a particular bus number, a particular slave address, a particular
PCB feedback divider, board local design notes) live exclusively in
``board/<vendor>/<board>/`` files.

CLI commands
------------

The framework publishes one top level command, ``pmbus``, plus a
vendor namespace dispatcher so per chip code can register chip
specific extensions without touching the framework.

Active device model
~~~~~~~~~~~~~~~~~~~

``pmbus`` mirrors the ``regulator`` command: select an active device
once, then operate on it across subcommands. The active device is
selected by I2C bus (decimal sequence number) and 7 bit address (hex,
``0x`` optional, à la ``i2c`` convention)::

    => pmbus dev 0:10
    pmbus: active i2c0:0x10  MFR_ID="MPS"  MFR_MODEL="MPQ8785"  vendor=mps

The framework probes ``MFR_ID`` (in both natural and reverse byte
orders) at selection time, looks the result up in the chip match
registry populated by per chip code via ``pmbus_register_chip()``,
and caches the matched ``pmbus_driver_info``. All subsequent
subcommands consume that cached metadata.

Standard subcommands
~~~~~~~~~~~~~~~~~~~~

::

    pmbus list                       list UCLASS_REGULATOR devices (DM bound)
    pmbus dev [<bus>:<addr>]         show / select active PMBus device
    pmbus info                       identification banner + driver_info
    pmbus telemetry                  decoded VIN, VOUT, IIN, IOUT, TEMP
    pmbus status                     decode every STATUS_* register
    pmbus dump                       hex dump of every standard register
    pmbus read <reg> [b|w|s]         raw read (b=byte, w=word, s=string)
    pmbus write <reg> <val> [b|w]    raw write
    pmbus clear [faults]             issue CLEAR_FAULTS (03h)
    pmbus vout [<uV>]                read or set VOUT_COMMAND (microvolts)
    pmbus scan [<bus>]               PMBus aware probe of one or all I2C buses

The ``<reg>`` argument accepts either a hexadecimal address
(``88``, ``0x`` optional) or a symbolic name (``READ_VIN``,
``VOUT_MODE``, ``MFR_ID``); symbolic names win when both parsed.
``<val>`` is hexadecimal too. Only ``pmbus vout``'s microvolt
argument and bus numbers are decimal.
Format selectors after the register select the SMBus transaction width:
``b`` for byte, ``w`` for 16 bit little endian word,
``s`` for the SMBus block read used by string registers.

Decoded telemetry honours the active device's ``pmbus_driver_info``;
when no chip match has been registered, VOUT falls back to LINEAR16
driven by ``VOUT_MODE`` and the other sensors fall back to LINEAR11.

Vendor namespace
~~~~~~~~~~~~~~~~

Per chip drivers and board files publish chip specific subcommands
in the ``pmbus <vendor> ...`` namespace by calling
``pmbus_register_vendor_handler()`` at init time. The framework
dispatches ``pmbus mps last``, ``pmbus mps clear last``, and
``pmbus mps clear force`` to the MPS handler when the active
device matches the ``mps`` vendor. Additional vendor handlers for
``lltc``, ``renesas``, etc. land alongside the per chip drivers
that need them.

Relationship to ``vdd_override`` / ``vdd_read``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The NXP Layerscape ``vdd_override <mV>`` and ``vdd_read`` commands
remain available in their original form for compatibility with
existing AVS production scripts. The new ``pmbus vout`` and
``pmbus vout <uV>`` subcommands cover the read and single shot
write paths against the same chips, but do not implement
``vdd_override``'s full sequence (board drop compensation, fuse
target derivation, multi step convergence loop, atomic
``PAGE_PLUS_WRITE`` block transaction, ``WRITE_PROTECT`` dance).
For interactive bring up ``pmbus vout`` is sufficient; for
production AVS, ``vdd_override`` stays canonical.

Lifecycle: from board boot to Linux handoff
-------------------------------------------

The PMBus framework spans the entire U-Boot lifecycle. This section
walks the boot timeline phase by phase, showing when each piece
comes online and how the regulator uclass and the ``pmbus`` CLI
converge on the same chip.

Timeline overview
~~~~~~~~~~~~~~~~~

::

    Phase 0  chip power on              chip ramps to NVM default VOUT
    Phase 1  boot ROM / SPL / TF-A      PMBus typically untouched
    Phase 2  U-Boot relocation, DM init regulators bound, not probed
    Phase 3  first regulator probe      chip driver runs, framework lights up
    Phase 4  board hooks / boot scripts snapshot, AVS trim, gating
    Phase 5  Linux handoff              DT passed, chip state preserved
    Phase 6  Linux runtime              kernel pmbus driver takes over

Phase 0: chip power on
~~~~~~~~~~~~~~~~~~~~~~

When the regulator chip receives its input voltage, it ramps its
output to the VOUT default programmed into its NVM at factory
provisioning. PMBus is silent: no software runs anywhere on the
SoC yet.

Phase 1: pre U-Boot stages
~~~~~~~~~~~~~~~~~~~~~~~~~~

Boot ROMs, secondary boot loaders (SPL, ARM TF-A BL2 / BL31)
typically do not touch PMBus. They focus on PLLs, DDR PHY init,
and bringing up enough hardware to load the next stage. Some
platforms have a pre U-Boot AVS path in board specific TF-A
code that writes ``VOUT_COMMAND`` from a fuse derived target;
that path is independent of the U-Boot framework described here.

Phase 2: U-Boot relocation and DM init
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After relocation, U-Boot binds device tree nodes to drivers but
does not probe them. UCLASS_REGULATOR devices for PMBus chips
are bound (driver and DT match resolved) but the ``.probe``
callback has not run yet.

Framework state at this point:

* chip match registry: empty
* vendor handler registry: empty
* active device: none
* regulator uclass: devices bound, none probed

Phase 3: lazy regulator probe
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The first caller into the regulator uclass for a given chip
triggers the chip driver's ``.probe``. Typical first callers:

* a board ``EVENT_SPY`` at ``EVT_LAST_STAGE_INIT`` (boot snapshot)
* a U-Boot script: ``regulator dev <name>; regulator value``
* the ``pmbus dev <name>`` CLI command (resolves to the regulator)
* another DT consumer with a ``regulator-supplies`` reference

The probe chain looks like this::

    <chip>_probe(dev)
        pmbus_regulator_probe_common(dev, &<chip>_info, page)
            dev_read_addr(dev)               -> reg = <addr>
            i2c_get_chip(dev->parent, addr)  -> I2C chip handle
            priv->i2c_dev = handle
            priv->info    = &<chip>_info
            priv->page    = page
            (page > 0)  write PMBUS_PAGE
        <chip>_identify_vout(priv->i2c_dev)        [optional]
            read VOUT_MODE; refine info->format[PSC_VOLTAGE_OUT]
        pmbus_regulator_apply_voltage_scale(dev, fb_div)  [optional]
            write PMBUS_VOUT_SCALE_LOOP if DT property set
        pmbus_register_chip(&<chip>_match)              [idempotent]
        pmbus_register_vendor_handler(&<chip>_op)       [idempotent]

Once probed, three independent surfaces are functional against
the same chip:

* the regulator uclass API (``regulator_get_value``,
  ``regulator_set_value``, ``regulator_get_enable``,
  ``regulator_set_enable``)
* the ``pmbus`` CLI (chip is reachable by name through
  ``pmbus_resolve_by_name()``, by raw ``<bus>:<addr>`` through
  ``pmbus_set_active()``)
* the chip's vendor extension subcommands (``pmbus <vendor> ...``)

Phase 4: board hooks and boot scripts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Boards hook the boot flow at well known points to drive board
specific PMBus behaviour. The framework prescribes none of these;
they are conventions:

* boot time rail snapshot. An ``EVENT_SPY`` at
  ``EVT_LAST_STAGE_INIT`` reads telemetry through the regulator
  uclass and prints a one shot summary to the console. Useful
  for operator visibility on serial during bring up.

* pre kernel rail trim (AVS). A board hook in
  ``board_late_init`` or a custom event spy reads a fuse derived
  target voltage and calls ``regulator_set_value_force()`` to
  trim the SoC core rail before kernel handoff.

* Linux handoff gate. A bootcmd reads the rail voltage
  through the regulator command and refuses to boot Linux if
  the rail is outside the expected range.

Phase 5: Linux handoff
~~~~~~~~~~~~~~~~~~~~~~

When U-Boot transfers control to Linux, it passes the device
tree (potentially patched). The DT compatible strings for PMBus
regulators must match those in the upstream kernel binding so
the kernel's ``drivers/hwmon/pmbus/<chip>.c`` picks them up.
Property names are shared with the kernel binding
(``regulator-name``, ``regulator-min-microvolt``,
``mps,vout-fb-divider-ratio-permille``, etc.); see "DT alignment
with Linux" below.

The chip itself is left in the state U-Boot wrote it to. If
U-Boot trimmed VOUT, the chip stays at the trimmed voltage
through handoff. ``CLEAR_FAULTS`` state is preserved unless an
operator explicitly issued one.

Phase 6: Linux runtime
~~~~~~~~~~~~~~~~~~~~~~

Linux's ``drivers/hwmon/pmbus/pmbus_core.c`` probes the chip,
exposes telemetry under ``/sys/class/hwmon``, and takes over
runtime voltage management through its regulator subsystem.
The hwmon framework polls periodically; U-Boot does not.

Operation paths through the regulator uclass
--------------------------------------------

After the first probe completes, calls into the regulator uclass
for a PMBus chip flow through the shared helper.

Read VOUT::

    regulator_get_value(dev)
       -> dm_regulator_ops->get_value
       -> pmbus_regulator_get_value(dev)
          pmbus_regulator_select_page(priv)
          pmbus_read_byte(priv->i2c_dev, VOUT_MODE, &mode)
          pmbus_read_word(priv->i2c_dev, READ_VOUT, &raw)
          pmbus_reg2data(priv->info, PSC_VOLTAGE_OUT, raw, mode)
              -> reg2data_linear16  (mode = 0)
              -> reg2data_direct    (chip configured for DIRECT)
          return engineering value (microvolts)

Write VOUT::

    regulator_set_value(dev, uV)
       -> dm_regulator_ops->set_value
       -> pmbus_regulator_set_value(dev, uV)
          pmbus_regulator_select_page(priv)
          pmbus_read_byte(VOUT_MODE)
          check (mode == LINEAR)         [LINEAR16 only today]
          raw = pmbus_data2reg_linear16(uV, mode)
          dm_i2c_write(VOUT_COMMAND, raw)

Read / write enable bit::

    regulator_get_enable(dev)
       -> pmbus_regulator_get_enable(dev)
          pmbus_read_byte(OPERATION) & PB_OPERATION_ON

    regulator_set_enable(dev, on)
       -> pmbus_regulator_set_enable(dev, on)
          read OPERATION, set or clear PB_OPERATION_ON, write back

Bus traffic per call:

* ``get_value``  : 1 byte read (VOUT_MODE) + 1 word read (READ_VOUT)
  + 1 byte write (PAGE) when ``page > 0``
* ``set_value``  : 1 byte read (VOUT_MODE) + 1 word write (VOUT_COMMAND)
  + 1 byte write (PAGE) when ``page > 0``
* ``get_enable`` : 1 byte read (OPERATION)
* ``set_enable`` : 1 byte read (OPERATION) + 1 byte write (OPERATION)

Common board hook patterns
~~~~~~~~~~~~~~~~~~~~~~~~~~

Boot time rail snapshot::

    static int my_board_pmbus_snapshot(void)
    {
        struct udevice *reg;

        if (regulator_get_by_platname("MY_RAIL", &reg))
            return 0;
        printf("MY_RAIL: VOUT = %d uV, enabled = %d\n",
               regulator_get_value(reg),
               regulator_get_enable(reg));
        return 0;
    }
    EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, my_board_pmbus_snapshot);

The first call to ``regulator_get_value()`` triggers the chip
driver's ``.probe``, which seeds the chip match and vendor
extension registries. Subsequent ``pmbus`` CLI commands work
without further setup.

Pre kernel rail trim (AVS)::

    int board_late_init(void)
    {
        struct udevice *reg;
        int target_uV = compute_avs_target();

        if (regulator_get_by_platname("VDD_CORE", &reg))
            return 0;
        return regulator_set_value_force(reg, target_uV);
    }

Use ``regulator_set_value_force()`` when the target may sit
outside the DT declared ``regulator-min-microvolt`` /
``regulator-max-microvolt`` range; force bypasses the bounds
check.

Adding a new PMBus chip from scratch
------------------------------------

Use this path when the chip has no Linux driver yet, or when you want
to validate the U-Boot port against the datasheet alone.

1. Confirm PMBus 1.x compliance level. Locate in the chip
   datasheet:

     which PMBus standard command codes the chip implements
     (``READ_VIN``, ``READ_VOUT``, ``STATUS_WORD``, ``MFR_ID`` ...),
     which numeric format(s) it uses for VOUT (LINEAR16 with the
     exponent in ``VOUT_MODE``, DIRECT with chip specific m/b/R, or
     VID with one of the documented VRM tables),
     which numeric format it uses for VIN, IIN, IOUT, TEMPERATURE
     (most commonly LINEAR11; some MPS / MPS derivative chips use
     DIRECT instead),
     how many output rails it exposes (single page parts vs.
     multi rail PMBus pages).

2. Declare a ``struct pmbus_driver_info``. Wire each sensor
   class to one ``enum pmbus_data_format``, plus the m/b/R triple if
   the format is DIRECT::

      static struct pmbus_driver_info chipname_info = {
          .pages = 1,
          .format[PSC_VOLTAGE_IN]  = pmbus_fmt_direct,
          .format[PSC_VOLTAGE_OUT] = pmbus_fmt_linear,
          .format[PSC_CURRENT_OUT] = pmbus_fmt_direct,
          .format[PSC_TEMPERATURE] = pmbus_fmt_direct,
          .m[PSC_VOLTAGE_IN]  = 4,  .R[PSC_VOLTAGE_IN]  = 1,
          .m[PSC_CURRENT_OUT] = 16, .R[PSC_CURRENT_OUT] = 0,
          .m[PSC_TEMPERATURE] = 1,  .R[PSC_TEMPERATURE] = 0,
      };

3. Bind to a DT compatible. Use the lowercase ``vendor,chip``
   tuple Linux uses (see "DT alignment with Linux" below). Add the
   driver under ``drivers/power/regulator/`` matching the existing
   skeleton (``fan53555.c``, ``pca9450.c``).

4. Rely on the DT binding from the Linux kernel which is imported into
   U-Boot under ``dts/upstream/Bindings/`` (for PMBus chips,
   ``dts/upstream/Bindings/hwmon/pmbus/``).

5. Smoke test. With the chip wired up in DT::

      => regulator dev <name>
      => regulator value
      => regulator info

   Numbers should match the bench measurement to within the chip's
   advertised LSB.

Porting an existing Linux PMBus driver to U-Boot
------------------------------------------------

When the chip already has a ``linux/drivers/hwmon/pmbus/<chip>.c``,
that driver is the authoritative reference for format, coefficients,
and quirks. Take what carries; leave what does not.

What carries verbatim
~~~~~~~~~~~~~~~~~~~~~

* Numeric formats (``format[PSC_*]``).
* DIRECT coefficients (``m[]``, ``b[]``, ``R[]``).
* Per page count and per page functionality bits (``pages``,
  ``func[]``).
* VOUT_MODE driven per chip identify hook (e.g. MPQ8785's
  switch between LINEAR16 and VID coerced DIRECT m=64 R=1).
* Vendor register addresses for chip specific quirks (fault
  history, scale-loop, page mapping).

What does not carry
~~~~~~~~~~~~~~~~~~~~~~~

* ``hwmon_device_register()`` and the attribute groups it consumes.
* ``struct pmbus_data`` / ``update_lock`` / ``last_updated``
  U-Boot has no caching layer.
* ALERT# IRQ wiring; U-Boot is single threaded boot code.
* Fan control hooks (``read_fan_*``, ``set_pwm_*``).
* Virtual register handling (``PMBUS_VIRT_READ_VIN_*`` etc.); those
  are entirely a hwmon publication aid.
* ``module_i2c_driver(...)`` and ``MODULE_*`` macros; U-Boot uses
  ``U_BOOT_DRIVER(...)``.

Worked example: porting MPQ8785
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Linux's ``drivers/hwmon/pmbus/mpq8785.c`` is 193 LOC; the U-Boot
equivalent is ~150 LOC.

The ``mpq8785_info`` struct transcribes verbatim::

    .pages = 1,
    .format[PSC_VOLTAGE_IN]  = direct,  .m[PSC_VOLTAGE_IN]  = 4,  .R[PSC_VOLTAGE_IN]  = 1,
    .format[PSC_CURRENT_OUT] = direct,  .m[PSC_CURRENT_OUT] = 16, .R[PSC_CURRENT_OUT] = 0,
    .format[PSC_TEMPERATURE] = direct,  .m[PSC_TEMPERATURE] = 1,  .R[PSC_TEMPERATURE] = 0,

The VOUT format is decided at probe time from VOUT_MODE bits[7:5] :
mode 0 means LINEAR16, mode 1 or 2 means DIRECT m=64 R=1 (the chip's
"VID" mode is coerced to DIRECT by the driver). Translate Linux's
``mpq8785_identify()`` 1:1.

The per chip quirks that carry over:

* MPS NVM string byte order: chip stores ``S P M`` for the human
  string ``MPS``. ``pmbus_read_string()`` accepts a ``reverse_bytes``
  flag for this case.
* ``mps,vout-fb-divider-ratio-permille`` DT property maps to
  ``VOUT_SCALE_LOOP`` write at probe time.

The quirks that do not carry over:

* The ``PMBUS_VIRT_*`` virtual sensor wiring. Drop entirely.
* The ``hwmon_chip_info`` attribute group registration.
* The ``MODULE_AUTHOR`` / ``MODULE_LICENSE`` declarations.

Using the generic ``compatible = "pmbus"`` driver
-------------------------------------------------

When a board carries a PMBus chip without a per chip U-Boot driver,
the catch all ``drivers/power/regulator/pmbus_generic.c`` (Layer 3b)
binds against ``compatible = "pmbus"``. It auto detects format via
``VOUT_MODE`` and ``PMBUS_QUERY`` (where the chip supports it) and
provides telemetry + voltage set/get against the standard PMBus 1.x
subset.

Decision tree:

1. Try the generic driver first. Add the regulator node to the
   board DT with ``compatible = "pmbus"`` plus the standard
   regulator properties. Boot, run ``regulator value``, compare
   against bench measurement.
2. Switch to a per chip driver only when the generic one is
   wrong: telemetry shows wrong values (chip uses DIRECT with
   non default coefficients), an alert can't be decoded (chip has
   vendor specific status bits), AVS is needed (the boot path has
   to actively trim VOUT before kernel handoff), or the chip has an
   ADDR-pin auto promotion / VID coercion / vendor register quirk.

DT alignment with Linux
-----------------------

The same ``.dts`` file should work under both U-Boot (BL33) and Linux
post handoff. To make that possible:

* Reuse the upstream Linux compatible for every PMBus chip. Look
  in ``linux/Documentation/devicetree/bindings/hwmon/pmbus/`` and
  ``linux/Documentation/devicetree/bindings/regulator/``. The
  ``<vendor>,<chip>`` tuple from the kernel binding goes into U-Boot's
  ``of_match_table`` unchanged.
* Reuse Linux property names verbatim: ``regulator-name``,
  ``regulator-min-microvolt``, ``regulator-max-microvolt``,
  ``regulator-boot-on``, ``regulator-always-on``,
  ``mps,vout-fb-divider-ratio-permille``, etc.
* The DT binding is the kernel's, imported under
  ``dts/upstream/Bindings/`` (PMBus chips live in
  ``dts/upstream/Bindings/hwmon/pmbus/``).

Multi rail/multi page chips (e.g. ISL68137 with seven outputs)
declare each rail as a child regulator node with ``reg = <page>``;
each child binds as a UCLASS_REGULATOR with that PMBus PAGE setting
applied at every read/write.

Common pitfalls
---------------

These have all bitten contributors during nbxv3 bring up; record them
here so the next port doesn't repeat them.

* VOUT_MODE/DIRECT format confusion. Most generic PMBus call
  sites assume LINEAR16. Several MPS chips report VOUT in DIRECT
  format with chip specific m/b/R after a single VOUT_MODE read,
  the same chip read at the same address produces different
  numbers depending on the format the driver applies. Always read
  ``VOUT_MODE`` at probe time and switch the decoder accordingly.
  Linux's per chip ``identify()`` callbacks document the exact
  rules; copy them rather than guessing.
* SMBus block read protocol. Some I2C controllers strict check
  block read transactions: the master must read the length byte
  first, then reissue the read for the payload. Over reading a
  fixed length and ignoring the length byte works on lenient
  controllers but errors on strict ones. ``pmbus_read_string()``
  does the two stage read; use it.
* I2C bus number stability. ``uclass_get_device_by_seq()``
  uses the DT alias index (``i2c0`` -> ``UCLASS_I2C`` seq 0) when
  aliases are declared, otherwise falls back to probe order which
  varies with which controllers are enabled in the defconfig.
  Always declare DT aliases for I2C buses you reference by index.
* ADDR-pin auto addressessing. Some chips (notably MPS parts) decode
  their PMBus 7-bit address from an external resistor divider on
  ADDR_VBOOT. The "default" address in the datasheet is the
  factory fused slot; a board with a different divider or a die
  with a different revision can land in another window. If the
  driver hardcodes the default and the board side scan finds the
  chip in another window, auto promote the working address rather
  than failing the probe.
* MFR string byte order. Most PMBus chips return ``MFR_ID``
  characters in human order. Some MPS personalities reverse them.
  Pass ``reverse_bytes=true`` to ``pmbus_read_string()`` for those;
  spec compliant chips pass false.

References
----------

* Linux PMBus core: ``linux/drivers/hwmon/pmbus/pmbus_core.c``,
  decoder reference; ignore the hwmon publication and caching layers.
* Linux PMBus header: ``linux/drivers/hwmon/pmbus/pmbus.h``; API
  surface reference; many constants and the ``struct
  pmbus_driver_info`` shape are mirrored verbatim into U-Boot's
  ``include/pmbus.h``.
* Linux DT bindings:
  ``linux/Documentation/devicetree/bindings/hwmon/pmbus/``.