Skip to content

Commit 5826eec

Browse files
committed
Merge branch 'dpll-zl3073x-include-current-frequency-in-supported-frequencies-list'
Ivan Vecera says: ==================== dpll: zl3073x: Include current frequency in supported frequencies list This series ensures that the current operating frequency of a DPLL pin is always reported in its supported frequencies list. Problem: When a ZL3073x DPLL pin is registered, its supported frequencies are read from the firmware node's "supported-frequencies-hz" property. However, if the firmware node is missing, or doesn't include the current operating frequency, the pin reports a frequency that isn't in its supported list. This inconsistency can confuse userspace tools that expect the current frequency to be among the supported values. Solution: Always include the current pin frequency as the first entry in the supported frequencies list, followed by any additional frequencies from the firmware node (with duplicates filtered out). Patch 1 refactors the output pin frequency calculation into a reusable helper function zl3073x_dev_output_pin_freq_get(), which mirrors the existing zl3073x_dev_ref_freq_get() for input pins. Patch 2 modifies zl3073x_pin_props_get() to obtain the current frequency early and place it at index 0 of the supported frequencies array, ensuring it is always present regardless of firmware node contents. ==================== Link: https://patch.msgid.link/20260205154350.3180465-1-ivecera@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents a14d931 + 85a9aaa commit 5826eec

4 files changed

Lines changed: 69 additions & 49 deletions

File tree

drivers/dpll/zl3073x/core.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,36 @@ u8 zl3073x_dev_out_dpll_get(struct zl3073x_dev *zldev, u8 index)
301301
return zl3073x_synth_dpll_get(synth);
302302
}
303303

304+
/**
305+
* zl3073x_dev_output_pin_freq_get - get output pin frequency
306+
* @zldev: pointer to zl3073x device
307+
* @id: output pin id
308+
*
309+
* Computes the output pin frequency based on the synth frequency, output
310+
* divisor, and signal format. For N-div formats, N-pin frequency is
311+
* additionally divided by esync_n_period.
312+
*
313+
* Return: frequency of the given output pin in Hz
314+
*/
315+
static inline u32
316+
zl3073x_dev_output_pin_freq_get(struct zl3073x_dev *zldev, u8 id)
317+
{
318+
const struct zl3073x_synth *synth;
319+
const struct zl3073x_out *out;
320+
u8 out_id;
321+
u32 freq;
322+
323+
out_id = zl3073x_output_pin_out_get(id);
324+
out = zl3073x_out_state_get(zldev, out_id);
325+
synth = zl3073x_synth_state_get(zldev, zl3073x_out_synth_get(out));
326+
freq = zl3073x_synth_freq_get(synth) / out->div;
327+
328+
if (zl3073x_out_is_ndiv(out) && zl3073x_is_n_pin(id))
329+
freq /= out->esync_n_period;
330+
331+
return freq;
332+
}
333+
304334
/**
305335
* zl3073x_dev_out_is_diff - check if the given output is differential
306336
* @zldev: pointer to zl3073x device

drivers/dpll/zl3073x/dpll.c

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -916,46 +916,9 @@ zl3073x_dpll_output_pin_frequency_get(const struct dpll_pin *dpll_pin,
916916
struct netlink_ext_ack *extack)
917917
{
918918
struct zl3073x_dpll *zldpll = dpll_priv;
919-
struct zl3073x_dev *zldev = zldpll->dev;
920919
struct zl3073x_dpll_pin *pin = pin_priv;
921-
const struct zl3073x_synth *synth;
922-
const struct zl3073x_out *out;
923-
u32 synth_freq;
924-
u8 out_id;
925920

926-
out_id = zl3073x_output_pin_out_get(pin->id);
927-
out = zl3073x_out_state_get(zldev, out_id);
928-
929-
/* Get attached synth frequency */
930-
synth = zl3073x_synth_state_get(zldev, zl3073x_out_synth_get(out));
931-
synth_freq = zl3073x_synth_freq_get(synth);
932-
933-
switch (zl3073x_out_signal_format_get(out)) {
934-
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV:
935-
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV:
936-
/* In case of divided format we have to distiguish between
937-
* given output pin type.
938-
*
939-
* For P-pin the resulting frequency is computed as simple
940-
* division of synth frequency and output divisor.
941-
*
942-
* For N-pin we have to divide additionally by divisor stored
943-
* in esync_n_period output mailbox register that is used as
944-
* N-pin divisor for these modes.
945-
*/
946-
*frequency = synth_freq / out->div;
947-
948-
if (!zl3073x_dpll_is_p_pin(pin))
949-
*frequency = (u32)*frequency / out->esync_n_period;
950-
951-
break;
952-
default:
953-
/* In other modes the resulting frequency is computed as
954-
* division of synth frequency and output divisor.
955-
*/
956-
*frequency = synth_freq / out->div;
957-
break;
958-
}
921+
*frequency = zl3073x_dev_output_pin_freq_get(zldpll->dev, pin->id);
959922

960923
return 0;
961924
}

drivers/dpll/zl3073x/out.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,23 @@ static inline bool zl3073x_out_is_enabled(const struct zl3073x_out *out)
7979
return !!FIELD_GET(ZL_OUTPUT_CTRL_EN, out->ctrl);
8080
}
8181

82+
/**
83+
* zl3073x_out_is_ndiv - check if the given output is in N-div mode
84+
* @out: pointer to out state
85+
*
86+
* Return: true if output is in N-div mode, false otherwise
87+
*/
88+
static inline bool zl3073x_out_is_ndiv(const struct zl3073x_out *out)
89+
{
90+
switch (zl3073x_out_signal_format_get(out)) {
91+
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV:
92+
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV:
93+
return true;
94+
default:
95+
return false;
96+
}
97+
}
98+
8299
/**
83100
* zl3073x_out_synth_get - get synth connected to given output
84101
* @out: pointer to out state

drivers/dpll/zl3073x/prop.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,10 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
193193
{
194194
struct dpll_pin_frequency *ranges;
195195
struct zl3073x_pin_props *props;
196-
int i, j, num_freqs, rc;
196+
int i, j, num_freqs = 0, rc;
197+
u64 *freqs = NULL;
197198
const char *type;
198-
u64 *freqs;
199+
u32 curr_freq;
199200

200201
props = kzalloc(sizeof(*props), GFP_KERNEL);
201202
if (!props)
@@ -207,6 +208,7 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
207208
props->dpll_props.capabilities =
208209
DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
209210
DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
211+
curr_freq = zl3073x_dev_ref_freq_get(zldev, index);
210212
} else {
211213
u8 out, synth;
212214
u32 f;
@@ -220,6 +222,7 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
220222
synth = zl3073x_dev_out_synth_get(zldev, out);
221223
f = 2 * zl3073x_dev_synth_freq_get(zldev, synth);
222224
props->dpll_props.phase_gran = f ? div_u64(PSEC_PER_SEC, f) : 1;
225+
curr_freq = zl3073x_dev_output_pin_freq_get(zldev, index);
223226
}
224227

225228
props->dpll_props.phase_range.min = S32_MIN;
@@ -230,7 +233,7 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
230233
/* Get firmware node for the given pin */
231234
rc = zl3073x_prop_pin_fwnode_get(zldev, props, dir, index);
232235
if (rc)
233-
return props; /* Return if it does not exist */
236+
goto skip_fwnode_props;
234237

235238
/* Look for label property and store the value as board label */
236239
fwnode_property_read_string(props->fwnode, "label",
@@ -264,9 +267,10 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
264267
/* Read supported frequencies property if it is specified */
265268
num_freqs = fwnode_property_count_u64(props->fwnode,
266269
"supported-frequencies-hz");
267-
if (num_freqs <= 0)
268-
/* Return if the property does not exist or number is 0 */
269-
return props;
270+
if (num_freqs <= 0) {
271+
num_freqs = 0;
272+
goto skip_fwnode_props;
273+
}
270274

271275
/* The firmware node specifies list of supported frequencies while
272276
* DPLL core pin properties requires list of frequency ranges.
@@ -283,19 +287,25 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
283287
"supported-frequencies-hz", freqs,
284288
num_freqs);
285289

286-
/* Allocate frequency ranges list and fill it */
287-
ranges = kcalloc(num_freqs, sizeof(*ranges), GFP_KERNEL);
290+
skip_fwnode_props:
291+
/* Allocate frequency ranges list - extra slot for current frequency */
292+
ranges = kcalloc(num_freqs + 1, sizeof(*ranges), GFP_KERNEL);
288293
if (!ranges) {
289294
rc = -ENOMEM;
290295
goto err_alloc_ranges;
291296
}
292297

293-
/* Convert list of frequencies to list of frequency ranges but
294-
* filter-out frequencies that are not representable by device
298+
/* Start with current frequency at index 0 */
299+
ranges[0] = (struct dpll_pin_frequency)DPLL_PIN_FREQUENCY(curr_freq);
300+
301+
/* Add frequencies from firmware node, skipping current frequency
302+
* and filtering out frequencies not representable by device
295303
*/
296-
for (i = 0, j = 0; i < num_freqs; i++) {
304+
for (i = 0, j = 1; i < num_freqs; i++) {
297305
struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]);
298306

307+
if (freqs[i] == curr_freq)
308+
continue;
299309
if (zl3073x_pin_check_freq(zldev, dir, index, freqs[i])) {
300310
ranges[j] = freq;
301311
j++;

0 commit comments

Comments
 (0)