Add both fractional-frequency-offset (PPM) and fractional-frequency-offset-ppt (PPT) attributes to the pin-parent-device nested attribute set, alongside the existing top-level pin attributes. Both carry the same measurement at different precisions. Introduce enum dpll_ffo_type and struct dpll_ffo_param to distinguish FFO contexts: DPLL_FFO_PORT_RXTX_RATE for the RX vs TX symbol rate offset reported at the top level, and DPLL_FFO_PIN_DEVICE for the pin vs parent DPLL offset reported in the pin-parent-device nest. Add a supported_ffo bitmask to struct dpll_pin_ops so drivers declare which FFO types they support. The core only calls ffo_get for types the driver has opted into, eliminating the need for per-driver NULL pointer guards. Validate at pin registration time that supported_ffo is not set without an ffo_get callback. Update mlx5 (DPLL_FFO_PORT_RXTX_RATE) and zl3073x (DPLL_FFO_PORT_RXTX_RATE) drivers to use the new API. Add documentation for both FFO types to dpll.rst. Changes v3 -> v4: - Replace dpll=NULL overloading with enum dpll_ffo_type and struct dpll_ffo_param (Jakub Kicinski) - Add supported_ffo opt-in bitmask in dpll_pin_ops for fail-close driver validation (Jakub Kicinski) - Add WARN_ON in dpll_pin_register for supported_ffo without ffo_get callback Reviewed-by: Jiri Pirko Signed-off-by: Ivan Vecera --- Documentation/driver-api/dpll.rst | 20 +++++++++++++ Documentation/netlink/specs/dpll.yaml | 28 ++++++++++------- drivers/dpll/dpll_core.c | 3 +- drivers/dpll/dpll_netlink.c | 30 ++++++++++--------- drivers/dpll/dpll_nl.c | 2 ++ drivers/dpll/zl3073x/dpll.c | 6 ++-- .../net/ethernet/mellanox/mlx5/core/dpll.c | 6 ++-- include/linux/dpll.h | 16 +++++++++- 8 files changed, 81 insertions(+), 30 deletions(-) diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst index 37eaef785e304..090cd4d017c3a 100644 --- a/Documentation/driver-api/dpll.rst +++ b/Documentation/driver-api/dpll.rst @@ -258,6 +258,26 @@ in the ``DPLL_A_PIN_PHASE_OFFSET`` attribute. ``DPLL_A_PHASE_OFFSET_MONITOR`` attr state of a feature =============================== ======================== +Fractional frequency offset +=========================== + +The fractional frequency offset (FFO) is reported through two attributes +that carry the same measurement at different precisions: + +- ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET`` in PPM (parts per million) +- ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT`` in PPT (parts per trillion) + +Both attributes appear at the top level of a pin and inside each +``pin-parent-device`` nest. Two FFO types are defined: + +- ``DPLL_FFO_PORT_RXTX_RATE`` - RX vs TX symbol rate offset (top-level) +- ``DPLL_FFO_PIN_DEVICE`` - pin vs parent DPLL offset (per-parent) + +The driver declares which types it supports via the ``supported_ffo`` +bitmask in ``struct dpll_pin_ops``. The core only calls the ``ffo_get`` +callback for types the driver has opted into. The requested type is +passed to the driver in the ``struct dpll_ffo_param``. + Frequency monitor ================= diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml index c45de70a47ce6..91a172617b3a9 100644 --- a/Documentation/netlink/specs/dpll.yaml +++ b/Documentation/netlink/specs/dpll.yaml @@ -448,12 +448,14 @@ attribute-sets: name: fractional-frequency-offset type: sint doc: | - The FFO (Fractional Frequency Offset) between the RX and TX - symbol rate on the media associated with the pin: - (rx_frequency-tx_frequency)/rx_frequency + The FFO (Fractional Frequency Offset) of the pin. + At top level this represents the RX vs TX symbol rate + offset on the media associated with the pin. Inside + the pin-parent-device nest it represents the frequency + offset between the pin and its parent DPLL device. Value is in PPM (parts per million). - This may be implemented for example for pin of type - PIN_TYPE_SYNCE_ETH_PORT. + This is a lower-precision version of + fractional-frequency-offset-ppt. - name: esync-frequency type: u64 @@ -492,12 +494,14 @@ attribute-sets: name: fractional-frequency-offset-ppt type: sint doc: | - The FFO (Fractional Frequency Offset) of the pin with respect to - the nominal frequency. - Value = (frequency_measured - frequency_nominal) / frequency_nominal + The FFO (Fractional Frequency Offset) of the pin. + At top level this represents the RX vs TX symbol rate + offset on the media associated with the pin. Inside + the pin-parent-device nest it represents the frequency + offset between the pin and its parent DPLL device. Value is in PPT (parts per trillion, 10^-12). - Note: This attribute provides higher resolution than the standard - fractional-frequency-offset (which is in PPM). + This is a higher-precision version of + fractional-frequency-offset. - name: measured-frequency type: u64 @@ -534,6 +538,10 @@ attribute-sets: name: operstate - name: phase-offset + - + name: fractional-frequency-offset + - + name: fractional-frequency-offset-ppt - name: pin-parent-pin subset-of: pin diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index cbb635db43210..20a54728549cc 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -879,7 +879,8 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, WARN_ON(!ops->direction_get) || WARN_ON(ops->measured_freq_get && (!dpll_device_ops(dpll)->freq_monitor_get || - !dpll_device_ops(dpll)->freq_monitor_set))) + !dpll_device_ops(dpll)->freq_monitor_set)) || + WARN_ON(ops->supported_ffo && !ops->ffo_get)) return -EINVAL; mutex_lock(&dpll_lock); diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 05cf946b4be5e..00e8696cb267b 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -417,31 +417,28 @@ dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin, static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin, struct dpll_pin_ref *ref, + enum dpll_ffo_type type, struct netlink_ext_ack *extack) { const struct dpll_pin_ops *ops = dpll_pin_ops(ref); - struct dpll_device *dpll = ref->dpll; - s64 ffo; + struct dpll_ffo_param ffo = { .type = type }; int ret; - if (!ops->ffo_get) + if (!ops->ffo_get || !(ops->supported_ffo & BIT(type))) return 0; - ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(dpll, pin), - dpll, dpll_priv(dpll), &ffo, extack); + ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(ref->dpll, pin), + ref->dpll, dpll_priv(ref->dpll), &ffo, extack); if (ret) { if (ret == -ENODATA) return 0; return ret; } - /* Put the FFO value in PPM to preserve compatibility with older - * programs. - */ - ret = nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, - div_s64(ffo, 1000000)); - if (ret) + if (nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, + div_s64(ffo.ffo, 1000000))) return -EMSGSIZE; - return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, - ffo); + return nla_put_sint(msg, + DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, + ffo.ffo); } static int dpll_msg_add_measured_freq(struct sk_buff *msg, struct dpll_pin *pin, @@ -686,6 +683,10 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin, if (ret) goto nest_cancel; ret = dpll_msg_add_phase_offset(msg, pin, ref, extack); + if (ret) + goto nest_cancel; + ret = dpll_msg_add_ffo(msg, pin, ref, + DPLL_FFO_PIN_DEVICE, extack); if (ret) goto nest_cancel; nla_nest_end(msg, attr); @@ -748,7 +749,8 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin, ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack); if (ret) return ret; - ret = dpll_msg_add_ffo(msg, pin, ref, extack); + ret = dpll_msg_add_ffo(msg, pin, ref, + DPLL_FFO_PORT_RXTX_RATE, extack); if (ret) return ret; ret = dpll_msg_add_measured_freq(msg, pin, ref, extack); diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c index 58235845fa3d5..b1d9182c7802f 100644 --- a/drivers/dpll/dpll_nl.c +++ b/drivers/dpll/dpll_nl.c @@ -19,6 +19,8 @@ const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3), [DPLL_A_PIN_OPERSTATE] = NLA_POLICY_RANGE(NLA_U32, 1, 4), [DPLL_A_PIN_PHASE_OFFSET] = { .type = NLA_S64, }, + [DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET] = { .type = NLA_SINT, }, + [DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT] = { .type = NLA_SINT, }, }; const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1] = { diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c index 6fd718696de0d..05e63661bf074 100644 --- a/drivers/dpll/zl3073x/dpll.c +++ b/drivers/dpll/zl3073x/dpll.c @@ -295,11 +295,12 @@ zl3073x_dpll_input_pin_ref_sync_set(const struct dpll_pin *dpll_pin, 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 dpll_ffo_param *ffo, + struct netlink_ext_ack *extack) { struct zl3073x_dpll_pin *pin = pin_priv; - *ffo = pin->freq_offset; + ffo->ffo = pin->freq_offset; return 0; } @@ -1274,6 +1275,7 @@ zl3073x_dpll_freq_monitor_set(const struct dpll_device *dpll, } static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = { + .supported_ffo = BIT(DPLL_FFO_PORT_RXTX_RATE), .direction_get = zl3073x_dpll_pin_direction_get, .esync_get = zl3073x_dpll_input_pin_esync_get, .esync_set = zl3073x_dpll_input_pin_esync_set, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c index bce72e8d1bc31..7c69d9029bfa4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c @@ -300,7 +300,8 @@ static int mlx5_dpll_state_on_dpll_set(const struct dpll_pin *pin, static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv, const struct dpll_device *dpll, void *dpll_priv, - s64 *ffo, struct netlink_ext_ack *extack) + struct dpll_ffo_param *ffo, + struct netlink_ext_ack *extack) { struct mlx5_dpll_synce_status synce_status; struct mlx5_dpll *mdpll = pin_priv; @@ -309,10 +310,11 @@ static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv, err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status); if (err) return err; - return mlx5_dpll_pin_ffo_get(&synce_status, ffo); + return mlx5_dpll_pin_ffo_get(&synce_status, &ffo->ffo); } static const struct dpll_pin_ops mlx5_dpll_pins_ops = { + .supported_ffo = BIT(DPLL_FFO_PORT_RXTX_RATE), .direction_get = mlx5_dpll_pin_direction_get, .state_on_dpll_get = mlx5_dpll_state_on_dpll_get, .state_on_dpll_set = mlx5_dpll_state_on_dpll_set, diff --git a/include/linux/dpll.h b/include/linux/dpll.h index b6f16c884b99e..945dfde9dc54d 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -60,7 +60,20 @@ struct dpll_device_ops { struct netlink_ext_ack *extack); }; +enum dpll_ffo_type { + DPLL_FFO_PORT_RXTX_RATE, + DPLL_FFO_PIN_DEVICE, + + __DPLL_FFO_TYPE_MAX, +}; + +struct dpll_ffo_param { + enum dpll_ffo_type type; + s64 ffo; +}; + struct dpll_pin_ops { + unsigned long supported_ffo; int (*frequency_set)(const struct dpll_pin *pin, void *pin_priv, const struct dpll_device *dpll, void *dpll_priv, const u64 frequency, @@ -121,7 +134,8 @@ struct dpll_pin_ops { struct netlink_ext_ack *extack); int (*ffo_get)(const struct dpll_pin *pin, void *pin_priv, const struct dpll_device *dpll, void *dpll_priv, - s64 *ffo, struct netlink_ext_ack *extack); + struct dpll_ffo_param *ffo, + struct netlink_ext_ack *extack); int (*measured_freq_get)(const struct dpll_pin *pin, void *pin_priv, const struct dpll_device *dpll, void *dpll_priv, u64 *measured_freq, -- 2.53.0 Replace the per-reference frequency offset measurement (which was redundant with measured-frequency) with a direct read of the DPLL's delta frequency offset vs its tracked input reference. The new implementation uses the dpll_df_offset_x register with ref_ofst=1 via the dpll_df_read_x semaphore mechanism. This provides 2^-48 resolution (~3.5 fE) and reports the actual frequency difference between the DPLL and its active input. Switch supported_ffo from DPLL_FFO_PORT_RXTX_RATE to DPLL_FFO_PIN_DEVICE so FFO is reported only in the per-parent context for the active input pin. Use atomic64_t for freq_offset to prevent torn reads on 32-bit architectures between the periodic worker and netlink callbacks. Rewrite ffo_check to compare the cached df_offset converted to PPT instead of using the old per-reference measurement. Remove the ref_ffo_update periodic measurement and the ref ffo field since they are no longer needed. Changes v3 -> v4: - Switch to DPLL_FFO_PIN_DEVICE, remove dpll=NULL guard - Use atomic64_t for freq_offset (torn read on 32-bit) Reviewed-by: Petr Oros Signed-off-by: Ivan Vecera --- drivers/dpll/zl3073x/chan.c | 31 +++++++++++++++++++++++-- drivers/dpll/zl3073x/chan.h | 14 ++++++++++++ drivers/dpll/zl3073x/core.c | 45 ------------------------------------- drivers/dpll/zl3073x/dpll.c | 38 ++++++++++++++----------------- drivers/dpll/zl3073x/ref.h | 14 ------------ drivers/dpll/zl3073x/regs.h | 15 +++++++++++++ 6 files changed, 75 insertions(+), 82 deletions(-) diff --git a/drivers/dpll/zl3073x/chan.c b/drivers/dpll/zl3073x/chan.c index 2f48ca2391494..2fe3c3da84bb5 100644 --- a/drivers/dpll/zl3073x/chan.c +++ b/drivers/dpll/zl3073x/chan.c @@ -18,6 +18,7 @@ int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index) { struct zl3073x_chan *chan = &zldev->chan[index]; + u64 val; int rc; rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MON_STATUS(index), @@ -25,8 +26,34 @@ int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index) if (rc) return rc; - return zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index), - &chan->refsel_status); + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index), + &chan->refsel_status); + if (rc) + return rc; + + /* Read df_offset vs tracked reference */ + rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index), + ZL_DPLL_DF_READ_SEM); + if (rc) + return rc; + + rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_DF_READ(index), + ZL_DPLL_DF_READ_SEM | ZL_DPLL_DF_READ_REF_OFST); + if (rc) + return rc; + + rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index), + ZL_DPLL_DF_READ_SEM); + if (rc) + return rc; + + rc = zl3073x_read_u48(zldev, ZL_REG_DPLL_DF_OFFSET(index), &val); + if (rc) + return rc; + + chan->df_offset = sign_extend64(val, 47); + + return 0; } /** diff --git a/drivers/dpll/zl3073x/chan.h b/drivers/dpll/zl3073x/chan.h index 481da2133202b..4353809c69122 100644 --- a/drivers/dpll/zl3073x/chan.h +++ b/drivers/dpll/zl3073x/chan.h @@ -17,6 +17,7 @@ struct zl3073x_dev; * @ref_prio: reference priority registers (4 bits per ref, P/N packed) * @mon_status: monitor status register value * @refsel_status: reference selection status register value + * @df_offset: frequency offset vs tracked reference in 2^-48 steps */ struct zl3073x_chan { struct_group(cfg, @@ -26,6 +27,7 @@ struct zl3073x_chan { struct_group(stat, u8 mon_status; u8 refsel_status; + s64 df_offset; ); }; @@ -37,6 +39,18 @@ int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index, int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index); +/** + * zl3073x_chan_df_offset_get - get cached df_offset vs tracked reference + * @chan: pointer to channel state + * + * Return: frequency offset in 2^-48 steps + */ +static inline s64 +zl3073x_chan_df_offset_get(const struct zl3073x_chan *chan) +{ + return chan->df_offset; +} + /** * zl3073x_chan_mode_get - get DPLL channel operating mode * @chan: pointer to channel state diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c index 5f1e70f3e40a0..b3345060490db 100644 --- a/drivers/dpll/zl3073x/core.c +++ b/drivers/dpll/zl3073x/core.c @@ -704,44 +704,6 @@ zl3073x_ref_freq_meas_update(struct zl3073x_dev *zldev) return 0; } -/** - * zl3073x_ref_ffo_update - update reference fractional frequency offsets - * @zldev: pointer to zl3073x_dev structure - * - * The function asks device to latch the latest measured fractional - * frequency offset values, reads and stores them into the ref state. - * - * Return: 0 on success, <0 on error - */ -static int -zl3073x_ref_ffo_update(struct zl3073x_dev *zldev) -{ - int i, rc; - - rc = zl3073x_ref_freq_meas_latch(zldev, - ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF); - if (rc) - return rc; - - /* Read DPLL-to-REFx frequency offset measurements */ - for (i = 0; i < ZL3073X_NUM_REFS; i++) { - s32 value; - - /* Read value stored in units of 2^-32 signed */ - rc = zl3073x_read_u32(zldev, ZL_REG_REF_FREQ(i), &value); - if (rc) - return rc; - - /* Convert to ppt - * ffo = (10^12 * value) / 2^32 - * ffo = ( 5^12 * value) / 2^20 - */ - zldev->ref[i].ffo = mul_s64_u64_shr(value, 244140625, 20); - } - - return 0; -} - static void zl3073x_dev_periodic_work(struct kthread_work *work) { @@ -776,13 +738,6 @@ zl3073x_dev_periodic_work(struct kthread_work *work) } } - /* Update references' fractional frequency offsets */ - rc = zl3073x_ref_ffo_update(zldev); - if (rc) - dev_warn(zldev->dev, - "Failed to update fractional frequency offsets: %pe\n", - ERR_PTR(rc)); - list_for_each_entry(zldpll, &zldev->dplls, list) zl3073x_dpll_changes_check(zldpll); diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c index 05e63661bf074..cff85cdb9d0e5 100644 --- a/drivers/dpll/zl3073x/dpll.c +++ b/drivers/dpll/zl3073x/dpll.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only +#include #include #include #include @@ -57,7 +58,7 @@ struct zl3073x_dpll_pin { s32 phase_gran; enum dpll_pin_operstate operstate; s64 phase_offset; - s64 freq_offset; + atomic64_t freq_offset; u32 measured_freq; }; @@ -300,7 +301,10 @@ zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv, { struct zl3073x_dpll_pin *pin = pin_priv; - ffo->ffo = pin->freq_offset; + if (pin->operstate != DPLL_PIN_OPERSTATE_ACTIVE) + return -ENODATA; + + ffo->ffo = atomic64_read(&pin->freq_offset); return 0; } @@ -1275,7 +1279,7 @@ zl3073x_dpll_freq_monitor_set(const struct dpll_device *dpll, } static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = { - .supported_ffo = BIT(DPLL_FFO_PORT_RXTX_RATE), + .supported_ffo = BIT(DPLL_FFO_PIN_DEVICE), .direction_get = zl3073x_dpll_pin_direction_get, .esync_get = zl3073x_dpll_input_pin_esync_get, .esync_set = zl3073x_dpll_input_pin_esync_set, @@ -1731,37 +1735,29 @@ zl3073x_dpll_pin_phase_offset_check(struct zl3073x_dpll_pin *pin) } /** - * zl3073x_dpll_pin_ffo_check - check for pin fractional frequency offset change + * zl3073x_dpll_pin_ffo_check - check for FFO change on active pin * @pin: pin to check * - * Check for the given pin's fractional frequency change. - * - * Return: true on fractional frequency offset change, false otherwise + * Return: true on change, false otherwise */ static bool zl3073x_dpll_pin_ffo_check(struct zl3073x_dpll_pin *pin) { struct zl3073x_dpll *zldpll = pin->dpll; struct zl3073x_dev *zldev = zldpll->dev; - const struct zl3073x_ref *ref; - u8 ref_id; + const struct zl3073x_chan *chan; s64 ffo; - /* Get reference monitor status */ - ref_id = zl3073x_input_pin_ref_get(pin->id); - ref = zl3073x_ref_state_get(zldev, ref_id); - - /* Do not report ffo changes if the reference monitor report errors */ - if (!zl3073x_ref_is_status_ok(ref)) + if (pin->operstate != DPLL_PIN_OPERSTATE_ACTIVE) return false; - /* Compare with previous value */ - ffo = zl3073x_ref_ffo_get(ref); - if (pin->freq_offset != ffo) { - dev_dbg(zldev->dev, "%s freq offset changed: %lld -> %lld\n", - pin->label, pin->freq_offset, ffo); - pin->freq_offset = ffo; + chan = zl3073x_chan_state_get(zldpll->dev, zldpll->id); + ffo = mul_s64_u64_shr(zl3073x_chan_df_offset_get(chan), + 244140625, 36); + if (atomic64_xchg(&pin->freq_offset, ffo) != ffo) { + dev_dbg(zldev->dev, "%s freq offset changed to: %lld\n", + pin->label, ffo); return true; } diff --git a/drivers/dpll/zl3073x/ref.h b/drivers/dpll/zl3073x/ref.h index 55e80e4f08734..e140ca3ea17dc 100644 --- a/drivers/dpll/zl3073x/ref.h +++ b/drivers/dpll/zl3073x/ref.h @@ -22,7 +22,6 @@ struct zl3073x_dev; * @freq_ratio_n: FEC mode divisor * @sync_ctrl: reference sync control * @config: reference config - * @ffo: current fractional frequency offset * @meas_freq: measured input frequency in Hz * @mon_status: reference monitor status */ @@ -40,7 +39,6 @@ struct zl3073x_ref { u8 config; ); struct_group(stat, /* Status */ - s64 ffo; u32 meas_freq; u8 mon_status; ); @@ -58,18 +56,6 @@ int zl3073x_ref_state_update(struct zl3073x_dev *zldev, u8 index); int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); -/** - * zl3073x_ref_ffo_get - get current fractional frequency offset - * @ref: pointer to ref state - * - * Return: the latest measured fractional frequency offset - */ -static inline s64 -zl3073x_ref_ffo_get(const struct zl3073x_ref *ref) -{ - return ref->ffo; -} - /** * zl3073x_ref_meas_freq_get - get measured input frequency * @ref: pointer to ref state diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h index 8015808bdf548..9578f00095282 100644 --- a/drivers/dpll/zl3073x/regs.h +++ b/drivers/dpll/zl3073x/regs.h @@ -164,6 +164,11 @@ #define ZL_DPLL_MODE_REFSEL_MODE_NCO 4 #define ZL_DPLL_MODE_REFSEL_REF GENMASK(7, 4) +#define ZL_REG_DPLL_DF_READ(_idx) \ + ZL_REG_IDX(_idx, 5, 0x28, 1, ZL3073X_MAX_CHANNELS, 1) +#define ZL_DPLL_DF_READ_SEM BIT(4) +#define ZL_DPLL_DF_READ_REF_OFST BIT(3) + #define ZL_REG_DPLL_MEAS_CTRL ZL_REG(5, 0x50, 1) #define ZL_DPLL_MEAS_CTRL_EN BIT(0) #define ZL_DPLL_MEAS_CTRL_AVG_FACTOR GENMASK(7, 4) @@ -176,6 +181,16 @@ #define ZL_REG_DPLL_PHASE_ERR_DATA(_idx) \ ZL_REG_IDX(_idx, 5, 0x55, 6, ZL3073X_MAX_CHANNELS, 6) +/******************************* + * Register Pages 6-7, DPLL Data + *******************************/ + +#define ZL_REG_DPLL_DF_OFFSET_03(_idx) \ + ZL_REG_IDX(_idx, 6, 0x00, 6, 4, 0x20) +#define ZL_REG_DPLL_DF_OFFSET_4 ZL_REG(7, 0x00, 6) +#define ZL_REG_DPLL_DF_OFFSET(_idx) \ + ((_idx) < 4 ? ZL_REG_DPLL_DF_OFFSET_03(_idx) : ZL_REG_DPLL_DF_OFFSET_4) + /*********************************** * Register Page 9, Synth and Output ***********************************/ -- 2.53.0