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-add-support-for-phase-adjustment-granularity'

Ivan Vecera says:

====================
dpll: Add support for phase adjustment granularity

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
====================

Link: https://patch.msgid.link/20251029153207.178448-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+65 -61
+20 -16
Documentation/driver-api/dpll.rst
··· 198 198 ================================== ====================================== 199 199 200 200 Device may also provide ability to adjust a signal phase on a pin. 201 - If pin phase adjustment is supported, minimal and maximal values that pin 202 - handle shall be provide to the user on ``DPLL_CMD_PIN_GET`` respond 203 - with ``DPLL_A_PIN_PHASE_ADJUST_MIN`` and ``DPLL_A_PIN_PHASE_ADJUST_MAX`` 201 + If pin phase adjustment is supported, minimal and maximal values and 202 + granularity that pin handle shall be provided to the user on 203 + ``DPLL_CMD_PIN_GET`` respond with ``DPLL_A_PIN_PHASE_ADJUST_MIN``, 204 + ``DPLL_A_PIN_PHASE_ADJUST_MAX`` and ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` 204 205 attributes. Configured phase adjust value is provided with 205 206 ``DPLL_A_PIN_PHASE_ADJUST`` attribute of a pin, and value change can be 206 207 requested with the same attribute with ``DPLL_CMD_PIN_SET`` command. 207 208 208 - =============================== ====================================== 209 - ``DPLL_A_PIN_ID`` configured pin id 210 - ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment 211 - ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment 212 - ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase 213 - adjustment on parent dpll device 214 - ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting 215 - configuration on given parent dpll 216 - device 217 - ``DPLL_A_PIN_PARENT_ID`` parent dpll device id 218 - ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference 219 - between a pin and parent dpll device 220 - =============================== ====================================== 209 + ================================ ========================================== 210 + ``DPLL_A_PIN_ID`` configured pin id 211 + ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase adjustment value 212 + ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase adjustment 213 + ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase adjustment 214 + ``DPLL_A_PIN_PHASE_ADJUST`` attr configured value of phase 215 + adjustment on parent dpll device 216 + ``DPLL_A_PIN_PARENT_DEVICE`` nested attribute for requesting 217 + configuration on given parent dpll 218 + device 219 + ``DPLL_A_PIN_PARENT_ID`` parent dpll device id 220 + ``DPLL_A_PIN_PHASE_OFFSET`` attr measured phase difference 221 + between a pin and parent dpll device 222 + ================================ ========================================== 221 223 222 224 All phase related values are provided in pico seconds, which represents 223 225 time difference between signals phase. The negative value means that ··· 386 384 frequencies 387 385 ``DPLL_A_PIN_ANY_FREQUENCY_MIN`` attr minimum value of frequency 388 386 ``DPLL_A_PIN_ANY_FREQUENCY_MAX`` attr maximum value of frequency 387 + ``DPLL_A_PIN_PHASE_ADJUST_GRAN`` attr granularity of phase 388 + adjustment value 389 389 ``DPLL_A_PIN_PHASE_ADJUST_MIN`` attr minimum value of phase 390 390 adjustment 391 391 ``DPLL_A_PIN_PHASE_ADJUST_MAX`` attr maximum value of phase
+7
Documentation/netlink/specs/dpll.yaml
··· 440 440 doc: | 441 441 Capable pin provides list of pins that can be bound to create a 442 442 reference-sync pin pair. 443 + - 444 + name: phase-adjust-gran 445 + type: u32 446 + doc: | 447 + Granularity of phase adjustment, in picoseconds. The value of 448 + phase adjustment must be a multiple of this granularity. 443 449 444 450 - 445 451 name: pin-parent-device ··· 622 616 - capabilities 623 617 - parent-device 624 618 - parent-pin 619 + - phase-adjust-gran 625 620 - phase-adjust-min 626 621 - phase-adjust-max 627 622 - phase-adjust
+11 -1
drivers/dpll/dpll_netlink.c
··· 637 637 ret = dpll_msg_add_pin_freq(msg, pin, ref, extack); 638 638 if (ret) 639 639 return ret; 640 + if (prop->phase_gran && 641 + nla_put_u32(msg, DPLL_A_PIN_PHASE_ADJUST_GRAN, 642 + prop->phase_gran)) 643 + return -EMSGSIZE; 640 644 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN, 641 645 prop->phase_range.min)) 642 646 return -EMSGSIZE; ··· 1265 1261 if (phase_adj > pin->prop.phase_range.max || 1266 1262 phase_adj < pin->prop.phase_range.min) { 1267 1263 NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr, 1268 - "phase adjust value not supported"); 1264 + "phase adjust value of out range"); 1265 + return -EINVAL; 1266 + } 1267 + if (pin->prop.phase_gran && phase_adj % (s32)pin->prop.phase_gran) { 1268 + NL_SET_ERR_MSG_ATTR_FMT(extack, phase_adj_attr, 1269 + "phase adjust value not multiple of %u", 1270 + pin->prop.phase_gran); 1269 1271 return -EINVAL; 1270 1272 } 1271 1273
+14 -44
drivers/dpll/zl3073x/dpll.c
··· 35 35 * @prio: pin priority <0, 14> 36 36 * @selectable: pin is selectable in automatic mode 37 37 * @esync_control: embedded sync is controllable 38 + * @phase_gran: phase adjustment granularity 38 39 * @pin_state: last saved pin state 39 40 * @phase_offset: last saved pin phase offset 40 41 * @freq_offset: last saved fractional frequency offset ··· 50 49 u8 prio; 51 50 bool selectable; 52 51 bool esync_control; 52 + s32 phase_gran; 53 53 enum dpll_pin_state pin_state; 54 54 s64 phase_offset; 55 55 s64 freq_offset; ··· 1390 1388 struct zl3073x_dpll *zldpll = dpll_priv; 1391 1389 struct zl3073x_dev *zldev = zldpll->dev; 1392 1390 struct zl3073x_dpll_pin *pin = pin_priv; 1393 - u32 synth_freq; 1394 1391 s32 phase_comp; 1395 - u8 out, synth; 1392 + u8 out; 1396 1393 int rc; 1397 - 1398 - out = zl3073x_output_pin_out_get(pin->id); 1399 - synth = zl3073x_out_synth_get(zldev, out); 1400 - synth_freq = zl3073x_synth_freq_get(zldev, synth); 1401 - 1402 - /* Check synth freq for zero */ 1403 - if (!synth_freq) { 1404 - dev_err(zldev->dev, "Got zero synth frequency for output %u\n", 1405 - out); 1406 - return -EINVAL; 1407 - } 1408 1394 1409 1395 guard(mutex)(&zldev->multiop_lock); 1410 1396 1411 1397 /* Read output configuration */ 1398 + out = zl3073x_output_pin_out_get(pin->id); 1412 1399 rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 1413 1400 ZL_REG_OUTPUT_MB_MASK, BIT(out)); 1414 1401 if (rc) ··· 1408 1417 if (rc) 1409 1418 return rc; 1410 1419 1411 - /* Value in register is expressed in half synth clock cycles */ 1412 - phase_comp *= (int)div_u64(PSEC_PER_SEC, 2 * synth_freq); 1413 - 1414 - /* Reverse two's complement negation applied during 'set' */ 1415 - *phase_adjust = -phase_comp; 1420 + /* Convert value to ps and reverse two's complement negation applied 1421 + * during 'set' 1422 + */ 1423 + *phase_adjust = -phase_comp * pin->phase_gran; 1416 1424 1417 1425 return rc; 1418 1426 } ··· 1427 1437 struct zl3073x_dpll *zldpll = dpll_priv; 1428 1438 struct zl3073x_dev *zldev = zldpll->dev; 1429 1439 struct zl3073x_dpll_pin *pin = pin_priv; 1430 - int half_synth_cycle; 1431 - u32 synth_freq; 1432 - u8 out, synth; 1440 + u8 out; 1433 1441 int rc; 1434 1442 1435 - /* Get attached synth */ 1436 - out = zl3073x_output_pin_out_get(pin->id); 1437 - synth = zl3073x_out_synth_get(zldev, out); 1438 - 1439 - /* Get synth's frequency */ 1440 - synth_freq = zl3073x_synth_freq_get(zldev, synth); 1441 - 1442 - /* Value in register is expressed in half synth clock cycles so 1443 - * the given phase adjustment a multiple of half synth clock. 1444 - */ 1445 - half_synth_cycle = (int)div_u64(PSEC_PER_SEC, 2 * synth_freq); 1446 - 1447 - if ((phase_adjust % half_synth_cycle) != 0) { 1448 - NL_SET_ERR_MSG_FMT(extack, 1449 - "Phase adjustment value has to be multiple of %d", 1450 - half_synth_cycle); 1451 - return -EINVAL; 1452 - } 1453 - phase_adjust /= half_synth_cycle; 1454 - 1455 1443 /* The value in the register is stored as two's complement negation 1456 - * of requested value. 1444 + * of requested value and expressed in half synth clock cycles. 1457 1445 */ 1458 - phase_adjust = -phase_adjust; 1446 + phase_adjust = -phase_adjust / pin->phase_gran; 1459 1447 1460 1448 guard(mutex)(&zldev->multiop_lock); 1461 1449 1462 1450 /* Read output configuration */ 1451 + out = zl3073x_output_pin_out_get(pin->id); 1463 1452 rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD, 1464 1453 ZL_REG_OUTPUT_MB_MASK, BIT(out)); 1465 1454 if (rc) ··· 1727 1758 if (IS_ERR(props)) 1728 1759 return PTR_ERR(props); 1729 1760 1730 - /* Save package label & esync capability */ 1761 + /* Save package label, esync capability and phase adjust granularity */ 1731 1762 strscpy(pin->label, props->package_label); 1732 1763 pin->esync_control = props->esync_control; 1764 + pin->phase_gran = props->dpll_props.phase_gran; 1733 1765 1734 1766 if (zl3073x_dpll_is_input_pin(pin)) { 1735 1767 rc = zl3073x_dpll_ref_prio_get(pin, &pin->prio);
+11
drivers/dpll/zl3073x/prop.c
··· 208 208 DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE | 209 209 DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE; 210 210 } else { 211 + u8 out, synth; 212 + u32 f; 213 + 211 214 props->dpll_props.type = DPLL_PIN_TYPE_GNSS; 215 + 216 + /* The output pin phase adjustment granularity equals half of 217 + * the synth frequency count. 218 + */ 219 + out = zl3073x_output_pin_out_get(index); 220 + synth = zl3073x_out_synth_get(zldev, out); 221 + f = 2 * zl3073x_synth_freq_get(zldev, synth); 222 + props->dpll_props.phase_gran = f ? div_u64(PSEC_PER_SEC, f) : 1; 212 223 } 213 224 214 225 props->dpll_props.phase_range.min = S32_MIN;
+1
include/linux/dpll.h
··· 163 163 u32 freq_supported_num; 164 164 struct dpll_pin_frequency *freq_supported; 165 165 struct dpll_pin_phase_adjust_range phase_range; 166 + u32 phase_gran; 166 167 }; 167 168 168 169 #if IS_ENABLED(CONFIG_DPLL)
+1
include/uapi/linux/dpll.h
··· 251 251 DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED, 252 252 DPLL_A_PIN_ESYNC_PULSE, 253 253 DPLL_A_PIN_REFERENCE_SYNC, 254 + DPLL_A_PIN_PHASE_ADJUST_GRAN, 254 255 255 256 __DPLL_A_PIN_MAX, 256 257 DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)