Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+69 -49
+30
drivers/dpll/zl3073x/core.h
··· 302 302 } 303 303 304 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 + 334 + /** 305 335 * zl3073x_dev_out_is_diff - check if the given output is differential 306 336 * @zldev: pointer to zl3073x device 307 337 * @index: output index
+1 -38
drivers/dpll/zl3073x/dpll.c
··· 916 916 struct netlink_ext_ack *extack) 917 917 { 918 918 struct zl3073x_dpll *zldpll = dpll_priv; 919 - struct zl3073x_dev *zldev = zldpll->dev; 920 919 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; 925 920 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); 959 922 960 923 return 0; 961 924 }
+17
drivers/dpll/zl3073x/out.h
··· 80 80 } 81 81 82 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 + 99 + /** 83 100 * zl3073x_out_synth_get - get synth connected to given output 84 101 * @out: pointer to out state 85 102 *
+21 -11
drivers/dpll/zl3073x/prop.c
··· 193 193 { 194 194 struct dpll_pin_frequency *ranges; 195 195 struct zl3073x_pin_props *props; 196 - int i, j, num_freqs, rc; 196 + int i, j, num_freqs = 0, rc; 197 + u64 *freqs = NULL; 197 198 const char *type; 198 - u64 *freqs; 199 + u32 curr_freq; 199 200 200 201 props = kzalloc(sizeof(*props), GFP_KERNEL); 201 202 if (!props) ··· 208 207 props->dpll_props.capabilities = 209 208 DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE | 210 209 DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE; 210 + curr_freq = zl3073x_dev_ref_freq_get(zldev, index); 211 211 } else { 212 212 u8 out, synth; 213 213 u32 f; ··· 222 220 synth = zl3073x_dev_out_synth_get(zldev, out); 223 221 f = 2 * zl3073x_dev_synth_freq_get(zldev, synth); 224 222 props->dpll_props.phase_gran = f ? div_u64(PSEC_PER_SEC, f) : 1; 223 + curr_freq = zl3073x_dev_output_pin_freq_get(zldev, index); 225 224 } 226 225 227 226 props->dpll_props.phase_range.min = S32_MIN; ··· 233 230 /* Get firmware node for the given pin */ 234 231 rc = zl3073x_prop_pin_fwnode_get(zldev, props, dir, index); 235 232 if (rc) 236 - return props; /* Return if it does not exist */ 233 + goto skip_fwnode_props; 237 234 238 235 /* Look for label property and store the value as board label */ 239 236 fwnode_property_read_string(props->fwnode, "label", ··· 267 264 /* Read supported frequencies property if it is specified */ 268 265 num_freqs = fwnode_property_count_u64(props->fwnode, 269 266 "supported-frequencies-hz"); 270 - if (num_freqs <= 0) 271 - /* Return if the property does not exist or number is 0 */ 272 - return props; 267 + if (num_freqs <= 0) { 268 + num_freqs = 0; 269 + goto skip_fwnode_props; 270 + } 273 271 274 272 /* The firmware node specifies list of supported frequencies while 275 273 * DPLL core pin properties requires list of frequency ranges. ··· 287 283 "supported-frequencies-hz", freqs, 288 284 num_freqs); 289 285 290 - /* Allocate frequency ranges list and fill it */ 291 - ranges = kcalloc(num_freqs, sizeof(*ranges), GFP_KERNEL); 286 + skip_fwnode_props: 287 + /* Allocate frequency ranges list - extra slot for current frequency */ 288 + ranges = kcalloc(num_freqs + 1, sizeof(*ranges), GFP_KERNEL); 292 289 if (!ranges) { 293 290 rc = -ENOMEM; 294 291 goto err_alloc_ranges; 295 292 } 296 293 297 - /* Convert list of frequencies to list of frequency ranges but 298 - * filter-out frequencies that are not representable by device 294 + /* Start with current frequency at index 0 */ 295 + ranges[0] = (struct dpll_pin_frequency)DPLL_PIN_FREQUENCY(curr_freq); 296 + 297 + /* Add frequencies from firmware node, skipping current frequency 298 + * and filtering out frequencies not representable by device 299 299 */ 300 - for (i = 0, j = 0; i < num_freqs; i++) { 300 + for (i = 0, j = 1; i < num_freqs; i++) { 301 301 struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]); 302 302 303 + if (freqs[i] == curr_freq) 304 + continue; 303 305 if (zl3073x_pin_check_freq(zldev, dir, index, freqs[i])) { 304 306 ranges[j] = freq; 305 307 j++;