ice: add callbacks for Embedded SYNC enablement on dpll pins

Allow the user to get and set configuration of Embedded SYNC feature
on the ice driver dpll pins.

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/20240822222513.255179-3-arkadiusz.kubalewski@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Arkadiusz Kubalewski 2024-08-23 00:25:13 +02:00 committed by Jakub Kicinski
parent cda1fba15c
commit 87abc5666a
2 changed files with 221 additions and 3 deletions

View file

@ -9,6 +9,7 @@
#define ICE_CGU_STATE_ACQ_ERR_THRESHOLD 50 #define ICE_CGU_STATE_ACQ_ERR_THRESHOLD 50
#define ICE_DPLL_PIN_IDX_INVALID 0xff #define ICE_DPLL_PIN_IDX_INVALID 0xff
#define ICE_DPLL_RCLK_NUM_PER_PF 1 #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: * enum ice_dpll_pin_type - enumerate ice pin types:
@ -30,6 +31,10 @@ static const char * const pin_type_name[] = {
[ICE_DPLL_PIN_TYPE_RCLK_INPUT] = "rclk-input", [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 * ice_dpll_is_reset - check if reset is in progress
* @pf: private board structure * @pf: private board structure
@ -394,8 +399,8 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin,
switch (pin_type) { switch (pin_type) {
case ICE_DPLL_PIN_TYPE_INPUT: case ICE_DPLL_PIN_TYPE_INPUT:
ret = ice_aq_get_input_pin_cfg(&pf->hw, pin->idx, NULL, NULL, ret = ice_aq_get_input_pin_cfg(&pf->hw, pin->idx, &pin->status,
NULL, &pin->flags[0], NULL, NULL, &pin->flags[0],
&pin->freq, &pin->phase_adjust); &pin->freq, &pin->phase_adjust);
if (ret) if (ret)
goto err; goto err;
@ -430,7 +435,7 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin,
goto err; goto err;
parent &= ICE_AQC_GET_CGU_OUT_CFG_DPLL_SRC_SEL; 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] = pin->state[pf->dplls.eec.dpll_idx] =
parent == pf->dplls.eec.dpll_idx ? parent == pf->dplls.eec.dpll_idx ?
DPLL_PIN_STATE_CONNECTED : DPLL_PIN_STATE_CONNECTED :
@ -1098,6 +1103,214 @@ ice_dpll_phase_offset_get(const struct dpll_pin *pin, void *pin_priv,
return 0; 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 * ice_dpll_rclk_state_on_pin_set - set a state on rclk pin
* @pin: pointer to a pin * @pin: pointer to a pin
@ -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_get = ice_dpll_pin_phase_adjust_get,
.phase_adjust_set = ice_dpll_input_phase_adjust_set, .phase_adjust_set = ice_dpll_input_phase_adjust_set,
.phase_offset_get = ice_dpll_phase_offset_get, .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 = { static const struct dpll_pin_ops ice_dpll_output_ops = {
@ -1232,6 +1447,8 @@ static const struct dpll_pin_ops ice_dpll_output_ops = {
.direction_get = ice_dpll_output_direction, .direction_get = ice_dpll_output_direction,
.phase_adjust_get = ice_dpll_pin_phase_adjust_get, .phase_adjust_get = ice_dpll_pin_phase_adjust_get,
.phase_adjust_set = ice_dpll_output_phase_adjust_set, .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 = { static const struct dpll_device_ops ice_dpll_ops = {

View file

@ -31,6 +31,7 @@ struct ice_dpll_pin {
struct dpll_pin_properties prop; struct dpll_pin_properties prop;
u32 freq; u32 freq;
s32 phase_adjust; s32 phase_adjust;
u8 status;
}; };
/** ice_dpll - store info required for DPLL control /** ice_dpll - store info required for DPLL control