Skip to content

Commit

Permalink
ice: add callbacks for Embedded SYNC enablement on dpll pins
Browse files Browse the repository at this point in the history
Allow the user to get and set configuration of Embedded SYNC feature
on the ice driver dpll pins.

Reviewed-by: Aleksandr Loktionov <[email protected]>
Signed-off-by: Arkadiusz Kubalewski <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
kubalewski authored and kuba-moo committed Aug 27, 2024
1 parent cda1fba commit 87abc56
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 3 deletions.
223 changes: 220 additions & 3 deletions drivers/net/ethernet/intel/ice/ice_dpll.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define ICE_CGU_STATE_ACQ_ERR_THRESHOLD 50
#define ICE_DPLL_PIN_IDX_INVALID 0xff
#define ICE_DPLL_RCLK_NUM_PER_PF 1
#define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT 25

/**
* enum ice_dpll_pin_type - enumerate ice pin types:
Expand All @@ -30,6 +31,10 @@ static const char * const pin_type_name[] = {
[ICE_DPLL_PIN_TYPE_RCLK_INPUT] = "rclk-input",
};

static const struct dpll_pin_frequency ice_esync_range[] = {
DPLL_PIN_FREQUENCY_RANGE(0, DPLL_PIN_FREQUENCY_1_HZ),
};

/**
* ice_dpll_is_reset - check if reset is in progress
* @pf: private board structure
Expand Down Expand Up @@ -394,8 +399,8 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin,

switch (pin_type) {
case ICE_DPLL_PIN_TYPE_INPUT:
ret = ice_aq_get_input_pin_cfg(&pf->hw, pin->idx, NULL, NULL,
NULL, &pin->flags[0],
ret = ice_aq_get_input_pin_cfg(&pf->hw, pin->idx, &pin->status,
NULL, NULL, &pin->flags[0],
&pin->freq, &pin->phase_adjust);
if (ret)
goto err;
Expand Down Expand Up @@ -430,7 +435,7 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin,
goto err;

parent &= ICE_AQC_GET_CGU_OUT_CFG_DPLL_SRC_SEL;
if (ICE_AQC_SET_CGU_OUT_CFG_OUT_EN & pin->flags[0]) {
if (ICE_AQC_GET_CGU_OUT_CFG_OUT_EN & pin->flags[0]) {
pin->state[pf->dplls.eec.dpll_idx] =
parent == pf->dplls.eec.dpll_idx ?
DPLL_PIN_STATE_CONNECTED :
Expand Down Expand Up @@ -1098,6 +1103,214 @@ ice_dpll_phase_offset_get(const struct dpll_pin *pin, void *pin_priv,
return 0;
}

/**
* ice_dpll_output_esync_set - callback for setting embedded sync
* @pin: pointer to a pin
* @pin_priv: private data pointer passed on pin registration
* @dpll: registered dpll pointer
* @dpll_priv: private data pointer passed on dpll registration
* @freq: requested embedded sync frequency
* @extack: error reporting
*
* Dpll subsystem callback. Handler for setting embedded sync frequency value
* on output pin.
*
* Context: Acquires pf->dplls.lock
* Return:
* * 0 - success
* * negative - error
*/
static int
ice_dpll_output_esync_set(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
u64 freq, struct netlink_ext_ack *extack)
{
struct ice_dpll_pin *p = pin_priv;
struct ice_dpll *d = dpll_priv;
struct ice_pf *pf = d->pf;
u8 flags = 0;
int ret;

if (ice_dpll_is_reset(pf, extack))
return -EBUSY;
mutex_lock(&pf->dplls.lock);
if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_OUT_EN)
flags = ICE_AQC_SET_CGU_OUT_CFG_OUT_EN;
if (freq == DPLL_PIN_FREQUENCY_1_HZ) {
if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN) {
ret = 0;
} else {
flags |= ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;
ret = ice_aq_set_output_pin_cfg(&pf->hw, p->idx, flags,
0, 0, 0);
}
} else {
if (!(p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN)) {
ret = 0;
} else {
flags &= ~ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;
ret = ice_aq_set_output_pin_cfg(&pf->hw, p->idx, flags,
0, 0, 0);
}
}
mutex_unlock(&pf->dplls.lock);

return ret;
}

/**
* ice_dpll_output_esync_get - callback for getting embedded sync config
* @pin: pointer to a pin
* @pin_priv: private data pointer passed on pin registration
* @dpll: registered dpll pointer
* @dpll_priv: private data pointer passed on dpll registration
* @esync: on success holds embedded sync pin properties
* @extack: error reporting
*
* Dpll subsystem callback. Handler for getting embedded sync frequency value
* and capabilities on output pin.
*
* Context: Acquires pf->dplls.lock
* Return:
* * 0 - success
* * negative - error
*/
static int
ice_dpll_output_esync_get(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
struct dpll_pin_esync *esync,
struct netlink_ext_ack *extack)
{
struct ice_dpll_pin *p = pin_priv;
struct ice_dpll *d = dpll_priv;
struct ice_pf *pf = d->pf;

if (ice_dpll_is_reset(pf, extack))
return -EBUSY;
mutex_lock(&pf->dplls.lock);
if (!(p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_ABILITY) ||
p->freq != DPLL_PIN_FREQUENCY_10_MHZ) {
mutex_unlock(&pf->dplls.lock);
return -EOPNOTSUPP;
}
esync->range = ice_esync_range;
esync->range_num = ARRAY_SIZE(ice_esync_range);
if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN) {
esync->freq = DPLL_PIN_FREQUENCY_1_HZ;
esync->pulse = ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT;
} else {
esync->freq = 0;
esync->pulse = 0;
}
mutex_unlock(&pf->dplls.lock);

return 0;
}

/**
* ice_dpll_input_esync_set - callback for setting embedded sync
* @pin: pointer to a pin
* @pin_priv: private data pointer passed on pin registration
* @dpll: registered dpll pointer
* @dpll_priv: private data pointer passed on dpll registration
* @freq: requested embedded sync frequency
* @extack: error reporting
*
* Dpll subsystem callback. Handler for setting embedded sync frequency value
* on input pin.
*
* Context: Acquires pf->dplls.lock
* Return:
* * 0 - success
* * negative - error
*/
static int
ice_dpll_input_esync_set(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
u64 freq, struct netlink_ext_ack *extack)
{
struct ice_dpll_pin *p = pin_priv;
struct ice_dpll *d = dpll_priv;
struct ice_pf *pf = d->pf;
u8 flags_en = 0;
int ret;

if (ice_dpll_is_reset(pf, extack))
return -EBUSY;
mutex_lock(&pf->dplls.lock);
if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN)
flags_en = ICE_AQC_SET_CGU_IN_CFG_FLG2_INPUT_EN;
if (freq == DPLL_PIN_FREQUENCY_1_HZ) {
if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN) {
ret = 0;
} else {
flags_en |= ICE_AQC_SET_CGU_IN_CFG_FLG2_ESYNC_EN;
ret = ice_aq_set_input_pin_cfg(&pf->hw, p->idx, 0,
flags_en, 0, 0);
}
} else {
if (!(p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN)) {
ret = 0;
} else {
flags_en &= ~ICE_AQC_SET_CGU_IN_CFG_FLG2_ESYNC_EN;
ret = ice_aq_set_input_pin_cfg(&pf->hw, p->idx, 0,
flags_en, 0, 0);
}
}
mutex_unlock(&pf->dplls.lock);

return ret;
}

/**
* ice_dpll_input_esync_get - callback for getting embedded sync config
* @pin: pointer to a pin
* @pin_priv: private data pointer passed on pin registration
* @dpll: registered dpll pointer
* @dpll_priv: private data pointer passed on dpll registration
* @esync: on success holds embedded sync pin properties
* @extack: error reporting
*
* Dpll subsystem callback. Handler for getting embedded sync frequency value
* and capabilities on input pin.
*
* Context: Acquires pf->dplls.lock
* Return:
* * 0 - success
* * negative - error
*/
static int
ice_dpll_input_esync_get(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
struct dpll_pin_esync *esync,
struct netlink_ext_ack *extack)
{
struct ice_dpll_pin *p = pin_priv;
struct ice_dpll *d = dpll_priv;
struct ice_pf *pf = d->pf;

if (ice_dpll_is_reset(pf, extack))
return -EBUSY;
mutex_lock(&pf->dplls.lock);
if (!(p->status & ICE_AQC_GET_CGU_IN_CFG_STATUS_ESYNC_CAP) ||
p->freq != DPLL_PIN_FREQUENCY_10_MHZ) {
mutex_unlock(&pf->dplls.lock);
return -EOPNOTSUPP;
}
esync->range = ice_esync_range;
esync->range_num = ARRAY_SIZE(ice_esync_range);
if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN) {
esync->freq = DPLL_PIN_FREQUENCY_1_HZ;
esync->pulse = ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT;
} else {
esync->freq = 0;
esync->pulse = 0;
}
mutex_unlock(&pf->dplls.lock);

return 0;
}

/**
* ice_dpll_rclk_state_on_pin_set - set a state on rclk pin
* @pin: pointer to a pin
Expand Down Expand Up @@ -1222,6 +1435,8 @@ static const struct dpll_pin_ops ice_dpll_input_ops = {
.phase_adjust_get = ice_dpll_pin_phase_adjust_get,
.phase_adjust_set = ice_dpll_input_phase_adjust_set,
.phase_offset_get = ice_dpll_phase_offset_get,
.esync_set = ice_dpll_input_esync_set,
.esync_get = ice_dpll_input_esync_get,
};

static const struct dpll_pin_ops ice_dpll_output_ops = {
Expand All @@ -1232,6 +1447,8 @@ static const struct dpll_pin_ops ice_dpll_output_ops = {
.direction_get = ice_dpll_output_direction,
.phase_adjust_get = ice_dpll_pin_phase_adjust_get,
.phase_adjust_set = ice_dpll_output_phase_adjust_set,
.esync_set = ice_dpll_output_esync_set,
.esync_get = ice_dpll_output_esync_get,
};

static const struct dpll_device_ops ice_dpll_ops = {
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice_dpll.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct ice_dpll_pin {
struct dpll_pin_properties prop;
u32 freq;
s32 phase_adjust;
u8 status;
};

/** ice_dpll - store info required for DPLL control
Expand Down

0 comments on commit 87abc56

Please sign in to comment.