Commit 713dcad2 authored by Michal Michalik's avatar Michal Michalik Committed by Jakub Kicinski
Browse files

ice: Add support for E825-C TS PLL handling

parent b390ecc2
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -27,6 +27,17 @@ union nac_cgu_dword9 {
	u32 val;
};

#define NAC_CGU_DWORD16_E825C 0x40
union nac_cgu_dword16_e825c {
	struct {
		u32 synce_remndr : 6;
		u32 synce_phlmt_en : 1;
		u32 misc13 : 17;
		u32 tspll_ck_refclkfreq : 8;
	};
	u32 val;
};

#define NAC_CGU_DWORD19 0x4c
union nac_cgu_dword19 {
	struct {
@@ -67,6 +78,22 @@ union nac_cgu_dword22 {
	u32 val;
};

#define NAC_CGU_DWORD23_E825C 0x5C
union nac_cgu_dword23_e825c {
	struct {
		u32 cgupll_fbdiv_intgr : 10;
		u32 ux56pll_fbdiv_intgr : 10;
		u32 misc20 : 4;
		u32 ts_pll_enable : 1;
		u32 time_sync_tspll_align_sel : 1;
		u32 ext_synce_sel : 1;
		u32 ref1588_ck_div : 4;
		u32 time_ref_sel : 1;

	};
	u32 val;
};

#define NAC_CGU_DWORD24 0x60
union nac_cgu_dword24 {
	struct {
@@ -113,4 +140,42 @@ union tspll_ro_bwm_lf {
	u32 val;
};

#define TSPLL_RO_LOCK_E825C 0x3f0
union tspll_ro_lock_e825c {
	struct {
		u32 bw_freqov_high_cri_7_0 : 8;
		u32 bw_freqov_high_cri_9_8 : 2;
		u32 reserved455 : 1;
		u32 plllock_gain_tran_cri : 1;
		u32 plllock_true_lock_cri : 1;
		u32 pllunlock_flag_cri : 1;
		u32 afcerr_cri : 1;
		u32 afcdone_cri : 1;
		u32 feedfwrdgain_cal_cri_7_0 : 8;
		u32 reserved462 : 8;
	};
	u32 val;
};

#define TSPLL_BW_TDC_E825C 0x31c
union tspll_bw_tdc_e825c {
	struct {
		u32 i_tdc_offset_lock_1_0 : 2;
		u32 i_bbthresh1_2_0 : 3;
		u32 i_bbthresh2_2_0 : 3;
		u32 i_tdcsel_1_0 : 2;
		u32 i_tdcovccorr_en_h : 1;
		u32 i_divretimeren : 1;
		u32 i_bw_ampmeas_window : 1;
		u32 i_bw_lowerbound_2_0 : 3;
		u32 i_bw_upperbound_2_0 : 3;
		u32 i_bw_mode_1_0 : 2;
		u32 i_ft_mode_sel_2_0 : 3;
		u32 i_bwphase_4_0 : 5;
		u32 i_plllock_sel_1_0 : 2;
		u32 i_afc_divratio : 1;
	};
	u32 val;
};

#endif /* _ICE_CGU_REGS_H_ */
+7 −2
Original line number Diff line number Diff line
@@ -2314,8 +2314,13 @@ ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
	info->tmr_index_owned = ((number & ICE_TS_TMR_IDX_OWND_M) != 0);
	info->tmr_index_assoc = ((number & ICE_TS_TMR_IDX_ASSOC_M) != 0);

	if (!ice_is_e825c(hw)) {
		info->clk_freq = FIELD_GET(ICE_TS_CLK_FREQ_M, number);
		info->clk_src = ((number & ICE_TS_CLK_SRC_M) != 0);
	} else {
		info->clk_freq = ICE_TIME_REF_FREQ_156_250;
		info->clk_src = ICE_CLK_SRC_TCXO;
	}

	if (info->clk_freq < NUM_ICE_TIME_REF_FREQ) {
		info->time_ref = (enum ice_time_ref_freq)info->clk_freq;
+87 −0
Original line number Diff line number Diff line
@@ -470,6 +470,93 @@ const struct ice_cgu_pll_params_e82x e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = {
	},
};

const
struct ice_cgu_pll_params_e825c e825c_cgu_params[NUM_ICE_TIME_REF_FREQ] = {
	/* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */
	{
		/* tspll_ck_refclkfreq */
		0x19,
		/* tspll_ndivratio */
		1,
		/* tspll_fbdiv_intgr */
		320,
		/* tspll_fbdiv_frac */
		0,
		/* ref1588_ck_div */
		0,
	},

	/* ICE_TIME_REF_FREQ_122_880 -> 122.88 MHz */
	{
		/* tspll_ck_refclkfreq */
		0x29,
		/* tspll_ndivratio */
		3,
		/* tspll_fbdiv_intgr */
		195,
		/* tspll_fbdiv_frac */
		1342177280UL,
		/* ref1588_ck_div */
		0,
	},

	/* ICE_TIME_REF_FREQ_125_000 -> 125 MHz */
	{
		/* tspll_ck_refclkfreq */
		0x3E,
		/* tspll_ndivratio */
		2,
		/* tspll_fbdiv_intgr */
		128,
		/* tspll_fbdiv_frac */
		0,
		/* ref1588_ck_div */
		0,
	},

	/* ICE_TIME_REF_FREQ_153_600 -> 153.6 MHz */
	{
		/* tspll_ck_refclkfreq */
		0x33,
		/* tspll_ndivratio */
		3,
		/* tspll_fbdiv_intgr */
		156,
		/* tspll_fbdiv_frac */
		1073741824UL,
		/* ref1588_ck_div */
		0,
	},

	/* ICE_TIME_REF_FREQ_156_250 -> 156.25 MHz */
	{
		/* tspll_ck_refclkfreq */
		0x1F,
		/* tspll_ndivratio */
		5,
		/* tspll_fbdiv_intgr */
		256,
		/* tspll_fbdiv_frac */
		0,
		/* ref1588_ck_div */
		0,
	},

	/* ICE_TIME_REF_FREQ_245_760 -> 245.76 MHz */
	{
		/* tspll_ck_refclkfreq */
		0x52,
		/* tspll_ndivratio */
		3,
		/* tspll_fbdiv_intgr */
		97,
		/* tspll_fbdiv_frac */
		2818572288UL,
		/* ref1588_ck_div */
		0,
	},
};

/* struct ice_vernier_info_e82x
 *
 * E822 hardware calibrates the delay of the timestamp indication from the
+246 −15
Original line number Diff line number Diff line
@@ -325,8 +325,8 @@ static const char *ice_clk_freq_str(enum ice_time_ref_freq clk_freq)
static const char *ice_clk_src_str(enum ice_clk_src clk_src)
{
	switch (clk_src) {
	case ICE_CLK_SRC_TCX0:
		return "TCX0";
	case ICE_CLK_SRC_TCXO:
		return "TCXO";
	case ICE_CLK_SRC_TIME_REF:
		return "TIME_REF";
	default:
@@ -338,7 +338,7 @@ static const char *ice_clk_src_str(enum ice_clk_src clk_src)
 * ice_cfg_cgu_pll_e82x - Configure the Clock Generation Unit
 * @hw: pointer to the HW struct
 * @clk_freq: Clock frequency to program
 * @clk_src: Clock source to select (TIME_REF, or TCX0)
 * @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 PLL which drives the PTP hardware clock.
@@ -372,10 +372,10 @@ static int ice_cfg_cgu_pll_e82x(struct ice_hw *hw,
		return -EINVAL;
	}

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

@@ -480,16 +480,198 @@ static int ice_cfg_cgu_pll_e82x(struct ice_hw *hw,
}

/**
 * ice_init_cgu_e82x - Initialize CGU with settings from firmware
 * @hw: pointer to the HW structure
 * ice_cfg_cgu_pll_e825c - Configure the Clock Generation Unit for E825-C
 * @hw: pointer to the HW struct
 * @clk_freq: Clock frequency to program
 * @clk_src: Clock source to select (TIME_REF, or TCXO)
 *
 * Initialize the Clock Generation Unit of the E822 device.
 * Configure the Clock Generation Unit with the desired clock frequency and
 * time reference, enabling the PLL which drives the PTP hardware clock.
 *
 * Return: 0 on success, other error codes when failed to read/write/cfg CGU
 * Return:
 * * %0       - success
 * * %-EINVAL - input parameters are incorrect
 * * %-EBUSY  - failed to lock TS PLL
 * * %other   - CGU read/write failure
 */
static int ice_init_cgu_e82x(struct ice_hw *hw)
static int ice_cfg_cgu_pll_e825c(struct ice_hw *hw,
				 enum ice_time_ref_freq clk_freq,
				 enum ice_clk_src clk_src)
{
	union tspll_ro_lock_e825c ro_lock;
	union nac_cgu_dword16_e825c dw16;
	union nac_cgu_dword23_e825c dw23;
	union nac_cgu_dword19 dw19;
	union nac_cgu_dword22 dw22;
	union nac_cgu_dword24 dw24;
	union nac_cgu_dword9 dw9;
	int err;

	if (clk_freq >= NUM_ICE_TIME_REF_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_TIME_REF_FREQ_156_250) {
		dev_warn(ice_hw_to_dev(hw),
			 "TCXO only supports 156.25 MHz frequency\n");
		return -EINVAL;
	}

	err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD9, &dw9.val);
	if (err)
		return err;

	err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD24, &dw24.val);
	if (err)
		return err;

	err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD16_E825C, &dw16.val);
	if (err)
		return err;

	err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD23_E825C, &dw23.val);
	if (err)
		return err;

	err = ice_read_cgu_reg_e82x(hw, TSPLL_RO_LOCK_E825C, &ro_lock.val);
	if (err)
		return err;

	/* Log the current clock configuration */
	ice_debug(hw, ICE_DBG_PTP, "Current CGU configuration -- %s, clk_src %s, clk_freq %s, PLL %s\n",
		  dw24.ts_pll_enable ? "enabled" : "disabled",
		  ice_clk_src_str(dw23.time_ref_sel),
		  ice_clk_freq_str(dw9.time_ref_freq_sel),
		  ro_lock.plllock_true_lock_cri ? "locked" : "unlocked");

	/* Disable the PLL before changing the clock source or frequency */
	if (dw23.ts_pll_enable) {
		dw23.ts_pll_enable = 0;

		err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD23_E825C,
					     dw23.val);
		if (err)
			return err;
	}

	/* Set the frequency */
	dw9.time_ref_freq_sel = clk_freq;

	/* Enable the correct receiver */
	if (clk_src == ICE_CLK_SRC_TCXO) {
		dw9.time_ref_en = 0;
		dw9.clk_eref0_en = 1;
	} else {
		dw9.time_ref_en = 1;
		dw9.clk_eref0_en = 0;
	}
	err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD9, dw9.val);
	if (err)
		return err;

	/* Choose the referenced frequency */
	dw16.tspll_ck_refclkfreq =
	e825c_cgu_params[clk_freq].tspll_ck_refclkfreq;
	err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD16_E825C, dw16.val);
	if (err)
		return err;

	/* Configure the TS PLL feedback divisor */
	err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD19, &dw19.val);
	if (err)
		return err;

	dw19.tspll_fbdiv_intgr =
		e825c_cgu_params[clk_freq].tspll_fbdiv_intgr;
	dw19.tspll_ndivratio =
		e825c_cgu_params[clk_freq].tspll_ndivratio;

	err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD19, dw19.val);
	if (err)
		return err;

	/* Configure the TS PLL post divisor */
	err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD22, &dw22.val);
	if (err)
		return err;

	/* These two are constant for E825C */
	dw22.time1588clk_div = 5;
	dw22.time1588clk_sel_div2 = 0;

	err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD22, dw22.val);
	if (err)
		return err;

	/* Configure the TS PLL pre divisor and clock source */
	err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD23_E825C, &dw23.val);
	if (err)
		return err;

	dw23.ref1588_ck_div =
		e825c_cgu_params[clk_freq].ref1588_ck_div;
	dw23.time_ref_sel = clk_src;

	err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD23_E825C, dw23.val);
	if (err)
		return err;

	dw24.tspll_fbdiv_frac =
		e825c_cgu_params[clk_freq].tspll_fbdiv_frac;

	err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val);
	if (err)
		return err;

	/* Finally, enable the PLL */
	dw23.ts_pll_enable = 1;

	err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD23_E825C, dw23.val);
	if (err)
		return err;

	/* Wait to verify if the PLL locks */
	usleep_range(1000, 5000);

	err = ice_read_cgu_reg_e82x(hw, TSPLL_RO_LOCK_E825C, &ro_lock.val);
	if (err)
		return err;

	if (!ro_lock.plllock_true_lock_cri) {
		dev_warn(ice_hw_to_dev(hw), "CGU PLL failed to lock\n");
		return -EBUSY;
	}

	/* Log the current clock configuration */
	ice_debug(hw, ICE_DBG_PTP, "New CGU configuration -- %s, clk_src %s, clk_freq %s, PLL %s\n",
		  dw24.ts_pll_enable ? "enabled" : "disabled",
		  ice_clk_src_str(dw23.time_ref_sel),
		  ice_clk_freq_str(dw9.time_ref_freq_sel),
		  ro_lock.plllock_true_lock_cri ? "locked" : "unlocked");

	return 0;
}

/**
 * ice_cfg_cgu_pll_dis_sticky_bits_e82x - disable TS PLL sticky bits
 * @hw: pointer to the HW struct
 *
 * Configure the Clock Generation Unit TS PLL sticky bits so they don't latch on
 * losing TS PLL lock, but always show current state.
 *
 * Return: 0 on success, other error codes when failed to read/write CGU
 */
static int ice_cfg_cgu_pll_dis_sticky_bits_e82x(struct ice_hw *hw)
{
	struct ice_ts_func_info *ts_info = &hw->func_caps.ts_func_info;
	union tspll_cntr_bist_settings cntr_bist;
	int err;

@@ -502,16 +684,65 @@ static int ice_init_cgu_e82x(struct ice_hw *hw)
	cntr_bist.i_plllock_sel_0 = 0;
	cntr_bist.i_plllock_sel_1 = 0;

	err = ice_write_cgu_reg_e82x(hw, TSPLL_CNTR_BIST_SETTINGS,
	return ice_write_cgu_reg_e82x(hw, TSPLL_CNTR_BIST_SETTINGS,
				      cntr_bist.val);
}

/**
 * ice_cfg_cgu_pll_dis_sticky_bits_e825c - disable TS PLL sticky bits for E825-C
 * @hw: pointer to the HW struct
 *
 * Configure the Clock Generation Unit TS PLL sticky bits so they don't latch on
 * losing TS PLL lock, but always show current state.
 *
 * Return: 0 on success, other error codes when failed to read/write CGU
 */
static int ice_cfg_cgu_pll_dis_sticky_bits_e825c(struct ice_hw *hw)
{
	union tspll_bw_tdc_e825c bw_tdc;
	int err;

	err = ice_read_cgu_reg_e82x(hw, TSPLL_BW_TDC_E825C, &bw_tdc.val);
	if (err)
		return err;

	bw_tdc.i_plllock_sel_1_0 = 0;

	return ice_write_cgu_reg_e82x(hw, TSPLL_BW_TDC_E825C, bw_tdc.val);
}

/**
 * ice_init_cgu_e82x - Initialize CGU with settings from firmware
 * @hw: pointer to the HW structure
 *
 * Initialize the Clock Generation Unit of the E822 device.
 *
 * Return: 0 on success, other error codes when failed to read/write/cfg CGU
 */
static int ice_init_cgu_e82x(struct ice_hw *hw)
{
	struct ice_ts_func_info *ts_info = &hw->func_caps.ts_func_info;
	int err;

	/* Disable sticky lock detection so lock err reported is accurate */
	if (ice_is_e825c(hw))
		err = ice_cfg_cgu_pll_dis_sticky_bits_e825c(hw);
	else
		err = ice_cfg_cgu_pll_dis_sticky_bits_e82x(hw);
	if (err)
		return err;

	/* Configure the CGU PLL using the parameters from the function
	 * capabilities.
	 */
	return ice_cfg_cgu_pll_e82x(hw, ts_info->time_ref,
	if (ice_is_e825c(hw))
		err = ice_cfg_cgu_pll_e825c(hw, ts_info->time_ref,
					    (enum ice_clk_src)ts_info->clk_src);
	else
		err = ice_cfg_cgu_pll_e82x(hw, ts_info->time_ref,
					   (enum ice_clk_src)ts_info->clk_src);

	return err;
}

/**
+23 −1
Original line number Diff line number Diff line
@@ -197,7 +197,7 @@ extern
const struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD];

/**
 * struct ice_cgu_pll_params_e82x
 * struct ice_cgu_pll_params_e82x - E82X CGU parameters
 * @refclk_pre_div: Reference clock pre-divisor
 * @feedback_div: Feedback divisor
 * @frac_n_div: Fractional divisor
@@ -287,6 +287,28 @@ struct ice_cgu_pin_desc {
extern const struct
ice_cgu_pll_params_e82x e822_cgu_params[NUM_ICE_TIME_REF_FREQ];

/**
 * struct ice_cgu_pll_params_e825c - E825C CGU parameters
 * @tspll_ck_refclkfreq: tspll_ck_refclkfreq selection
 * @tspll_ndivratio: ndiv ratio that goes directly to the pll
 * @tspll_fbdiv_intgr: TS PLL integer feedback divide
 * @tspll_fbdiv_frac:  TS PLL fractional feedback divide
 * @ref1588_ck_div: clock divider for tspll ref
 *
 * Clock Generation Unit parameters used to program the PLL based on the
 * selected TIME_REF/TCXO frequency.
 */
struct ice_cgu_pll_params_e825c {
	u32 tspll_ck_refclkfreq;
	u32 tspll_ndivratio;
	u32 tspll_fbdiv_intgr;
	u32 tspll_fbdiv_frac;
	u32 ref1588_ck_div;
};

extern const struct
ice_cgu_pll_params_e825c e825c_cgu_params[NUM_ICE_TIME_REF_FREQ];

#define E810C_QSFP_C827_0_HANDLE 2
#define E810C_QSFP_C827_1_HANDLE 3

Loading