[PATCH v10 00/14] dpll: add SiTime SiT9531x DPLL clock driver

Ali Rouhi posted 14 patches 2 days, 20 hours ago
.../bindings/dpll/sitime,sit95316.yaml        |  183 +
.../devicetree/bindings/vendor-prefixes.yaml  |    2 +
MAINTAINERS                                   |    7 +
drivers/dpll/Kconfig                          |    2 +
drivers/dpll/Makefile                         |    1 +
drivers/dpll/sit9531x/Kconfig                 |   17 +
drivers/dpll/sit9531x/Makefile                |    4 +
drivers/dpll/sit9531x/core.c                  | 4553 +++++++++++++++++
drivers/dpll/sit9531x/core.h                  |  429 ++
drivers/dpll/sit9531x/dpll.c                  | 1445 ++++++
drivers/dpll/sit9531x/dpll.h                  |   66 +
drivers/dpll/sit9531x/prop.c                  |  469 ++
drivers/dpll/sit9531x/prop.h                  |   37 +
drivers/dpll/sit9531x/regs.h                  |  364 ++
14 files changed, 7579 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dpll/sitime,sit95316.yaml
create mode 100644 drivers/dpll/sit9531x/Kconfig
create mode 100644 drivers/dpll/sit9531x/Makefile
create mode 100644 drivers/dpll/sit9531x/core.c
create mode 100644 drivers/dpll/sit9531x/core.h
create mode 100644 drivers/dpll/sit9531x/dpll.c
create mode 100644 drivers/dpll/sit9531x/dpll.h
create mode 100644 drivers/dpll/sit9531x/prop.c
create mode 100644 drivers/dpll/sit9531x/prop.h
create mode 100644 drivers/dpll/sit9531x/regs.h
[PATCH v10 00/14] dpll: add SiTime SiT9531x DPLL clock driver
Posted by Ali Rouhi 2 days, 20 hours ago
This series adds a DPLL subsystem driver for the SiTime SiT95316 and
SiT95317 I2C clock generators. Each device integrates four PLLs with
automatic reference selection and on-chip TDC phase-offset measurement,
and is used for synchronization in telecom, networking, and data-center
timing.

The series contains the device-tree binding, the driver under
drivers/dpll/sit9531x/, and the MAINTAINERS entry.

v1: https://lore.kernel.org/netdev/20260511211143.19792-1-arouhi@sitime.com/
v2: https://lore.kernel.org/netdev/20260520191943.73938-1-arouhi@sitime.com/
v3: https://lore.kernel.org/netdev/20260731180951.65725-1-arouhi@sitime.com/
v4: https://lore.kernel.org/netdev/20260806232439.27551-1-arouhi@sitime.com/
v5: https://lore.kernel.org/netdev/20260810230439.22866-1-arouhi@sitime.com/
v6: https://lore.kernel.org/netdev/20260812175337.18155-1-arouhi@sitime.com/
v7: https://lore.kernel.org/netdev/20260815221919.64226-1-arouhi@sitime.com/
v8: https://lore.kernel.org/netdev/20260902214030.20955-1-arouhi@sitime.com/
v9: https://lore.kernel.org/netdev/20260915000015.80480-1-arouhi@sitime.com/

v10 follows v9 by less than a week because three things did not want to
wait for a longer cycle. Carolina Jubran ran v9 on a board and found two
defects in input handling. A divide-error in the frequency path turned
out to be reachable from an ordinary pin get. And the embedded-sync
patch is withdrawn, which takes the series from fifteen patches to
fourteen.

  1-2   bindings: vendor prefix, then the device schema
  3     basic support: paged regmap, variant detection, probe
  4     DPLL types and pin properties from system firmware
  5     register the DPLL devices and pins, and keep their state
  6     input pin state on a DPLL, with the pin-state contract
  7     input pin priority
  8     pin frequency, both directions
  9     output pin state (mute)
  10    output phase adjust
  11    phase offset through the TDC
  12    fractional frequency offset of the selected reference
  13    the inter-PLL sync net as a pair of pins
  14    optional device-tree overrides for two board facts

The two bindings patches come first, so the driver never matches on a
compatible string before the schema that describes it is in the tree.

Each of the twelve driver patches builds and links on its own: no patch
calls something a later patch introduces, so a bisect cannot land on a
tree that fails to compile. For this posting that was re-checked patch
by patch with W=1 and with sparse. checkpatch --strict is clean except
for the "does MAINTAINERS need updating?" hint on patches 4 and 5,
which add files under drivers/dpll/sit9531x/ -- patch 3 already covers
that directory with an F: entry.

Three things are worth reading before the changelog.

The first is a divide-error, found by inspection rather than on a
board. The feedback divider is a fraction, and the frequency path
divided by its denominator without first establishing that the
numerator was below it. The device can hold that combination from a
profile the driver did not program, and the quotient then leaves what
the division helper can return, which on x86 faults rather than
yielding a value the caller could reject. An ordinary pin get reaches
that path, so we did not want to leave it standing for a cycle. There
is no trace to show; the argument is the one in the comment on
sit9531x_divn_static(). The fraction is now refused instead of
divided.

The second is a change in behaviour that userspace can see. An output
rate the divider cannot produce exactly is now refused with -EINVAL.
Until v9 the driver programmed the nearest rate it could reach and
reported success, so a request for a frequency this device cannot make
came back as though it had been honoured. Refusing it is the smaller
surprise: a caller that asked for a rate and got zero errors has no
other way to learn that it is not running at that rate.

The third is the withdrawal of embedded sync.

Patch 11 of v9, embedded sync on pins, is dropped and not replaced.

This device does not implement embedded sync. What it has in that area
is SYSREF-triggered output gating with a per-output burst count, which
is a different function: the byte patch 11 programmed sets how many
pulses an output emits per trigger, so the 50 it wrote was a pulse
count and not the 50 percent duty the getter reported. The patch had
been written to the shape of the ABI rather than derived from the
register, and the two quantities happen to share a literal, which is
what let it look right.

The automated review of v8 asked whether that write could take effect
at all, given that the path never selects the SYSREF or SYNCB mode the
byte belongs to. This was the right question, and the answer we gave
then, and gave again for v9, was wrong. The patch is withdrawn rather
than fixed, and we are not planning to resubmit it. Nothing else in the
series depended on it.

Changes in v10:

  - Arithmetic. Besides the feedback-divider fraction above, the
    runtime tap of that divider is now guarded the same way as the
    configured one, and the denominator's high bit has its own name
    instead of borrowing the integer field's. The device-tree override
    arrays are checked against the part: the VCO override needs an
    entry per PLL, and an output map shorter than the variant's output
    count is ignored rather than read as a run of unmapped outputs.

  - Input selection and state, from Carolina's bench report.
    Disconnecting the last reference now empties the priority table
    instead of being refused, so a DPLL can be left with no source at
    all. The slot encoding has codes for an input pair this part does
    not have, which read back as no valid reference, and every slot is
    given one rather than being left to read as input zero. Connected
    now means the device has selected the pin, not that the loop has
    locked to it -- those are different questions and only the first
    one is what the pin state answers.

  - Answer from the device rather than from a cache. An output's
    current rate comes from its divider instead of the first entry in
    the list of rates the board supports. The programmed phase delay is
    decoded from the device at probe, so a delay a profile carries can
    be cleared through the ABI, and it is re-read when a request could
    not be confirmed. The reference a phase measurement is taken
    against is read at the point of measurement rather than from a poll
    that may be a period old. The input receiver refcounts are
    re-derived from the priority tables the poll reads, so a request
    that failed part way cannot leave a receiver gated off while
    another PLL is still using it.

  - Leave the device in a state the caller can describe. A priority
    table that was written only in part is put back rather than
    latched, and the mask that is reported describes what reached the
    device rather than what was asked for. The forced Hi-Z pair value
    is written before the override, so the pad is never briefly pinned
    driven between the two, and the half that reached the device is
    released when the other did not. Ownership of the inter-PLL sync
    net is recorded before the read-back that can fail, and a disable
    that fails part way leaves the state describable so the request can
    be repeated. Entering the programming state closes the loops and
    the debug key when it fails.

  - Interrupt and notification. The driver gives up the interrupt line
    after repeated failures to clear the notification latch, rather
    than re-entering the handler behind a still-asserted INTRB. A
    change in the lock-status error is treated like a change in the
    status itself. Priority changes notify the sibling pins through the
    helper meant for a caller that already holds the device lock, leave
    the pin the request named to the core, and skip a pin that is being
    unregistered.

  - Output pin identity. Output pins are named and matched by the chip
    pin they drive rather than by the driver's index for them. The two
    differ on the variant whose outputs are bonded out from a subset of
    the slots, which is where the wrong pin would otherwise be
    programmed.

  - Binding. dpll-types is bounded to the four PLLs the part has. The
    example is made self-consistent with the driver: the Fvco override
    is on a PLL whose band the value belongs to, and is a rate the
    example's own output pin divides down from exactly. Patch 1 is
    unchanged since v8 and keeps Conor's Acked-by. Patch 2 has changed
    again, so Krzysztof's Reviewed-by is still not carried across it.

  - Housekeeping. The page selector is cached; it is the only register
    in the map that is not volatile, which removes a selector write per
    register access on a paged device. The sign handling in the output
    phase encoder is folded into one abs() and a remainder, and a zero
    offset skips the coarse and fine encoding entirely. Both of those
    came from Ivan Vecera. Two per-input status flags and the register
    read that filled them are dropped, along with a cached per-pin
    phase offset that was written on every path of the getter and read
    on none. Text that described registering DPLL devices
    moved to the patch that registers them. kernel-doc that had stopped
    listing members the structs still have is corrected.

Four items from earlier rounds are unchanged and are repeated here so
they are not re-raised.

The phase-adjust granularity stays at 1 ps rather than the 30 ps fine
step. The delays this device can reach are not a lattice of 30 ps: a
request is split between a coarse delay counted in VCO cycles and a
three-bit fine field of 30 ps steps, and the two are added, so the
spacing depends on the VCO period in force. Advertising 30 would name
a step the device does not have. A request is accepted at 1 ps and
rounded to the nearest delay the registers can hold, and the getter
reports what they hold rather than what was asked for, so a caller
that needs the exact figure reads it back.

A frequency request of 0 Hz is still refused with -EINVAL rather than
treated as a request to stop the output. Nothing in the ABI says zero
means off, and this device already has a mute control that says so
explicitly.

The use-after-free report on the pin properties remains a false
positive: dpll_pin_alloc() calls dpll_pin_prop_dup(), which copies
freq_supported with kmemdup() and the labels with kstrdup(), so the
core owns its copies and the driver has to free its own.

The u64 truncation in dpll_pin_freq_set() is still there and is still
not ours to fix in this series: the requested frequency is read as a
u64 and validated through a helper that takes a u32, so a rate of
U32_MAX + 1 + N is accepted as N against ranges that are themselves
u64. That affects every driver behind the interface. It will be posted
as its own patch against the core rather than buried here; this driver
range-checks its own input in the meantime.

Ali Rouhi (2):
  dt-bindings: vendor-prefixes: add SiTime Corporation
  dt-bindings: dpll: add SiTime SiT95316 clock generator

Oleg Zadorozhnyi (12):
  dpll: add basic SiTime SiT9531x support
  dpll: sit9531x: read DPLL types and pin properties from system
    firmware
  dpll: sit9531x: register DPLL devices and pins
  dpll: sit9531x: implement input pin state on a DPLL
  dpll: sit9531x: add support to get and set priority on input pins
  dpll: sit9531x: add support to get and set frequency on pins
  dpll: sit9531x: implement output pin state on a DPLL
  dpll: sit9531x: add support to adjust output phase
  dpll: sit9531x: add support to get phase offset on the connected input
    pin
  dpll: sit9531x: add support to get fractional frequency offset
  dpll: sit9531x: model the inter-PLL sync net as a pair of pins
  dpll: sit9531x: allow the device tree to override two board facts

 .../bindings/dpll/sitime,sit95316.yaml        |  183 +
 .../devicetree/bindings/vendor-prefixes.yaml  |    2 +
 MAINTAINERS                                   |    7 +
 drivers/dpll/Kconfig                          |    2 +
 drivers/dpll/Makefile                         |    1 +
 drivers/dpll/sit9531x/Kconfig                 |   17 +
 drivers/dpll/sit9531x/Makefile                |    4 +
 drivers/dpll/sit9531x/core.c                  | 4553 +++++++++++++++++
 drivers/dpll/sit9531x/core.h                  |  429 ++
 drivers/dpll/sit9531x/dpll.c                  | 1445 ++++++
 drivers/dpll/sit9531x/dpll.h                  |   66 +
 drivers/dpll/sit9531x/prop.c                  |  469 ++
 drivers/dpll/sit9531x/prop.h                  |   37 +
 drivers/dpll/sit9531x/regs.h                  |  364 ++
 14 files changed, 7579 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dpll/sitime,sit95316.yaml
 create mode 100644 drivers/dpll/sit9531x/Kconfig
 create mode 100644 drivers/dpll/sit9531x/Makefile
 create mode 100644 drivers/dpll/sit9531x/core.c
 create mode 100644 drivers/dpll/sit9531x/core.h
 create mode 100644 drivers/dpll/sit9531x/dpll.c
 create mode 100644 drivers/dpll/sit9531x/dpll.h
 create mode 100644 drivers/dpll/sit9531x/prop.c
 create mode 100644 drivers/dpll/sit9531x/prop.h
 create mode 100644 drivers/dpll/sit9531x/regs.h


base-commit: 4bb9710c6a68d35207f123aef55dcd50e7195ec5
-- 
2.43.0