Merge branch 'ice-introduce-eth56g-phy-model-for-e825c-products'

Jacob Keller says:

====================
ice: Introduce ETH56G PHY model for E825C products

E825C products have a different PHY model than E822, E823 and E810 products.
This PHY is ETH56G and its support is necessary to have functional PTP stack
for E825C products.

This series refactors the ice driver to add support for the new PHY model.

Karol introduces the ice_ptp_hw structure. This is used to replace some
hard-coded values relating to the PHY quad and port numbers, as well as to
hold the phy_model type.

Jacob refactors the driver code that converts between the ice_ptp_tmr_cmd
enumeration and hardware register values to better re-use logic and reduce
duplication when introducing another PHY type.

Sergey introduces functions to help enable and disable the Tx timestamp
interrupts. This makes the ice_ptp.c code more generic and encapsulates the
PHY specifics into ice_ptp_hw.c

Karol introduces helper functions to clear the valid bits for Tx and Rx
timestamps. This enables informing hardware to discard stale timestamps
after performing clock operations.

Sergey moves the Clock Generation Unit (CGU) logic out of the E822 specific
area of the ice_ptp_hw.c file as it will be re-used for other device PHY
models.

Jacob introduces a helper function for obtaining the base increment values,
moving this logic out of ice_ptp.c and into the ice_ptp_hw.c file to better
encapsulate hardware differences.

Sergey builds on these refactors to introduce the new ETH56G PHY model used
by the E825C products. This includes introducing the required helpers,
constants, and PHY model checks.

Karol simplifies the CGU logic by using anonymous structures, dropping an
unnecessary ".field" name for accessing the CGU data.

Michal Michalik updates the CGU logic to support the E825C hardware,
ensuring that the clock generation is configured properly.

Grzegorz Nitka adds support to read the NAC topology data from the device.
This is in preparation for supporting devices which combine two NACs
together, connecting all ports to the same clock source. This enables the
driver to determine if its operating on such a device, or if its operating
on the standard 1-NAC configuration.

Grzsecgorz Nitka adjusts the PTP initialization to prepare for the 2x50G
E825C devices, introducing special mapping for the PHY ports to prepare for
support of the 2-NAC devices.

With this, the ice driver is capable of handling PTP for the single-NAC
E825C devices. Complete support for the 2-NAC devices requirs some work on
how the ports connect to the clock owner. During review of this work, it
was pointed out that our existing use of auxiliary bus is disliked, and
Jiri requested that we change it. We are currently working on developing a
replacement solution for the auxiliary bus implementation and have dropped
the relevant changes out of this series. A future series will refactor the
port to clock connection, at which time we will finish the support for
2-NAC E825C devices.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
====================

Link: https://lore.kernel.org/r/20240528-next-2024-05-28-ptp-refactors-v1-0-c082739bb6f6@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2024-06-01 15:51:53 -07:00
commit fc5570e0bd
12 changed files with 3754 additions and 634 deletions

View File

@ -122,6 +122,7 @@ struct ice_aqc_list_caps_elem {
#define ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT 0x0077
#define ICE_AQC_CAPS_NVM_MGMT 0x0080
#define ICE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE 0x0085
#define ICE_AQC_CAPS_NAC_TOPOLOGY 0x0087
#define ICE_AQC_CAPS_FW_LAG_SUPPORT 0x0092
#define ICE_AQC_BIT_ROCEV2_LAG 0x01
#define ICE_AQC_BIT_SRIOV_LAG 0x02

View File

@ -23,7 +23,18 @@ union nac_cgu_dword9 {
u32 clk_synce0_amp : 2;
u32 one_pps_out_amp : 2;
u32 misc24 : 12;
} field;
};
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;
};
@ -39,7 +50,7 @@ union nac_cgu_dword19 {
u32 japll_ndivratio : 4;
u32 japll_iref_ndivratio : 3;
u32 misc27 : 1;
} field;
};
u32 val;
};
@ -63,7 +74,23 @@ union nac_cgu_dword22 {
u32 fdpllclk_sel_div2 : 1;
u32 time1588clk_sel_div2 : 1;
u32 misc3 : 1;
} field;
};
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;
};
@ -77,7 +104,7 @@ union nac_cgu_dword24 {
u32 ext_synce_sel : 1;
u32 ref1588_ck_div : 4;
u32 time_ref_sel : 1;
} field;
};
u32 val;
};
@ -92,7 +119,7 @@ union tspll_cntr_bist_settings {
u32 i_plllock_cnt_6_0 : 7;
u32 i_plllock_cnt_10_7 : 4;
u32 reserved200 : 4;
} field;
};
u32 val;
};
@ -109,7 +136,45 @@ union tspll_ro_bwm_lf {
u32 afcdone_cri : 1;
u32 feedfwrdgain_cal_cri_7_0 : 8;
u32 m2fbdivmod_cri_7_0 : 8;
} field;
};
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;
};

View File

@ -239,6 +239,30 @@ bool ice_is_e810t(struct ice_hw *hw)
return false;
}
/**
* ice_is_e822 - Check if a device is E822 family device
* @hw: pointer to the hardware structure
*
* Return: true if the device is E822 based, false if not.
*/
bool ice_is_e822(struct ice_hw *hw)
{
switch (hw->device_id) {
case ICE_DEV_ID_E822C_BACKPLANE:
case ICE_DEV_ID_E822C_QSFP:
case ICE_DEV_ID_E822C_SFP:
case ICE_DEV_ID_E822C_10G_BASE_T:
case ICE_DEV_ID_E822C_SGMII:
case ICE_DEV_ID_E822L_BACKPLANE:
case ICE_DEV_ID_E822L_SFP:
case ICE_DEV_ID_E822L_10G_BASE_T:
case ICE_DEV_ID_E822L_SGMII:
return true;
default:
return false;
}
}
/**
* ice_is_e823
* @hw: pointer to the hardware structure
@ -2290,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);
info->clk_freq = FIELD_GET(ICE_TS_CLK_FREQ_M, number);
info->clk_src = ((number & ICE_TS_CLK_SRC_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;
@ -2564,6 +2593,34 @@ ice_parse_sensor_reading_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
dev_p->supported_sensors);
}
/**
* ice_parse_nac_topo_dev_caps - Parse ICE_AQC_CAPS_NAC_TOPOLOGY cap
* @hw: pointer to the HW struct
* @dev_p: pointer to device capabilities structure
* @cap: capability element to parse
*
* Parse ICE_AQC_CAPS_NAC_TOPOLOGY for device capabilities.
*/
static void ice_parse_nac_topo_dev_caps(struct ice_hw *hw,
struct ice_hw_dev_caps *dev_p,
struct ice_aqc_list_caps_elem *cap)
{
dev_p->nac_topo.mode = le32_to_cpu(cap->number);
dev_p->nac_topo.id = le32_to_cpu(cap->phys_id) & ICE_NAC_TOPO_ID_M;
dev_info(ice_hw_to_dev(hw),
"PF is configured in %s mode with IP instance ID %d\n",
(dev_p->nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M) ?
"primary" : "secondary", dev_p->nac_topo.id);
ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology is_primary = %d\n",
!!(dev_p->nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M));
ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology is_dual = %d\n",
!!(dev_p->nac_topo.mode & ICE_NAC_TOPO_DUAL_M));
ice_debug(hw, ICE_DBG_INIT, "dev caps: nac topology id = %d\n",
dev_p->nac_topo.id);
}
/**
* ice_parse_dev_caps - Parse device capabilities
* @hw: pointer to the HW struct
@ -2615,6 +2672,9 @@ ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
case ICE_AQC_CAPS_SENSOR_READING:
ice_parse_sensor_reading_cap(hw, dev_p, &cap_resp[i]);
break;
case ICE_AQC_CAPS_NAC_TOPOLOGY:
ice_parse_nac_topo_dev_caps(hw, dev_p, &cap_resp[i]);
break;
default:
/* Don't list common capabilities as unknown */
if (!found)
@ -3043,11 +3103,13 @@ bool ice_is_100m_speed_supported(struct ice_hw *hw)
* Note: In the structure of [phy_type_low, phy_type_high], there should
* be one bit set, as this function will convert one PHY type to its
* speed.
* If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
* If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
*
* Return:
* * PHY speed for recognized PHY type
* * If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
* * If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
*/
static u16
ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
{
u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;

View File

@ -249,6 +249,7 @@ void
ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
u64 *prev_stat, u64 *cur_stat);
bool ice_is_e810t(struct ice_hw *hw);
bool ice_is_e822(struct ice_hw *hw);
bool ice_is_e823(struct ice_hw *hw);
bool ice_is_e825c(struct ice_hw *hw);
int
@ -261,6 +262,7 @@ int
ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
bool *value, struct ice_sq_cd *cd);
bool ice_is_100m_speed_supported(struct ice_hw *hw);
u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high);
int
ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
struct ice_sq_cd *cd);

View File

@ -157,6 +157,8 @@
#define GLGEN_RTRIG_CORER_M BIT(0)
#define GLGEN_RTRIG_GLOBR_M BIT(1)
#define GLGEN_STAT 0x000B612C
#define GLGEN_SWITCH_MODE_CONFIG 0x000B81E0
#define GLGEN_SWITCH_MODE_CONFIG_25X4_QUAD_M BIT(2)
#define GLGEN_VFLRSTAT(_i) (0x00093A04 + ((_i) * 4))
#define PFGEN_CTRL 0x00091000
#define PFGEN_CTRL_PFSWR_M BIT(0)
@ -177,6 +179,8 @@
#define GLINT_CTL_ITR_GRAN_50_M ICE_M(0xF, 24)
#define GLINT_CTL_ITR_GRAN_25_S 28
#define GLINT_CTL_ITR_GRAN_25_M ICE_M(0xF, 28)
#define GLGEN_MAC_LINK_TOPO 0x000B81DC
#define GLGEN_MAC_LINK_TOPO_LINK_TOPO_M GENMASK(1, 0)
#define GLINT_DYN_CTL(_INT) (0x00160000 + ((_INT) * 4))
#define GLINT_DYN_CTL_INTENA_M BIT(0)
#define GLINT_DYN_CTL_CLEARPBA_M BIT(1)

View File

@ -7,8 +7,6 @@
#define E810_OUT_PROP_DELAY_NS 1
#define UNKNOWN_INCVAL_E82X 0x100000000ULL
static const struct ptp_pin_desc ice_pin_desc_e810t[] = {
/* name idx func chan */
{ "GNSS", GNSS, PTP_PF_EXTTS, 0, { 0, } },
@ -813,7 +811,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
}
mutex_unlock(&pf->ptp.ports_owner.lock);
for (i = 0; i < ICE_MAX_QUAD; i++) {
for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) {
u64 tstamp_ready;
int err;
@ -1013,6 +1011,28 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
tx->len = 0;
}
/**
* ice_ptp_init_tx_eth56g - Initialize tracking for Tx timestamps
* @pf: Board private structure
* @tx: the Tx tracking structure to initialize
* @port: the port this structure tracks
*
* Initialize the Tx timestamp tracker for this port. ETH56G PHYs
* have independent memory blocks for all ports.
*
* Return: 0 for success, -ENOMEM when failed to allocate Tx tracker
*/
static int ice_ptp_init_tx_eth56g(struct ice_pf *pf, struct ice_ptp_tx *tx,
u8 port)
{
tx->block = port;
tx->offset = 0;
tx->len = INDEX_PER_PORT_ETH56G;
tx->has_ready_bitmap = 1;
return ice_ptp_alloc_tx_tracker(tx);
}
/**
* ice_ptp_init_tx_e82x - Initialize tracking for Tx timestamps
* @pf: Board private structure
@ -1027,7 +1047,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
static int
ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
{
tx->block = port / ICE_PORTS_PER_QUAD;
tx->block = ICE_GET_QUAD_NUM(port);
tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E82X;
tx->len = INDEX_PER_PORT_E82X;
tx->has_ready_bitmap = 1;
@ -1210,12 +1230,7 @@ static u64 ice_base_incval(struct ice_pf *pf)
struct ice_hw *hw = &pf->hw;
u64 incval;
if (ice_is_e810(hw))
incval = ICE_PTP_NOMINAL_INCVAL_E810;
else if (ice_e82x_time_ref(hw) < NUM_ICE_TIME_REF_FREQ)
incval = ice_e82x_nominal_incval(ice_e82x_time_ref(hw));
else
incval = UNKNOWN_INCVAL_E82X;
incval = ice_get_base_incval(hw);
dev_dbg(ice_pf_to_dev(pf), "PTP: using base increment value of 0x%016llx\n",
incval);
@ -1229,8 +1244,8 @@ static u64 ice_base_incval(struct ice_pf *pf)
*/
static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port)
{
int quad = port->port_num / ICE_PORTS_PER_QUAD;
int offs = port->port_num % ICE_PORTS_PER_QUAD;
int quad = ICE_GET_QUAD_NUM(port->port_num);
struct ice_pf *pf;
struct ice_hw *hw;
u32 val, phy_sts;
@ -1348,10 +1363,19 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
mutex_lock(&ptp_port->ps_lock);
kthread_cancel_delayed_work_sync(&ptp_port->ov_work);
switch (hw->ptp.phy_model) {
case ICE_PHY_ETH56G:
err = ice_stop_phy_timer_eth56g(hw, port, true);
break;
case ICE_PHY_E82X:
kthread_cancel_delayed_work_sync(&ptp_port->ov_work);
err = ice_stop_phy_timer_e82x(hw, port, true);
if (err)
err = ice_stop_phy_timer_e82x(hw, port, true);
break;
default:
err = -ENODEV;
}
if (err && err != -EBUSY)
dev_err(ice_pf_to_dev(pf), "PTP failed to set PHY port %d down, err %d\n",
port, err);
@ -1385,27 +1409,39 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
mutex_lock(&ptp_port->ps_lock);
kthread_cancel_delayed_work_sync(&ptp_port->ov_work);
switch (hw->ptp.phy_model) {
case ICE_PHY_ETH56G:
err = ice_start_phy_timer_eth56g(hw, port);
break;
case ICE_PHY_E82X:
/* Start the PHY timer in Vernier mode */
kthread_cancel_delayed_work_sync(&ptp_port->ov_work);
/* temporarily disable Tx timestamps while calibrating PHY offset */
spin_lock_irqsave(&ptp_port->tx.lock, flags);
ptp_port->tx.calibrating = true;
spin_unlock_irqrestore(&ptp_port->tx.lock, flags);
ptp_port->tx_fifo_busy_cnt = 0;
/* temporarily disable Tx timestamps while calibrating
* PHY offset
*/
spin_lock_irqsave(&ptp_port->tx.lock, flags);
ptp_port->tx.calibrating = true;
spin_unlock_irqrestore(&ptp_port->tx.lock, flags);
ptp_port->tx_fifo_busy_cnt = 0;
/* Start the PHY timer in Vernier mode */
err = ice_start_phy_timer_e82x(hw, port);
if (err)
goto out_unlock;
/* Start the PHY timer in Vernier mode */
err = ice_start_phy_timer_e82x(hw, port);
if (err)
break;
/* Enable Tx timestamps right away */
spin_lock_irqsave(&ptp_port->tx.lock, flags);
ptp_port->tx.calibrating = false;
spin_unlock_irqrestore(&ptp_port->tx.lock, flags);
/* Enable Tx timestamps right away */
spin_lock_irqsave(&ptp_port->tx.lock, flags);
ptp_port->tx.calibrating = false;
spin_unlock_irqrestore(&ptp_port->tx.lock, flags);
kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work, 0);
kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work,
0);
break;
default:
err = -ENODEV;
}
out_unlock:
if (err)
dev_err(ice_pf_to_dev(pf), "PTP failed to set PHY port %d up, err %d\n",
port, err);
@ -1429,20 +1465,23 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
if (pf->ptp.state != ICE_PTP_READY)
return;
if (WARN_ON_ONCE(port >= ICE_NUM_EXTERNAL_PORTS))
if (WARN_ON_ONCE(port >= hw->ptp.num_lports))
return;
ptp_port = &pf->ptp.port;
if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
port *= 2;
if (WARN_ON_ONCE(ptp_port->port_num != port))
return;
/* Update cached link status for this port immediately */
ptp_port->link_up = linkup;
switch (hw->phy_model) {
switch (hw->ptp.phy_model) {
case ICE_PHY_E810:
/* Do not reconfigure E810 PHY */
return;
case ICE_PHY_ETH56G:
case ICE_PHY_E82X:
ice_ptp_port_phy_restart(ptp_port);
return;
@ -1457,42 +1496,62 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
* @ena: bool value to enable or disable interrupt
* @threshold: Minimum number of packets at which intr is triggered
*
* Utility function to enable or disable Tx timestamp interrupt and threshold
* Utility function to configure all the PHY interrupt settings, including
* whether the PHY interrupt is enabled, and what threshold to use. Also
* configures The E82X timestamp owner to react to interrupts from all PHYs.
*
* Return: 0 on success, -EOPNOTSUPP when PHY model incorrect, other error codes
* when failed to configure PHY interrupt for E82X
*/
static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw;
int err = 0;
int quad;
u32 val;
ice_ptp_reset_ts_memory(hw);
for (quad = 0; quad < ICE_MAX_QUAD; quad++) {
err = ice_read_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG,
&val);
if (err)
break;
switch (hw->ptp.phy_model) {
case ICE_PHY_ETH56G: {
int port;
if (ena) {
val |= Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M;
val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_THR_M;
val |= FIELD_PREP(Q_REG_TX_MEM_GBL_CFG_INTR_THR_M,
threshold);
} else {
val &= ~Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M;
for (port = 0; port < hw->ptp.num_lports; port++) {
int err;
err = ice_phy_cfg_intr_eth56g(hw, port, ena, threshold);
if (err) {
dev_err(dev, "Failed to configure PHY interrupt for port %d, err %d\n",
port, err);
return err;
}
}
err = ice_write_quad_reg_e82x(hw, quad, Q_REG_TX_MEM_GBL_CFG,
val);
if (err)
break;
return 0;
}
case ICE_PHY_E82X: {
int quad;
if (err)
dev_err(ice_pf_to_dev(pf), "PTP failed in intr ena, err %d\n",
err);
return err;
for (quad = 0; quad < ICE_GET_QUAD_NUM(hw->ptp.num_lports);
quad++) {
int err;
err = ice_phy_cfg_intr_e82x(hw, quad, ena, threshold);
if (err) {
dev_err(dev, "Failed to configure PHY interrupt for quad %d, err %d\n",
quad, err);
return err;
}
}
return 0;
}
case ICE_PHY_E810:
return 0;
case ICE_PHY_UNSUP:
default:
dev_warn(dev, "%s: Unexpected PHY model %d\n", __func__,
hw->ptp.phy_model);
return -EOPNOTSUPP;
}
}
/**
@ -1929,11 +1988,14 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
struct ice_hw *hw = &pf->hw;
int err;
/* For Vernier mode, we need to recalibrate after new settime
* Start with disabling timestamp block
/* For Vernier mode on E82X, we need to recalibrate after new settime.
* Start with marking timestamps as invalid.
*/
if (pf->ptp.port.link_up)
ice_ptp_port_phy_stop(&pf->ptp.port);
if (hw->ptp.phy_model == ICE_PHY_E82X) {
err = ice_ptp_clear_phy_offset_ready_e82x(hw);
if (err)
dev_warn(ice_pf_to_dev(pf), "Failed to mark timestamps as invalid before settime\n");
}
if (!ice_ptp_lock(hw)) {
err = -EBUSY;
@ -1953,7 +2015,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
ice_ptp_enable_all_clkout(pf);
/* Recalibrate and re-enable timestamp blocks for E822/E823 */
if (hw->phy_model == ICE_PHY_E82X)
if (hw->ptp.phy_model == ICE_PHY_E82X)
ice_ptp_restart_all_phy(pf);
exit:
if (err) {
@ -2578,7 +2640,7 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf)
if (!ice_pf_src_tmr_owned(pf))
return;
for (i = 0; i < ICE_MAX_QUAD; i++) {
for (i = 0; i < ICE_GET_QUAD_NUM(hw->ptp.num_lports); i++) {
u64 tstamp_ready;
int err;
@ -3010,12 +3072,10 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
/* Release the global hardware lock */
ice_ptp_unlock(hw);
if (!ice_is_e810(hw)) {
/* Enable quad interrupts */
err = ice_ptp_cfg_phy_interrupt(pf, true, 1);
if (err)
goto err_exit;
}
/* Configure PHY interrupt settings */
err = ice_ptp_cfg_phy_interrupt(pf, true, 1);
if (err)
goto err_exit;
/* Ensure we have a clock device */
err = ice_ptp_create_clock(pf);
@ -3076,7 +3136,10 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
mutex_init(&ptp_port->ps_lock);
switch (hw->phy_model) {
switch (hw->ptp.phy_model) {
case ICE_PHY_ETH56G:
return ice_ptp_init_tx_eth56g(pf, &ptp_port->tx,
ptp_port->port_num);
case ICE_PHY_E810:
return ice_ptp_init_tx_e810(pf, &ptp_port->tx);
case ICE_PHY_E82X:
@ -3171,7 +3234,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
*/
static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf)
{
switch (pf->hw.phy_model) {
switch (pf->hw.ptp.phy_model) {
case ICE_PHY_E82X:
/* E822 based PHY has the clock owner process the interrupt
* for all ports.
@ -3207,7 +3270,7 @@ void ice_ptp_init(struct ice_pf *pf)
ptp->state = ICE_PTP_INITIALIZING;
ice_ptp_init_phy_model(hw);
ice_ptp_init_hw(hw);
ice_ptp_init_tx_interrupt_mode(pf);
@ -3221,6 +3284,9 @@ void ice_ptp_init(struct ice_pf *pf)
}
ptp->port.port_num = hw->pf_id;
if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
ptp->port.port_num = hw->pf_id * 2;
err = ice_ptp_init_port(pf, &ptp->port);
if (err)
goto err;

View File

@ -153,6 +153,7 @@ struct ice_ptp_tx {
#define INDEX_PER_QUAD 64
#define INDEX_PER_PORT_E82X 16
#define INDEX_PER_PORT_E810 64
#define INDEX_PER_PORT_ETH56G 64
/**
* struct ice_ptp_port - data used to initialize an external port for PTP

View File

@ -9,6 +9,321 @@
*/
/* Constants defined for the PTP 1588 clock hardware. */
const struct ice_phy_reg_info_eth56g eth56g_phy_res[NUM_ETH56G_PHY_RES] = {
/* ETH56G_PHY_REG_PTP */
{
/* base_addr */
{
0x092000,
0x126000,
0x1BA000,
0x24E000,
0x2E2000,
},
/* step */
0x98,
},
/* ETH56G_PHY_MEM_PTP */
{
/* base_addr */
{
0x093000,
0x127000,
0x1BB000,
0x24F000,
0x2E3000,
},
/* step */
0x200,
},
/* ETH56G_PHY_REG_XPCS */
{
/* base_addr */
{
0x000000,
0x009400,
0x128000,
0x1BC000,
0x250000,
},
/* step */
0x21000,
},
/* ETH56G_PHY_REG_MAC */
{
/* base_addr */
{
0x085000,
0x119000,
0x1AD000,
0x241000,
0x2D5000,
},
/* step */
0x1000,
},
/* ETH56G_PHY_REG_GPCS */
{
/* base_addr */
{
0x084000,
0x118000,
0x1AC000,
0x240000,
0x2D4000,
},
/* step */
0x400,
},
};
const
struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD] = {
[ICE_ETH56G_LNK_SPD_1G] = {
.tx_mode = { .def = 6, },
.rx_mode = { .def = 6, },
.blks_per_clk = 1,
.blktime = 0x4000, /* 32 */
.tx_offset = {
.serdes = 0x6666, /* 51.2 */
.no_fec = 0xd066, /* 104.2 */
.sfd = 0x3000, /* 24 */
.onestep = 0x30000 /* 384 */
},
.rx_offset = {
.serdes = 0xffffc59a, /* -29.2 */
.no_fec = 0xffff0a80, /* -122.75 */
.sfd = 0x2c00, /* 22 */
.bs_ds = 0x19a /* 0.8 */
/* Dynamic bitslip 0 equals to 10 */
}
},
[ICE_ETH56G_LNK_SPD_2_5G] = {
.tx_mode = { .def = 6, },
.rx_mode = { .def = 6, },
.blks_per_clk = 1,
.blktime = 0x199a, /* 12.8 */
.tx_offset = {
.serdes = 0x28f6, /* 20.48 */
.no_fec = 0x53b8, /* 41.86 */
.sfd = 0x1333, /* 9.6 */
.onestep = 0x13333 /* 153.6 */
},
.rx_offset = {
.serdes = 0xffffe8a4, /* -11.68 */
.no_fec = 0xffff9a76, /* -50.77 */
.sfd = 0xf33, /* 7.6 */
.bs_ds = 0xa4 /* 0.32 */
}
},
[ICE_ETH56G_LNK_SPD_10G] = {
.tx_mode = { .def = 1, },
.rx_mode = { .def = 1, },
.blks_per_clk = 1,
.blktime = 0x666, /* 3.2 */
.tx_offset = {
.serdes = 0x234c, /* 17.6484848 */
.no_fec = 0x8e80, /* 71.25 */
.fc = 0xb4a4, /* 90.32 */
.sfd = 0x4a4, /* 2.32 */
.onestep = 0x4ccd /* 38.4 */
},
.rx_offset = {
.serdes = 0xffffeb27, /* -10.42424 */
.no_fec = 0xffffcccd, /* -25.6 */
.fc = 0xfffe0014, /* -255.96 */
.sfd = 0x4a4, /* 2.32 */
.bs_ds = 0x32 /* 0.0969697 */
}
},
[ICE_ETH56G_LNK_SPD_25G] = {
.tx_mode = {
.def = 1,
.rs = 4
},
.tx_mk_dly = 4,
.tx_cw_dly = {
.def = 1,
.onestep = 6
},
.rx_mode = {
.def = 1,
.rs = 4
},
.rx_mk_dly = {
.def = 1,
.rs = 1
},
.rx_cw_dly = {
.def = 1,
.rs = 1
},
.blks_per_clk = 1,
.blktime = 0x28f, /* 1.28 */
.mktime = 0x147b, /* 10.24, only if RS-FEC enabled */
.tx_offset = {
.serdes = 0xe1e, /* 7.0593939 */
.no_fec = 0x3857, /* 28.17 */
.fc = 0x48c3, /* 36.38 */
.rs = 0x8100, /* 64.5 */
.sfd = 0x1dc, /* 0.93 */
.onestep = 0x1eb8 /* 15.36 */
},
.rx_offset = {
.serdes = 0xfffff7a9, /* -4.1697 */
.no_fec = 0xffffe71a, /* -12.45 */
.fc = 0xfffe894d, /* -187.35 */
.rs = 0xfffff8cd, /* -3.6 */
.sfd = 0x1dc, /* 0.93 */
.bs_ds = 0x14 /* 0.0387879, RS-FEC 0 */
}
},
[ICE_ETH56G_LNK_SPD_40G] = {
.tx_mode = { .def = 3 },
.tx_mk_dly = 4,
.tx_cw_dly = {
.def = 1,
.onestep = 6
},
.rx_mode = { .def = 4 },
.rx_mk_dly = { .def = 1 },
.rx_cw_dly = { .def = 1 },
.blktime = 0x333, /* 1.6 */
.mktime = 0xccd, /* 6.4 */
.tx_offset = {
.serdes = 0x234c, /* 17.6484848 */
.no_fec = 0x5a8a, /* 45.27 */
.fc = 0x81b8, /* 64.86 */
.sfd = 0x4a4, /* 2.32 */
.onestep = 0x1333 /* 9.6 */
},
.rx_offset = {
.serdes = 0xffffeb27, /* -10.42424 */
.no_fec = 0xfffff594, /* -5.21 */
.fc = 0xfffe3080, /* -231.75 */
.sfd = 0x4a4, /* 2.32 */
.bs_ds = 0xccd /* 6.4 */
}
},
[ICE_ETH56G_LNK_SPD_50G] = {
.tx_mode = { .def = 5 },
.tx_mk_dly = 4,
.tx_cw_dly = {
.def = 1,
.onestep = 6
},
.rx_mode = { .def = 5 },
.rx_mk_dly = { .def = 1 },
.rx_cw_dly = { .def = 1 },
.blktime = 0x28f, /* 1.28 */
.mktime = 0xa3d, /* 5.12 */
.tx_offset = {
.serdes = 0x13ba, /* 9.86353 */
.rs = 0x5400, /* 42 */
.sfd = 0xe6, /* 0.45 */
.onestep = 0xf5c /* 7.68 */
},
.rx_offset = {
.serdes = 0xfffff7e8, /* -4.04706 */
.rs = 0xfffff994, /* -3.21 */
.sfd = 0xe6 /* 0.45 */
}
},
[ICE_ETH56G_LNK_SPD_50G2] = {
.tx_mode = {
.def = 3,
.rs = 2
},
.tx_mk_dly = 4,
.tx_cw_dly = {
.def = 1,
.onestep = 6
},
.rx_mode = {
.def = 4,
.rs = 1
},
.rx_mk_dly = { .def = 1 },
.rx_cw_dly = { .def = 1 },
.blktime = 0x28f, /* 1.28 */
.mktime = 0xa3d, /* 5.12 */
.tx_offset = {
.serdes = 0xe1e, /* 7.0593939 */
.no_fec = 0x3d33, /* 30.6 */
.rs = 0x5057, /* 40.17 */
.sfd = 0x1dc, /* 0.93 */
.onestep = 0xf5c /* 7.68 */
},
.rx_offset = {
.serdes = 0xfffff7a9, /* -4.1697 */
.no_fec = 0xfffff8cd, /* -3.6 */
.rs = 0xfffff21a, /* -6.95 */
.sfd = 0x1dc, /* 0.93 */
.bs_ds = 0xa3d /* 5.12, RS-FEC 0x633 (3.1) */
}
},
[ICE_ETH56G_LNK_SPD_100G] = {
.tx_mode = {
.def = 3,
.rs = 2
},
.tx_mk_dly = 10,
.tx_cw_dly = {
.def = 3,
.onestep = 6
},
.rx_mode = {
.def = 4,
.rs = 1
},
.rx_mk_dly = { .def = 5 },
.rx_cw_dly = { .def = 5 },
.blks_per_clk = 1,
.blktime = 0x148, /* 0.64 */
.mktime = 0x199a, /* 12.8 */
.tx_offset = {
.serdes = 0xe1e, /* 7.0593939 */
.no_fec = 0x67ec, /* 51.96 */
.rs = 0x44fb, /* 34.49 */
.sfd = 0x1dc, /* 0.93 */
.onestep = 0xf5c /* 7.68 */
},
.rx_offset = {
.serdes = 0xfffff7a9, /* -4.1697 */
.no_fec = 0xfffff5a9, /* -5.17 */
.rs = 0xfffff6e6, /* -4.55 */
.sfd = 0x1dc, /* 0.93 */
.bs_ds = 0x199a /* 12.8, RS-FEC 0x31b (1.552) */
}
},
[ICE_ETH56G_LNK_SPD_100G2] = {
.tx_mode = { .def = 5 },
.tx_mk_dly = 10,
.tx_cw_dly = {
.def = 3,
.onestep = 6
},
.rx_mode = { .def = 5 },
.rx_mk_dly = { .def = 5 },
.rx_cw_dly = { .def = 5 },
.blks_per_clk = 1,
.blktime = 0x148, /* 0.64 */
.mktime = 0x199a, /* 12.8 */
.tx_offset = {
.serdes = 0x13ba, /* 9.86353 */
.rs = 0x460a, /* 35.02 */
.sfd = 0xe6, /* 0.45 */
.onestep = 0xf5c /* 7.68 */
},
.rx_offset = {
.serdes = 0xfffff7e8, /* -4.04706 */
.rs = 0xfffff548, /* -5.36 */
.sfd = 0xe6, /* 0.45 */
.bs_ds = 0x303 /* 1.506 */
}
}
};
/* struct ice_time_ref_info_e82x
*
* E822 hardware can use different sources as the reference for the PTP
@ -155,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

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,41 @@ enum ice_ptp_fec_mode {
ICE_PTP_FEC_MODE_RS_FEC
};
enum eth56g_res_type {
ETH56G_PHY_REG_PTP,
ETH56G_PHY_MEM_PTP,
ETH56G_PHY_REG_XPCS,
ETH56G_PHY_REG_MAC,
ETH56G_PHY_REG_GPCS,
NUM_ETH56G_PHY_RES
};
enum ice_eth56g_link_spd {
ICE_ETH56G_LNK_SPD_1G,
ICE_ETH56G_LNK_SPD_2_5G,
ICE_ETH56G_LNK_SPD_10G,
ICE_ETH56G_LNK_SPD_25G,
ICE_ETH56G_LNK_SPD_40G,
ICE_ETH56G_LNK_SPD_50G,
ICE_ETH56G_LNK_SPD_50G2,
ICE_ETH56G_LNK_SPD_100G,
ICE_ETH56G_LNK_SPD_100G2,
NUM_ICE_ETH56G_LNK_SPD /* Must be last */
};
/**
* struct ice_phy_reg_info_eth56g - ETH56G PHY register parameters
* @base: base address for each PHY block
* @step: step between PHY lanes
*
* Characteristic information for the various PHY register parameters in the
* ETH56G devices
*/
struct ice_phy_reg_info_eth56g {
u32 base[NUM_ETH56G_PHY_RES];
u32 step;
};
/**
* struct ice_time_ref_info_e82x
* @pll_freq: Frequency of PLL that drives timer ticks in Hz
@ -94,8 +129,75 @@ struct ice_vernier_info_e82x {
u32 rx_fixed_delay;
};
#define ICE_ETH56G_MAC_CFG_RX_OFFSET_INT GENMASK(19, 9)
#define ICE_ETH56G_MAC_CFG_RX_OFFSET_FRAC GENMASK(8, 0)
#define ICE_ETH56G_MAC_CFG_FRAC_W 9
/**
* struct ice_cgu_pll_params_e82x
* struct ice_eth56g_mac_reg_cfg - MAC config values for specific PTP registers
* @tx_mode: Tx timestamp compensation mode
* @tx_mk_dly: Tx timestamp marker start strobe delay
* @tx_cw_dly: Tx timestamp codeword start strobe delay
* @rx_mode: Rx timestamp compensation mode
* @rx_mk_dly: Rx timestamp marker start strobe delay
* @rx_cw_dly: Rx timestamp codeword start strobe delay
* @blks_per_clk: number of blocks transferred per clock cycle
* @blktime: block time, fixed point
* @mktime: marker time, fixed point
* @tx_offset: total Tx offset, fixed point
* @rx_offset: total Rx offset, contains value for bitslip/deskew, fixed point
*
* All fixed point registers except Rx offset are 23 bit unsigned ints with
* a 9 bit fractional.
* Rx offset is 11 bit unsigned int with a 9 bit fractional.
*/
struct ice_eth56g_mac_reg_cfg {
struct {
u8 def;
u8 rs;
} tx_mode;
u8 tx_mk_dly;
struct {
u8 def;
u8 onestep;
} tx_cw_dly;
struct {
u8 def;
u8 rs;
} rx_mode;
struct {
u8 def;
u8 rs;
} rx_mk_dly;
struct {
u8 def;
u8 rs;
} rx_cw_dly;
u8 blks_per_clk;
u16 blktime;
u16 mktime;
struct {
u32 serdes;
u32 no_fec;
u32 fc;
u32 rs;
u32 sfd;
u32 onestep;
} tx_offset;
struct {
u32 serdes;
u32 no_fec;
u32 fc;
u32 rs;
u32 sfd;
u32 bs_ds;
} rx_offset;
};
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
@ -185,9 +287,34 @@ 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
/* Table of constants related to possible ETH56G PHY resources */
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 e822_time_ref[NUM_ICE_TIME_REF_FREQ];
@ -197,7 +324,9 @@ extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
/* Increment value to generate nanoseconds in the GLTSYN_TIME_L register for
* the E810 devices. Based off of a PLL with an 812.5 MHz frequency.
*/
#define ICE_PTP_NOMINAL_INCVAL_E810 0x13b13b13bULL
#define ICE_E810_PLL_FREQ 812500000
#define ICE_PTP_NOMINAL_INCVAL_E810 0x13b13b13bULL
#define E810_OUT_PROP_DELAY_NS 1
/* Device agnostic functions */
u8 ice_get_ptp_src_clock_index(struct ice_hw *hw);
@ -208,11 +337,15 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time);
int ice_ptp_write_incval(struct ice_hw *hw, u64 incval);
int ice_ptp_write_incval_locked(struct ice_hw *hw, u64 incval);
int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj);
int ice_ptp_clear_phy_offset_ready_e82x(struct ice_hw *hw);
int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp);
int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx);
void ice_ptp_reset_ts_memory(struct ice_hw *hw);
int ice_ptp_init_phc(struct ice_hw *hw);
void ice_ptp_init_hw(struct ice_hw *hw);
int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready);
int ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port,
enum ice_ptp_tmr_cmd configured_cmd);
/* E822 family functions */
int ice_read_quad_reg_e82x(struct ice_hw *hw, u8 quad, u16 offset, u32 *val);
@ -264,9 +397,9 @@ int ice_stop_phy_timer_e82x(struct ice_hw *hw, u8 port, bool soft_reset);
int ice_start_phy_timer_e82x(struct ice_hw *hw, u8 port);
int ice_phy_cfg_tx_offset_e82x(struct ice_hw *hw, u8 port);
int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port);
int ice_phy_cfg_intr_e82x(struct ice_hw *hw, u8 quad, bool ena, u8 threshold);
/* E810 family functions */
int ice_ptp_init_phy_e810(struct ice_hw *hw);
int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data);
int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data);
int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data);
@ -280,11 +413,44 @@ int ice_get_cgu_state(struct ice_hw *hw, u8 dpll_idx,
u8 *ref_state, u8 *eec_mode, s64 *phase_offset,
enum dpll_lock_status *dpll_state);
int ice_get_cgu_rclk_pin_info(struct ice_hw *hw, u8 *base_idx, u8 *pin_num);
void ice_ptp_init_phy_model(struct ice_hw *hw);
int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id,
unsigned long *caps);
/* ETH56G family functions */
int ice_ptp_read_tx_hwtstamp_status_eth56g(struct ice_hw *hw, u32 *ts_status);
int ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset);
int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port);
int ice_phy_cfg_tx_offset_eth56g(struct ice_hw *hw, u8 port);
int ice_phy_cfg_rx_offset_eth56g(struct ice_hw *hw, u8 port);
int ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold);
int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port);
#define ICE_ETH56G_NOMINAL_INCVAL 0x140000000ULL
#define ICE_ETH56G_NOMINAL_PCS_REF_TUS 0x100000000ULL
#define ICE_ETH56G_NOMINAL_PCS_REF_INC 0x300000000ULL
#define ICE_ETH56G_NOMINAL_THRESH4 0x7777
#define ICE_ETH56G_NOMINAL_TX_THRESH 0x6
/**
* ice_get_base_incval - Get base clock increment value
* @hw: pointer to the HW struct
*
* Return: base clock increment value for supported PHYs, 0 otherwise
*/
static inline u64 ice_get_base_incval(struct ice_hw *hw)
{
switch (hw->ptp.phy_model) {
case ICE_PHY_ETH56G:
return ICE_ETH56G_NOMINAL_INCVAL;
case ICE_PHY_E810:
return ICE_PTP_NOMINAL_INCVAL_E810;
case ICE_PHY_E82X:
return ice_e82x_nominal_incval(ice_e82x_time_ref(hw));
default:
return 0;
}
}
#define PFTSYN_SEM_BYTES 4
#define ICE_PTP_CLOCK_INDEX_0 0x00
@ -312,6 +478,7 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id,
#define TS_CMD_MASK_E810 0xFF
#define TS_CMD_MASK 0xF
#define SYNC_EXEC_CMD 0x3
#define TS_CMD_RX_TYPE ICE_M(0x18, 0x4)
/* Macros to derive port low and high addresses on both quads */
#define P_Q0_L(a, p) ((((a) + (0x2000 * (p)))) & 0xFFFF)
@ -344,11 +511,8 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id,
#define Q_REG_TX_MEM_GBL_CFG 0xC08
#define Q_REG_TX_MEM_GBL_CFG_LANE_TYPE_S 0
#define Q_REG_TX_MEM_GBL_CFG_LANE_TYPE_M BIT(0)
#define Q_REG_TX_MEM_GBL_CFG_TX_TYPE_S 1
#define Q_REG_TX_MEM_GBL_CFG_TX_TYPE_M ICE_M(0xFF, 1)
#define Q_REG_TX_MEM_GBL_CFG_INTR_THR_S 9
#define Q_REG_TX_MEM_GBL_CFG_INTR_THR_M ICE_M(0x3F, 9)
#define Q_REG_TX_MEM_GBL_CFG_INTR_ENA_S 15
#define Q_REG_TX_MEM_GBL_CFG_INTR_ENA_M BIT(15)
/* Tx Timestamp data registers */
@ -380,7 +544,7 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id,
#define P_REG_TIMETUS_L 0x410
#define P_REG_TIMETUS_U 0x414
#define P_REG_40B_LOW_M 0xFF
#define P_REG_40B_LOW_M GENMASK(7, 0)
#define P_REG_40B_HIGH_S 8
/* PHY window length registers */
@ -487,7 +651,7 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id,
#define ETH_GLTSYN_SHADJ_H(_i) (0x0300037C + ((_i) * 32))
/* E810 timer command register */
#define ETH_GLTSYN_CMD 0x03000344
#define E810_ETH_GLTSYN_CMD 0x03000344
/* Source timer incval macros */
#define INCVAL_HIGH_M 0xFF
@ -549,4 +713,115 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id,
/* E810T PCA9575 IO controller pin control */
#define ICE_E810T_P0_GNSS_PRSNT_N BIT(4)
/* ETH56G PHY register addresses */
/* Timestamp PHY incval registers */
#define PHY_REG_TIMETUS_L 0x8
#define PHY_REG_TIMETUS_U 0xC
/* Timestamp PCS registers */
#define PHY_PCS_REF_TUS_L 0x18
#define PHY_PCS_REF_TUS_U 0x1C
/* Timestamp PCS ref incval registers */
#define PHY_PCS_REF_INC_L 0x20
#define PHY_PCS_REF_INC_U 0x24
/* Timestamp init registers */
#define PHY_REG_RX_TIMER_INC_PRE_L 0x64
#define PHY_REG_RX_TIMER_INC_PRE_U 0x68
#define PHY_REG_TX_TIMER_INC_PRE_L 0x44
#define PHY_REG_TX_TIMER_INC_PRE_U 0x48
/* Timestamp match and adjust target registers */
#define PHY_REG_RX_TIMER_CNT_ADJ_L 0x6C
#define PHY_REG_RX_TIMER_CNT_ADJ_U 0x70
#define PHY_REG_TX_TIMER_CNT_ADJ_L 0x4C
#define PHY_REG_TX_TIMER_CNT_ADJ_U 0x50
/* Timestamp command registers */
#define PHY_REG_TX_TMR_CMD 0x40
#define PHY_REG_RX_TMR_CMD 0x60
/* Phy offset ready registers */
#define PHY_REG_TX_OFFSET_READY 0x54
#define PHY_REG_RX_OFFSET_READY 0x74
/* Phy total offset registers */
#define PHY_REG_TOTAL_TX_OFFSET_L 0x38
#define PHY_REG_TOTAL_TX_OFFSET_U 0x3C
#define PHY_REG_TOTAL_RX_OFFSET_L 0x58
#define PHY_REG_TOTAL_RX_OFFSET_U 0x5C
/* Timestamp capture registers */
#define PHY_REG_TX_CAPTURE_L 0x78
#define PHY_REG_TX_CAPTURE_U 0x7C
#define PHY_REG_RX_CAPTURE_L 0x8C
#define PHY_REG_RX_CAPTURE_U 0x90
/* Memory status registers */
#define PHY_REG_TX_MEMORY_STATUS_L 0x80
#define PHY_REG_TX_MEMORY_STATUS_U 0x84
/* Interrupt config register */
#define PHY_REG_TS_INT_CONFIG 0x88
/* XIF mode config register */
#define PHY_MAC_XIF_MODE 0x24
#define PHY_MAC_XIF_1STEP_ENA_M ICE_M(0x1, 5)
#define PHY_MAC_XIF_TS_BIN_MODE_M ICE_M(0x1, 11)
#define PHY_MAC_XIF_TS_SFD_ENA_M ICE_M(0x1, 20)
#define PHY_MAC_XIF_GMII_TS_SEL_M ICE_M(0x1, 21)
/* GPCS config register */
#define PHY_GPCS_CONFIG_REG0 0x268
#define PHY_GPCS_CONFIG_REG0_TX_THR_M ICE_M(0xF, 24)
#define PHY_GPCS_BITSLIP 0x5C
#define PHY_TS_INT_CONFIG_THRESHOLD_M ICE_M(0x3F, 0)
#define PHY_TS_INT_CONFIG_ENA_M BIT(6)
/* 1-step PTP config */
#define PHY_PTP_1STEP_CONFIG 0x270
#define PHY_PTP_1STEP_T1S_UP64_M ICE_M(0xF, 4)
#define PHY_PTP_1STEP_T1S_DELTA_M ICE_M(0xF, 8)
#define PHY_PTP_1STEP_PEER_DELAY(_port) (0x274 + 4 * (_port))
#define PHY_PTP_1STEP_PD_ADD_PD_M ICE_M(0x1, 0)
#define PHY_PTP_1STEP_PD_DELAY_M ICE_M(0x3fffffff, 1)
#define PHY_PTP_1STEP_PD_DLY_V_M ICE_M(0x1, 31)
/* Macros to derive offsets for TimeStampLow and TimeStampHigh */
#define PHY_TSTAMP_L(x) (((x) * 8) + 0)
#define PHY_TSTAMP_U(x) (((x) * 8) + 4)
#define PHY_REG_REVISION 0x85000
#define PHY_REG_DESKEW_0 0x94
#define PHY_REG_DESKEW_0_RLEVEL GENMASK(6, 0)
#define PHY_REG_DESKEW_0_RLEVEL_FRAC GENMASK(9, 7)
#define PHY_REG_DESKEW_0_RLEVEL_FRAC_W 3
#define PHY_REG_DESKEW_0_VALID GENMASK(10, 10)
#define PHY_REG_GPCS_BITSLIP 0x5C
#define PHY_REG_SD_BIT_SLIP(_port_offset) (0x29C + 4 * (_port_offset))
#define PHY_REVISION_ETH56G 0x10200
#define PHY_VENDOR_TXLANE_THRESH 0x2000C
#define PHY_MAC_TSU_CONFIG 0x40
#define PHY_MAC_TSU_CFG_RX_MODE_M ICE_M(0x7, 0)
#define PHY_MAC_TSU_CFG_RX_MII_CW_DLY_M ICE_M(0x7, 4)
#define PHY_MAC_TSU_CFG_RX_MII_MK_DLY_M ICE_M(0x7, 8)
#define PHY_MAC_TSU_CFG_TX_MODE_M ICE_M(0x7, 12)
#define PHY_MAC_TSU_CFG_TX_MII_CW_DLY_M ICE_M(0x1F, 16)
#define PHY_MAC_TSU_CFG_TX_MII_MK_DLY_M ICE_M(0x1F, 21)
#define PHY_MAC_TSU_CFG_BLKS_PER_CLK_M ICE_M(0x1, 28)
#define PHY_MAC_RX_MODULO 0x44
#define PHY_MAC_RX_OFFSET 0x48
#define PHY_MAC_RX_OFFSET_M ICE_M(0xFFFFFF, 0)
#define PHY_MAC_TX_MODULO 0x4C
#define PHY_MAC_BLOCKTIME 0x50
#define PHY_MAC_MARKERTIME 0x54
#define PHY_MAC_TX_OFFSET 0x58
#define PHY_PTP_INT_STATUS 0x7FD140
#endif /* _ICE_PTP_HW_H_ */

View File

@ -47,10 +47,12 @@ struct ice_sbq_evt_desc {
};
enum ice_sbq_msg_dev {
rmn_0 = 0x02,
rmn_1 = 0x03,
rmn_2 = 0x04,
cgu = 0x06
eth56g_phy_0 = 0x02,
rmn_0 = 0x02,
rmn_1 = 0x03,
rmn_2 = 0x04,
cgu = 0x06,
eth56g_phy_1 = 0x0D,
};
enum ice_sbq_msg_opcode {

View File

@ -322,12 +322,14 @@ enum ice_time_ref_freq {
ICE_TIME_REF_FREQ_156_250 = 4,
ICE_TIME_REF_FREQ_245_760 = 5,
NUM_ICE_TIME_REF_FREQ
NUM_ICE_TIME_REF_FREQ,
ICE_TIME_REF_FREQ_INVALID = -1,
};
/* Clock source specification */
enum ice_clk_src {
ICE_CLK_SRC_TCX0 = 0, /* Temperature compensated oscillator */
ICE_CLK_SRC_TCXO = 0, /* Temperature compensated oscillator */
ICE_CLK_SRC_TIME_REF = 1, /* Use TIME_REF reference clock */
NUM_ICE_CLK_SRC
@ -372,6 +374,15 @@ struct ice_ts_dev_info {
u8 ts_ll_int_read;
};
#define ICE_NAC_TOPO_PRIMARY_M BIT(0)
#define ICE_NAC_TOPO_DUAL_M BIT(1)
#define ICE_NAC_TOPO_ID_M GENMASK(0xF, 0)
struct ice_nac_topology {
u32 mode;
u8 id;
};
/* Function specific capabilities */
struct ice_hw_func_caps {
struct ice_hw_common_caps common_cap;
@ -393,6 +404,7 @@ struct ice_hw_dev_caps {
u32 num_flow_director_fltr; /* Number of FD filters available */
struct ice_ts_dev_info ts_dev_info;
u32 num_funcs;
struct ice_nac_topology nac_topo;
/* bitmap of supported sensors
* bit 0 - internal temperature sensor
* bit 31:1 - Reserved
@ -818,11 +830,43 @@ struct ice_mbx_data {
u16 async_watermark_val;
};
#define ICE_PORTS_PER_QUAD 4
#define ICE_GET_QUAD_NUM(port) ((port) / ICE_PORTS_PER_QUAD)
struct ice_eth56g_params {
u8 num_phys;
u8 phy_addr[2];
bool onestep_ena;
bool sfd_ena;
u32 peer_delay;
};
union ice_phy_params {
struct ice_eth56g_params eth56g;
};
/* PHY model */
enum ice_phy_model {
ICE_PHY_UNSUP = -1,
ICE_PHY_E810 = 1,
ICE_PHY_E810 = 1,
ICE_PHY_E82X,
ICE_PHY_ETH56G,
};
/* Global Link Topology */
enum ice_global_link_topo {
ICE_LINK_TOPO_UP_TO_2_LINKS,
ICE_LINK_TOPO_UP_TO_4_LINKS,
ICE_LINK_TOPO_UP_TO_8_LINKS,
ICE_LINK_TOPO_RESERVED,
};
struct ice_ptp_hw {
enum ice_phy_model phy_model;
union ice_phy_params phy;
u8 num_lports;
u8 ports_per_phy;
bool is_2x50g_muxed_topo;
};
/* Port hardware description */
@ -846,7 +890,6 @@ struct ice_hw {
u8 revision_id;
u8 pf_id; /* device profile info */
enum ice_phy_model phy_model;
u16 max_burst_size; /* driver sets this value */
@ -909,12 +952,7 @@ struct ice_hw {
/* INTRL granularity in 1 us */
u8 intrl_gran;
#define ICE_MAX_QUAD 2
#define ICE_QUADS_PER_PHY_E82X 2
#define ICE_PORTS_PER_PHY_E82X 8
#define ICE_PORTS_PER_QUAD 4
#define ICE_PORTS_PER_PHY_E810 4
#define ICE_NUM_EXTERNAL_PORTS (ICE_MAX_QUAD * ICE_PORTS_PER_QUAD)
struct ice_ptp_hw ptp;
/* Active package version (currently active) */
struct ice_pkg_ver active_pkg_ver;