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-reference-sync-feature'

Arkadiusz Kubalewski says:

====================
dpll: add Reference SYNC feature

The device may support the Reference SYNC feature, which allows the
combination of two inputs into a input pair. In this configuration,
clock signals from both inputs are used to synchronize the DPLL device.
The higher frequency signal is utilized for the loop bandwidth of the DPLL,
while the lower frequency signal is used to syntonize the output signal of
the DPLL device. This feature enables the provision of a high-quality loop
bandwidth signal from an external source.

A capable input provides a list of inputs that can be bound with to create
Reference SYNC. To control this feature, the user must request a
desired state for a target pin: use ``DPLL_PIN_STATE_CONNECTED`` to
enable or ``DPLL_PIN_STATE_DISCONNECTED`` to disable the feature. An input
pin can be bound to only one other pin at any given time.

Verify pins bind state/capabilities:
$ ./tools/net/ynl/pyynl/cli.py \
--spec Documentation/netlink/specs/dpll.yaml \
--do pin-get \
--json '{"id":0}'
{'board-label': 'CVL-SDP22',
'id': 0,
[...]
'reference-sync': [{'id': 1, 'state': 'disconnected'}],
[...]}

Bind the pins by setting connected state between them:
$ ./tools/net/ynl/pyynl/cli.py \
--spec Documentation/netlink/specs/dpll.yaml \
--do pin-set \
--json '{"id":0, "reference-sync":{"id":1, "state":"connected"}}'

Verify pins bind state:
$ ./tools/net/ynl/pyynl/cli.py \
--spec Documentation/netlink/specs/dpll.yaml \
--do pin-get \
--json '{"id":0}'
{'board-label': 'CVL-SDP22',
'id': 0,
[...]
'reference-sync': [{'id': 1, 'state': 'connected'}],
[...]}

Unbind the pins by setting disconnected state between them:
$ ./tools/net/ynl/pyynl/cli.py \
--spec Documentation/netlink/specs/dpll.yaml \
--do pin-set \
--json '{"id":0, "reference-sync":{"id":1, "state":"disconnected"}}'
====================

Link: https://patch.msgid.link/20250626135219.1769350-1-arkadiusz.kubalewski@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+575 -21
+25
Documentation/driver-api/dpll.rst
··· 253 253 ``DPLL_A_PIN_ESYNC_PULSE`` pulse type of Embedded SYNC 254 254 ========================================= ================================= 255 255 256 + Reference SYNC 257 + ============== 258 + 259 + The device may support the Reference SYNC feature, which allows the combination 260 + of two inputs into a input pair. In this configuration, clock signals 261 + from both inputs are used to synchronize the DPLL device. The higher frequency 262 + signal is utilized for the loop bandwidth of the DPLL, while the lower frequency 263 + signal is used to syntonize the output signal of the DPLL device. This feature 264 + enables the provision of a high-quality loop bandwidth signal from an external 265 + source. 266 + 267 + A capable input provides a list of inputs that can be bound with to create 268 + Reference SYNC. To control this feature, the user must request a desired 269 + state for a target pin: use ``DPLL_PIN_STATE_CONNECTED`` to enable or 270 + ``DPLL_PIN_STATE_DISCONNECTED`` to disable the feature. An input pin can be 271 + bound to only one other pin at any given time. 272 + 273 + ============================== ========================================== 274 + ``DPLL_A_PIN_REFERENCE_SYNC`` nested attribute for providing info or 275 + requesting configuration of the Reference 276 + SYNC feature 277 + ``DPLL_A_PIN_ID`` target pin id for Reference SYNC feature 278 + ``DPLL_A_PIN_STATE`` state of Reference SYNC connection 279 + ============================== ========================================== 280 + 256 281 Configuration commands group 257 282 ============================ 258 283
+19
Documentation/netlink/specs/dpll.yaml
··· 428 428 doc: | 429 429 A ratio of high to low state of a SYNC signal pulse embedded 430 430 into base clock frequency. Value is in percents. 431 + - 432 + name: reference-sync 433 + type: nest 434 + multi-attr: true 435 + nested-attributes: reference-sync 436 + doc: | 437 + Capable pin provides list of pins that can be bound to create a 438 + reference-sync pin pair. 439 + 431 440 - 432 441 name: pin-parent-device 433 442 subset-of: pin ··· 467 458 name: frequency-min 468 459 - 469 460 name: frequency-max 461 + - 462 + name: reference-sync 463 + subset-of: pin 464 + attributes: 465 + - 466 + name: id 467 + - 468 + name: state 470 469 471 470 operations: 472 471 enum-name: dpll_cmd ··· 615 598 - esync-frequency 616 599 - esync-frequency-supported 617 600 - esync-pulse 601 + - reference-sync 618 602 619 603 dump: 620 604 request: ··· 643 625 - parent-pin 644 626 - phase-adjust 645 627 - esync-frequency 628 + - reference-sync 646 629 - 647 630 name: pin-create-ntf 648 631 doc: Notification about pin appearing
+45
drivers/dpll/dpll_core.c
··· 506 506 refcount_set(&pin->refcount, 1); 507 507 xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); 508 508 xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); 509 + xa_init_flags(&pin->ref_sync_pins, XA_FLAGS_ALLOC); 509 510 ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b, 510 511 &dpll_pin_xa_id, GFP_KERNEL); 511 512 if (ret < 0) ··· 515 514 err_xa_alloc: 516 515 xa_destroy(&pin->dpll_refs); 517 516 xa_destroy(&pin->parent_refs); 517 + xa_destroy(&pin->ref_sync_pins); 518 518 dpll_pin_prop_free(&pin->prop); 519 519 err_pin_prop: 520 520 kfree(pin); ··· 597 595 xa_erase(&dpll_pin_xa, pin->id); 598 596 xa_destroy(&pin->dpll_refs); 599 597 xa_destroy(&pin->parent_refs); 598 + xa_destroy(&pin->ref_sync_pins); 600 599 dpll_pin_prop_free(&pin->prop); 601 600 kfree_rcu(pin, rcu); 602 601 } ··· 662 659 } 663 660 EXPORT_SYMBOL_GPL(dpll_pin_register); 664 661 662 + static void dpll_pin_ref_sync_pair_del(u32 ref_sync_pin_id) 663 + { 664 + struct dpll_pin *pin, *ref_sync_pin; 665 + unsigned long i; 666 + 667 + xa_for_each(&dpll_pin_xa, i, pin) { 668 + ref_sync_pin = xa_load(&pin->ref_sync_pins, ref_sync_pin_id); 669 + if (ref_sync_pin) { 670 + xa_erase(&pin->ref_sync_pins, ref_sync_pin_id); 671 + __dpll_pin_change_ntf(pin); 672 + } 673 + } 674 + } 675 + 665 676 static void 666 677 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 667 678 const struct dpll_pin_ops *ops, void *priv, void *cookie) 668 679 { 669 680 ASSERT_DPLL_PIN_REGISTERED(pin); 681 + dpll_pin_ref_sync_pair_del(pin->id); 670 682 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); 671 683 dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); 672 684 if (xa_empty(&pin->dpll_refs)) ··· 800 782 mutex_unlock(&dpll_lock); 801 783 } 802 784 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister); 785 + 786 + /** 787 + * dpll_pin_ref_sync_pair_add - create a reference sync signal pin pair 788 + * @pin: pin which produces the base frequency 789 + * @ref_sync_pin: pin which produces the sync signal 790 + * 791 + * Once pins are paired, the user-space configuration of reference sync pair 792 + * is possible. 793 + * Context: Acquires a lock (dpll_lock) 794 + * Return: 795 + * * 0 on success 796 + * * negative - error value 797 + */ 798 + int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin, 799 + struct dpll_pin *ref_sync_pin) 800 + { 801 + int ret; 802 + 803 + mutex_lock(&dpll_lock); 804 + ret = xa_insert(&pin->ref_sync_pins, ref_sync_pin->id, 805 + ref_sync_pin, GFP_KERNEL); 806 + __dpll_pin_change_ntf(pin); 807 + mutex_unlock(&dpll_lock); 808 + 809 + return ret; 810 + } 811 + EXPORT_SYMBOL_GPL(dpll_pin_ref_sync_pair_add); 803 812 804 813 static struct dpll_device_registration * 805 814 dpll_device_registration_first(struct dpll_device *dpll)
+2
drivers/dpll/dpll_core.h
··· 44 44 * @module: module of creator 45 45 * @dpll_refs: hold referencees to dplls pin was registered with 46 46 * @parent_refs: hold references to parent pins pin was registered with 47 + * @ref_sync_pins: hold references to pins for Reference SYNC feature 47 48 * @prop: pin properties copied from the registerer 48 49 * @refcount: refcount 49 50 * @rcu: rcu_head for kfree_rcu() ··· 56 55 struct module *module; 57 56 struct xarray dpll_refs; 58 57 struct xarray parent_refs; 58 + struct xarray ref_sync_pins; 59 59 struct dpll_pin_properties prop; 60 60 refcount_t refcount; 61 61 struct rcu_head rcu;
+171 -19
drivers/dpll/dpll_netlink.c
··· 48 48 return 0; 49 49 } 50 50 51 + static bool dpll_pin_available(struct dpll_pin *pin) 52 + { 53 + struct dpll_pin_ref *par_ref; 54 + unsigned long i; 55 + 56 + if (!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED)) 57 + return false; 58 + xa_for_each(&pin->parent_refs, i, par_ref) 59 + if (xa_get_mark(&dpll_pin_xa, par_ref->pin->id, 60 + DPLL_REGISTERED)) 61 + return true; 62 + xa_for_each(&pin->dpll_refs, i, par_ref) 63 + if (xa_get_mark(&dpll_device_xa, par_ref->dpll->id, 64 + DPLL_REGISTERED)) 65 + return true; 66 + return false; 67 + } 68 + 51 69 /** 52 70 * dpll_msg_add_pin_handle - attach pin handle attribute to a given message 53 71 * @msg: pointer to sk_buff message to attach a pin handle ··· 446 428 return -EMSGSIZE; 447 429 } 448 430 431 + static int 432 + dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin, 433 + struct dpll_pin_ref *ref, 434 + struct netlink_ext_ack *extack) 435 + { 436 + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 437 + struct dpll_device *dpll = ref->dpll; 438 + void *pin_priv, *ref_sync_pin_priv; 439 + struct dpll_pin *ref_sync_pin; 440 + enum dpll_pin_state state; 441 + struct nlattr *nest; 442 + unsigned long index; 443 + int ret; 444 + 445 + pin_priv = dpll_pin_on_dpll_priv(dpll, pin); 446 + xa_for_each(&pin->ref_sync_pins, index, ref_sync_pin) { 447 + if (!dpll_pin_available(ref_sync_pin)) 448 + continue; 449 + ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin); 450 + if (WARN_ON(!ops->ref_sync_get)) 451 + return -EOPNOTSUPP; 452 + ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin, 453 + ref_sync_pin_priv, &state, extack); 454 + if (ret) 455 + return ret; 456 + nest = nla_nest_start(msg, DPLL_A_PIN_REFERENCE_SYNC); 457 + if (!nest) 458 + return -EMSGSIZE; 459 + if (nla_put_s32(msg, DPLL_A_PIN_ID, ref_sync_pin->id)) 460 + goto nest_cancel; 461 + if (nla_put_s32(msg, DPLL_A_PIN_STATE, state)) 462 + goto nest_cancel; 463 + nla_nest_end(msg, nest); 464 + } 465 + return 0; 466 + 467 + nest_cancel: 468 + nla_nest_cancel(msg, nest); 469 + return -EMSGSIZE; 470 + } 471 + 449 472 static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq) 450 473 { 451 474 int fs; ··· 631 572 ret = dpll_msg_add_pin_esync(msg, pin, ref, extack); 632 573 if (ret) 633 574 return ret; 575 + if (!xa_empty(&pin->ref_sync_pins)) 576 + ret = dpll_msg_add_pin_ref_sync(msg, pin, ref, extack); 577 + if (ret) 578 + return ret; 634 579 if (xa_empty(&pin->parent_refs)) 635 580 ret = dpll_msg_add_pin_dplls(msg, pin, extack); 636 581 else ··· 728 665 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll); 729 666 } 730 667 731 - static bool dpll_pin_available(struct dpll_pin *pin) 732 - { 733 - struct dpll_pin_ref *par_ref; 734 - unsigned long i; 735 - 736 - if (!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED)) 737 - return false; 738 - xa_for_each(&pin->parent_refs, i, par_ref) 739 - if (xa_get_mark(&dpll_pin_xa, par_ref->pin->id, 740 - DPLL_REGISTERED)) 741 - return true; 742 - xa_for_each(&pin->dpll_refs, i, par_ref) 743 - if (xa_get_mark(&dpll_device_xa, par_ref->dpll->id, 744 - DPLL_REGISTERED)) 745 - return true; 746 - return false; 747 - } 748 - 749 668 /** 750 669 * dpll_device_change_ntf - notify that the dpll device has been changed 751 670 * @dpll: registered dpll pointer ··· 790 745 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin); 791 746 } 792 747 793 - static int __dpll_pin_change_ntf(struct dpll_pin *pin) 748 + int __dpll_pin_change_ntf(struct dpll_pin *pin) 794 749 { 795 750 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin); 796 751 } ··· 978 933 NL_SET_ERR_MSG(extack, "set embedded sync frequency rollback failed"); 979 934 } 980 935 return ret; 936 + } 937 + 938 + static int 939 + dpll_pin_ref_sync_state_set(struct dpll_pin *pin, 940 + unsigned long ref_sync_pin_idx, 941 + const enum dpll_pin_state state, 942 + struct netlink_ext_ack *extack) 943 + 944 + { 945 + struct dpll_pin_ref *ref, *failed; 946 + const struct dpll_pin_ops *ops; 947 + enum dpll_pin_state old_state; 948 + struct dpll_pin *ref_sync_pin; 949 + struct dpll_device *dpll; 950 + unsigned long i; 951 + int ret; 952 + 953 + ref_sync_pin = xa_find(&pin->ref_sync_pins, &ref_sync_pin_idx, 954 + ULONG_MAX, XA_PRESENT); 955 + if (!ref_sync_pin) { 956 + NL_SET_ERR_MSG(extack, "reference sync pin not found"); 957 + return -EINVAL; 958 + } 959 + if (!dpll_pin_available(ref_sync_pin)) { 960 + NL_SET_ERR_MSG(extack, "reference sync pin not available"); 961 + return -EINVAL; 962 + } 963 + ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); 964 + ASSERT_NOT_NULL(ref); 965 + ops = dpll_pin_ops(ref); 966 + if (!ops->ref_sync_set || !ops->ref_sync_get) { 967 + NL_SET_ERR_MSG(extack, "reference sync not supported by this pin"); 968 + return -EOPNOTSUPP; 969 + } 970 + dpll = ref->dpll; 971 + ret = ops->ref_sync_get(pin, dpll_pin_on_dpll_priv(dpll, pin), 972 + ref_sync_pin, 973 + dpll_pin_on_dpll_priv(dpll, ref_sync_pin), 974 + &old_state, extack); 975 + if (ret) { 976 + NL_SET_ERR_MSG(extack, "unable to get old reference sync state"); 977 + return ret; 978 + } 979 + if (state == old_state) 980 + return 0; 981 + xa_for_each(&pin->dpll_refs, i, ref) { 982 + ops = dpll_pin_ops(ref); 983 + dpll = ref->dpll; 984 + ret = ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin), 985 + ref_sync_pin, 986 + dpll_pin_on_dpll_priv(dpll, 987 + ref_sync_pin), 988 + state, extack); 989 + if (ret) { 990 + failed = ref; 991 + NL_SET_ERR_MSG_FMT(extack, "reference sync set failed for dpll_id:%u", 992 + dpll->id); 993 + goto rollback; 994 + } 995 + } 996 + __dpll_pin_change_ntf(pin); 997 + 998 + return 0; 999 + 1000 + rollback: 1001 + xa_for_each(&pin->dpll_refs, i, ref) { 1002 + if (ref == failed) 1003 + break; 1004 + ops = dpll_pin_ops(ref); 1005 + dpll = ref->dpll; 1006 + if (ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin), 1007 + ref_sync_pin, 1008 + dpll_pin_on_dpll_priv(dpll, ref_sync_pin), 1009 + old_state, extack)) 1010 + NL_SET_ERR_MSG(extack, "set reference sync rollback failed"); 1011 + } 1012 + return ret; 1013 + } 1014 + 1015 + static int 1016 + dpll_pin_ref_sync_set(struct dpll_pin *pin, struct nlattr *nest, 1017 + struct netlink_ext_ack *extack) 1018 + { 1019 + struct nlattr *tb[DPLL_A_PIN_MAX + 1]; 1020 + enum dpll_pin_state state; 1021 + u32 sync_pin_id; 1022 + 1023 + nla_parse_nested(tb, DPLL_A_PIN_MAX, nest, 1024 + dpll_reference_sync_nl_policy, extack); 1025 + if (!tb[DPLL_A_PIN_ID]) { 1026 + NL_SET_ERR_MSG(extack, "sync pin id expected"); 1027 + return -EINVAL; 1028 + } 1029 + sync_pin_id = nla_get_u32(tb[DPLL_A_PIN_ID]); 1030 + 1031 + if (!tb[DPLL_A_PIN_STATE]) { 1032 + NL_SET_ERR_MSG(extack, "sync pin state expected"); 1033 + return -EINVAL; 1034 + } 1035 + state = nla_get_u32(tb[DPLL_A_PIN_STATE]); 1036 + 1037 + return dpll_pin_ref_sync_state_set(pin, sync_pin_id, state, extack); 981 1038 } 982 1039 983 1040 static int ··· 1385 1238 break; 1386 1239 case DPLL_A_PIN_ESYNC_FREQUENCY: 1387 1240 ret = dpll_pin_esync_set(pin, a, info->extack); 1241 + if (ret) 1242 + return ret; 1243 + break; 1244 + case DPLL_A_PIN_REFERENCE_SYNC: 1245 + ret = dpll_pin_ref_sync_set(pin, a, info->extack); 1388 1246 if (ret) 1389 1247 return ret; 1390 1248 break;
+2
drivers/dpll/dpll_netlink.h
··· 11 11 int dpll_pin_create_ntf(struct dpll_pin *pin); 12 12 13 13 int dpll_pin_delete_ntf(struct dpll_pin *pin); 14 + 15 + int __dpll_pin_change_ntf(struct dpll_pin *pin);
+8 -2
drivers/dpll/dpll_nl.c
··· 24 24 [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3), 25 25 }; 26 26 27 + const struct nla_policy dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1] = { 28 + [DPLL_A_PIN_ID] = { .type = NLA_U32, }, 29 + [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3), 30 + }; 31 + 27 32 /* DPLL_CMD_DEVICE_ID_GET - do */ 28 33 static const struct nla_policy dpll_device_id_get_nl_policy[DPLL_A_TYPE + 1] = { 29 34 [DPLL_A_MODULE_NAME] = { .type = NLA_NUL_STRING, }, ··· 68 63 }; 69 64 70 65 /* DPLL_CMD_PIN_SET - do */ 71 - static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_ESYNC_FREQUENCY + 1] = { 66 + static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_REFERENCE_SYNC + 1] = { 72 67 [DPLL_A_PIN_ID] = { .type = NLA_U32, }, 73 68 [DPLL_A_PIN_FREQUENCY] = { .type = NLA_U64, }, 74 69 [DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2), ··· 78 73 [DPLL_A_PIN_PARENT_PIN] = NLA_POLICY_NESTED(dpll_pin_parent_pin_nl_policy), 79 74 [DPLL_A_PIN_PHASE_ADJUST] = { .type = NLA_S32, }, 80 75 [DPLL_A_PIN_ESYNC_FREQUENCY] = { .type = NLA_U64, }, 76 + [DPLL_A_PIN_REFERENCE_SYNC] = NLA_POLICY_NESTED(dpll_reference_sync_nl_policy), 81 77 }; 82 78 83 79 /* Ops table for dpll */ ··· 146 140 .doit = dpll_nl_pin_set_doit, 147 141 .post_doit = dpll_pin_post_doit, 148 142 .policy = dpll_pin_set_nl_policy, 149 - .maxattr = DPLL_A_PIN_ESYNC_FREQUENCY, 143 + .maxattr = DPLL_A_PIN_REFERENCE_SYNC, 150 144 .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, 151 145 }, 152 146 };
+1
drivers/dpll/dpll_nl.h
··· 14 14 /* Common nested types */ 15 15 extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1]; 16 16 extern const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1]; 17 + extern const struct nla_policy dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1]; 17 18 18 19 int dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 19 20 struct genl_info *info);
+2
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 2304 2304 u8 rsvd[3]; 2305 2305 }; 2306 2306 2307 + #define ICE_AQC_CGU_IN_CFG_FLG2_REFSYNC_EN BIT(7) 2308 + 2307 2309 /* Set CGU input config (direct 0x0C62) */ 2308 2310 struct ice_aqc_set_cgu_input_config { 2309 2311 u8 input_idx;
+284
drivers/net/ethernet/intel/ice/ice_dpll.c
··· 36 36 #define ICE_DPLL_PIN_SW_2_OUTPUT_ABS_IDX \ 37 37 (ICE_DPLL_PIN_SW_OUTPUT_ABS(ICE_DPLL_PIN_SW_2_IDX)) 38 38 39 + #define ICE_SR_PFA_DPLL_DEFAULTS 0x152 40 + #define ICE_DPLL_PFA_REF_SYNC_TYPE 0x2420 41 + #define ICE_DPLL_PFA_REF_SYNC_TYPE2 0x2424 42 + #define ICE_DPLL_PFA_END 0xFFFF 43 + #define ICE_DPLL_PFA_HEADER_LEN 4 44 + #define ICE_DPLL_PFA_ENTRY_LEN 3 45 + #define ICE_DPLL_PFA_MAILBOX_REF_SYNC_PIN_S 4 46 + #define ICE_DPLL_PFA_MASK_OFFSET 1 47 + #define ICE_DPLL_PFA_VALUE_OFFSET 2 48 + 49 + #define ICE_DPLL_E810C_SFP_NC_PINS 2 50 + #define ICE_DPLL_E810C_SFP_NC_START 4 51 + 39 52 /** 40 53 * enum ice_dpll_pin_type - enumerate ice pin types: 41 54 * @ICE_DPLL_PIN_INVALID: invalid pin type ··· 2120 2107 extack); 2121 2108 } 2122 2109 2110 + /* 2111 + * ice_dpll_input_ref_sync_set - callback for setting reference sync feature 2112 + * @pin: pointer to a pin 2113 + * @pin_priv: private data pointer passed on pin registration 2114 + * @ref_pin: pin pointer for reference sync pair 2115 + * @ref_pin_priv: private data pointer of ref_pin 2116 + * @state: requested state for reference sync for pin pair 2117 + * @extack: error reporting 2118 + * 2119 + * Dpll subsystem callback. Handler for setting reference sync frequency 2120 + * feature for input pin. 2121 + * 2122 + * Context: Acquires and releases pf->dplls.lock 2123 + * Return: 2124 + * * 0 - success 2125 + * * negative - error 2126 + */ 2127 + static int 2128 + ice_dpll_input_ref_sync_set(const struct dpll_pin *pin, void *pin_priv, 2129 + const struct dpll_pin *ref_pin, void *ref_pin_priv, 2130 + const enum dpll_pin_state state, 2131 + struct netlink_ext_ack *extack) 2132 + { 2133 + struct ice_dpll_pin *p = pin_priv; 2134 + struct ice_pf *pf = p->pf; 2135 + u8 flags_en = 0; 2136 + int ret; 2137 + 2138 + if (ice_dpll_is_reset(pf, extack)) 2139 + return -EBUSY; 2140 + mutex_lock(&pf->dplls.lock); 2141 + 2142 + if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN) 2143 + flags_en = ICE_AQC_SET_CGU_IN_CFG_FLG2_INPUT_EN; 2144 + if (state == DPLL_PIN_STATE_CONNECTED) 2145 + flags_en |= ICE_AQC_CGU_IN_CFG_FLG2_REFSYNC_EN; 2146 + ret = ice_aq_set_input_pin_cfg(&pf->hw, p->idx, 0, flags_en, 0, 0); 2147 + if (!ret) 2148 + ret = ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_INPUT, 2149 + extack); 2150 + mutex_unlock(&pf->dplls.lock); 2151 + 2152 + return ret; 2153 + } 2154 + 2155 + /** 2156 + * ice_dpll_input_ref_sync_get - callback for getting reference sync config 2157 + * @pin: pointer to a pin 2158 + * @pin_priv: private data pointer passed on pin registration 2159 + * @ref_pin: pin pointer for reference sync pair 2160 + * @ref_pin_priv: private data pointer of ref_pin 2161 + * @state: on success holds reference sync state for pin pair 2162 + * @extack: error reporting 2163 + * 2164 + * Dpll subsystem callback. Handler for setting reference sync frequency 2165 + * feature for input pin. 2166 + * 2167 + * Context: Acquires and releases pf->dplls.lock 2168 + * Return: 2169 + * * 0 - success 2170 + * * negative - error 2171 + */ 2172 + static int 2173 + ice_dpll_input_ref_sync_get(const struct dpll_pin *pin, void *pin_priv, 2174 + const struct dpll_pin *ref_pin, void *ref_pin_priv, 2175 + enum dpll_pin_state *state, 2176 + struct netlink_ext_ack *extack) 2177 + { 2178 + struct ice_dpll_pin *p = pin_priv; 2179 + struct ice_pf *pf = p->pf; 2180 + 2181 + if (ice_dpll_is_reset(pf, extack)) 2182 + return -EBUSY; 2183 + mutex_lock(&pf->dplls.lock); 2184 + if (p->flags[0] & ICE_AQC_CGU_IN_CFG_FLG2_REFSYNC_EN) 2185 + *state = DPLL_PIN_STATE_CONNECTED; 2186 + else 2187 + *state = DPLL_PIN_STATE_DISCONNECTED; 2188 + mutex_unlock(&pf->dplls.lock); 2189 + 2190 + return 0; 2191 + } 2192 + 2193 + /* 2194 + * ice_dpll_sw_input_ref_sync_set - callback for setting reference sync feature 2195 + * @pin: pointer to a pin 2196 + * @pin_priv: private data pointer passed on pin registration 2197 + * @ref_pin: pin pointer for reference sync pair 2198 + * @ref_pin_priv: private data pointer of ref_pin 2199 + * @state: requested state for reference sync for pin pair 2200 + * @extack: error reporting 2201 + * 2202 + * Dpll subsystem callback. Handler for setting reference sync 2203 + * feature for input pins. 2204 + * 2205 + * Context: Calls a function which acquires and releases pf->dplls.lock 2206 + * Return: 2207 + * * 0 - success 2208 + * * negative - error 2209 + */ 2210 + static int 2211 + ice_dpll_sw_input_ref_sync_set(const struct dpll_pin *pin, void *pin_priv, 2212 + const struct dpll_pin *ref_pin, 2213 + void *ref_pin_priv, 2214 + const enum dpll_pin_state state, 2215 + struct netlink_ext_ack *extack) 2216 + { 2217 + struct ice_dpll_pin *p = pin_priv; 2218 + 2219 + return ice_dpll_input_ref_sync_set(pin, p->input, ref_pin, ref_pin_priv, 2220 + state, extack); 2221 + } 2222 + 2223 + /** 2224 + * ice_dpll_sw_input_ref_sync_get - callback for getting reference sync config 2225 + * @pin: pointer to a pin 2226 + * @pin_priv: private data pointer passed on pin registration 2227 + * @ref_pin: pin pointer for reference sync pair 2228 + * @ref_pin_priv: private data pointer of ref_pin 2229 + * @state: on success holds reference sync state for pin pair 2230 + * @extack: error reporting 2231 + * 2232 + * Dpll subsystem callback. Handler for setting reference sync feature for 2233 + * input pins. 2234 + * 2235 + * Context: Calls a function which acquires and releases pf->dplls.lock 2236 + * Return: 2237 + * * 0 - success 2238 + * * negative - error 2239 + */ 2240 + static int 2241 + ice_dpll_sw_input_ref_sync_get(const struct dpll_pin *pin, void *pin_priv, 2242 + const struct dpll_pin *ref_pin, 2243 + void *ref_pin_priv, 2244 + enum dpll_pin_state *state, 2245 + struct netlink_ext_ack *extack) 2246 + { 2247 + struct ice_dpll_pin *p = pin_priv; 2248 + 2249 + return ice_dpll_input_ref_sync_get(pin, p->input, ref_pin, ref_pin_priv, 2250 + state, extack); 2251 + } 2252 + 2123 2253 /** 2124 2254 * ice_dpll_rclk_state_on_pin_set - set a state on rclk pin 2125 2255 * @pin: pointer to a pin ··· 2390 2234 .phase_offset_get = ice_dpll_phase_offset_get, 2391 2235 .esync_set = ice_dpll_sw_esync_set, 2392 2236 .esync_get = ice_dpll_sw_esync_get, 2237 + .ref_sync_set = ice_dpll_sw_input_ref_sync_set, 2238 + .ref_sync_get = ice_dpll_sw_input_ref_sync_get, 2393 2239 }; 2394 2240 2395 2241 static const struct dpll_pin_ops ice_dpll_pin_ufl_ops = { ··· 2420 2262 .phase_offset_get = ice_dpll_phase_offset_get, 2421 2263 .esync_set = ice_dpll_input_esync_set, 2422 2264 .esync_get = ice_dpll_input_esync_get, 2265 + .ref_sync_set = ice_dpll_input_ref_sync_set, 2266 + .ref_sync_get = ice_dpll_input_ref_sync_get, 2423 2267 }; 2424 2268 2425 2269 static const struct dpll_pin_ops ice_dpll_output_ops = { ··· 2721 2561 } 2722 2562 2723 2563 /** 2564 + * ice_dpll_init_ref_sync_inputs - initialize reference sync pin pairs 2565 + * @pf: pf private structure 2566 + * 2567 + * Read DPLL TLV capabilities and initialize reference sync pin pairs in 2568 + * dpll subsystem. 2569 + * 2570 + * Return: 2571 + * * 0 - success or nothing to do (no ref-sync tlv are present) 2572 + * * negative - AQ failure 2573 + */ 2574 + static int ice_dpll_init_ref_sync_inputs(struct ice_pf *pf) 2575 + { 2576 + struct ice_dpll_pin *inputs = pf->dplls.inputs; 2577 + struct ice_hw *hw = &pf->hw; 2578 + u16 addr, len, end, hdr; 2579 + int ret; 2580 + 2581 + ret = ice_get_pfa_module_tlv(hw, &hdr, &len, ICE_SR_PFA_DPLL_DEFAULTS); 2582 + if (ret) { 2583 + dev_err(ice_pf_to_dev(pf), 2584 + "Failed to read PFA dpll defaults TLV ret=%d\n", ret); 2585 + return ret; 2586 + } 2587 + end = hdr + len; 2588 + 2589 + for (addr = hdr + ICE_DPLL_PFA_HEADER_LEN; addr < end; 2590 + addr += ICE_DPLL_PFA_ENTRY_LEN) { 2591 + unsigned long bit, ul_mask, offset; 2592 + u16 pin, mask, buf; 2593 + bool valid = false; 2594 + 2595 + ret = ice_read_sr_word(hw, addr, &buf); 2596 + if (ret) 2597 + return ret; 2598 + 2599 + switch (buf) { 2600 + case ICE_DPLL_PFA_REF_SYNC_TYPE: 2601 + case ICE_DPLL_PFA_REF_SYNC_TYPE2: 2602 + { 2603 + u16 mask_addr = addr + ICE_DPLL_PFA_MASK_OFFSET; 2604 + u16 val_addr = addr + ICE_DPLL_PFA_VALUE_OFFSET; 2605 + 2606 + ret = ice_read_sr_word(hw, mask_addr, &mask); 2607 + if (ret) 2608 + return ret; 2609 + ret = ice_read_sr_word(hw, val_addr, &pin); 2610 + if (ret) 2611 + return ret; 2612 + if (buf == ICE_DPLL_PFA_REF_SYNC_TYPE) 2613 + pin >>= ICE_DPLL_PFA_MAILBOX_REF_SYNC_PIN_S; 2614 + valid = true; 2615 + break; 2616 + } 2617 + case ICE_DPLL_PFA_END: 2618 + addr = end; 2619 + break; 2620 + default: 2621 + continue; 2622 + } 2623 + if (!valid) 2624 + continue; 2625 + 2626 + ul_mask = mask; 2627 + offset = 0; 2628 + for_each_set_bit(bit, &ul_mask, BITS_PER_TYPE(u16)) { 2629 + int i, j; 2630 + 2631 + if (hw->device_id == ICE_DEV_ID_E810C_SFP && 2632 + pin > ICE_DPLL_E810C_SFP_NC_START) 2633 + offset = -ICE_DPLL_E810C_SFP_NC_PINS; 2634 + i = pin + offset; 2635 + j = bit + offset; 2636 + if (i < 0 || j < 0) 2637 + return -ERANGE; 2638 + inputs[i].ref_sync = j; 2639 + } 2640 + } 2641 + 2642 + return 0; 2643 + } 2644 + 2645 + /** 2724 2646 * ice_dpll_release_pins - release pins resources from dpll subsystem 2725 2647 * @pins: pointer to pins array 2726 2648 * @count: number of pins ··· 2874 2632 for (i = 0; i < count; i++) 2875 2633 if (!pins[i].hidden) 2876 2634 dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]); 2635 + } 2636 + 2637 + /** 2638 + * ice_dpll_pin_ref_sync_register - register reference sync pins 2639 + * @pins: pointer to pins array 2640 + * @count: number of pins 2641 + * 2642 + * Register reference sync pins in dpll subsystem. 2643 + * 2644 + * Return: 2645 + * * 0 - success 2646 + * * negative - registration failure reason 2647 + */ 2648 + static int 2649 + ice_dpll_pin_ref_sync_register(struct ice_dpll_pin *pins, int count) 2650 + { 2651 + int ret, i; 2652 + 2653 + for (i = 0; i < count; i++) { 2654 + if (!pins[i].hidden && pins[i].ref_sync) { 2655 + int j = pins[i].ref_sync; 2656 + 2657 + ret = dpll_pin_ref_sync_pair_add(pins[i].pin, 2658 + pins[j].pin); 2659 + if (ret) 2660 + return ret; 2661 + } 2662 + } 2663 + 2664 + return 0; 2877 2665 } 2878 2666 2879 2667 /** ··· 3194 2922 goto deinit_sma; 3195 2923 count += ICE_DPLL_PIN_SW_NUM; 3196 2924 } 2925 + ret = ice_dpll_pin_ref_sync_register(pf->dplls.inputs, 2926 + pf->dplls.num_inputs); 2927 + if (ret) 2928 + goto deinit_ufl; 2929 + ret = ice_dpll_pin_ref_sync_register(pf->dplls.sma, 2930 + ICE_DPLL_PIN_SW_NUM); 2931 + if (ret) 2932 + goto deinit_ufl; 3197 2933 } else { 3198 2934 count += pf->dplls.num_outputs + 2 * ICE_DPLL_PIN_SW_NUM; 3199 2935 } ··· 3499 3219 pins[i].prop.freq_supported_num = freq_supp_num; 3500 3220 pins[i].pf = pf; 3501 3221 } 3222 + if (input) 3223 + ret = ice_dpll_init_ref_sync_inputs(pf); 3502 3224 3503 3225 return ret; 3504 3226 } ··· 3566 3284 pin->pf = pf; 3567 3285 pin->prop.board_label = ice_dpll_sw_pin_sma[i]; 3568 3286 pin->input = &d->inputs[pin_abs_idx]; 3287 + if (pin->input->ref_sync) 3288 + pin->ref_sync = pin->input->ref_sync - pin_abs_idx; 3569 3289 pin->output = &d->outputs[ICE_DPLL_PIN_SW_OUTPUT_ABS(i)]; 3570 3290 ice_dpll_phase_range_set(&pin->prop.phase_range, phase_adj_max); 3571 3291 }
+2
drivers/net/ethernet/intel/ice/ice_dpll.h
··· 32 32 * @freq: current frequency of a pin 33 33 * @phase_adjust: current phase adjust value 34 34 * @phase_offset: monitored phase offset value 35 + * @ref_sync: store id of reference sync pin 35 36 */ 36 37 struct ice_dpll_pin { 37 38 struct dpll_pin *pin; ··· 50 49 enum dpll_pin_direction direction; 51 50 s64 phase_offset; 52 51 u8 status; 52 + u8 ref_sync; 53 53 bool active; 54 54 bool hidden; 55 55 };
+13
include/linux/dpll.h
··· 103 103 const struct dpll_device *dpll, void *dpll_priv, 104 104 struct dpll_pin_esync *esync, 105 105 struct netlink_ext_ack *extack); 106 + int (*ref_sync_set)(const struct dpll_pin *pin, void *pin_priv, 107 + const struct dpll_pin *ref_sync_pin, 108 + void *ref_sync_pin_priv, 109 + const enum dpll_pin_state state, 110 + struct netlink_ext_ack *extack); 111 + int (*ref_sync_get)(const struct dpll_pin *pin, void *pin_priv, 112 + const struct dpll_pin *ref_sync_pin, 113 + void *ref_sync_pin_priv, 114 + enum dpll_pin_state *state, 115 + struct netlink_ext_ack *extack); 106 116 }; 107 117 108 118 struct dpll_pin_frequency { ··· 211 201 212 202 void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, 213 203 const struct dpll_pin_ops *ops, void *priv); 204 + 205 + int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin, 206 + struct dpll_pin *ref_sync_pin); 214 207 215 208 int dpll_device_change_ntf(struct dpll_device *dpll); 216 209
+1
include/uapi/linux/dpll.h
··· 249 249 DPLL_A_PIN_ESYNC_FREQUENCY, 250 250 DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED, 251 251 DPLL_A_PIN_ESYNC_PULSE, 252 + DPLL_A_PIN_REFERENCE_SYNC, 252 253 253 254 __DPLL_A_PIN_MAX, 254 255 DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)