Add the RHEL 211.19.1..211.20.1 backports (1245-1287) from centos-stream-10 and upstream, on top of 211.18.1, plus the dpll RHEL kABI adaptation (1287). RHEL now ships the smb cifs.spnego fix too; the existing ahead-fix 1105 is byte-identical, so RHEL's redundant copy is omitted. Bump to 211.20.1.
326 lines
10 KiB
Diff
326 lines
10 KiB
Diff
From ef38c6a6c3f4e6f931e21f54c88741a1a0c84f27 Mon Sep 17 00:00:00 2001
|
|
From: Ivan Vecera <ivecera@redhat.com>
|
|
Date: Wed, 29 Apr 2026 14:55:45 +0200
|
|
Subject: [PATCH] dpll: zl3073x: add ref-sync pair support
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-157828
|
|
|
|
commit 14f269ae699869ddaca7c29c9c6c52288e3bfb73
|
|
Author: Ivan Vecera <ivecera@redhat.com>
|
|
Date: Wed Apr 8 12:27:16 2026 +0200
|
|
|
|
dpll: zl3073x: add ref-sync pair support
|
|
|
|
Add support for ref-sync pair registration using the 'ref-sync-sources'
|
|
phandle property from device tree. A ref-sync pair consists of a clock
|
|
reference and a low-frequency sync signal where the DPLL locks to the
|
|
clock reference but phase-aligns to the sync reference.
|
|
|
|
The implementation:
|
|
- Stores fwnode handle in zl3073x_dpll_pin during pin registration
|
|
- Adds ref_sync_get/set callbacks to read and write the sync control
|
|
mode and pair registers
|
|
- Validates ref-sync frequency constraints: sync signal must be 8 kHz
|
|
or less, clock reference must be 1 kHz or more and higher than sync
|
|
- Excludes sync source from automatic reference selection by setting
|
|
its priority to NONE on connect; on disconnect the priority is left
|
|
as NONE and the user must explicitly make the pin selectable again
|
|
- Iterates ref-sync-sources phandles to register declared pairings
|
|
via dpll_pin_ref_sync_pair_add()
|
|
|
|
Reviewed-by: Petr Oros <poros@redhat.com>
|
|
Reviewed-by: Prathosh Satish <Prathosh.Satish@microchip.com>
|
|
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
|
|
Link: https://patch.msgid.link/20260408102716.443099-6-ivecera@redhat.com
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
|
(cherry picked from commit 14f269ae699869ddaca7c29c9c6c52288e3bfb73)
|
|
Assisted-by: Patchpal
|
|
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
|
|
|
|
diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
|
|
index a151be700e6e..55195dcd21d6 100644
|
|
--- a/drivers/dpll/zl3073x/dpll.c
|
|
+++ b/drivers/dpll/zl3073x/dpll.c
|
|
@@ -13,6 +13,7 @@
|
|
#include <linux/module.h>
|
|
#include <linux/netlink.h>
|
|
#include <linux/platform_device.h>
|
|
+#include <linux/property.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/sprintf.h>
|
|
|
|
@@ -30,6 +31,7 @@
|
|
* @dpll: DPLL the pin is registered to
|
|
* @dpll_pin: pointer to registered dpll_pin
|
|
* @tracker: tracking object for the acquired reference
|
|
+ * @fwnode: firmware node handle
|
|
* @label: package label
|
|
* @dir: pin direction
|
|
* @id: pin id
|
|
@@ -46,6 +48,7 @@ struct zl3073x_dpll_pin {
|
|
struct zl3073x_dpll *dpll;
|
|
struct dpll_pin *dpll_pin;
|
|
dpll_tracker tracker;
|
|
+ struct fwnode_handle *fwnode;
|
|
char label[8];
|
|
enum dpll_pin_direction dir;
|
|
u8 id;
|
|
@@ -186,6 +189,109 @@ zl3073x_dpll_input_pin_esync_set(const struct dpll_pin *dpll_pin,
|
|
return zl3073x_ref_state_set(zldev, ref_id, &ref);
|
|
}
|
|
|
|
+static int
|
|
+zl3073x_dpll_input_pin_ref_sync_get(const struct dpll_pin *dpll_pin,
|
|
+ void *pin_priv,
|
|
+ const struct dpll_pin *ref_sync_pin,
|
|
+ void *ref_sync_pin_priv,
|
|
+ enum dpll_pin_state *state,
|
|
+ struct netlink_ext_ack *extack)
|
|
+{
|
|
+ struct zl3073x_dpll_pin *sync_pin = ref_sync_pin_priv;
|
|
+ struct zl3073x_dpll_pin *pin = pin_priv;
|
|
+ struct zl3073x_dpll *zldpll = pin->dpll;
|
|
+ struct zl3073x_dev *zldev = zldpll->dev;
|
|
+ const struct zl3073x_ref *ref;
|
|
+ u8 ref_id, mode, pair;
|
|
+
|
|
+ ref_id = zl3073x_input_pin_ref_get(pin->id);
|
|
+ ref = zl3073x_ref_state_get(zldev, ref_id);
|
|
+ mode = zl3073x_ref_sync_mode_get(ref);
|
|
+ pair = zl3073x_ref_sync_pair_get(ref);
|
|
+
|
|
+ if (mode == ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR &&
|
|
+ pair == zl3073x_input_pin_ref_get(sync_pin->id))
|
|
+ *state = DPLL_PIN_STATE_CONNECTED;
|
|
+ else
|
|
+ *state = DPLL_PIN_STATE_DISCONNECTED;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+zl3073x_dpll_input_pin_ref_sync_set(const struct dpll_pin *dpll_pin,
|
|
+ void *pin_priv,
|
|
+ const struct dpll_pin *ref_sync_pin,
|
|
+ void *ref_sync_pin_priv,
|
|
+ const enum dpll_pin_state state,
|
|
+ struct netlink_ext_ack *extack)
|
|
+{
|
|
+ struct zl3073x_dpll_pin *sync_pin = ref_sync_pin_priv;
|
|
+ struct zl3073x_dpll_pin *pin = pin_priv;
|
|
+ struct zl3073x_dpll *zldpll = pin->dpll;
|
|
+ struct zl3073x_dev *zldev = zldpll->dev;
|
|
+ u8 mode, ref_id, sync_ref_id;
|
|
+ struct zl3073x_chan chan;
|
|
+ struct zl3073x_ref ref;
|
|
+ int rc;
|
|
+
|
|
+ ref_id = zl3073x_input_pin_ref_get(pin->id);
|
|
+ sync_ref_id = zl3073x_input_pin_ref_get(sync_pin->id);
|
|
+ ref = *zl3073x_ref_state_get(zldev, ref_id);
|
|
+
|
|
+ if (state == DPLL_PIN_STATE_CONNECTED) {
|
|
+ const struct zl3073x_ref *sync_ref;
|
|
+ u32 ref_freq, sync_freq;
|
|
+
|
|
+ sync_ref = zl3073x_ref_state_get(zldev, sync_ref_id);
|
|
+ ref_freq = zl3073x_ref_freq_get(&ref);
|
|
+ sync_freq = zl3073x_ref_freq_get(sync_ref);
|
|
+
|
|
+ /* Sync signal must be 8 kHz or less and clock reference
|
|
+ * must be 1 kHz or more and higher than the sync signal.
|
|
+ */
|
|
+ if (sync_freq > 8000) {
|
|
+ NL_SET_ERR_MSG(extack,
|
|
+ "sync frequency must be 8 kHz or less");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ if (ref_freq < 1000) {
|
|
+ NL_SET_ERR_MSG(extack,
|
|
+ "clock frequency must be 1 kHz or more");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ if (ref_freq <= sync_freq) {
|
|
+ NL_SET_ERR_MSG(extack,
|
|
+ "clock frequency must be higher than sync frequency");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ zl3073x_ref_sync_pair_set(&ref, sync_ref_id);
|
|
+ mode = ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR;
|
|
+ } else {
|
|
+ mode = ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR_OFF;
|
|
+ }
|
|
+
|
|
+ zl3073x_ref_sync_mode_set(&ref, mode);
|
|
+
|
|
+ rc = zl3073x_ref_state_set(zldev, ref_id, &ref);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
+ /* Exclude sync source from automatic reference selection by setting
|
|
+ * its priority to NONE. On disconnect the priority is left as NONE
|
|
+ * and the user must explicitly make the pin selectable again.
|
|
+ */
|
|
+ if (state == DPLL_PIN_STATE_CONNECTED) {
|
|
+ chan = *zl3073x_chan_state_get(zldev, zldpll->id);
|
|
+ zl3073x_chan_ref_prio_set(&chan, sync_ref_id,
|
|
+ ZL_DPLL_REF_PRIO_NONE);
|
|
+ return zl3073x_chan_state_set(zldev, zldpll->id, &chan);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv,
|
|
const struct dpll_device *dpll, void *dpll_priv,
|
|
@@ -1147,6 +1253,8 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = {
|
|
.phase_adjust_set = zl3073x_dpll_input_pin_phase_adjust_set,
|
|
.prio_get = zl3073x_dpll_input_pin_prio_get,
|
|
.prio_set = zl3073x_dpll_input_pin_prio_set,
|
|
+ .ref_sync_get = zl3073x_dpll_input_pin_ref_sync_get,
|
|
+ .ref_sync_set = zl3073x_dpll_input_pin_ref_sync_set,
|
|
.state_on_dpll_get = zl3073x_dpll_input_pin_state_on_dpll_get,
|
|
.state_on_dpll_set = zl3073x_dpll_input_pin_state_on_dpll_set,
|
|
};
|
|
@@ -1239,8 +1347,11 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
|
|
if (IS_ERR(props))
|
|
return PTR_ERR(props);
|
|
|
|
- /* Save package label, esync capability and phase adjust granularity */
|
|
+ /* Save package label, fwnode, esync capability and phase adjust
|
|
+ * granularity.
|
|
+ */
|
|
strscpy(pin->label, props->package_label);
|
|
+ pin->fwnode = fwnode_handle_get(props->fwnode);
|
|
pin->esync_control = props->esync_control;
|
|
pin->phase_gran = props->dpll_props.phase_gran;
|
|
|
|
@@ -1285,6 +1396,8 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
|
|
dpll_pin_put(pin->dpll_pin, &pin->tracker);
|
|
pin->dpll_pin = NULL;
|
|
err_pin_get:
|
|
+ fwnode_handle_put(pin->fwnode);
|
|
+ pin->fwnode = NULL;
|
|
zl3073x_pin_props_put(props);
|
|
|
|
return rc;
|
|
@@ -1314,6 +1427,9 @@ zl3073x_dpll_pin_unregister(struct zl3073x_dpll_pin *pin)
|
|
|
|
dpll_pin_put(pin->dpll_pin, &pin->tracker);
|
|
pin->dpll_pin = NULL;
|
|
+
|
|
+ fwnode_handle_put(pin->fwnode);
|
|
+ pin->fwnode = NULL;
|
|
}
|
|
|
|
/**
|
|
@@ -1827,6 +1943,88 @@ zl3073x_dpll_free(struct zl3073x_dpll *zldpll)
|
|
kfree(zldpll);
|
|
}
|
|
|
|
+/**
|
|
+ * zl3073x_dpll_ref_sync_pair_register - register ref_sync pairs for a pin
|
|
+ * @pin: pointer to zl3073x_dpll_pin structure
|
|
+ *
|
|
+ * Iterates 'ref-sync-sources' phandles in the pin's firmware node and
|
|
+ * registers each declared pairing.
|
|
+ *
|
|
+ * Return: 0 on success, <0 on error
|
|
+ */
|
|
+static int
|
|
+zl3073x_dpll_ref_sync_pair_register(struct zl3073x_dpll_pin *pin)
|
|
+{
|
|
+ struct zl3073x_dev *zldev = pin->dpll->dev;
|
|
+ struct fwnode_handle *fwnode;
|
|
+ struct dpll_pin *sync_pin;
|
|
+ dpll_tracker tracker;
|
|
+ int n, rc;
|
|
+
|
|
+ for (n = 0; ; n++) {
|
|
+ /* Get n'th ref-sync source */
|
|
+ fwnode = fwnode_find_reference(pin->fwnode, "ref-sync-sources",
|
|
+ n);
|
|
+ if (IS_ERR(fwnode)) {
|
|
+ rc = PTR_ERR(fwnode);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Find associated dpll pin */
|
|
+ sync_pin = fwnode_dpll_pin_find(fwnode, &tracker);
|
|
+ fwnode_handle_put(fwnode);
|
|
+ if (!sync_pin) {
|
|
+ dev_warn(zldev->dev, "%s: ref-sync source %d not found",
|
|
+ pin->label, n);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Register new ref-sync pair */
|
|
+ rc = dpll_pin_ref_sync_pair_add(pin->dpll_pin, sync_pin);
|
|
+ dpll_pin_put(sync_pin, &tracker);
|
|
+
|
|
+ /* -EBUSY means pairing already exists from another DPLL's
|
|
+ * registration.
|
|
+ */
|
|
+ if (rc && rc != -EBUSY) {
|
|
+ dev_err(zldev->dev,
|
|
+ "%s: failed to add ref-sync source %d: %pe",
|
|
+ pin->label, n, ERR_PTR(rc));
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return rc != -ENOENT ? rc : 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * zl3073x_dpll_ref_sync_pairs_register - register ref_sync pairs for a DPLL
|
|
+ * @zldpll: pointer to zl3073x_dpll structure
|
|
+ *
|
|
+ * Iterates all registered input pins of the given DPLL and establishes
|
|
+ * ref_sync pairings declared by 'ref-sync-sources' phandles in the
|
|
+ * device tree.
|
|
+ *
|
|
+ * Return: 0 on success, <0 on error
|
|
+ */
|
|
+static int
|
|
+zl3073x_dpll_ref_sync_pairs_register(struct zl3073x_dpll *zldpll)
|
|
+{
|
|
+ struct zl3073x_dpll_pin *pin;
|
|
+ int rc;
|
|
+
|
|
+ list_for_each_entry(pin, &zldpll->pins, list) {
|
|
+ if (!zl3073x_dpll_is_input_pin(pin) || !pin->fwnode)
|
|
+ continue;
|
|
+
|
|
+ rc = zl3073x_dpll_ref_sync_pair_register(pin);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/**
|
|
* zl3073x_dpll_register - register DPLL device and all its pins
|
|
* @zldpll: pointer to zl3073x_dpll structure
|
|
@@ -1850,6 +2048,13 @@ zl3073x_dpll_register(struct zl3073x_dpll *zldpll)
|
|
return rc;
|
|
}
|
|
|
|
+ rc = zl3073x_dpll_ref_sync_pairs_register(zldpll);
|
|
+ if (rc) {
|
|
+ zl3073x_dpll_pins_unregister(zldpll);
|
|
+ zl3073x_dpll_device_unregister(zldpll);
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--
|
|
2.50.1 (Apple Git-155)
|
|
|