mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
Merge branch 'dpll-rework-fractional-frequency-offset-reporting'
Ivan Vecera says: ==================== dpll: rework fractional frequency offset reporting Rework how the fractional frequency offset (FFO) is reported in the DPLL subsystem. Both fractional-frequency-offset (PPM) and fractional-frequency-offset-ppt (PPT) attributes are now present at the top level of a pin and inside each pin-parent-device nest. They 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 at the top level, and DPLL_FFO_PIN_DEVICE for the pin vs parent DPLL offset in the nest. Drivers declare which types they support via the supported_ffo bitmask in dpll_pin_ops; the core only calls ffo_get for opted-in types. Patch 1 adds the type-safe FFO API, updates the YAML spec, netlink handling, and documentation, and converts mlx5 and zl3073x drivers. Patch 2 implements the nested FFO for zl3073x using the dpll_df_offset_x register with ref_ofst=1, providing 2^-48 resolution. The old per-reference frequency measurement is removed as it was redundant with measured-frequency. ==================== Link: https://patch.msgid.link/20260511155816.99936-1-ivecera@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
8ebd24a782
|
|
@ -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
|
||||
=================
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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] = {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bug.h>
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
@ -295,11 +296,15 @@ 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;
|
||||
if (pin->operstate != DPLL_PIN_OPERSTATE_ACTIVE)
|
||||
return -ENODATA;
|
||||
|
||||
ffo->ffo = atomic64_read(&pin->freq_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1274,6 +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_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,
|
||||
|
|
@ -1729,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
***********************************/
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user