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
>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
© 2016 - 2026 Red Hat, Inc.