* [PATCH net-next v2 1/2] dpll: add phase-adjust-gran pin attribute
2025-10-29 15:32 [PATCH net-next v2 0/2] dpll: Add support for phase adjustment granularity Ivan Vecera
@ 2025-10-29 15:32 ` Ivan Vecera
2025-10-31 11:11 ` Jiri Pirko
2025-10-31 11:51 ` Kubalewski, Arkadiusz
2025-10-29 15:32 ` [PATCH net-next v2 2/2] dpll: zl3073x: Specify phase adjustment granularity for pins Ivan Vecera
2025-11-01 1:10 ` [PATCH net-next v2 0/2] dpll: Add support for phase adjustment granularity patchwork-bot+netdevbpf
2 siblings, 2 replies; 7+ messages in thread
From: Ivan Vecera @ 2025-10-29 15:32 UTC (permalink / raw)
To: netdev
Cc: Michal Schmidt, Petr Oros, Prathosh Satish, Vadim Fedorenko,
Arkadiusz Kubalewski, Jiri Pirko, Jonathan Corbet,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Donald Hunter, linux-doc, linux-kernel
Phase-adjust values are currently limited by a min-max range. Some
hardware requires, for certain pin types, that values be multiples of
a specific granularity, as in the zl3073x driver.
Add a `phase-adjust-gran` pin attribute and an appropriate field in
dpll_pin_properties. If set by the driver, use its value to validate
user-provided phase-adjust values.
Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
Reviewed-by: Petr Oros <poros@redhat.com>
Tested-by: Prathosh Satish <Prathosh.Satish@microchip.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
v2:
* changed type to u32 and added explicit cast to s32 during remainder
computation (per Jiri's request)
---
Documentation/driver-api/dpll.rst | 36 +++++++++++++++------------
Documentation/netlink/specs/dpll.yaml | 7 ++++++
drivers/dpll/dpll_netlink.c | 12 ++++++++-
include/linux/dpll.h | 1 +
include/uapi/linux/dpll.h | 1 +
5 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst
index be1fc643b645e..83118c728ed90 100644
--- a/Documentation/driver-api/dpll.rst
+++ b/Documentation/driver-api/dpll.rst
@@ -198,26 +198,28 @@ be requested with the same attribute with ``DPLL_CMD_DEVICE_SET`` command.
================================== ======================================
Device may also provide ability to adjust a signal phase on a pin.
-If pin phase adjustment is supported, minimal and maximal values that pin
-handle shall be provide to the user on ``DPLL_CMD_PIN_GET`` respond
-with ``DPLL_A_PIN_PHASE_ADJUST_MIN`` and ``DPLL_A_PIN_PHASE_ADJUST_MAX``
+If pin phase adjustment is supported, minimal and maximal values and
+granularity that pin handle shall be provided to the user on
+``DPLL_CMD_PIN_GET`` respond with ``DPLL_A_PIN_PHASE_ADJUST_MIN``,
+``DPLL_A_PIN_PHASE_ADJUST_MAX`` and ``DPLL_A_PIN_PHASE_ADJUST_GRAN``
attributes. Configured phase adjust value is provided with
``DPLL_A_PIN_PHASE_ADJUST`` attribute of a pin, and value change can be
requested with the same attribute with ``DPLL_CMD_PIN_SET`` command.
- =============================== ======================================
- ``DPLL_A_PIN_ID`` configured pin id
- ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment
- ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment
- ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
- adjustment on parent dpll device
- ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting
- configuration on given parent dpll
- device
- ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
- ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
- between a pin and parent dpll device
- =============================== ======================================
+ ================================ ==========================================
+ ``DPLL_A_PIN_ID`` configured pin id
+ ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase adjustment value
+ ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment
+ ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment
+ ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
+ adjustment on parent dpll device
+ ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting
+ configuration on given parent dpll
+ device
+ ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
+ ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
+ between a pin and parent dpll device
+ ================================ ==========================================
All phase related values are provided in pico seconds, which represents
time difference between signals phase. The negative value means that
@@ -384,6 +386,8 @@ according to attribute purpose.
frequencies
``DPLL_A_PIN_ANY_FREQUENCY_MIN`` attr minimum value of frequency
``DPLL_A_PIN_ANY_FREQUENCY_MAX`` attr maximum value of frequency
+ ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase
+ adjustment value
``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase
adjustment
``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase
diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
index cafb4ec20447e..4e5f0b7c41492 100644
--- a/Documentation/netlink/specs/dpll.yaml
+++ b/Documentation/netlink/specs/dpll.yaml
@@ -440,6 +440,12 @@ attribute-sets:
doc: |
Capable pin provides list of pins that can be bound to create a
reference-sync pin pair.
+ -
+ name: phase-adjust-gran
+ type: u32
+ doc: |
+ Granularity of phase adjustment, in picoseconds. The value of
+ phase adjustment must be a multiple of this granularity.
-
name: pin-parent-device
@@ -614,6 +620,7 @@ operations:
- capabilities
- parent-device
- parent-pin
+ - phase-adjust-gran
- phase-adjust-min
- phase-adjust-max
- phase-adjust
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 74c1f0ca95f24..017999beccba8 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -637,6 +637,10 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
ret = dpll_msg_add_pin_freq(msg, pin, ref, extack);
if (ret)
return ret;
+ if (prop->phase_gran &&
+ nla_put_u32(msg, DPLL_A_PIN_PHASE_ADJUST_GRAN,
+ prop->phase_gran))
+ return -EMSGSIZE;
if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
prop->phase_range.min))
return -EMSGSIZE;
@@ -1261,7 +1265,13 @@ dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
if (phase_adj > pin->prop.phase_range.max ||
phase_adj < pin->prop.phase_range.min) {
NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
- "phase adjust value not supported");
+ "phase adjust value of out range");
+ return -EINVAL;
+ }
+ if (pin->prop.phase_gran && phase_adj % (s32)pin->prop.phase_gran) {
+ NL_SET_ERR_MSG_ATTR_FMT(extack, phase_adj_attr,
+ "phase adjust value not multiple of %u",
+ pin->prop.phase_gran);
return -EINVAL;
}
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 25be745bf41f1..562f520b23c27 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -163,6 +163,7 @@ struct dpll_pin_properties {
u32 freq_supported_num;
struct dpll_pin_frequency *freq_supported;
struct dpll_pin_phase_adjust_range phase_range;
+ u32 phase_gran;
};
#if IS_ENABLED(CONFIG_DPLL)
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index ab1725a954d74..69d35570ac4f1 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -251,6 +251,7 @@ enum dpll_a_pin {
DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED,
DPLL_A_PIN_ESYNC_PULSE,
DPLL_A_PIN_REFERENCE_SYNC,
+ DPLL_A_PIN_PHASE_ADJUST_GRAN,
__DPLL_A_PIN_MAX,
DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH net-next v2 1/2] dpll: add phase-adjust-gran pin attribute
2025-10-29 15:32 ` [PATCH net-next v2 1/2] dpll: add phase-adjust-gran pin attribute Ivan Vecera
@ 2025-10-31 11:11 ` Jiri Pirko
2025-10-31 11:51 ` Kubalewski, Arkadiusz
1 sibling, 0 replies; 7+ messages in thread
From: Jiri Pirko @ 2025-10-31 11:11 UTC (permalink / raw)
To: Ivan Vecera
Cc: netdev, Michal Schmidt, Petr Oros, Prathosh Satish,
Vadim Fedorenko, Arkadiusz Kubalewski, Jonathan Corbet,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Donald Hunter, linux-doc, linux-kernel
Wed, Oct 29, 2025 at 04:32:06PM +0100, ivecera@redhat.com wrote:
>Phase-adjust values are currently limited by a min-max range. Some
>hardware requires, for certain pin types, that values be multiples of
>a specific granularity, as in the zl3073x driver.
>
>Add a `phase-adjust-gran` pin attribute and an appropriate field in
>dpll_pin_properties. If set by the driver, use its value to validate
>user-provided phase-adjust values.
>
>Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
>Reviewed-by: Petr Oros <poros@redhat.com>
>Tested-by: Prathosh Satish <Prathosh.Satish@microchip.com>
>Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* RE: [PATCH net-next v2 1/2] dpll: add phase-adjust-gran pin attribute
2025-10-29 15:32 ` [PATCH net-next v2 1/2] dpll: add phase-adjust-gran pin attribute Ivan Vecera
2025-10-31 11:11 ` Jiri Pirko
@ 2025-10-31 11:51 ` Kubalewski, Arkadiusz
1 sibling, 0 replies; 7+ messages in thread
From: Kubalewski, Arkadiusz @ 2025-10-31 11:51 UTC (permalink / raw)
To: Vecera, Ivan, netdev@vger.kernel.org
Cc: Schmidt, Michal, Oros, Petr, Prathosh Satish, Vadim Fedorenko,
Jiri Pirko, Jonathan Corbet, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Donald Hunter,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org
>From: Ivan Vecera <ivecera@redhat.com>
>Sent: Wednesday, October 29, 2025 4:32 PM
>
>Phase-adjust values are currently limited by a min-max range. Some
>hardware requires, for certain pin types, that values be multiples of
>a specific granularity, as in the zl3073x driver.
>
>Add a `phase-adjust-gran` pin attribute and an appropriate field in
>dpll_pin_properties. If set by the driver, use its value to validate
>user-provided phase-adjust values.
>
>Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
>Reviewed-by: Petr Oros <poros@redhat.com>
LGTM, Thank you!
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>Tested-by: Prathosh Satish <Prathosh.Satish@microchip.com>
>Signed-off-by: Ivan Vecera <ivecera@redhat.com>
>---
>v2:
>* changed type to u32 and added explicit cast to s32 during remainder
> computation (per Jiri's request)
>---
> Documentation/driver-api/dpll.rst | 36 +++++++++++++++------------
> Documentation/netlink/specs/dpll.yaml | 7 ++++++
> drivers/dpll/dpll_netlink.c | 12 ++++++++-
> include/linux/dpll.h | 1 +
> include/uapi/linux/dpll.h | 1 +
> 5 files changed, 40 insertions(+), 17 deletions(-)
>
>diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-
>api/dpll.rst
>index be1fc643b645e..83118c728ed90 100644
>--- a/Documentation/driver-api/dpll.rst
>+++ b/Documentation/driver-api/dpll.rst
>@@ -198,26 +198,28 @@ be requested with the same attribute with
>``DPLL_CMD_DEVICE_SET`` command.
> ==================================
>======================================
>
> Device may also provide ability to adjust a signal phase on a pin.
>-If pin phase adjustment is supported, minimal and maximal values that pin
>-handle shall be provide to the user on ``DPLL_CMD_PIN_GET`` respond
>-with ``DPLL_A_PIN_PHASE_ADJUST_MIN`` and ``DPLL_A_PIN_PHASE_ADJUST_MAX``
>+If pin phase adjustment is supported, minimal and maximal values and
>+granularity that pin handle shall be provided to the user on
>+``DPLL_CMD_PIN_GET`` respond with ``DPLL_A_PIN_PHASE_ADJUST_MIN``,
>+``DPLL_A_PIN_PHASE_ADJUST_MAX`` and ``DPLL_A_PIN_PHASE_ADJUST_GRAN``
> attributes. Configured phase adjust value is provided with
> ``DPLL_A_PIN_PHASE_ADJUST`` attribute of a pin, and value change can be
> requested with the same attribute with ``DPLL_CMD_PIN_SET`` command.
>
>- =============================== ======================================
>- ``DPLL_A_PIN_ID`` configured pin id
>- ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment
>- ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment
>- ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
>- adjustment on parent dpll device
>- ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting
>- configuration on given parent dpll
>- device
>- ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
>- ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
>- between a pin and parent dpll device
>- =============================== ======================================
>+ ================================
>==========================================
>+ ``DPLL_A_PIN_ID`` configured pin id
>+ ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase adjustment
>value
>+ ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment
>+ ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment
>+ ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase
>+ adjustment on parent dpll device
>+ ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting
>+ configuration on given parent dpll
>+ device
>+ ``DPLL_A_PIN_PARENT_ID`` parent dpll device id
>+ ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference
>+ between a pin and parent dpll device
>+ ================================
>==========================================
>
> All phase related values are provided in pico seconds, which represents
> time difference between signals phase. The negative value means that
>@@ -384,6 +386,8 @@ according to attribute purpose.
> frequencies
> ``DPLL_A_PIN_ANY_FREQUENCY_MIN`` attr minimum value of frequency
> ``DPLL_A_PIN_ANY_FREQUENCY_MAX`` attr maximum value of frequency
>+ ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase
>+ adjustment value
> ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase
> adjustment
> ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase
>diff --git a/Documentation/netlink/specs/dpll.yaml
>b/Documentation/netlink/specs/dpll.yaml
>index cafb4ec20447e..4e5f0b7c41492 100644
>--- a/Documentation/netlink/specs/dpll.yaml
>+++ b/Documentation/netlink/specs/dpll.yaml
>@@ -440,6 +440,12 @@ attribute-sets:
> doc: |
> Capable pin provides list of pins that can be bound to create a
> reference-sync pin pair.
>+ -
>+ name: phase-adjust-gran
>+ type: u32
>+ doc: |
>+ Granularity of phase adjustment, in picoseconds. The value of
>+ phase adjustment must be a multiple of this granularity.
>
> -
> name: pin-parent-device
>@@ -614,6 +620,7 @@ operations:
> - capabilities
> - parent-device
> - parent-pin
>+ - phase-adjust-gran
> - phase-adjust-min
> - phase-adjust-max
> - phase-adjust
>diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>index 74c1f0ca95f24..017999beccba8 100644
>--- a/drivers/dpll/dpll_netlink.c
>+++ b/drivers/dpll/dpll_netlink.c
>@@ -637,6 +637,10 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct
>dpll_pin *pin,
> ret = dpll_msg_add_pin_freq(msg, pin, ref, extack);
> if (ret)
> return ret;
>+ if (prop->phase_gran &&
>+ nla_put_u32(msg, DPLL_A_PIN_PHASE_ADJUST_GRAN,
>+ prop->phase_gran))
>+ return -EMSGSIZE;
> if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
> prop->phase_range.min))
> return -EMSGSIZE;
>@@ -1261,7 +1265,13 @@ dpll_pin_phase_adj_set(struct dpll_pin *pin, struct
>nlattr *phase_adj_attr,
> if (phase_adj > pin->prop.phase_range.max ||
> phase_adj < pin->prop.phase_range.min) {
> NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
>- "phase adjust value not supported");
>+ "phase adjust value of out range");
>+ return -EINVAL;
>+ }
>+ if (pin->prop.phase_gran && phase_adj % (s32)pin->prop.phase_gran) {
>+ NL_SET_ERR_MSG_ATTR_FMT(extack, phase_adj_attr,
>+ "phase adjust value not multiple of %u",
>+ pin->prop.phase_gran);
> return -EINVAL;
> }
>
>diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>index 25be745bf41f1..562f520b23c27 100644
>--- a/include/linux/dpll.h
>+++ b/include/linux/dpll.h
>@@ -163,6 +163,7 @@ struct dpll_pin_properties {
> u32 freq_supported_num;
> struct dpll_pin_frequency *freq_supported;
> struct dpll_pin_phase_adjust_range phase_range;
>+ u32 phase_gran;
> };
>
> #if IS_ENABLED(CONFIG_DPLL)
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>index ab1725a954d74..69d35570ac4f1 100644
>--- a/include/uapi/linux/dpll.h
>+++ b/include/uapi/linux/dpll.h
>@@ -251,6 +251,7 @@ enum dpll_a_pin {
> DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED,
> DPLL_A_PIN_ESYNC_PULSE,
> DPLL_A_PIN_REFERENCE_SYNC,
>+ DPLL_A_PIN_PHASE_ADJUST_GRAN,
>
> __DPLL_A_PIN_MAX,
> DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)
>--
>2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v2 2/2] dpll: zl3073x: Specify phase adjustment granularity for pins
2025-10-29 15:32 [PATCH net-next v2 0/2] dpll: Add support for phase adjustment granularity Ivan Vecera
2025-10-29 15:32 ` [PATCH net-next v2 1/2] dpll: add phase-adjust-gran pin attribute Ivan Vecera
@ 2025-10-29 15:32 ` Ivan Vecera
2025-10-31 11:57 ` Kubalewski, Arkadiusz
2025-11-01 1:10 ` [PATCH net-next v2 0/2] dpll: Add support for phase adjustment granularity patchwork-bot+netdevbpf
2 siblings, 1 reply; 7+ messages in thread
From: Ivan Vecera @ 2025-10-29 15:32 UTC (permalink / raw)
To: netdev
Cc: Michal Schmidt, Petr Oros, Prathosh Satish, Vadim Fedorenko,
Arkadiusz Kubalewski, Jiri Pirko, Jonathan Corbet,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Donald Hunter, linux-doc, linux-kernel
Output pins phase adjustment values in the device are expressed
in half synth clock cycles. Use this number of cycles as output
pins' phase adjust granularity and simplify both get/set callbacks.
Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
Reviewed-by: Petr Oros <poros@redhat.com>
Tested-by: Prathosh Satish <Prathosh.Satish@microchip.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
drivers/dpll/zl3073x/dpll.c | 58 +++++++++----------------------------
drivers/dpll/zl3073x/prop.c | 11 +++++++
2 files changed, 25 insertions(+), 44 deletions(-)
diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
index 93dc93eec79ed..b13eb4e342d58 100644
--- a/drivers/dpll/zl3073x/dpll.c
+++ b/drivers/dpll/zl3073x/dpll.c
@@ -35,6 +35,7 @@
* @prio: pin priority <0, 14>
* @selectable: pin is selectable in automatic mode
* @esync_control: embedded sync is controllable
+ * @phase_gran: phase adjustment granularity
* @pin_state: last saved pin state
* @phase_offset: last saved pin phase offset
* @freq_offset: last saved fractional frequency offset
@@ -49,6 +50,7 @@ struct zl3073x_dpll_pin {
u8 prio;
bool selectable;
bool esync_control;
+ s32 phase_gran;
enum dpll_pin_state pin_state;
s64 phase_offset;
s64 freq_offset;
@@ -1388,25 +1390,14 @@ zl3073x_dpll_output_pin_phase_adjust_get(const struct dpll_pin *dpll_pin,
struct zl3073x_dpll *zldpll = dpll_priv;
struct zl3073x_dev *zldev = zldpll->dev;
struct zl3073x_dpll_pin *pin = pin_priv;
- u32 synth_freq;
s32 phase_comp;
- u8 out, synth;
+ u8 out;
int rc;
- out = zl3073x_output_pin_out_get(pin->id);
- synth = zl3073x_out_synth_get(zldev, out);
- synth_freq = zl3073x_synth_freq_get(zldev, synth);
-
- /* Check synth freq for zero */
- if (!synth_freq) {
- dev_err(zldev->dev, "Got zero synth frequency for output %u\n",
- out);
- return -EINVAL;
- }
-
guard(mutex)(&zldev->multiop_lock);
/* Read output configuration */
+ out = zl3073x_output_pin_out_get(pin->id);
rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
ZL_REG_OUTPUT_MB_MASK, BIT(out));
if (rc)
@@ -1417,11 +1408,10 @@ zl3073x_dpll_output_pin_phase_adjust_get(const struct dpll_pin *dpll_pin,
if (rc)
return rc;
- /* Value in register is expressed in half synth clock cycles */
- phase_comp *= (int)div_u64(PSEC_PER_SEC, 2 * synth_freq);
-
- /* Reverse two's complement negation applied during 'set' */
- *phase_adjust = -phase_comp;
+ /* Convert value to ps and reverse two's complement negation applied
+ * during 'set'
+ */
+ *phase_adjust = -phase_comp * pin->phase_gran;
return rc;
}
@@ -1437,39 +1427,18 @@ zl3073x_dpll_output_pin_phase_adjust_set(const struct dpll_pin *dpll_pin,
struct zl3073x_dpll *zldpll = dpll_priv;
struct zl3073x_dev *zldev = zldpll->dev;
struct zl3073x_dpll_pin *pin = pin_priv;
- int half_synth_cycle;
- u32 synth_freq;
- u8 out, synth;
+ u8 out;
int rc;
- /* Get attached synth */
- out = zl3073x_output_pin_out_get(pin->id);
- synth = zl3073x_out_synth_get(zldev, out);
-
- /* Get synth's frequency */
- synth_freq = zl3073x_synth_freq_get(zldev, synth);
-
- /* Value in register is expressed in half synth clock cycles so
- * the given phase adjustment a multiple of half synth clock.
- */
- half_synth_cycle = (int)div_u64(PSEC_PER_SEC, 2 * synth_freq);
-
- if ((phase_adjust % half_synth_cycle) != 0) {
- NL_SET_ERR_MSG_FMT(extack,
- "Phase adjustment value has to be multiple of %d",
- half_synth_cycle);
- return -EINVAL;
- }
- phase_adjust /= half_synth_cycle;
-
/* The value in the register is stored as two's complement negation
- * of requested value.
+ * of requested value and expressed in half synth clock cycles.
*/
- phase_adjust = -phase_adjust;
+ phase_adjust = -phase_adjust / pin->phase_gran;
guard(mutex)(&zldev->multiop_lock);
/* Read output configuration */
+ out = zl3073x_output_pin_out_get(pin->id);
rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
ZL_REG_OUTPUT_MB_MASK, BIT(out));
if (rc)
@@ -1758,9 +1727,10 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
if (IS_ERR(props))
return PTR_ERR(props);
- /* Save package label & esync capability */
+ /* Save package label, esync capability and phase adjust granularity */
strscpy(pin->label, props->package_label);
pin->esync_control = props->esync_control;
+ pin->phase_gran = props->dpll_props.phase_gran;
if (zl3073x_dpll_is_input_pin(pin)) {
rc = zl3073x_dpll_ref_prio_get(pin, &pin->prio);
diff --git a/drivers/dpll/zl3073x/prop.c b/drivers/dpll/zl3073x/prop.c
index 4cf7e8aefcb37..9e1fca5cdaf1e 100644
--- a/drivers/dpll/zl3073x/prop.c
+++ b/drivers/dpll/zl3073x/prop.c
@@ -208,7 +208,18 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
} else {
+ u8 out, synth;
+ u32 f;
+
props->dpll_props.type = DPLL_PIN_TYPE_GNSS;
+
+ /* The output pin phase adjustment granularity equals half of
+ * the synth frequency count.
+ */
+ out = zl3073x_output_pin_out_get(index);
+ synth = zl3073x_out_synth_get(zldev, out);
+ f = 2 * zl3073x_synth_freq_get(zldev, synth);
+ props->dpll_props.phase_gran = f ? div_u64(PSEC_PER_SEC, f) : 1;
}
props->dpll_props.phase_range.min = S32_MIN;
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* RE: [PATCH net-next v2 2/2] dpll: zl3073x: Specify phase adjustment granularity for pins
2025-10-29 15:32 ` [PATCH net-next v2 2/2] dpll: zl3073x: Specify phase adjustment granularity for pins Ivan Vecera
@ 2025-10-31 11:57 ` Kubalewski, Arkadiusz
0 siblings, 0 replies; 7+ messages in thread
From: Kubalewski, Arkadiusz @ 2025-10-31 11:57 UTC (permalink / raw)
To: Vecera, Ivan, netdev@vger.kernel.org
Cc: Schmidt, Michal, Oros, Petr, Prathosh Satish, Vadim Fedorenko,
Jiri Pirko, Jonathan Corbet, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Donald Hunter,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org
>From: Ivan Vecera <ivecera@redhat.com>
>Sent: Wednesday, October 29, 2025 4:32 PM
>
>Output pins phase adjustment values in the device are expressed
>in half synth clock cycles. Use this number of cycles as output
>pins' phase adjust granularity and simplify both get/set callbacks.
>
>Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
>Reviewed-by: Petr Oros <poros@redhat.com>
>Tested-by: Prathosh Satish <Prathosh.Satish@microchip.com>
LGTM, Thank you!
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>Signed-off-by: Ivan Vecera <ivecera@redhat.com>
>---
> drivers/dpll/zl3073x/dpll.c | 58 +++++++++----------------------------
> drivers/dpll/zl3073x/prop.c | 11 +++++++
> 2 files changed, 25 insertions(+), 44 deletions(-)
>
>diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
>index 93dc93eec79ed..b13eb4e342d58 100644
>--- a/drivers/dpll/zl3073x/dpll.c
>+++ b/drivers/dpll/zl3073x/dpll.c
>@@ -35,6 +35,7 @@
> * @prio: pin priority <0, 14>
> * @selectable: pin is selectable in automatic mode
> * @esync_control: embedded sync is controllable
>+ * @phase_gran: phase adjustment granularity
> * @pin_state: last saved pin state
> * @phase_offset: last saved pin phase offset
> * @freq_offset: last saved fractional frequency offset
>@@ -49,6 +50,7 @@ struct zl3073x_dpll_pin {
> u8 prio;
> bool selectable;
> bool esync_control;
>+ s32 phase_gran;
> enum dpll_pin_state pin_state;
> s64 phase_offset;
> s64 freq_offset;
>@@ -1388,25 +1390,14 @@ zl3073x_dpll_output_pin_phase_adjust_get(const
>struct dpll_pin *dpll_pin,
> struct zl3073x_dpll *zldpll = dpll_priv;
> struct zl3073x_dev *zldev = zldpll->dev;
> struct zl3073x_dpll_pin *pin = pin_priv;
>- u32 synth_freq;
> s32 phase_comp;
>- u8 out, synth;
>+ u8 out;
> int rc;
>
>- out = zl3073x_output_pin_out_get(pin->id);
>- synth = zl3073x_out_synth_get(zldev, out);
>- synth_freq = zl3073x_synth_freq_get(zldev, synth);
>-
>- /* Check synth freq for zero */
>- if (!synth_freq) {
>- dev_err(zldev->dev, "Got zero synth frequency for output %u\n",
>- out);
>- return -EINVAL;
>- }
>-
> guard(mutex)(&zldev->multiop_lock);
>
> /* Read output configuration */
>+ out = zl3073x_output_pin_out_get(pin->id);
> rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
> ZL_REG_OUTPUT_MB_MASK, BIT(out));
> if (rc)
>@@ -1417,11 +1408,10 @@ zl3073x_dpll_output_pin_phase_adjust_get(const
>struct dpll_pin *dpll_pin,
> if (rc)
> return rc;
>
>- /* Value in register is expressed in half synth clock cycles */
>- phase_comp *= (int)div_u64(PSEC_PER_SEC, 2 * synth_freq);
>-
>- /* Reverse two's complement negation applied during 'set' */
>- *phase_adjust = -phase_comp;
>+ /* Convert value to ps and reverse two's complement negation applied
>+ * during 'set'
>+ */
>+ *phase_adjust = -phase_comp * pin->phase_gran;
>
> return rc;
> }
>@@ -1437,39 +1427,18 @@ zl3073x_dpll_output_pin_phase_adjust_set(const
>struct dpll_pin *dpll_pin,
> struct zl3073x_dpll *zldpll = dpll_priv;
> struct zl3073x_dev *zldev = zldpll->dev;
> struct zl3073x_dpll_pin *pin = pin_priv;
>- int half_synth_cycle;
>- u32 synth_freq;
>- u8 out, synth;
>+ u8 out;
> int rc;
>
>- /* Get attached synth */
>- out = zl3073x_output_pin_out_get(pin->id);
>- synth = zl3073x_out_synth_get(zldev, out);
>-
>- /* Get synth's frequency */
>- synth_freq = zl3073x_synth_freq_get(zldev, synth);
>-
>- /* Value in register is expressed in half synth clock cycles so
>- * the given phase adjustment a multiple of half synth clock.
>- */
>- half_synth_cycle = (int)div_u64(PSEC_PER_SEC, 2 * synth_freq);
>-
>- if ((phase_adjust % half_synth_cycle) != 0) {
>- NL_SET_ERR_MSG_FMT(extack,
>- "Phase adjustment value has to be multiple of
>%d",
>- half_synth_cycle);
>- return -EINVAL;
>- }
>- phase_adjust /= half_synth_cycle;
>-
> /* The value in the register is stored as two's complement negation
>- * of requested value.
>+ * of requested value and expressed in half synth clock cycles.
> */
>- phase_adjust = -phase_adjust;
>+ phase_adjust = -phase_adjust / pin->phase_gran;
>
> guard(mutex)(&zldev->multiop_lock);
>
> /* Read output configuration */
>+ out = zl3073x_output_pin_out_get(pin->id);
> rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
> ZL_REG_OUTPUT_MB_MASK, BIT(out));
> if (rc)
>@@ -1758,9 +1727,10 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin
>*pin, u32 index)
> if (IS_ERR(props))
> return PTR_ERR(props);
>
>- /* Save package label & esync capability */
>+ /* Save package label, esync capability and phase adjust granularity
>*/
> strscpy(pin->label, props->package_label);
> pin->esync_control = props->esync_control;
>+ pin->phase_gran = props->dpll_props.phase_gran;
>
> if (zl3073x_dpll_is_input_pin(pin)) {
> rc = zl3073x_dpll_ref_prio_get(pin, &pin->prio);
>diff --git a/drivers/dpll/zl3073x/prop.c b/drivers/dpll/zl3073x/prop.c
>index 4cf7e8aefcb37..9e1fca5cdaf1e 100644
>--- a/drivers/dpll/zl3073x/prop.c
>+++ b/drivers/dpll/zl3073x/prop.c
>@@ -208,7 +208,18 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct
>zl3073x_dev *zldev,
> DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
> DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
> } else {
>+ u8 out, synth;
>+ u32 f;
>+
> props->dpll_props.type = DPLL_PIN_TYPE_GNSS;
>+
>+ /* The output pin phase adjustment granularity equals half of
>+ * the synth frequency count.
>+ */
>+ out = zl3073x_output_pin_out_get(index);
>+ synth = zl3073x_out_synth_get(zldev, out);
>+ f = 2 * zl3073x_synth_freq_get(zldev, synth);
>+ props->dpll_props.phase_gran = f ? div_u64(PSEC_PER_SEC, f) :
>1;
> }
>
> props->dpll_props.phase_range.min = S32_MIN;
>--
>2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next v2 0/2] dpll: Add support for phase adjustment granularity
2025-10-29 15:32 [PATCH net-next v2 0/2] dpll: Add support for phase adjustment granularity Ivan Vecera
2025-10-29 15:32 ` [PATCH net-next v2 1/2] dpll: add phase-adjust-gran pin attribute Ivan Vecera
2025-10-29 15:32 ` [PATCH net-next v2 2/2] dpll: zl3073x: Specify phase adjustment granularity for pins Ivan Vecera
@ 2025-11-01 1:10 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-11-01 1:10 UTC (permalink / raw)
To: Ivan Vecera
Cc: netdev, vadim.fedorenko, arkadiusz.kubalewski, jiri, corbet,
davem, edumazet, kuba, pabeni, horms, donald.hunter,
Prathosh.Satish, linux-doc, linux-kernel
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 29 Oct 2025 16:32:05 +0100 you wrote:
> Phase-adjust values are currently limited only by a min-max range. Some
> hardware requires, for certain pin types, that values be multiples of
> a specific granularity, as in the zl3073x driver.
>
> Patch 1: Adds 'phase-adjust-gran' pin attribute and an appropriate
> handling
> Patch 2: Adds a support for this attribute into zl3073x driver
>
> [...]
Here is the summary with links:
- [net-next,v2,1/2] dpll: add phase-adjust-gran pin attribute
https://git.kernel.org/netdev/net-next/c/30176bf7c871
- [net-next,v2,2/2] dpll: zl3073x: Specify phase adjustment granularity for pins
https://git.kernel.org/netdev/net-next/c/055a01b29fd6
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 7+ messages in thread