From: Ivan Vecera <ivecera@redhat.com>
To: netdev@vger.kernel.org
Cc: Michal Schmidt <mschmidt@redhat.com>,
Prathosh Satish <Prathosh.Satish@microchip.com>,
Vadim Fedorenko <vadim.fedorenko@linux.dev>,
Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>,
Jiri Pirko <jiri@resnulli.us>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>, Lee Jones <lee@kernel.org>,
Kees Cook <kees@kernel.org>, Andy Shevchenko <andy@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-hardening@vger.kernel.org
Subject: [PATCH 28/28] dpll: zl3073x: Add support to get fractional frequency offset on input pins
Date: Mon, 7 Apr 2025 19:33:01 +0200 [thread overview]
Message-ID: <20250407173301.1010462-9-ivecera@redhat.com> (raw)
In-Reply-To: <20250407172836.1009461-1-ivecera@redhat.com>
This adds support to get fractional frequency offset for input pins.
Implement the appropriate callback that performs reference frequency
measurement and reports the frequency offset between the DPLL and
the reference.
Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
Co-developed-by: Prathosh Satish <Prathosh.Satish@microchip.com>
Signed-off-by: Prathosh Satish <Prathosh.Satish@microchip.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
drivers/dpll/dpll_zl3073x.c | 110 +++++++++++++++++++++++++++++++++++-
1 file changed, 109 insertions(+), 1 deletion(-)
diff --git a/drivers/dpll/dpll_zl3073x.c b/drivers/dpll/dpll_zl3073x.c
index e1d7f6d4c3d57..f5a58c3bab382 100644
--- a/drivers/dpll/dpll_zl3073x.c
+++ b/drivers/dpll/dpll_zl3073x.c
@@ -36,12 +36,31 @@ ZL3073X_REG8_IDX_DEF(dpll_refsel_status, 0x130, ZL3073X_NUM_CHANNELS, 1);
#define DPLL_REFSEL_STATUS_STATE_ACQUIRING 3
#define DPLL_REFSEL_STATUS_STATE_LOCK 4
+ZL3073X_REG32_IDX_DEF(ref_freq, 0x144,
+ ZL3073X_NUM_INPUT_PINS, 4);
+
/*
* Register Map Page 4, Ref
*/
ZL3073X_REG8_DEF(ref_phase_err_read_rqst, 0x20f);
#define REF_PHASE_ERR_READ_RQST_RD BIT(0)
+ZL3073X_REG8_DEF(ref_freq_meas_ctrl, 0x21c);
+#define REF_FREQ_MEAS_CTRL_LATCH GENMASK(1, 0)
+#define REF_FREQ_MEAS_CTRL_LATCH_REF_FREQ 1
+#define REF_FREQ_MEAS_CTRL_LATCH_REF_FREQ_OFF 2
+#define REF_FREQ_MEAS_CTRL_LATCH_DPLL_FREQ_OFF 3
+
+ZL3073X_REG8_DEF(ref_freq_meas_mask_3_0, 0x21d);
+#define REF_FREQ_MEAS_MASK_3_0(_ref) BIT(_ref)
+
+ZL3073X_REG8_DEF(ref_freq_meas_mask_4, 0x21e);
+#define REF_FREQ_MEAS_MASK_4(_ref) BIT((_ref) - 8)
+
+ZL3073X_REG8_DEF(dpll_meas_ref_freq_ctrl, 0x21f);
+#define DPLL_MEAS_REF_FREQ_CTRL_EN BIT(0)
+#define DPLL_MEAS_REF_FREQ_CTRL_IDX GENMASK(6, 4)
+
ZL3073X_REG48_IDX_DEF(ref_phase, 0x220,
ZL3073X_NUM_INPUT_PINS, 6);
@@ -140,6 +159,7 @@ struct zl3073x_dpll_pin_info {
* @esync_control: embedded sync is controllable
* @pin_state: last saved pin state
* @phase_offset: last saved pin phase offset
+ * @freq_offset: last saved fractional frequency offset
*/
struct zl3073x_dpll_pin {
struct dpll_pin *dpll_pin;
@@ -149,6 +169,7 @@ struct zl3073x_dpll_pin {
bool esync_control;
enum dpll_pin_state pin_state;
s64 phase_offset;
+ s64 freq_offset;
};
/**
@@ -498,6 +519,79 @@ zl3073x_dpll_input_pin_esync_set(const struct dpll_pin *dpll_pin,
return rc;
}
+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,
+ s64 *ffo, struct netlink_ext_ack *extack)
+{
+ struct zl3073x_dpll *zldpll = dpll_priv;
+ struct zl3073x_dev *zldev = zldpll->mfd;
+ struct zl3073x_dpll_pin *pin = pin_priv;
+ u8 dpll_meas_ref_freq_ctrl, ref_id;
+ u8 ref_freq_meas_ctrl, ref_mask;
+ s32 freq_offset;
+ int rc;
+
+ /* Take device lock */
+ guard(zl3073x)(zldev);
+
+ /* Get index of the pin */
+ ref_id = zl3073x_dpll_pin_index_get(pin);
+
+ /* Wait for being ready */
+ rc = zl3073x_wait_clear_bits(zldev, ref_freq_meas_ctrl,
+ REF_FREQ_MEAS_CTRL_LATCH);
+ if (rc)
+ return rc;
+
+ /* Select channel index in the mask and enable freq measurement */
+ dpll_meas_ref_freq_ctrl =
+ DPLL_MEAS_REF_FREQ_CTRL_EN |
+ FIELD_PREP(DPLL_MEAS_REF_FREQ_CTRL_IDX, zldpll->id);
+
+ rc = zl3073x_write_dpll_meas_ref_freq_ctrl(zldev,
+ dpll_meas_ref_freq_ctrl);
+ if (rc)
+ return rc;
+
+ /* Set reference mask
+ * REF0P,REF0N..REF3P,REF3N are set in ref_freq_meas_mask_3_0 register
+ * REF4P and REF4N are set in ref_freq_meas_mask_4 register
+ */
+ if (ref_id < 8) {
+ ref_mask = REF_FREQ_MEAS_MASK_3_0(ref_id);
+ rc = zl3073x_write_ref_freq_meas_mask_3_0(zldev, ref_mask);
+ } else {
+ ref_mask = REF_FREQ_MEAS_MASK_4(ref_id);
+ rc = zl3073x_write_ref_freq_meas_mask_4(zldev, ref_mask);
+ }
+ if (rc)
+ return rc;
+
+ /* Request a reading of the frequency offset between the DPLL and
+ * the reference
+ */
+ ref_freq_meas_ctrl = REF_FREQ_MEAS_CTRL_LATCH_DPLL_FREQ_OFF;
+ rc = zl3073x_write_ref_freq_meas_ctrl(zldev, ref_freq_meas_ctrl);
+ if (rc)
+ return rc;
+
+ /* Wait for the command to actually finish */
+ rc = zl3073x_wait_clear_bits(zldev, ref_freq_meas_ctrl,
+ REF_FREQ_MEAS_CTRL_LATCH);
+ if (rc)
+ return rc;
+
+ /* Read the frequency offset between DPLL and reference */
+ rc = zl3073x_read_ref_freq(zldev, ref_id, &freq_offset);
+ if (rc)
+ return rc;
+
+ *ffo = freq_offset;
+
+ return rc;
+}
+
static int
zl3073x_dpll_input_pin_frequency_get(const struct dpll_pin *dpll_pin,
void *pin_priv,
@@ -1778,6 +1872,7 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = {
.direction_get = zl3073x_dpll_pin_direction_get,
.esync_get = zl3073x_dpll_input_pin_esync_get,
.esync_set = zl3073x_dpll_input_pin_esync_set,
+ .ffo_get = zl3073x_dpll_input_pin_ffo_get,
.frequency_get = zl3073x_dpll_input_pin_frequency_get,
.frequency_set = zl3073x_dpll_input_pin_frequency_set,
.phase_offset_get = zl3073x_dpll_input_pin_phase_offset_get,
@@ -2484,9 +2579,9 @@ zl3073x_dpll_periodic_work(struct kthread_work *work)
* are constant.
*/
for (i = 0; i < ZL3073X_NUM_INPUT_PINS; i++) {
+ s64 freq_offset, phase_offset;
struct zl3073x_dpll_pin *pin;
enum dpll_pin_state state;
- s64 phase_offset;
bool pin_changed;
/* Input pins starts are stored after output pins */
@@ -2513,6 +2608,12 @@ zl3073x_dpll_periodic_work(struct kthread_work *work)
if (rc)
goto out;
+ rc = zl3073x_dpll_input_pin_ffo_get(pin->dpll_pin, pin,
+ zldpll->dpll_dev, zldpll,
+ &freq_offset, NULL);
+ if (rc)
+ goto out;
+
if (state != pin->pin_state) {
dev_dbg(zldev->dev,
"INPUT%u state changed to %u\n",
@@ -2527,6 +2628,13 @@ zl3073x_dpll_periodic_work(struct kthread_work *work)
pin->phase_offset = phase_offset;
pin_changed = true;
}
+ if (freq_offset != pin->freq_offset) {
+ dev_dbg(zldev->dev,
+ "INPUT%u frequency offset changed to %llu\n",
+ pin->index, freq_offset);
+ pin->freq_offset = freq_offset;
+ pin_changed = true;
+ }
if (pin_changed)
dpll_pin_change_ntf(pin->dpll_pin);
--
2.48.1
next prev parent reply other threads:[~2025-04-07 17:34 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-07 17:28 [PATCH 00/28] Add Microchip ZL3073x support Ivan Vecera
2025-04-07 17:28 ` [PATCH 01/28] mfd: " Ivan Vecera
2025-04-07 17:53 ` Krzysztof Kozlowski
2025-04-09 6:31 ` Ivan Vecera
2025-04-07 18:05 ` Andy Shevchenko
2025-04-09 6:40 ` Ivan Vecera
2025-04-14 6:36 ` Andy Shevchenko
2025-04-14 11:39 ` Ivan Vecera
2025-04-14 11:52 ` Ivan Vecera
2025-04-14 13:55 ` Andy Shevchenko
2025-04-14 14:08 ` Ivan Vecera
2025-04-14 14:07 ` Ivan Vecera
2025-04-14 14:10 ` Andy Shevchenko
2025-04-14 14:13 ` Andy Shevchenko
2025-04-14 14:16 ` Andy Shevchenko
2025-04-14 14:53 ` Ivan Vecera
2025-04-14 17:09 ` Andy Shevchenko
2025-04-14 17:42 ` Ivan Vecera
2025-04-14 13:58 ` Andy Shevchenko
2025-04-07 17:28 ` [PATCH 02/28] mfd: zl3073x: Register itself as devlink device Ivan Vecera
2025-04-07 20:57 ` Andrew Lunn
2025-04-09 6:41 ` Ivan Vecera
2025-04-07 17:28 ` [PATCH 03/28] mfd: zl3073x: Add register access helpers Ivan Vecera
2025-04-07 21:03 ` Andrew Lunn
2025-04-09 6:42 ` Ivan Vecera
2025-04-07 17:28 ` [PATCH 04/28] mfd: zl3073x: Add macros for device registers access Ivan Vecera
2025-04-07 17:28 ` [PATCH 05/28] mfd: zl3073x: Add components versions register defs Ivan Vecera
2025-04-07 21:09 ` Andrew Lunn
2025-04-09 6:44 ` Ivan Vecera
2025-04-10 7:11 ` Krzysztof Kozlowski
2025-04-10 10:23 ` Ivan Vecera
2025-04-10 10:42 ` Krzysztof Kozlowski
2025-04-10 12:01 ` Ivan Vecera
2025-04-07 17:28 ` [PATCH 06/28] mfd: zl3073x: Implement devlink device info Ivan Vecera
2025-04-07 17:28 ` [PATCH 07/28] mfd: zl3073x: Add macro to wait for register value bits to be cleared Ivan Vecera
2025-04-07 17:28 ` [PATCH 08/28] mfd: zl3073x: Add functions to work with register mailboxes Ivan Vecera
2025-04-07 17:28 ` [PATCH 09/28] mfd: zl3073x: Add clock_id field Ivan Vecera
2025-04-07 17:31 ` [PATCH 10/28] lib: Allow modules to use strnchrnul Ivan Vecera
2025-04-07 17:50 ` Kees Cook
2025-04-07 17:31 ` [PATCH 11/28] mfd: zl3073x: Load mfg file into HW if it is present Ivan Vecera
2025-04-07 17:31 ` [PATCH 12/28] mfd: zl3073x: Fetch invariants during probe Ivan Vecera
2025-04-07 17:31 ` [PATCH 13/28] dpll: Add Microchip ZL3073x DPLL driver Ivan Vecera
2025-04-07 17:31 ` [PATCH 14/28] mfd: zl3073x: Register DPLL sub-device during init Ivan Vecera
2025-04-07 17:31 ` [PATCH 15/28] dt-bindings: dpll: Add device tree bindings for DPLL device and pin Ivan Vecera
2025-04-07 18:01 ` Krzysztof Kozlowski
2025-04-07 18:10 ` Krzysztof Kozlowski
2025-04-08 5:19 ` Michal Schmidt
2025-04-09 7:09 ` Ivan Vecera
2025-04-07 17:31 ` [PATCH 16/28] dt-bindings: dpll: Add support for Microchip Azurite chip family Ivan Vecera
2025-04-07 18:04 ` Krzysztof Kozlowski
2025-04-09 7:19 ` Ivan Vecera
2025-04-10 7:01 ` Krzysztof Kozlowski
2025-04-10 10:28 ` Ivan Vecera
2025-04-10 12:19 ` Krzysztof Kozlowski
2025-04-10 12:38 ` Ivan Vecera
2025-04-07 17:31 ` [PATCH 17/28] dpll: zl3073x: Read DPLL types from firmware Ivan Vecera
2025-04-07 17:31 ` [PATCH 18/28] dpll: zl3073x: Read optional pin properties " Ivan Vecera
2025-04-07 18:06 ` Krzysztof Kozlowski
2025-04-09 7:22 ` Ivan Vecera
2025-04-07 17:31 ` [PATCH 19/28] dpll: zl3073x: Implement input pin selection in manual mode Ivan Vecera
2025-04-07 17:32 ` [PATCH 20/28] dpll: zl3073x: Add support to get/set priority on input pins Ivan Vecera
2025-04-07 17:32 ` [PATCH 21/28] dpll: zl3073x: Implement input pin state setting in automatic mode Ivan Vecera
2025-04-07 17:32 ` [PATCH 22/28] dpll: zl3073x: Add support to get/set frequency on input pins Ivan Vecera
2025-04-07 17:32 ` [PATCH 23/28] dpll: zl3073x: Add support to get/set frequency on output pins Ivan Vecera
2025-04-07 17:32 ` [PATCH 24/28] dpll: zl3073x: Read pin supported frequencies from firmware Ivan Vecera
2025-04-07 17:32 ` [PATCH 25/28] dpll: zl3073x: Add support to get phase offset on input pins Ivan Vecera
2025-04-07 17:32 ` [PATCH 26/28] dpll: zl3073x: Add support to get/set phase adjust on pins Ivan Vecera
2025-04-07 17:33 ` [PATCH 27/28] dpll: zl3073x: Add support to get/set esync " Ivan Vecera
2025-04-07 17:33 ` Ivan Vecera [this message]
2025-04-07 18:06 ` [PATCH 00/28] Add Microchip ZL3073x support Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250407173301.1010462-9-ivecera@redhat.com \
--to=ivecera@redhat.com \
--cc=Prathosh.Satish@microchip.com \
--cc=akpm@linux-foundation.org \
--cc=andy@kernel.org \
--cc=arkadiusz.kubalewski@intel.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=jiri@resnulli.us \
--cc=kees@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=lee@kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mschmidt@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=robh@kernel.org \
--cc=vadim.fedorenko@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox