mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-14 11:11:22 -04:00
Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
Tony Nguyen says: ==================== ice: Separate TSPLL from PTP and clean up [part] Jake Keller says: Separate TSPLL related functions and definitions from all PTP-related files and clean up the code by implementing multiple helpers. * '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue: ice: add TSPLL log config helper ice: use designated initializers for TSPLL consts ice: remove ice_tspll_params_e825 definitions ice: fix E825-C TSPLL register definitions ice: rename TSPLL and CGU functions and definitions ice: move TSPLL functions to a separate file ==================== Link: https://patch.msgid.link/20250618174231.3100231-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -53,7 +53,7 @@ ice-$(CONFIG_PCI_IOV) += \
|
||||
ice_vf_mbx.o \
|
||||
ice_vf_vsi_vlan_ops.o \
|
||||
ice_vf_lib.o
|
||||
ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o ice_dpll.o
|
||||
ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o ice_dpll.o ice_tspll.o
|
||||
ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o
|
||||
ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o
|
||||
ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "ice_sriov.h"
|
||||
#include "ice_vf_mbx.h"
|
||||
#include "ice_ptp.h"
|
||||
#include "ice_tspll.h"
|
||||
#include "ice_fdir.h"
|
||||
#include "ice_xsk.h"
|
||||
#include "ice_arfs.h"
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2018-2021, Intel Corporation. */
|
||||
|
||||
#ifndef _ICE_CGU_REGS_H_
|
||||
#define _ICE_CGU_REGS_H_
|
||||
|
||||
#define NAC_CGU_DWORD9 0x24
|
||||
union nac_cgu_dword9 {
|
||||
struct {
|
||||
u32 time_ref_freq_sel : 3;
|
||||
u32 clk_eref1_en : 1;
|
||||
u32 clk_eref0_en : 1;
|
||||
u32 time_ref_en : 1;
|
||||
u32 time_sync_en : 1;
|
||||
u32 one_pps_out_en : 1;
|
||||
u32 clk_ref_synce_en : 1;
|
||||
u32 clk_synce1_en : 1;
|
||||
u32 clk_synce0_en : 1;
|
||||
u32 net_clk_ref1_en : 1;
|
||||
u32 net_clk_ref0_en : 1;
|
||||
u32 clk_synce1_amp : 2;
|
||||
u32 misc6 : 1;
|
||||
u32 clk_synce0_amp : 2;
|
||||
u32 one_pps_out_amp : 2;
|
||||
u32 misc24 : 12;
|
||||
};
|
||||
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 {
|
||||
u32 tspll_fbdiv_intgr : 8;
|
||||
u32 fdpll_ulck_thr : 5;
|
||||
u32 misc15 : 3;
|
||||
u32 tspll_ndivratio : 4;
|
||||
u32 tspll_iref_ndivratio : 3;
|
||||
u32 misc19 : 1;
|
||||
u32 japll_ndivratio : 4;
|
||||
u32 japll_iref_ndivratio : 3;
|
||||
u32 misc27 : 1;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#define NAC_CGU_DWORD22 0x58
|
||||
union nac_cgu_dword22 {
|
||||
struct {
|
||||
u32 fdpll_frac_div_out_nc : 2;
|
||||
u32 fdpll_lock_int_for : 1;
|
||||
u32 synce_hdov_int_for : 1;
|
||||
u32 synce_lock_int_for : 1;
|
||||
u32 fdpll_phlead_slip_nc : 1;
|
||||
u32 fdpll_acc1_ovfl_nc : 1;
|
||||
u32 fdpll_acc2_ovfl_nc : 1;
|
||||
u32 synce_status_nc : 6;
|
||||
u32 fdpll_acc1f_ovfl : 1;
|
||||
u32 misc18 : 1;
|
||||
u32 fdpllclk_div : 4;
|
||||
u32 time1588clk_div : 4;
|
||||
u32 synceclk_div : 4;
|
||||
u32 synceclk_sel_div2 : 1;
|
||||
u32 fdpllclk_sel_div2 : 1;
|
||||
u32 time1588clk_sel_div2 : 1;
|
||||
u32 misc3 : 1;
|
||||
};
|
||||
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 {
|
||||
u32 tspll_fbdiv_frac : 22;
|
||||
u32 misc20 : 2;
|
||||
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 TSPLL_CNTR_BIST_SETTINGS 0x344
|
||||
union tspll_cntr_bist_settings {
|
||||
struct {
|
||||
u32 i_irefgen_settling_time_cntr_7_0 : 8;
|
||||
u32 i_irefgen_settling_time_ro_standby_1_0 : 2;
|
||||
u32 reserved195 : 5;
|
||||
u32 i_plllock_sel_0 : 1;
|
||||
u32 i_plllock_sel_1 : 1;
|
||||
u32 i_plllock_cnt_6_0 : 7;
|
||||
u32 i_plllock_cnt_10_7 : 4;
|
||||
u32 reserved200 : 4;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#define TSPLL_RO_BWM_LF 0x370
|
||||
union tspll_ro_bwm_lf {
|
||||
struct {
|
||||
u32 bw_freqov_high_cri_7_0 : 8;
|
||||
u32 bw_freqov_high_cri_9_8 : 2;
|
||||
u32 biascaldone_cri : 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 m2fbdivmod_cri_7_0 : 8;
|
||||
};
|
||||
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_ */
|
||||
@@ -2301,12 +2301,12 @@ ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
|
||||
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_freq = ICE_TSPLL_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;
|
||||
if (info->clk_freq < NUM_ICE_TSPLL_FREQ) {
|
||||
info->time_ref = (enum ice_tspll_freq)info->clk_freq;
|
||||
} else {
|
||||
/* Unknown clock frequency, so assume a (probably incorrect)
|
||||
* default to avoid out-of-bounds look ups of frequency
|
||||
@@ -2314,7 +2314,7 @@ ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
|
||||
*/
|
||||
ice_debug(hw, ICE_DBG_INIT, "1588 func caps: unknown clock frequency %u\n",
|
||||
info->clk_freq);
|
||||
info->time_ref = ICE_TIME_REF_FREQ_25_000;
|
||||
info->time_ref = ICE_TSPLL_FREQ_25_000;
|
||||
}
|
||||
|
||||
ice_debug(hw, ICE_DBG_INIT, "func caps: ieee_1588 = %u\n",
|
||||
@@ -6132,3 +6132,64 @@ u32 ice_get_link_speed(u16 index)
|
||||
|
||||
return ice_aq_to_link_speed[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_read_cgu_reg - Read a CGU register
|
||||
* @hw: Pointer to the HW struct
|
||||
* @addr: Register address to read
|
||||
* @val: Storage for register value read
|
||||
*
|
||||
* Read the contents of a register of the Clock Generation Unit. Only
|
||||
* applicable to E82X devices.
|
||||
*
|
||||
* Return: 0 on success, other error codes when failed to read from CGU.
|
||||
*/
|
||||
int ice_read_cgu_reg(struct ice_hw *hw, u32 addr, u32 *val)
|
||||
{
|
||||
struct ice_sbq_msg_input cgu_msg = {
|
||||
.opcode = ice_sbq_msg_rd,
|
||||
.dest_dev = ice_sbq_dev_cgu,
|
||||
.msg_addr_low = addr
|
||||
};
|
||||
int err;
|
||||
|
||||
err = ice_sbq_rw_reg(hw, &cgu_msg, ICE_AQ_FLAG_RD);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to read CGU register 0x%04x, err %d\n",
|
||||
addr, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*val = cgu_msg.data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_write_cgu_reg - Write a CGU register
|
||||
* @hw: Pointer to the HW struct
|
||||
* @addr: Register address to write
|
||||
* @val: Value to write into the register
|
||||
*
|
||||
* Write the specified value to a register of the Clock Generation Unit. Only
|
||||
* applicable to E82X devices.
|
||||
*
|
||||
* Return: 0 on success, other error codes when failed to write to CGU.
|
||||
*/
|
||||
int ice_write_cgu_reg(struct ice_hw *hw, u32 addr, u32 val)
|
||||
{
|
||||
struct ice_sbq_msg_input cgu_msg = {
|
||||
.opcode = ice_sbq_msg_wr,
|
||||
.dest_dev = ice_sbq_dev_cgu,
|
||||
.msg_addr_low = addr,
|
||||
.data = val
|
||||
};
|
||||
int err;
|
||||
|
||||
err = ice_sbq_rw_reg(hw, &cgu_msg, ICE_AQ_FLAG_RD);
|
||||
if (err)
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to write CGU register 0x%04x, err %d\n",
|
||||
addr, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,195 @@
|
||||
#define FEC_RECEIVER_ID_PCS0 (0x33 << FEC_RECV_ID_SHIFT)
|
||||
#define FEC_RECEIVER_ID_PCS1 (0x34 << FEC_RECV_ID_SHIFT)
|
||||
|
||||
#define ICE_CGU_R9 0x24
|
||||
union ice_cgu_r9 {
|
||||
struct {
|
||||
u32 time_ref_freq_sel : 3;
|
||||
u32 clk_eref1_en : 1;
|
||||
u32 clk_eref0_en : 1;
|
||||
u32 time_ref_en : 1;
|
||||
u32 time_sync_en : 1;
|
||||
u32 one_pps_out_en : 1;
|
||||
u32 clk_ref_synce_en : 1;
|
||||
u32 clk_synce1_en : 1;
|
||||
u32 clk_synce0_en : 1;
|
||||
u32 net_clk_ref1_en : 1;
|
||||
u32 net_clk_ref0_en : 1;
|
||||
u32 clk_synce1_amp : 2;
|
||||
u32 misc6 : 1;
|
||||
u32 clk_synce0_amp : 2;
|
||||
u32 one_pps_out_amp : 2;
|
||||
u32 misc24 : 12;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#define ICE_CGU_R16 0x40
|
||||
union ice_cgu_r16 {
|
||||
struct {
|
||||
u32 synce_remndr : 6;
|
||||
u32 synce_phlmt_en : 1;
|
||||
u32 misc13 : 17;
|
||||
u32 ck_refclkfreq : 8;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#define ICE_CGU_R19 0x4c
|
||||
union ice_cgu_r19_e82x {
|
||||
struct {
|
||||
u32 fbdiv_intgr : 8;
|
||||
u32 fdpll_ulck_thr : 5;
|
||||
u32 misc15 : 3;
|
||||
u32 ndivratio : 4;
|
||||
u32 tspll_iref_ndivratio : 3;
|
||||
u32 misc19 : 1;
|
||||
u32 japll_ndivratio : 4;
|
||||
u32 japll_iref_ndivratio : 3;
|
||||
u32 misc27 : 1;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
union ice_cgu_r19_e825 {
|
||||
struct {
|
||||
u32 tspll_fbdiv_intgr : 10;
|
||||
u32 fdpll_ulck_thr : 5;
|
||||
u32 misc15 : 1;
|
||||
u32 tspll_ndivratio : 4;
|
||||
u32 tspll_iref_ndivratio : 3;
|
||||
u32 misc19 : 1;
|
||||
u32 japll_ndivratio : 4;
|
||||
u32 japll_postdiv_pdivratio : 3;
|
||||
u32 misc27 : 1;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#define ICE_CGU_R22 0x58
|
||||
union ice_cgu_r22 {
|
||||
struct {
|
||||
u32 fdpll_frac_div_out_nc : 2;
|
||||
u32 fdpll_lock_int_for : 1;
|
||||
u32 synce_hdov_int_for : 1;
|
||||
u32 synce_lock_int_for : 1;
|
||||
u32 fdpll_phlead_slip_nc : 1;
|
||||
u32 fdpll_acc1_ovfl_nc : 1;
|
||||
u32 fdpll_acc2_ovfl_nc : 1;
|
||||
u32 synce_status_nc : 6;
|
||||
u32 fdpll_acc1f_ovfl : 1;
|
||||
u32 misc18 : 1;
|
||||
u32 fdpllclk_div : 4;
|
||||
u32 time1588clk_div : 4;
|
||||
u32 synceclk_div : 4;
|
||||
u32 synceclk_sel_div2 : 1;
|
||||
u32 fdpllclk_sel_div2 : 1;
|
||||
u32 time1588clk_sel_div2 : 1;
|
||||
u32 misc3 : 1;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#define ICE_CGU_R23 0x5C
|
||||
union ice_cgu_r23 {
|
||||
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 ICE_CGU_R24 0x60
|
||||
union ice_cgu_r24 {
|
||||
struct {
|
||||
u32 fbdiv_frac : 22;
|
||||
u32 misc20 : 2;
|
||||
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 TSPLL_CNTR_BIST_SETTINGS 0x344
|
||||
union tspll_cntr_bist_settings {
|
||||
struct {
|
||||
u32 i_irefgen_settling_time_cntr_7_0 : 8;
|
||||
u32 i_irefgen_settling_time_ro_standby_1_0 : 2;
|
||||
u32 reserved195 : 5;
|
||||
u32 i_plllock_sel_0 : 1;
|
||||
u32 i_plllock_sel_1 : 1;
|
||||
u32 i_plllock_cnt_6_0 : 7;
|
||||
u32 i_plllock_cnt_10_7 : 4;
|
||||
u32 reserved200 : 4;
|
||||
};
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#define TSPLL_RO_BWM_LF 0x370
|
||||
union tspll_ro_bwm_lf {
|
||||
struct {
|
||||
u32 bw_freqov_high_cri_7_0 : 8;
|
||||
u32 bw_freqov_high_cri_9_8 : 2;
|
||||
u32 biascaldone_cri : 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 m2fbdivmod_cri_7_0 : 8;
|
||||
};
|
||||
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;
|
||||
};
|
||||
|
||||
int ice_init_hw(struct ice_hw *hw);
|
||||
void ice_deinit_hw(struct ice_hw *hw);
|
||||
int ice_check_reset(struct ice_hw *hw);
|
||||
@@ -306,4 +495,6 @@ ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
|
||||
int ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle);
|
||||
int ice_read_pca9575_reg(struct ice_hw *hw, u8 offset, u8 *data);
|
||||
bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw);
|
||||
int ice_read_cgu_reg(struct ice_hw *hw, u32 addr, u32 *val);
|
||||
int ice_write_cgu_reg(struct ice_hw *hw, u32 addr, u32 val);
|
||||
#endif /* _ICE_COMMON_H_ */
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "ice.h"
|
||||
#include "ice_lib.h"
|
||||
#include "ice_trace.h"
|
||||
#include "ice_cgu_regs.h"
|
||||
|
||||
static const char ice_pin_names[][64] = {
|
||||
"SDP0",
|
||||
@@ -1637,7 +1636,7 @@ static int ice_ptp_write_perout(struct ice_hw *hw, unsigned int chan,
|
||||
int err;
|
||||
|
||||
/* Enable/disable CGU 1PPS output for E825C */
|
||||
err = ice_cgu_cfg_pps_out(hw, !!period);
|
||||
err = ice_tspll_cfg_pps_out_e825c(hw, !!period);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD] = {
|
||||
|
||||
/* struct ice_time_ref_info_e82x
|
||||
*
|
||||
* E822 hardware can use different sources as the reference for the PTP
|
||||
* E82X hardware can use different sources as the reference for the PTP
|
||||
* hardware clock. Each clock has different characteristics such as a slightly
|
||||
* different frequency, etc.
|
||||
*
|
||||
@@ -289,8 +289,8 @@ struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD] = {
|
||||
* reference. See the struct ice_time_ref_info_e82x for information about the
|
||||
* meaning of each constant.
|
||||
*/
|
||||
const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
|
||||
/* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */
|
||||
const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TSPLL_FREQ] = {
|
||||
/* ICE_TSPLL_FREQ_25_000 -> 25 MHz */
|
||||
{
|
||||
/* pll_freq */
|
||||
823437500, /* 823.4375 MHz PLL */
|
||||
@@ -298,7 +298,7 @@ const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
|
||||
0x136e44fabULL,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_122_880 -> 122.88 MHz */
|
||||
/* ICE_TSPLL_FREQ_122_880 -> 122.88 MHz */
|
||||
{
|
||||
/* pll_freq */
|
||||
783360000, /* 783.36 MHz */
|
||||
@@ -306,7 +306,7 @@ const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
|
||||
0x146cc2177ULL,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_125_000 -> 125 MHz */
|
||||
/* ICE_TSPLL_FREQ_125_000 -> 125 MHz */
|
||||
{
|
||||
/* pll_freq */
|
||||
796875000, /* 796.875 MHz */
|
||||
@@ -314,7 +314,7 @@ const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
|
||||
0x141414141ULL,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_153_600 -> 153.6 MHz */
|
||||
/* ICE_TSPLL_FREQ_153_600 -> 153.6 MHz */
|
||||
{
|
||||
/* pll_freq */
|
||||
816000000, /* 816 MHz */
|
||||
@@ -322,7 +322,7 @@ const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
|
||||
0x139b9b9baULL,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_156_250 -> 156.25 MHz */
|
||||
/* ICE_TSPLL_FREQ_156_250 -> 156.25 MHz */
|
||||
{
|
||||
/* pll_freq */
|
||||
830078125, /* 830.78125 MHz */
|
||||
@@ -330,7 +330,7 @@ const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
|
||||
0x134679aceULL,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_245_760 -> 245.76 MHz */
|
||||
/* ICE_TSPLL_FREQ_245_760 -> 245.76 MHz */
|
||||
{
|
||||
/* pll_freq */
|
||||
783360000, /* 783.36 MHz */
|
||||
@@ -339,167 +339,6 @@ const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
|
||||
},
|
||||
};
|
||||
|
||||
const struct ice_cgu_pll_params_e82x e822_cgu_params[NUM_ICE_TIME_REF_FREQ] = {
|
||||
/* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */
|
||||
{
|
||||
/* refclk_pre_div */
|
||||
1,
|
||||
/* feedback_div */
|
||||
197,
|
||||
/* frac_n_div */
|
||||
2621440,
|
||||
/* post_pll_div */
|
||||
6,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_122_880 -> 122.88 MHz */
|
||||
{
|
||||
/* refclk_pre_div */
|
||||
5,
|
||||
/* feedback_div */
|
||||
223,
|
||||
/* frac_n_div */
|
||||
524288,
|
||||
/* post_pll_div */
|
||||
7,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_125_000 -> 125 MHz */
|
||||
{
|
||||
/* refclk_pre_div */
|
||||
5,
|
||||
/* feedback_div */
|
||||
223,
|
||||
/* frac_n_div */
|
||||
524288,
|
||||
/* post_pll_div */
|
||||
7,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_153_600 -> 153.6 MHz */
|
||||
{
|
||||
/* refclk_pre_div */
|
||||
5,
|
||||
/* feedback_div */
|
||||
159,
|
||||
/* frac_n_div */
|
||||
1572864,
|
||||
/* post_pll_div */
|
||||
6,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_156_250 -> 156.25 MHz */
|
||||
{
|
||||
/* refclk_pre_div */
|
||||
5,
|
||||
/* feedback_div */
|
||||
159,
|
||||
/* frac_n_div */
|
||||
1572864,
|
||||
/* post_pll_div */
|
||||
6,
|
||||
},
|
||||
|
||||
/* ICE_TIME_REF_FREQ_245_760 -> 245.76 MHz */
|
||||
{
|
||||
/* refclk_pre_div */
|
||||
10,
|
||||
/* feedback_div */
|
||||
223,
|
||||
/* frac_n_div */
|
||||
524288,
|
||||
/* post_pll_div */
|
||||
7,
|
||||
},
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "ice_common.h"
|
||||
#include "ice_ptp_hw.h"
|
||||
#include "ice_ptp_consts.h"
|
||||
#include "ice_cgu_regs.h"
|
||||
|
||||
static struct dpll_pin_frequency ice_cgu_pin_freq_common[] = {
|
||||
DPLL_PIN_FREQUENCY_1PPS,
|
||||
@@ -225,547 +224,6 @@ static u64 ice_ptp_read_src_incval(struct ice_hw *hw)
|
||||
return ((u64)(hi & INCVAL_HIGH_M) << 32) | lo;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_read_cgu_reg_e82x - Read a CGU register
|
||||
* @hw: pointer to the HW struct
|
||||
* @addr: Register address to read
|
||||
* @val: storage for register value read
|
||||
*
|
||||
* Read the contents of a register of the Clock Generation Unit. Only
|
||||
* applicable to E822 devices.
|
||||
*
|
||||
* Return: 0 on success, other error codes when failed to read from CGU
|
||||
*/
|
||||
static int ice_read_cgu_reg_e82x(struct ice_hw *hw, u32 addr, u32 *val)
|
||||
{
|
||||
struct ice_sbq_msg_input cgu_msg = {
|
||||
.opcode = ice_sbq_msg_rd,
|
||||
.dest_dev = ice_sbq_dev_cgu,
|
||||
.msg_addr_low = addr
|
||||
};
|
||||
int err;
|
||||
|
||||
err = ice_sbq_rw_reg(hw, &cgu_msg, ICE_AQ_FLAG_RD);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to read CGU register 0x%04x, err %d\n",
|
||||
addr, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*val = cgu_msg.data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_write_cgu_reg_e82x - Write a CGU register
|
||||
* @hw: pointer to the HW struct
|
||||
* @addr: Register address to write
|
||||
* @val: value to write into the register
|
||||
*
|
||||
* Write the specified value to a register of the Clock Generation Unit. Only
|
||||
* applicable to E822 devices.
|
||||
*
|
||||
* Return: 0 on success, other error codes when failed to write to CGU
|
||||
*/
|
||||
static int ice_write_cgu_reg_e82x(struct ice_hw *hw, u32 addr, u32 val)
|
||||
{
|
||||
struct ice_sbq_msg_input cgu_msg = {
|
||||
.opcode = ice_sbq_msg_wr,
|
||||
.dest_dev = ice_sbq_dev_cgu,
|
||||
.msg_addr_low = addr,
|
||||
.data = val
|
||||
};
|
||||
int err;
|
||||
|
||||
err = ice_sbq_rw_reg(hw, &cgu_msg, ICE_AQ_FLAG_RD);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to write CGU register 0x%04x, err %d\n",
|
||||
addr, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_clk_freq_str - Convert time_ref_freq to string
|
||||
* @clk_freq: Clock frequency
|
||||
*
|
||||
* Return: specified TIME_REF clock frequency converted to a string
|
||||
*/
|
||||
static const char *ice_clk_freq_str(enum ice_time_ref_freq clk_freq)
|
||||
{
|
||||
switch (clk_freq) {
|
||||
case ICE_TIME_REF_FREQ_25_000:
|
||||
return "25 MHz";
|
||||
case ICE_TIME_REF_FREQ_122_880:
|
||||
return "122.88 MHz";
|
||||
case ICE_TIME_REF_FREQ_125_000:
|
||||
return "125 MHz";
|
||||
case ICE_TIME_REF_FREQ_153_600:
|
||||
return "153.6 MHz";
|
||||
case ICE_TIME_REF_FREQ_156_250:
|
||||
return "156.25 MHz";
|
||||
case ICE_TIME_REF_FREQ_245_760:
|
||||
return "245.76 MHz";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_clk_src_str - Convert time_ref_src to string
|
||||
* @clk_src: Clock source
|
||||
*
|
||||
* Return: specified clock source converted to its string name
|
||||
*/
|
||||
static const char *ice_clk_src_str(enum ice_clk_src clk_src)
|
||||
{
|
||||
switch (clk_src) {
|
||||
case ICE_CLK_SRC_TCXO:
|
||||
return "TCXO";
|
||||
case ICE_CLK_SRC_TIME_REF:
|
||||
return "TIME_REF";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 TCXO)
|
||||
*
|
||||
* Configure the Clock Generation Unit with the desired clock frequency and
|
||||
* time reference, enabling the PLL which drives the PTP hardware clock.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - success
|
||||
* * %-EINVAL - input parameters are incorrect
|
||||
* * %-EBUSY - failed to lock TS PLL
|
||||
* * %other - CGU read/write failure
|
||||
*/
|
||||
static int ice_cfg_cgu_pll_e82x(struct ice_hw *hw,
|
||||
enum ice_time_ref_freq clk_freq,
|
||||
enum ice_clk_src clk_src)
|
||||
{
|
||||
union tspll_ro_bwm_lf bwm_lf;
|
||||
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_25_000) {
|
||||
dev_warn(ice_hw_to_dev(hw),
|
||||
"TCXO only supports 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, TSPLL_RO_BWM_LF, &bwm_lf.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",
|
||||
str_enabled_disabled(dw24.ts_pll_enable),
|
||||
ice_clk_src_str(dw24.time_ref_sel),
|
||||
ice_clk_freq_str(dw9.time_ref_freq_sel),
|
||||
bwm_lf.plllock_true_lock_cri ? "locked" : "unlocked");
|
||||
|
||||
/* Disable the PLL before changing the clock source or frequency */
|
||||
if (dw24.ts_pll_enable) {
|
||||
dw24.ts_pll_enable = 0;
|
||||
|
||||
err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Set the frequency */
|
||||
dw9.time_ref_freq_sel = clk_freq;
|
||||
err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD9, dw9.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 = e822_cgu_params[clk_freq].feedback_div;
|
||||
dw19.tspll_ndivratio = 1;
|
||||
|
||||
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;
|
||||
|
||||
dw22.time1588clk_div = e822_cgu_params[clk_freq].post_pll_div;
|
||||
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_DWORD24, &dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw24.ref1588_ck_div = e822_cgu_params[clk_freq].refclk_pre_div;
|
||||
dw24.tspll_fbdiv_frac = e822_cgu_params[clk_freq].frac_n_div;
|
||||
dw24.time_ref_sel = clk_src;
|
||||
|
||||
err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Finally, enable the PLL */
|
||||
dw24.ts_pll_enable = 1;
|
||||
|
||||
err = ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD24, dw24.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_BWM_LF, &bwm_lf.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!bwm_lf.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",
|
||||
str_enabled_disabled(dw24.ts_pll_enable),
|
||||
ice_clk_src_str(dw24.time_ref_sel),
|
||||
ice_clk_freq_str(dw9.time_ref_freq_sel),
|
||||
bwm_lf.plllock_true_lock_cri ? "locked" : "unlocked");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*
|
||||
* Configure the Clock Generation Unit with the desired clock frequency and
|
||||
* time reference, enabling the PLL which drives the PTP hardware clock.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - success
|
||||
* * %-EINVAL - input parameters are incorrect
|
||||
* * %-EBUSY - failed to lock TS PLL
|
||||
* * %other - CGU read/write failure
|
||||
*/
|
||||
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",
|
||||
str_enabled_disabled(dw24.ts_pll_enable),
|
||||
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",
|
||||
str_enabled_disabled(dw24.ts_pll_enable),
|
||||
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;
|
||||
}
|
||||
|
||||
#define ICE_ONE_PPS_OUT_AMP_MAX 3
|
||||
|
||||
/**
|
||||
* ice_cgu_cfg_pps_out - Configure 1PPS output from CGU
|
||||
* @hw: pointer to the HW struct
|
||||
* @enable: true to enable 1PPS output, false to disable it
|
||||
*
|
||||
* Return: 0 on success, other negative error code when CGU read/write failed
|
||||
*/
|
||||
int ice_cgu_cfg_pps_out(struct ice_hw *hw, bool enable)
|
||||
{
|
||||
union nac_cgu_dword9 dw9;
|
||||
int err;
|
||||
|
||||
err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD9, &dw9.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw9.one_pps_out_en = enable;
|
||||
dw9.one_pps_out_amp = enable * ICE_ONE_PPS_OUT_AMP_MAX;
|
||||
return ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD9, dw9.val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
union tspll_cntr_bist_settings cntr_bist;
|
||||
int err;
|
||||
|
||||
err = ice_read_cgu_reg_e82x(hw, TSPLL_CNTR_BIST_SETTINGS,
|
||||
&cntr_bist.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Disable sticky lock detection so lock err reported is accurate */
|
||||
cntr_bist.i_plllock_sel_0 = 0;
|
||||
cntr_bist.i_plllock_sel_1 = 0;
|
||||
|
||||
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 (hw->mac_type == ICE_MAC_GENERIC_3K_E825)
|
||||
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.
|
||||
*/
|
||||
if (hw->mac_type == ICE_MAC_GENERIC_3K_E825)
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_tmr_cmd_to_src_reg - Convert to source timer command value
|
||||
* @hw: pointer to HW struct
|
||||
@@ -2668,7 +2126,7 @@ int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port)
|
||||
static int ice_ptp_init_phc_e825(struct ice_hw *hw)
|
||||
{
|
||||
/* Initialize the Clock Generation Unit */
|
||||
return ice_init_cgu_e82x(hw);
|
||||
return ice_tspll_init(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3341,7 +2799,7 @@ static int ice_ptp_init_phc_e82x(struct ice_hw *hw)
|
||||
wr32(hw, PF_SB_REM_DEV_CTL, val);
|
||||
|
||||
/* Initialize the Clock Generation Unit */
|
||||
err = ice_init_cgu_e82x(hw);
|
||||
err = ice_tspll_init(hw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -194,23 +194,6 @@ struct ice_eth56g_mac_reg_cfg {
|
||||
extern
|
||||
const struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD];
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @post_pll_div: Post PLL divisor
|
||||
*
|
||||
* Clock Generation Unit parameters used to program the PLL based on the
|
||||
* selected TIME_REF frequency.
|
||||
*/
|
||||
struct ice_cgu_pll_params_e82x {
|
||||
u32 refclk_pre_div;
|
||||
u32 feedback_div;
|
||||
u32 frac_n_div;
|
||||
u32 post_pll_div;
|
||||
};
|
||||
|
||||
#define E810C_QSFP_C827_0_HANDLE 2
|
||||
#define E810C_QSFP_C827_1_HANDLE 3
|
||||
enum ice_e810_c827_idx {
|
||||
@@ -282,31 +265,6 @@ struct ice_cgu_pin_desc {
|
||||
struct dpll_pin_frequency *freq_supp;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@@ -314,7 +272,7 @@ ice_cgu_pll_params_e825c e825c_cgu_params[NUM_ICE_TIME_REF_FREQ];
|
||||
extern const struct ice_phy_reg_info_eth56g eth56g_phy_res[NUM_ETH56G_PHY_RES];
|
||||
|
||||
/* Table of constants related to possible TIME_REF sources */
|
||||
extern const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ];
|
||||
extern const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TSPLL_FREQ];
|
||||
|
||||
/* Table of constants for Vernier calibration on E822 */
|
||||
extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
|
||||
@@ -328,7 +286,6 @@ extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
|
||||
|
||||
/* Device agnostic functions */
|
||||
u8 ice_get_ptp_src_clock_index(struct ice_hw *hw);
|
||||
int ice_cgu_cfg_pps_out(struct ice_hw *hw, bool enable);
|
||||
bool ice_ptp_lock(struct ice_hw *hw);
|
||||
void ice_ptp_unlock(struct ice_hw *hw);
|
||||
void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd);
|
||||
@@ -357,7 +314,8 @@ void ice_ptp_reset_ts_memory_quad_e82x(struct ice_hw *hw, u8 quad);
|
||||
*
|
||||
* Returns the current TIME_REF from the capabilities structure.
|
||||
*/
|
||||
static inline enum ice_time_ref_freq ice_e82x_time_ref(const struct ice_hw *hw)
|
||||
|
||||
static inline enum ice_tspll_freq ice_e82x_time_ref(const struct ice_hw *hw)
|
||||
{
|
||||
return hw->func_caps.ts_func_info.time_ref;
|
||||
}
|
||||
@@ -371,17 +329,17 @@ static inline enum ice_time_ref_freq ice_e82x_time_ref(const struct ice_hw *hw)
|
||||
* change, such as an update to the CGU registers.
|
||||
*/
|
||||
static inline void
|
||||
ice_set_e82x_time_ref(struct ice_hw *hw, enum ice_time_ref_freq time_ref)
|
||||
ice_set_e82x_time_ref(struct ice_hw *hw, enum ice_tspll_freq time_ref)
|
||||
{
|
||||
hw->func_caps.ts_func_info.time_ref = time_ref;
|
||||
}
|
||||
|
||||
static inline u64 ice_e82x_pll_freq(enum ice_time_ref_freq time_ref)
|
||||
static inline u64 ice_e82x_pll_freq(enum ice_tspll_freq time_ref)
|
||||
{
|
||||
return e82x_time_ref[time_ref].pll_freq;
|
||||
}
|
||||
|
||||
static inline u64 ice_e82x_nominal_incval(enum ice_time_ref_freq time_ref)
|
||||
static inline u64 ice_e82x_nominal_incval(enum ice_tspll_freq time_ref)
|
||||
{
|
||||
return e82x_time_ref[time_ref].nominal_incval;
|
||||
}
|
||||
|
||||
511
drivers/net/ethernet/intel/ice/ice_tspll.c
Normal file
511
drivers/net/ethernet/intel/ice/ice_tspll.c
Normal file
@@ -0,0 +1,511 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2025, Intel Corporation. */
|
||||
|
||||
#include "ice.h"
|
||||
#include "ice_lib.h"
|
||||
#include "ice_ptp_hw.h"
|
||||
|
||||
static const struct
|
||||
ice_tspll_params_e82x e82x_tspll_params[NUM_ICE_TSPLL_FREQ] = {
|
||||
[ICE_TSPLL_FREQ_25_000] = {
|
||||
.refclk_pre_div = 1,
|
||||
.post_pll_div = 6,
|
||||
.feedback_div = 197,
|
||||
.frac_n_div = 2621440,
|
||||
},
|
||||
[ICE_TSPLL_FREQ_122_880] = {
|
||||
.refclk_pre_div = 5,
|
||||
.post_pll_div = 7,
|
||||
.feedback_div = 223,
|
||||
.frac_n_div = 524288
|
||||
},
|
||||
[ICE_TSPLL_FREQ_125_000] = {
|
||||
.refclk_pre_div = 5,
|
||||
.post_pll_div = 7,
|
||||
.feedback_div = 223,
|
||||
.frac_n_div = 524288
|
||||
},
|
||||
[ICE_TSPLL_FREQ_153_600] = {
|
||||
.refclk_pre_div = 5,
|
||||
.post_pll_div = 6,
|
||||
.feedback_div = 159,
|
||||
.frac_n_div = 1572864
|
||||
},
|
||||
[ICE_TSPLL_FREQ_156_250] = {
|
||||
.refclk_pre_div = 5,
|
||||
.post_pll_div = 6,
|
||||
.feedback_div = 159,
|
||||
.frac_n_div = 1572864
|
||||
},
|
||||
[ICE_TSPLL_FREQ_245_760] = {
|
||||
.refclk_pre_div = 10,
|
||||
.post_pll_div = 7,
|
||||
.feedback_div = 223,
|
||||
.frac_n_div = 524288
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* ice_tspll_clk_freq_str - Convert time_ref_freq to string
|
||||
* @clk_freq: Clock frequency
|
||||
*
|
||||
* Return: specified TIME_REF clock frequency converted to a string.
|
||||
*/
|
||||
static const char *ice_tspll_clk_freq_str(enum ice_tspll_freq clk_freq)
|
||||
{
|
||||
switch (clk_freq) {
|
||||
case ICE_TSPLL_FREQ_25_000:
|
||||
return "25 MHz";
|
||||
case ICE_TSPLL_FREQ_122_880:
|
||||
return "122.88 MHz";
|
||||
case ICE_TSPLL_FREQ_125_000:
|
||||
return "125 MHz";
|
||||
case ICE_TSPLL_FREQ_153_600:
|
||||
return "153.6 MHz";
|
||||
case ICE_TSPLL_FREQ_156_250:
|
||||
return "156.25 MHz";
|
||||
case ICE_TSPLL_FREQ_245_760:
|
||||
return "245.76 MHz";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_tspll_clk_src_str - Convert time_ref_src to string
|
||||
* @clk_src: Clock source
|
||||
*
|
||||
* Return: specified clock source converted to its string name
|
||||
*/
|
||||
static const char *ice_tspll_clk_src_str(enum ice_clk_src clk_src)
|
||||
{
|
||||
switch (clk_src) {
|
||||
case ICE_CLK_SRC_TCXO:
|
||||
return "TCXO";
|
||||
case ICE_CLK_SRC_TIME_REF:
|
||||
return "TIME_REF";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_tspll_log_cfg - Log current/new TSPLL configuration
|
||||
* @hw: Pointer to the HW struct
|
||||
* @enable: CGU enabled/disabled
|
||||
* @clk_src: Current clock source
|
||||
* @tspll_freq: Current clock frequency
|
||||
* @lock: CGU lock status
|
||||
* @new_cfg: true if this is a new config
|
||||
*/
|
||||
static void ice_tspll_log_cfg(struct ice_hw *hw, bool enable, u8 clk_src,
|
||||
u8 tspll_freq, bool lock, bool new_cfg)
|
||||
{
|
||||
dev_dbg(ice_hw_to_dev(hw),
|
||||
"%s TSPLL configuration -- %s, src %s, freq %s, PLL %s\n",
|
||||
new_cfg ? "New" : "Current", str_enabled_disabled(enable),
|
||||
ice_tspll_clk_src_str((enum ice_clk_src)clk_src),
|
||||
ice_tspll_clk_freq_str((enum ice_tspll_freq)tspll_freq),
|
||||
lock ? "locked" : "unlocked");
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_tspll_cfg_e82x - 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 PLL which drives the PTP hardware clock.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - success
|
||||
* * %-EINVAL - input parameters are incorrect
|
||||
* * %-EBUSY - failed to lock TSPLL
|
||||
* * %other - CGU read/write failure
|
||||
*/
|
||||
static int ice_tspll_cfg_e82x(struct ice_hw *hw, enum ice_tspll_freq clk_freq,
|
||||
enum ice_clk_src clk_src)
|
||||
{
|
||||
union tspll_ro_bwm_lf bwm_lf;
|
||||
union ice_cgu_r19_e82x dw19;
|
||||
union ice_cgu_r22 dw22;
|
||||
union ice_cgu_r24 dw24;
|
||||
union ice_cgu_r9 dw9;
|
||||
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, &dw9.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R24, &dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ice_read_cgu_reg(hw, TSPLL_RO_BWM_LF, &bwm_lf.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ice_tspll_log_cfg(hw, dw24.ts_pll_enable, dw24.time_ref_sel,
|
||||
dw9.time_ref_freq_sel, bwm_lf.plllock_true_lock_cri,
|
||||
false);
|
||||
|
||||
/* Disable the PLL before changing the clock source or frequency */
|
||||
if (dw24.ts_pll_enable) {
|
||||
dw24.ts_pll_enable = 0;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R24, dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Set the frequency */
|
||||
dw9.time_ref_freq_sel = clk_freq;
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R9, dw9.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Configure the TSPLL feedback divisor */
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R19, &dw19.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw19.fbdiv_intgr = e82x_tspll_params[clk_freq].feedback_div;
|
||||
dw19.ndivratio = 1;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R19, dw19.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Configure the TSPLL post divisor */
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R22, &dw22.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw22.time1588clk_div = e82x_tspll_params[clk_freq].post_pll_div;
|
||||
dw22.time1588clk_sel_div2 = 0;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R22, dw22.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Configure the TSPLL pre divisor and clock source */
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R24, &dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw24.ref1588_ck_div = e82x_tspll_params[clk_freq].refclk_pre_div;
|
||||
dw24.fbdiv_frac = e82x_tspll_params[clk_freq].frac_n_div;
|
||||
dw24.time_ref_sel = clk_src;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R24, dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Finally, enable the PLL */
|
||||
dw24.ts_pll_enable = 1;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R24, dw24.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Wait to verify if the PLL locks */
|
||||
usleep_range(1000, 5000);
|
||||
|
||||
err = ice_read_cgu_reg(hw, TSPLL_RO_BWM_LF, &bwm_lf.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!bwm_lf.plllock_true_lock_cri) {
|
||||
dev_warn(ice_hw_to_dev(hw), "TSPLL failed to lock\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ice_tspll_log_cfg(hw, dw24.ts_pll_enable, clk_src, clk_freq, true,
|
||||
true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_tspll_dis_sticky_bits_e82x - 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, other error codes when failed to read/write CGU.
|
||||
*/
|
||||
static int ice_tspll_dis_sticky_bits_e82x(struct ice_hw *hw)
|
||||
{
|
||||
union tspll_cntr_bist_settings cntr_bist;
|
||||
int err;
|
||||
|
||||
err = ice_read_cgu_reg(hw, TSPLL_CNTR_BIST_SETTINGS, &cntr_bist.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Disable sticky lock detection so lock err reported is accurate */
|
||||
cntr_bist.i_plllock_sel_0 = 0;
|
||||
cntr_bist.i_plllock_sel_1 = 0;
|
||||
|
||||
return ice_write_cgu_reg(hw, TSPLL_CNTR_BIST_SETTINGS, cntr_bist.val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_tspll_cfg_e825c - Configure the TSPLL 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)
|
||||
*
|
||||
* Configure the Clock Generation Unit with the desired clock frequency and
|
||||
* time reference, enabling the PLL which drives the PTP hardware clock.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - success
|
||||
* * %-EINVAL - input parameters are incorrect
|
||||
* * %-EBUSY - failed to lock TSPLL
|
||||
* * %other - CGU read/write failure
|
||||
*/
|
||||
static int ice_tspll_cfg_e825c(struct ice_hw *hw, enum ice_tspll_freq clk_freq,
|
||||
enum ice_clk_src clk_src)
|
||||
{
|
||||
union tspll_ro_lock_e825c ro_lock;
|
||||
union ice_cgu_r19_e825 dw19;
|
||||
union ice_cgu_r16 dw16;
|
||||
union ice_cgu_r23 dw23;
|
||||
union ice_cgu_r22 dw22;
|
||||
union ice_cgu_r9 dw9;
|
||||
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, &dw9.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R16, &dw16.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R23, &dw23.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ice_read_cgu_reg(hw, TSPLL_RO_LOCK_E825C, &ro_lock.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ice_tspll_log_cfg(hw, dw23.ts_pll_enable, dw23.time_ref_sel,
|
||||
dw9.time_ref_freq_sel,
|
||||
ro_lock.plllock_true_lock_cri, false);
|
||||
|
||||
/* 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(hw, ICE_CGU_R23, 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(hw, ICE_CGU_R9, dw9.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Choose the referenced frequency */
|
||||
dw16.ck_refclkfreq = ICE_TSPLL_CK_REFCLKFREQ_E825;
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R16, dw16.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Configure the TSPLL feedback divisor */
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R19, &dw19.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw19.tspll_fbdiv_intgr = ICE_TSPLL_FBDIV_INTGR_E825;
|
||||
dw19.tspll_ndivratio = ICE_TSPLL_NDIVRATIO_E825;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R19, dw19.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Configure the TSPLL post divisor */
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R22, &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(hw, ICE_CGU_R22, dw22.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Configure the TSPLL pre divisor and clock source */
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R23, &dw23.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dw23.ref1588_ck_div = 0;
|
||||
dw23.time_ref_sel = clk_src;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R23, dw23.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Clear the R24 register. */
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R24, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Finally, enable the PLL */
|
||||
dw23.ts_pll_enable = 1;
|
||||
|
||||
err = ice_write_cgu_reg(hw, ICE_CGU_R23, dw23.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Wait to verify if the PLL locks */
|
||||
usleep_range(1000, 5000);
|
||||
|
||||
err = ice_read_cgu_reg(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), "TSPLL failed to lock\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ice_tspll_log_cfg(hw, dw23.ts_pll_enable, clk_src, clk_freq, true,
|
||||
true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_tspll_dis_sticky_bits_e825c - disable TSPLL sticky bits for E825-C
|
||||
* @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, other error codes when failed to read/write CGU.
|
||||
*/
|
||||
static int ice_tspll_dis_sticky_bits_e825c(struct ice_hw *hw)
|
||||
{
|
||||
union tspll_bw_tdc_e825c bw_tdc;
|
||||
int err;
|
||||
|
||||
err = ice_read_cgu_reg(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(hw, TSPLL_BW_TDC_E825C, bw_tdc.val);
|
||||
}
|
||||
|
||||
#define ICE_ONE_PPS_OUT_AMP_MAX 3
|
||||
|
||||
/**
|
||||
* ice_tspll_cfg_pps_out_e825c - Enable/disable 1PPS output and set amplitude
|
||||
* @hw: pointer to the HW struct
|
||||
* @enable: true to enable 1PPS output, false to disable it
|
||||
*
|
||||
* Return: 0 on success, other negative error code when CGU read/write failed.
|
||||
*/
|
||||
int ice_tspll_cfg_pps_out_e825c(struct ice_hw *hw, bool enable)
|
||||
{
|
||||
union ice_cgu_r9 r9;
|
||||
int err;
|
||||
|
||||
err = ice_read_cgu_reg(hw, ICE_CGU_R9, &r9.val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
r9.one_pps_out_en = enable;
|
||||
r9.one_pps_out_amp = enable * ICE_ONE_PPS_OUT_AMP_MAX;
|
||||
return ice_write_cgu_reg(hw, ICE_CGU_R9, r9.val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_tspll_init - Initialize TSPLL with settings from firmware
|
||||
* @hw: Pointer to the HW structure
|
||||
*
|
||||
* Initialize the Clock Generation Unit of the E82X/E825 device.
|
||||
*
|
||||
* Return: 0 on success, other error codes when failed to read/write/cfg CGU.
|
||||
*/
|
||||
int ice_tspll_init(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 (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);
|
||||
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;
|
||||
}
|
||||
31
drivers/net/ethernet/intel/ice/ice_tspll.h
Normal file
31
drivers/net/ethernet/intel/ice/ice_tspll.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2025, Intel Corporation. */
|
||||
|
||||
#ifndef _ICE_TSPLL_H_
|
||||
#define _ICE_TSPLL_H_
|
||||
|
||||
/**
|
||||
* struct ice_tspll_params_e82x - E82X TSPLL parameters
|
||||
* @refclk_pre_div: Reference clock pre-divisor
|
||||
* @post_pll_div: Post PLL divisor
|
||||
* @feedback_div: Feedback divisor
|
||||
* @frac_n_div: Fractional divisor
|
||||
*
|
||||
* Clock Generation Unit parameters used to program the PLL based on the
|
||||
* selected TIME_REF/TCXO frequency.
|
||||
*/
|
||||
struct ice_tspll_params_e82x {
|
||||
u8 refclk_pre_div;
|
||||
u8 post_pll_div;
|
||||
u8 feedback_div;
|
||||
u32 frac_n_div;
|
||||
};
|
||||
|
||||
#define ICE_TSPLL_CK_REFCLKFREQ_E825 0x1F
|
||||
#define ICE_TSPLL_NDIVRATIO_E825 5
|
||||
#define ICE_TSPLL_FBDIV_INTGR_E825 256
|
||||
|
||||
int ice_tspll_cfg_pps_out_e825c(struct ice_hw *hw, bool enable);
|
||||
int ice_tspll_init(struct ice_hw *hw);
|
||||
|
||||
#endif /* _ICE_TSPLL_H_ */
|
||||
@@ -326,17 +326,17 @@ struct ice_hw_common_caps {
|
||||
#define ICE_TS_TMR_IDX_ASSOC_M BIT(24)
|
||||
|
||||
/* TIME_REF clock rate specification */
|
||||
enum ice_time_ref_freq {
|
||||
ICE_TIME_REF_FREQ_25_000 = 0,
|
||||
ICE_TIME_REF_FREQ_122_880 = 1,
|
||||
ICE_TIME_REF_FREQ_125_000 = 2,
|
||||
ICE_TIME_REF_FREQ_153_600 = 3,
|
||||
ICE_TIME_REF_FREQ_156_250 = 4,
|
||||
ICE_TIME_REF_FREQ_245_760 = 5,
|
||||
enum ice_tspll_freq {
|
||||
ICE_TSPLL_FREQ_25_000 = 0,
|
||||
ICE_TSPLL_FREQ_122_880 = 1,
|
||||
ICE_TSPLL_FREQ_125_000 = 2,
|
||||
ICE_TSPLL_FREQ_153_600 = 3,
|
||||
ICE_TSPLL_FREQ_156_250 = 4,
|
||||
ICE_TSPLL_FREQ_245_760 = 5,
|
||||
|
||||
NUM_ICE_TIME_REF_FREQ,
|
||||
NUM_ICE_TSPLL_FREQ,
|
||||
|
||||
ICE_TIME_REF_FREQ_INVALID = -1,
|
||||
ICE_TSPLL_FREQ_INVALID = -1,
|
||||
};
|
||||
|
||||
/* Clock source specification */
|
||||
@@ -349,7 +349,7 @@ enum ice_clk_src {
|
||||
|
||||
struct ice_ts_func_info {
|
||||
/* Function specific info */
|
||||
enum ice_time_ref_freq time_ref;
|
||||
enum ice_tspll_freq time_ref;
|
||||
u8 clk_freq;
|
||||
u8 clk_src;
|
||||
u8 tmr_index_assoc;
|
||||
|
||||
Reference in New Issue
Block a user