Commit 87abc566 authored by Arkadiusz Kubalewski's avatar Arkadiusz Kubalewski Committed by Jakub Kicinski
Browse files

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: default avatarAleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: default avatarArkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/20240822222513.255179-3-arkadiusz.kubalewski@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent cda1fba1
Loading
Loading
Loading
Loading
+220 −3
Original line number Diff line number Diff line
@@ -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:
@@ -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
@@ -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;
@@ -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 :
@@ -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
@@ -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 = {
@@ -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 = {
+1 −0
Original line number Diff line number Diff line
@@ -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