[PATCH 6.18 319/641] dpll: zl3073x: Store raw register values instead of parsed state

Greg Kroah-Hartman
2026-02-25T06:56:23Z

6.18-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ivan Vecera <ivecera@redhat.com>

[ Upstream commit 58fb88d30b0250f928e1afa0eaa4547770d86229 ]

The zl3073x_ref, zl3073x_out and zl3073x_synth structures
previously stored state that was parsed from register reads. This
included values like boolean 'enabled' flags, synthesizer selections,
and pre-calculated frequencies.

This commit refactors the state management to store the raw register
values directly in these structures. The various inline helper functions
are updated to parse these raw values on-demand using FIELD_GET.

Reviewed-by: Petr Oros <poros@redhat.com>
Tested-by: Prathosh Satish <Prathosh.Satish@microchip.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20251113074105.141379-2-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 5d41f95f5d0b ("dpll: zl3073x: Fix output pin phase adjustment sign")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/dpll/zl3073x/core.c | 81 ++++++++++++-------------------------
drivers/dpll/zl3073x/core.h | 61 ++++++++++++++++------------
2 files changed, 60 insertions(+), 82 deletions(-)

diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c
index e42e527813cf8..50c1fe59bc7f0 100644
--- a/drivers/dpll/zl3073x/core.c
+++ b/drivers/dpll/zl3073x/core.c
@@ -598,25 +598,22 @@ int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
* @zldev: pointer to zl3073x_dev structure
* @index: input reference index to fetch state for
*
- * Function fetches information for the given input reference that are
- * invariant and stores them for later use.
+ * Function fetches state for the given input reference and stores it for
+ * later user.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
{
- struct zl3073x_ref *input = &zldev->ref[index];
- u8 ref_config;
+ struct zl3073x_ref *ref = &zldev->ref[index];
int rc;

/* If the input is differential then the configuration for N-pin
* reference is ignored and P-pin config is used for both.
*/
- if (zl3073x_is_n_pin(index) &&
- zl3073x_ref_is_diff(zldev, index - 1)) {
- input->enabled = zl3073x_ref_is_enabled(zldev, index - 1);
- input->diff = true;
+ if (zl3073x_is_n_pin(index) && zl3073x_ref_is_diff(zldev, index - 1)) {
+ memcpy(ref, &zldev->ref[index - 1], sizeof(*ref));

return 0;
}
@@ -630,16 +627,14 @@ zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
return rc;

/* Read ref_config register */
- rc = zl3073x_read_u8(zldev, ZL_REG_REF_CONFIG, &ref_config);
+ rc = zl3073x_read_u8(zldev, ZL_REG_REF_CONFIG, &ref->config);
if (rc)
return rc;

- input->enabled = FIELD_GET(ZL_REF_CONFIG_ENABLE, ref_config);
- input->diff = FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref_config);
-
dev_dbg(zldev->dev, "REF%u is %s and configured as %s\n", index,
- str_enabled_disabled(input->enabled),
- input->diff ? "differential" : "single-ended");
+ str_enabled_disabled(zl3073x_ref_is_enabled(zldev, index)),
+ zl3073x_ref_is_diff(zldev, index)
+ ? "differential" : "single-ended");

return rc;
}
@@ -649,8 +644,8 @@ zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
* @zldev: pointer to zl3073x_dev structure
* @index: output index to fetch state for
*
- * Function fetches information for the given output (not output pin)
- * that are invariant and stores them for later use.
+ * Function fetches state of the given output (not output pin) and stores it
+ * for later use.
*
* Return: 0 on success, <0 on error
*/
@@ -658,22 +653,16 @@ static int
zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index)
{
struct zl3073x_out *out = &zldev->out[index];
- u8 output_ctrl, output_mode;
int rc;

/* Read output configuration */
- rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_CTRL(index), &output_ctrl);
+ rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_CTRL(index), &out->ctrl);
if (rc)
return rc;

- /* Store info about output enablement and synthesizer the output
- * is connected to.
- */
- out->enabled = FIELD_GET(ZL_OUTPUT_CTRL_EN, output_ctrl);
- out->synth = FIELD_GET(ZL_OUTPUT_CTRL_SYNTH_SEL, output_ctrl);
-
dev_dbg(zldev->dev, "OUT%u is %s and connected to SYNTH%u\n", index,
- str_enabled_disabled(out->enabled), out->synth);
+ str_enabled_disabled(zl3073x_out_is_enabled(zldev, index)),
+ zl3073x_out_synth_get(zldev, index));

guard(mutex)(&zldev->multiop_lock);

@@ -683,17 +672,13 @@ zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index)
if (rc)
return rc;

- /* Read output_mode */
- rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &output_mode);
+ /* Read output mode */
+ rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &out->mode);
if (rc)
return rc;

- /* Extract and store output signal format */
- out->signal_format = FIELD_GET(ZL_OUTPUT_MODE_SIGNAL_FORMAT,
- output_mode);
-
dev_dbg(zldev->dev, "OUT%u has signal format 0x%02x\n", index,
- out->signal_format);
+ zl3073x_out_signal_format_get(zldev, index));

return rc;
}
@@ -703,8 +688,7 @@ zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index)
* @zldev: pointer to zl3073x_dev structure
* @index: synth index to fetch state for
*
- * Function fetches information for the given synthesizer that are
- * invariant and stores them for later use.
+ * Function fetches state of the given synthesizer and stores it for later use.
*
* Return: 0 on success, <0 on error
*/
@@ -712,25 +696,13 @@ static int
zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 index)
{
struct zl3073x_synth *synth = &zldev->synth[index];
- u16 base, m, n;
- u8 synth_ctrl;
- u32 mult;
int rc;

/* Read synth control register */
- rc = zl3073x_read_u8(zldev, ZL_REG_SYNTH_CTRL(index), &synth_ctrl);
+ rc = zl3073x_read_u8(zldev, ZL_REG_SYNTH_CTRL(index), &synth->ctrl);
if (rc)
return rc;

- /* Store info about synth enablement and DPLL channel the synth is
- * driven by.
- */
- synth->enabled = FIELD_GET(ZL_SYNTH_CTRL_EN, synth_ctrl);
- synth->dpll = FIELD_GET(ZL_SYNTH_CTRL_DPLL_SEL, synth_ctrl);
-
- dev_dbg(zldev->dev, "SYNTH%u is %s and driven by DPLL%u\n", index,
- str_enabled_disabled(synth->enabled), synth->dpll);
-
guard(mutex)(&zldev->multiop_lock);

/* Read synth configuration */
@@ -744,35 +716,32 @@ zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 index)
*
* Read registers with these values
*/
- rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_BASE, &base);
+ rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_BASE, &synth->freq_base);
if (rc)
return rc;

- rc = zl3073x_read_u32(zldev, ZL_REG_SYNTH_FREQ_MULT, &mult);
+ rc = zl3073x_read_u32(zldev, ZL_REG_SYNTH_FREQ_MULT, &synth->freq_mult);
if (rc)
return rc;

- rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_M, &m);
+ rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_M, &synth->freq_m);
if (rc)
return rc;

- rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_N, &n);
+ rc = zl3073x_read_u16(zldev, ZL_REG_SYNTH_FREQ_N, &synth->freq_n);
if (rc)
return rc;

/* Check denominator for zero to avoid div by 0 */
- if (!n) {
+ if (!synth->freq_n) {
dev_err(zldev->dev,
"Zero divisor for SYNTH%u retrieved from device\n",
index);
return -EINVAL;
}

- /* Compute and store synth frequency */
- zldev->synth[index].freq = div_u64(mul_u32_u32(base * m, mult), n);
-
dev_dbg(zldev->dev, "SYNTH%u frequency: %u Hz\n", index,
- zldev->synth[index].freq);
+ zl3073x_synth_freq_get(zldev, index));

return rc;
}
diff --git a/drivers/dpll/zl3073x/core.h b/drivers/dpll/zl3073x/core.h
index 1dca4ddcf2350..51d0fd6cfabfc 100644
--- a/drivers/dpll/zl3073x/core.h
+++ b/drivers/dpll/zl3073x/core.h
@@ -29,38 +29,38 @@ struct zl3073x_dpll;

/**
* struct zl3073x_ref - input reference invariant info
- * @enabled: input reference is enabled or disabled
- * @diff: true if input reference is differential
* @ffo: current fractional frequency offset
+ * @config: reference config
*/
struct zl3073x_ref {
- bool enabled;
- bool diff;
s64 ffo;
+ u8 config;
};

/**
* struct zl3073x_out - output invariant info
- * @enabled: out is enabled or disabled
- * @synth: synthesizer the out is connected to
- * @signal_format: out signal format
+ * @ctrl: output control
+ * @mode: output mode
*/
struct zl3073x_out {
- bool enabled;
- u8 synth;
- u8 signal_format;
+ u8 ctrl;
+ u8 mode;
};

/**
* struct zl3073x_synth - synthesizer invariant info
- * @freq: synthesizer frequency
- * @dpll: ID of DPLL the synthesizer is driven by
- * @enabled: synth is enabled or disabled
+ * @freq_mult: frequency multiplier
+ * @freq_base: frequency base
+ * @freq_m: frequency numerator
+ * @freq_n: frequency denominator
+ * @ctrl: synth control
*/
struct zl3073x_synth {
- u32 freq;
- u8 dpll;
- bool enabled;
+ u32 freq_mult;
+ u16 freq_base;
+ u16 freq_m;
+ u16 freq_n;
+ u8 ctrl;
};

/**
@@ -239,7 +239,10 @@ zl3073x_ref_ffo_get(struct zl3073x_dev *zldev, u8 index)
static inline bool
zl3073x_ref_is_diff(struct zl3073x_dev *zldev, u8 index)
{
- return zldev->ref[index].diff;
+ if (FIELD_GET(ZL_REF_CONFIG_DIFF_EN, zldev->ref[index].config))
+ return true;
+
+ return false;
}

/**
@@ -252,7 +255,10 @@ zl3073x_ref_is_diff(struct zl3073x_dev *zldev, u8 index)
static inline bool
zl3073x_ref_is_enabled(struct zl3073x_dev *zldev, u8 index)
{
- return zldev->ref[index].enabled;
+ if (FIELD_GET(ZL_REF_CONFIG_ENABLE, zldev->ref[index].config))
+ return true;
+
+ return false;
}

/**
@@ -265,7 +271,7 @@ zl3073x_ref_is_enabled(struct zl3073x_dev *zldev, u8 index)
static inline u8
zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index)
{
- return zldev->synth[index].dpll;
+ return FIELD_GET(ZL_SYNTH_CTRL_DPLL_SEL, zldev->synth[index].ctrl);
}

/**
@@ -278,7 +284,10 @@ zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index)
static inline u32
zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index)
{
- return zldev->synth[index].freq;
+ struct zl3073x_synth *synth = &zldev->synth[index];
+
+ return mul_u64_u32_div(synth->freq_base * synth->freq_m,
+ synth->freq_mult, synth->freq_n);
}

/**
@@ -291,7 +300,7 @@ zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index)
static inline bool
zl3073x_synth_is_enabled(struct zl3073x_dev *zldev, u8 index)
{
- return zldev->synth[index].enabled;
+ return FIELD_GET(ZL_SYNTH_CTRL_EN, zldev->synth[index].ctrl);
}

/**
@@ -304,7 +313,7 @@ zl3073x_synth_is_enabled(struct zl3073x_dev *zldev, u8 index)
static inline u8
zl3073x_out_synth_get(struct zl3073x_dev *zldev, u8 index)
{
- return zldev->out[index].synth;
+ return FIELD_GET(ZL_OUTPUT_CTRL_SYNTH_SEL, zldev->out[index].ctrl);
}

/**
@@ -321,10 +330,10 @@ zl3073x_out_is_enabled(struct zl3073x_dev *zldev, u8 index)

/* Output is enabled only if associated synth is enabled */
synth = zl3073x_out_synth_get(zldev, index);
- if (zl3073x_synth_is_enabled(zldev, synth))
- return zldev->out[index].enabled;
+ if (!zl3073x_synth_is_enabled(zldev, synth))
+ return false;

- return false;
+ return FIELD_GET(ZL_OUTPUT_CTRL_EN, zldev->out[index].ctrl);
}

/**
@@ -337,7 +346,7 @@ zl3073x_out_is_enabled(struct zl3073x_dev *zldev, u8 index)
static inline u8
zl3073x_out_signal_format_get(struct zl3073x_dev *zldev, u8 index)
{
- return zldev->out[index].signal_format;
+ return FIELD_GET(ZL_OUTPUT_MODE_SIGNAL_FORMAT, zldev->out[index].mode);
}

/**
--
2.51.0