Commit 5755b4c0 authored by Karol Kolacinski's avatar Karol Kolacinski Committed by Tony Nguyen
Browse files

ice: add multiple TSPLL helpers



Add helpers for checking TSPLL params, disabling sticky bits,
configuring TSPLL and getting default clock frequency to simplify
the code flows.

Reviewed-by: default avatarMilena Olech <milena.olech@intel.com>
Signed-off-by: default avatarKarol Kolacinski <karol.kolacinski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent c6b4486a
Loading
Loading
Loading
Loading
+108 −48
Original line number Diff line number Diff line
@@ -71,6 +71,58 @@ static const char *ice_tspll_clk_freq_str(enum ice_tspll_freq clk_freq)
	}
}

/**
 * ice_tspll_default_freq - Return default frequency for a MAC type
 * @mac_type: MAC type
 *
 * Return: default TSPLL frequency for a correct MAC type, -ERANGE otherwise.
 */
static enum ice_tspll_freq ice_tspll_default_freq(enum ice_mac_type mac_type)
{
	switch (mac_type) {
	case ICE_MAC_GENERIC:
		return ICE_TSPLL_FREQ_25_000;
	case ICE_MAC_GENERIC_3K_E825:
		return ICE_TSPLL_FREQ_156_250;
	default:
		return -ERANGE;
	}
}

/**
 * ice_tspll_check_params - Check if TSPLL params are correct
 * @hw: Pointer to the HW struct
 * @clk_freq: Clock frequency to program
 * @clk_src: Clock source to select (TIME_REF or TCXO)
 *
 * Return: true if TSPLL params are correct, false otherwise.
 */
static bool ice_tspll_check_params(struct ice_hw *hw,
				   enum ice_tspll_freq clk_freq,
				   enum ice_clk_src clk_src)
{
	if (clk_freq >= NUM_ICE_TSPLL_FREQ) {
		dev_warn(ice_hw_to_dev(hw), "Invalid TSPLL frequency %u\n",
			 clk_freq);
		return false;
	}

	if (clk_src >= NUM_ICE_CLK_SRC) {
		dev_warn(ice_hw_to_dev(hw), "Invalid clock source %u\n",
			 clk_src);
		return false;
	}

	if ((hw->mac_type == ICE_MAC_GENERIC_3K_E825 ||
	     clk_src == ICE_CLK_SRC_TCXO) &&
	    clk_freq != ice_tspll_default_freq(hw->mac_type)) {
		dev_warn(ice_hw_to_dev(hw), "Unsupported frequency for this clock source\n");
		return false;
	}

	return true;
}

/**
 * ice_tspll_clk_src_str - Convert time_ref_src to string
 * @clk_src: Clock source
@@ -130,24 +182,6 @@ static int ice_tspll_cfg_e82x(struct ice_hw *hw, enum ice_tspll_freq clk_freq,
	u32 val, r9, r24;
	int err;

	if (clk_freq >= NUM_ICE_TSPLL_FREQ) {
		dev_warn(ice_hw_to_dev(hw), "Invalid TIME_REF frequency %u\n",
			 clk_freq);
		return -EINVAL;
	}

	if (clk_src >= NUM_ICE_CLK_SRC) {
		dev_warn(ice_hw_to_dev(hw), "Invalid clock source %u\n",
			 clk_src);
		return -EINVAL;
	}

	if (clk_src == ICE_CLK_SRC_TCXO && clk_freq != ICE_TSPLL_FREQ_25_000) {
		dev_warn(ice_hw_to_dev(hw),
			 "TCXO only supports 25 MHz frequency\n");
		return -EINVAL;
	}

	err = ice_read_cgu_reg(hw, ICE_CGU_R9, &r9);
	if (err)
		return err;
@@ -306,23 +340,6 @@ static int ice_tspll_cfg_e825c(struct ice_hw *hw, enum ice_tspll_freq clk_freq,
	u32 val, r9, r23;
	int err;

	if (clk_freq >= NUM_ICE_TSPLL_FREQ) {
		dev_warn(ice_hw_to_dev(hw), "Invalid TIME_REF frequency %u\n",
			 clk_freq);
		return -EINVAL;
	}

	if (clk_src >= NUM_ICE_CLK_SRC) {
		dev_warn(ice_hw_to_dev(hw), "Invalid clock source %u\n",
			 clk_src);
		return -EINVAL;
	}

	if (clk_freq != ICE_TSPLL_FREQ_156_250) {
		dev_warn(ice_hw_to_dev(hw), "Adapter only supports 156.25 MHz frequency\n");
		return -EINVAL;
	}

	err = ice_read_cgu_reg(hw, ICE_CGU_R9, &r9);
	if (err)
		return err;
@@ -508,6 +525,52 @@ int ice_tspll_cfg_pps_out_e825c(struct ice_hw *hw, bool enable)
	return ice_write_cgu_reg(hw, ICE_CGU_R9, val);
}

/**
 * ice_tspll_cfg - Configure the Clock Generation Unit TSPLL
 * @hw: Pointer to the HW struct
 * @clk_freq: Clock frequency to program
 * @clk_src: Clock source to select (TIME_REF, or TCXO)
 *
 * Configure the Clock Generation Unit with the desired clock frequency and
 * time reference, enabling the TSPLL which drives the PTP hardware clock.
 *
 * Return: 0 on success, -ERANGE on unsupported MAC type, other negative error
 *         codes when failed to configure CGU.
 */
static int ice_tspll_cfg(struct ice_hw *hw, enum ice_tspll_freq clk_freq,
			 enum ice_clk_src clk_src)
{
	switch (hw->mac_type) {
	case ICE_MAC_GENERIC:
		return ice_tspll_cfg_e82x(hw, clk_freq, clk_src);
	case ICE_MAC_GENERIC_3K_E825:
		return ice_tspll_cfg_e825c(hw, clk_freq, clk_src);
	default:
		return -ERANGE;
	}
}

/**
 * ice_tspll_dis_sticky_bits - disable TSPLL sticky bits
 * @hw: Pointer to the HW struct
 *
 * Configure the Clock Generation Unit TSPLL sticky bits so they don't latch on
 * losing TSPLL lock, but always show current state.
 *
 * Return: 0 on success, -ERANGE on unsupported MAC type.
 */
static int ice_tspll_dis_sticky_bits(struct ice_hw *hw)
{
	switch (hw->mac_type) {
	case ICE_MAC_GENERIC:
		return ice_tspll_dis_sticky_bits_e82x(hw);
	case ICE_MAC_GENERIC_3K_E825:
		return ice_tspll_dis_sticky_bits_e825c(hw);
	default:
		return -ERANGE;
	}
}

/**
 * ice_tspll_init - Initialize TSPLL with settings from firmware
 * @hw: Pointer to the HW structure
@@ -519,25 +582,22 @@ int ice_tspll_cfg_pps_out_e825c(struct ice_hw *hw, bool enable)
int ice_tspll_init(struct ice_hw *hw)
{
	struct ice_ts_func_info *ts_info = &hw->func_caps.ts_func_info;
	enum ice_tspll_freq tspll_freq;
	enum ice_clk_src clk_src;
	int err;

	/* Disable sticky lock detection so lock err reported is accurate. */
	if (hw->mac_type == ICE_MAC_GENERIC_3K_E825)
		err = ice_tspll_dis_sticky_bits_e825c(hw);
	else
		err = ice_tspll_dis_sticky_bits_e82x(hw);
	tspll_freq = (enum ice_tspll_freq)ts_info->time_ref;
	clk_src = (enum ice_clk_src)ts_info->clk_src;
	if (!ice_tspll_check_params(hw, tspll_freq, clk_src))
		return -EINVAL;

	/* Disable sticky lock detection so lock status reported is accurate */
	err = ice_tspll_dis_sticky_bits(hw);
	if (err)
		return err;

	/* Configure the TSPLL using the parameters from the function
	 * capabilities.
	 */
	if (hw->mac_type == ICE_MAC_GENERIC_3K_E825)
		err = ice_tspll_cfg_e825c(hw, ts_info->time_ref,
					  (enum ice_clk_src)ts_info->clk_src);
	else
		err = ice_tspll_cfg_e82x(hw, ts_info->time_ref,
					 (enum ice_clk_src)ts_info->clk_src);

	return err;
	return ice_tspll_cfg(hw, tspll_freq, clk_src);
}