Merge branch 'dpll-add-all-inputs-phase-offset-monitor'

Arkadiusz Kubalewski says:

====================
dpll: add all inputs phase offset monitor

Add dpll device level feature: phase offset monitor.

Phase offset measurement is typically performed against the current active
source. However, some DPLL (Digital Phase-Locked Loop) devices may offer
the capability to monitor phase offsets across all available inputs.
The attribute and current feature state shall be included in the response
message of the ``DPLL_CMD_DEVICE_GET`` command for supported DPLL devices.
In such cases, users can also control the feature using the
``DPLL_CMD_DEVICE_SET`` command by setting the ``enum dpll_feature_state``
values for the attribute.
Once enabled the phase offset measurements for the input shall be returned
in the ``DPLL_A_PIN_PHASE_OFFSET`` attribute.

Implement feature support in ice driver for dpll-enabled devices.

Verify capability:
$ ./tools/net/ynl/pyynl/cli.py \
 --spec Documentation/netlink/specs/dpll.yaml \
 --dump device-get
[{'clock-id': 4658613174691613800,
  'id': 0,
  'lock-status': 'locked-ho-acq',
  'mode': 'automatic',
  'mode-supported': ['automatic'],
  'module-name': 'ice',
  'type': 'eec'},
 {'clock-id': 4658613174691613800,
  'id': 1,
  'lock-status': 'locked-ho-acq',
  'mode': 'automatic',
  'mode-supported': ['automatic'],
  'module-name': 'ice',
  'phase-offset-monitor': 'disable',
  'type': 'pps'}]

Enable the feature:
$ ./tools/net/ynl/pyynl/cli.py \
 --spec Documentation/netlink/specs/dpll.yaml \
 --do device-set --json '{"id":1, "phase-offset-monitor":"enable"}'

Verify feature is enabled:
$ ./tools/net/ynl/pyynl/cli.py \
 --spec Documentation/netlink/specs/dpll.yaml \
 --dump device-get
[
 [...]
 {'capabilities': {'all-inputs-phase-offset-monitor'},
  'clock-id': 4658613174691613800,
  'id': 1,
 [...]
  'phase-offset-monitor': 'enable',
 [...]]

v6:
- rebase.
====================

Link: https://patch.msgid.link/20250612152835.1703397-1-arkadiusz.kubalewski@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2025-06-13 18:21:59 -07:00
12 changed files with 384 additions and 6 deletions
+18
View File
@@ -214,6 +214,24 @@ offset values are fractional with 3-digit decimal places and shell be
divided with ``DPLL_PIN_PHASE_OFFSET_DIVIDER`` to get integer part and
modulo divided to get fractional part.
Phase offset monitor
====================
Phase offset measurement is typically performed against the current active
source. However, some DPLL (Digital Phase-Locked Loop) devices may offer
the capability to monitor phase offsets across all available inputs.
The attribute and current feature state shall be included in the response
message of the ``DPLL_CMD_DEVICE_GET`` command for supported DPLL devices.
In such cases, users can also control the feature using the
``DPLL_CMD_DEVICE_SET`` command by setting the ``enum dpll_feature_state``
values for the attribute.
Once enabled the phase offset measurements for the input shall be returned
in the ``DPLL_A_PIN_PHASE_OFFSET`` attribute.
=============================== ========================
``DPLL_A_PHASE_OFFSET_MONITOR`` attr state of a feature
=============================== ========================
Embedded SYNC
=============
+24
View File
@@ -240,6 +240,20 @@ definitions:
integer part of a measured phase offset value.
Value of (DPLL_A_PHASE_OFFSET % DPLL_PHASE_OFFSET_DIVIDER) is a
fractional part of a measured phase offset value.
-
type: enum
name: feature-state
doc: |
Allow control (enable/disable) and status checking over features.
entries:
-
name: disable
doc: |
feature shall be disabled
-
name: enable
doc: |
feature shall be enabled
attribute-sets:
-
@@ -293,6 +307,14 @@ attribute-sets:
be put to message multiple times to indicate possible parallel
quality levels (e.g. one specified by ITU option 1 and another
one specified by option 2).
-
name: phase-offset-monitor
type: u32
enum: feature-state
doc: Receive or request state of phase offset monitor feature.
If enabled, dpll device shall monitor and notify all currently
available inputs for changes of their phase offset against the
dpll device.
-
name: pin
enum-name: dpll_a_pin
@@ -483,6 +505,7 @@ operations:
- temp
- clock-id
- type
- phase-offset-monitor
dump:
reply: *dev-attrs
@@ -499,6 +522,7 @@ operations:
request:
attributes:
- id
- phase-offset-monitor
-
name: device-create-ntf
doc: Notification about device appearing
+67 -2
View File
@@ -126,6 +126,26 @@ dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll,
return 0;
}
static int
dpll_msg_add_phase_offset_monitor(struct sk_buff *msg, struct dpll_device *dpll,
struct netlink_ext_ack *extack)
{
const struct dpll_device_ops *ops = dpll_device_ops(dpll);
enum dpll_feature_state state;
int ret;
if (ops->phase_offset_monitor_set && ops->phase_offset_monitor_get) {
ret = ops->phase_offset_monitor_get(dpll, dpll_priv(dpll),
&state, extack);
if (ret)
return ret;
if (nla_put_u32(msg, DPLL_A_PHASE_OFFSET_MONITOR, state))
return -EMSGSIZE;
}
return 0;
}
static int
dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll,
struct netlink_ext_ack *extack)
@@ -591,6 +611,9 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
return ret;
if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type))
return -EMSGSIZE;
ret = dpll_msg_add_phase_offset_monitor(msg, dpll, extack);
if (ret)
return ret;
return 0;
}
@@ -746,6 +769,31 @@ int dpll_pin_change_ntf(struct dpll_pin *pin)
}
EXPORT_SYMBOL_GPL(dpll_pin_change_ntf);
static int
dpll_phase_offset_monitor_set(struct dpll_device *dpll, struct nlattr *a,
struct netlink_ext_ack *extack)
{
const struct dpll_device_ops *ops = dpll_device_ops(dpll);
enum dpll_feature_state state = nla_get_u32(a), old_state;
int ret;
if (!(ops->phase_offset_monitor_set && ops->phase_offset_monitor_get)) {
NL_SET_ERR_MSG_ATTR(extack, a, "dpll device not capable of phase offset monitor");
return -EOPNOTSUPP;
}
ret = ops->phase_offset_monitor_get(dpll, dpll_priv(dpll), &old_state,
extack);
if (ret) {
NL_SET_ERR_MSG(extack, "unable to get current state of phase offset monitor");
return ret;
}
if (state == old_state)
return 0;
return ops->phase_offset_monitor_set(dpll, dpll_priv(dpll), state,
extack);
}
static int
dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
struct netlink_ext_ack *extack)
@@ -1533,10 +1581,27 @@ int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
return genlmsg_reply(msg, info);
}
static int
dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info)
{
int ret;
if (info->attrs[DPLL_A_PHASE_OFFSET_MONITOR]) {
struct nlattr *a = info->attrs[DPLL_A_PHASE_OFFSET_MONITOR];
ret = dpll_phase_offset_monitor_set(dpll, a, info->extack);
if (ret)
return ret;
}
return 0;
}
int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info)
{
/* placeholder for set command */
return 0;
struct dpll_device *dpll = info->user_ptr[0];
return dpll_set_from_nlattr(dpll, info);
}
int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+3 -2
View File
@@ -37,8 +37,9 @@ static const struct nla_policy dpll_device_get_nl_policy[DPLL_A_ID + 1] = {
};
/* DPLL_CMD_DEVICE_SET - do */
static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_ID + 1] = {
static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_PHASE_OFFSET_MONITOR + 1] = {
[DPLL_A_ID] = { .type = NLA_U32, },
[DPLL_A_PHASE_OFFSET_MONITOR] = NLA_POLICY_MAX(NLA_U32, 1),
};
/* DPLL_CMD_PIN_ID_GET - do */
@@ -105,7 +106,7 @@ static const struct genl_split_ops dpll_nl_ops[] = {
.doit = dpll_nl_device_set_doit,
.post_doit = dpll_post_doit,
.policy = dpll_device_set_nl_policy,
.maxattr = DPLL_A_ID,
.maxattr = DPLL_A_PHASE_OFFSET_MONITOR,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
@@ -2272,6 +2272,22 @@ struct ice_aqc_get_pkg_info_resp {
struct ice_aqc_get_pkg_info pkg_info[];
};
#define ICE_CGU_INPUT_PHASE_OFFSET_BYTES 6
struct ice_cgu_input_measure {
u8 phase_offset[ICE_CGU_INPUT_PHASE_OFFSET_BYTES];
__le32 freq;
} __packed __aligned(sizeof(__le16));
#define ICE_AQC_GET_CGU_IN_MEAS_DPLL_IDX_M ICE_M(0xf, 0)
/* Get CGU input measure command response data structure (indirect 0x0C59) */
struct ice_aqc_get_cgu_input_measure {
u8 dpll_idx_opt;
u8 length;
u8 rsvd[6];
};
#define ICE_AQC_GET_CGU_MAX_PHASE_ADJ GENMASK(30, 0)
/* Get CGU abilities command response data structure (indirect 0x0C61) */
@@ -2721,6 +2737,7 @@ struct ice_aq_desc {
struct ice_aqc_add_get_update_free_vsi vsi_cmd;
struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res;
struct ice_aqc_download_pkg download_pkg;
struct ice_aqc_get_cgu_input_measure get_cgu_input_measure;
struct ice_aqc_set_cgu_input_config set_cgu_input_config;
struct ice_aqc_get_cgu_input_config get_cgu_input_config;
struct ice_aqc_set_cgu_output_config set_cgu_output_config;
@@ -2772,6 +2789,8 @@ enum ice_aq_err {
ICE_AQ_RC_OK = 0, /* Success */
ICE_AQ_RC_EPERM = 1, /* Operation not permitted */
ICE_AQ_RC_ENOENT = 2, /* No such element */
ICE_AQ_RC_ESRCH = 3, /* Bad opcode */
ICE_AQ_RC_EAGAIN = 8, /* Try again */
ICE_AQ_RC_ENOMEM = 9, /* Out of memory */
ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */
ICE_AQ_RC_EEXIST = 13, /* Object already exists */
@@ -2927,6 +2946,7 @@ enum ice_adminq_opc {
ice_aqc_opc_get_pkg_info_list = 0x0C43,
/* 1588/SyncE commands/events */
ice_aqc_opc_get_cgu_input_measure = 0x0C59,
ice_aqc_opc_get_cgu_abilities = 0x0C61,
ice_aqc_opc_set_cgu_input_config = 0x0C62,
ice_aqc_opc_get_cgu_input_config = 0x0C63,
@@ -4970,6 +4970,32 @@ ice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid,
return status;
}
/**
* ice_aq_get_cgu_input_pin_measure - get input pin signal measurements
* @hw: pointer to the HW struct
* @dpll_idx: index of dpll to be measured
* @meas: array to be filled with results
* @meas_num: max number of results array can hold
*
* Get CGU measurements (0x0C59) of phase and frequency offsets for input
* pins on given dpll.
*
* Return: 0 on success or negative value on failure.
*/
int ice_aq_get_cgu_input_pin_measure(struct ice_hw *hw, u8 dpll_idx,
struct ice_cgu_input_measure *meas,
u16 meas_num)
{
struct ice_aqc_get_cgu_input_measure *cmd;
struct ice_aq_desc desc;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cgu_input_measure);
cmd = &desc.params.get_cgu_input_measure;
cmd->dpll_idx_opt = dpll_idx & ICE_AQC_GET_CGU_IN_MEAS_DPLL_IDX_M;
return ice_aq_send_cmd(hw, &desc, meas, meas_num * sizeof(*meas), NULL);
}
/**
* ice_aq_get_cgu_abilities - get cgu abilities
* @hw: pointer to the HW struct
@@ -229,6 +229,9 @@ void ice_replay_post(struct ice_hw *hw);
struct ice_q_ctx *
ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle);
int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in, u16 flag);
int ice_aq_get_cgu_input_pin_measure(struct ice_hw *hw, u8 dpll_idx,
struct ice_cgu_input_measure *meas,
u16 meas_num);
int
ice_aq_get_cgu_abilities(struct ice_hw *hw,
struct ice_aqc_get_cgu_abilities *abilities);
+191 -2
View File
@@ -12,6 +12,8 @@
#define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT 25
#define ICE_DPLL_PIN_GEN_RCLK_FREQ 1953125
#define ICE_DPLL_PIN_PRIO_OUTPUT 0xff
#define ICE_DPLL_INPUT_REF_NUM 10
#define ICE_DPLL_PHASE_OFFSET_PERIOD 2
#define ICE_DPLL_SW_PIN_INPUT_BASE_SFP 4
#define ICE_DPLL_SW_PIN_INPUT_BASE_QSFP 6
#define ICE_DPLL_SW_PIN_OUTPUT_BASE 0
@@ -792,6 +794,67 @@ static int ice_dpll_mode_get(const struct dpll_device *dpll, void *dpll_priv,
return 0;
}
/**
* ice_dpll_phase_offset_monitor_set - set phase offset monitor state
* @dpll: registered dpll pointer
* @dpll_priv: private data pointer passed on dpll registration
* @state: feature state to be set
* @extack: error reporting
*
* Dpll subsystem callback. Enable/disable phase offset monitor feature of dpll.
*
* Context: Acquires and releases pf->dplls.lock
* Return: 0 - success
*/
static int ice_dpll_phase_offset_monitor_set(const struct dpll_device *dpll,
void *dpll_priv,
enum dpll_feature_state state,
struct netlink_ext_ack *extack)
{
struct ice_dpll *d = dpll_priv;
struct ice_pf *pf = d->pf;
mutex_lock(&pf->dplls.lock);
if (state == DPLL_FEATURE_STATE_ENABLE)
d->phase_offset_monitor_period = ICE_DPLL_PHASE_OFFSET_PERIOD;
else
d->phase_offset_monitor_period = 0;
mutex_unlock(&pf->dplls.lock);
return 0;
}
/**
* ice_dpll_phase_offset_monitor_get - get phase offset monitor state
* @dpll: registered dpll pointer
* @dpll_priv: private data pointer passed on dpll registration
* @state: on success holds current state of phase offset monitor
* @extack: error reporting
*
* Dpll subsystem callback. Provides current state of phase offset monitor
* features on dpll device.
*
* Context: Acquires and releases pf->dplls.lock
* Return: 0 - success
*/
static int ice_dpll_phase_offset_monitor_get(const struct dpll_device *dpll,
void *dpll_priv,
enum dpll_feature_state *state,
struct netlink_ext_ack *extack)
{
struct ice_dpll *d = dpll_priv;
struct ice_pf *pf = d->pf;
mutex_lock(&pf->dplls.lock);
if (d->phase_offset_monitor_period)
*state = DPLL_FEATURE_STATE_ENABLE;
else
*state = DPLL_FEATURE_STATE_DISABLE;
mutex_unlock(&pf->dplls.lock);
return 0;
}
/**
* ice_dpll_pin_state_set - set pin's state on dpll
* @pin: pointer to a pin
@@ -1757,6 +1820,8 @@ ice_dpll_phase_offset_get(const struct dpll_pin *pin, void *pin_priv,
if (d->active_input == pin || (p->input &&
d->active_input == p->input->pin))
*phase_offset = d->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR;
else if (d->phase_offset_monitor_period)
*phase_offset = p->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR;
else
*phase_offset = 0;
mutex_unlock(&pf->dplls.lock);
@@ -2216,6 +2281,13 @@ static const struct dpll_device_ops ice_dpll_ops = {
.mode_get = ice_dpll_mode_get,
};
static const struct dpll_device_ops ice_dpll_pom_ops = {
.lock_status_get = ice_dpll_lock_status_get,
.mode_get = ice_dpll_mode_get,
.phase_offset_monitor_set = ice_dpll_phase_offset_monitor_set,
.phase_offset_monitor_get = ice_dpll_phase_offset_monitor_get,
};
/**
* ice_generate_clock_id - generates unique clock_id for registering dpll.
* @pf: board private structure
@@ -2260,6 +2332,110 @@ static void ice_dpll_notify_changes(struct ice_dpll *d)
}
}
/**
* ice_dpll_is_pps_phase_monitor - check if dpll capable of phase offset monitor
* @pf: pf private structure
*
* Check if firmware is capable of supporting admin command to provide
* phase offset monitoring on all the input pins on PPS dpll.
*
* Returns:
* * true - PPS dpll phase offset monitoring is supported
* * false - PPS dpll phase offset monitoring is not supported
*/
static bool ice_dpll_is_pps_phase_monitor(struct ice_pf *pf)
{
struct ice_cgu_input_measure meas[ICE_DPLL_INPUT_REF_NUM];
int ret = ice_aq_get_cgu_input_pin_measure(&pf->hw, DPLL_TYPE_PPS, meas,
ARRAY_SIZE(meas));
if (ret && pf->hw.adminq.sq_last_status == ICE_AQ_RC_ESRCH)
return false;
return true;
}
/**
* ice_dpll_pins_notify_mask - notify dpll subsystem about bulk pin changes
* @pins: array of ice_dpll_pin pointers registered within dpll subsystem
* @pin_num: number of pins
* @phase_offset_ntf_mask: bitmask of pin indexes to notify
*
* Iterate over array of pins and call dpll subsystem pin notify if
* corresponding pin index within bitmask is set.
*
* Context: Must be called while pf->dplls.lock is released.
*/
static void ice_dpll_pins_notify_mask(struct ice_dpll_pin *pins,
u8 pin_num,
u32 phase_offset_ntf_mask)
{
int i = 0;
for (i = 0; i < pin_num; i++)
if (phase_offset_ntf_mask & (1 << i))
dpll_pin_change_ntf(pins[i].pin);
}
/**
* ice_dpll_pps_update_phase_offsets - update phase offset measurements
* @pf: pf private structure
* @phase_offset_pins_updated: returns mask of updated input pin indexes
*
* Read phase offset measurements for PPS dpll device and store values in
* input pins array. On success phase_offset_pins_updated - fills bitmask of
* updated input pin indexes, pins shall be notified.
*
* Context: Shall be called with pf->dplls.lock being locked.
* Returns:
* * 0 - success or no data available
* * negative - AQ failure
*/
static int ice_dpll_pps_update_phase_offsets(struct ice_pf *pf,
u32 *phase_offset_pins_updated)
{
struct ice_cgu_input_measure meas[ICE_DPLL_INPUT_REF_NUM];
struct ice_dpll_pin *p;
s64 phase_offset, tmp;
int i, j, ret;
*phase_offset_pins_updated = 0;
ret = ice_aq_get_cgu_input_pin_measure(&pf->hw, DPLL_TYPE_PPS, meas,
ARRAY_SIZE(meas));
if (ret && pf->hw.adminq.sq_last_status == ICE_AQ_RC_EAGAIN) {
return 0;
} else if (ret) {
dev_err(ice_pf_to_dev(pf),
"failed to get input pin measurements dpll=%d, ret=%d %s\n",
DPLL_TYPE_PPS, ret,
ice_aq_str(pf->hw.adminq.sq_last_status));
return ret;
}
for (i = 0; i < pf->dplls.num_inputs; i++) {
p = &pf->dplls.inputs[i];
phase_offset = 0;
for (j = 0; j < ICE_CGU_INPUT_PHASE_OFFSET_BYTES; j++) {
tmp = meas[i].phase_offset[j];
#ifdef __LITTLE_ENDIAN
phase_offset += tmp << 8 * j;
#else
phase_offset += tmp << 8 *
(ICE_CGU_INPUT_PHASE_OFFSET_BYTES - 1 - j);
#endif
}
phase_offset = sign_extend64(phase_offset, 47);
if (p->phase_offset != phase_offset) {
dev_dbg(ice_pf_to_dev(pf),
"phase offset changed for pin:%d old:%llx, new:%llx\n",
p->idx, p->phase_offset, phase_offset);
p->phase_offset = phase_offset;
*phase_offset_pins_updated |= (1 << i);
}
}
return 0;
}
/**
* ice_dpll_update_state - update dpll state
* @pf: pf private structure
@@ -2346,14 +2522,19 @@ static void ice_dpll_periodic_work(struct kthread_work *work)
struct ice_pf *pf = container_of(d, struct ice_pf, dplls);
struct ice_dpll *de = &pf->dplls.eec;
struct ice_dpll *dp = &pf->dplls.pps;
u32 phase_offset_ntf = 0;
int ret = 0;
if (ice_is_reset_in_progress(pf->state))
goto resched;
mutex_lock(&pf->dplls.lock);
d->periodic_counter++;
ret = ice_dpll_update_state(pf, de, false);
if (!ret)
ret = ice_dpll_update_state(pf, dp, false);
if (!ret && dp->phase_offset_monitor_period &&
d->periodic_counter % dp->phase_offset_monitor_period == 0)
ret = ice_dpll_pps_update_phase_offsets(pf, &phase_offset_ntf);
if (ret) {
d->cgu_state_acq_err_num++;
/* stop rescheduling this worker */
@@ -2368,6 +2549,9 @@ static void ice_dpll_periodic_work(struct kthread_work *work)
mutex_unlock(&pf->dplls.lock);
ice_dpll_notify_changes(de);
ice_dpll_notify_changes(dp);
if (phase_offset_ntf)
ice_dpll_pins_notify_mask(d->inputs, d->num_inputs,
phase_offset_ntf);
resched:
/* Run twice a second or reschedule if update failed */
@@ -2782,7 +2966,7 @@ static void
ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu)
{
if (cgu)
dpll_device_unregister(d->dpll, &ice_dpll_ops, d);
dpll_device_unregister(d->dpll, d->ops, d);
dpll_device_put(d->dpll);
}
@@ -2816,12 +3000,17 @@ ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu,
}
d->pf = pf;
if (cgu) {
const struct dpll_device_ops *ops = &ice_dpll_ops;
if (type == DPLL_TYPE_PPS && ice_dpll_is_pps_phase_monitor(pf))
ops = &ice_dpll_pom_ops;
ice_dpll_update_state(pf, d, true);
ret = dpll_device_register(d->dpll, type, &ice_dpll_ops, d);
ret = dpll_device_register(d->dpll, type, ops, d);
if (ret) {
dpll_device_put(d->dpll);
return ret;
}
d->ops = ops;
}
return 0;
@@ -31,6 +31,7 @@ enum ice_dpll_pin_sw {
* @prop: pin properties
* @freq: current frequency of a pin
* @phase_adjust: current phase adjust value
* @phase_offset: monitored phase offset value
*/
struct ice_dpll_pin {
struct dpll_pin *pin;
@@ -46,6 +47,7 @@ struct ice_dpll_pin {
struct ice_dpll_pin *input;
struct ice_dpll_pin *output;
enum dpll_pin_direction direction;
s64 phase_offset;
u8 status;
bool active;
bool hidden;
@@ -64,8 +66,10 @@ struct ice_dpll_pin {
* @input_prio: priorities of each input
* @dpll_state: current dpll sync state
* @prev_dpll_state: last dpll sync state
* @phase_offset_monitor_period: period for phase offset monitor read frequency
* @active_input: pointer to active input pin
* @prev_input: pointer to previous active input pin
* @ops: holds the registered ops
*/
struct ice_dpll {
struct dpll_device *dpll;
@@ -81,8 +85,10 @@ struct ice_dpll {
enum dpll_lock_status dpll_state;
enum dpll_lock_status prev_dpll_state;
enum dpll_mode mode;
u32 phase_offset_monitor_period;
struct dpll_pin *active_input;
struct dpll_pin *prev_input;
const struct dpll_device_ops *ops;
};
/** ice_dplls - store info required for CCU (clock controlling unit)
@@ -101,6 +107,7 @@ struct ice_dpll {
* @clock_id: clock_id of dplls
* @input_phase_adj_max: max phase adjust value for an input pins
* @output_phase_adj_max: max phase adjust value for an output pins
* @periodic_counter: counter of periodic work executions
*/
struct ice_dplls {
struct kthread_worker *kworker;
@@ -121,6 +128,7 @@ struct ice_dplls {
u64 clock_id;
s32 input_phase_adj_max;
s32 output_phase_adj_max;
u32 periodic_counter;
bool generic;
};
@@ -7936,6 +7936,10 @@ const char *ice_aq_str(enum ice_aq_err aq_err)
return "ICE_AQ_RC_EPERM";
case ICE_AQ_RC_ENOENT:
return "ICE_AQ_RC_ENOENT";
case ICE_AQ_RC_ESRCH:
return "ICE_AQ_RC_ESRCH";
case ICE_AQ_RC_EAGAIN:
return "ICE_AQ_RC_EAGAIN";
case ICE_AQ_RC_ENOMEM:
return "ICE_AQ_RC_ENOMEM";
case ICE_AQ_RC_EBUSY:
+8
View File
@@ -30,6 +30,14 @@ struct dpll_device_ops {
void *dpll_priv,
unsigned long *qls,
struct netlink_ext_ack *extack);
int (*phase_offset_monitor_set)(const struct dpll_device *dpll,
void *dpll_priv,
enum dpll_feature_state state,
struct netlink_ext_ack *extack);
int (*phase_offset_monitor_get)(const struct dpll_device *dpll,
void *dpll_priv,
enum dpll_feature_state *state,
struct netlink_ext_ack *extack);
};
struct dpll_pin_ops {
+12
View File
@@ -192,6 +192,17 @@ enum dpll_pin_capabilities {
#define DPLL_PHASE_OFFSET_DIVIDER 1000
/**
* enum dpll_feature_state - Allow control (enable/disable) and status checking
* over features.
* @DPLL_FEATURE_STATE_DISABLE: feature shall be disabled
* @DPLL_FEATURE_STATE_ENABLE: feature shall be enabled
*/
enum dpll_feature_state {
DPLL_FEATURE_STATE_DISABLE,
DPLL_FEATURE_STATE_ENABLE,
};
enum dpll_a {
DPLL_A_ID = 1,
DPLL_A_MODULE_NAME,
@@ -204,6 +215,7 @@ enum dpll_a {
DPLL_A_TYPE,
DPLL_A_LOCK_STATUS_ERROR,
DPLL_A_CLOCK_QUALITY_LEVEL,
DPLL_A_PHASE_OFFSET_MONITOR,
__DPLL_A_MAX,
DPLL_A_MAX = (__DPLL_A_MAX - 1)