Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
Tony Nguyen says: ==================== Intel Wired LAN Driver Updates 2023-09-18 (ice) This series contains updates to ice driver only. Sergey prepends ICE_ to PTP timer commands to clearly convey namespace of commands. Karol adds retrying to acquire hardware semaphore for cross-timestamping and avoids writing to timestamp registers on E822 devices. He also renames some defines to be more clear and align with the data sheet. Additionally, a range check is moved in order to reduce duplicated code. Jake adds cross-timestamping support for E823 devices as well as adds checks against netlist to aid in determining support for GNSS. He also corrects improper pin assignment for certain E810-T devices and refactors/cleanups PTP related code such as adding PHY model to ease checks for different needed implementations, removing unneeded EXTTS flag, and adding macro to check for source timer owner. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4fa7011d4f
@ -196,9 +196,10 @@
|
||||
|
||||
#define ice_pf_to_dev(pf) (&((pf)->pdev->dev))
|
||||
|
||||
#define ice_pf_src_tmr_owned(pf) ((pf)->hw.func_caps.ts_func_info.src_tmr_owned)
|
||||
|
||||
enum ice_feature {
|
||||
ICE_F_DSCP,
|
||||
ICE_F_PTP_EXTTS,
|
||||
ICE_F_PHY_RCLK,
|
||||
ICE_F_SMA_CTRL,
|
||||
ICE_F_CGU,
|
||||
|
@ -1393,6 +1393,7 @@ struct ice_aqc_link_topo_params {
|
||||
#define ICE_AQC_LINK_TOPO_NODE_TYPE_ID_EEPROM 8
|
||||
#define ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL 9
|
||||
#define ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_MUX 10
|
||||
#define ICE_AQC_LINK_TOPO_NODE_TYPE_GPS 11
|
||||
#define ICE_AQC_LINK_TOPO_NODE_CTX_S 4
|
||||
#define ICE_AQC_LINK_TOPO_NODE_CTX_M \
|
||||
(0xF << ICE_AQC_LINK_TOPO_NODE_CTX_S)
|
||||
@ -1435,6 +1436,7 @@ struct ice_aqc_get_link_topo {
|
||||
#define ICE_AQC_GET_LINK_TOPO_NODE_NR_E822_PHY 0x30
|
||||
#define ICE_AQC_GET_LINK_TOPO_NODE_NR_C827 0x31
|
||||
#define ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX 0x47
|
||||
#define ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_GPS 0x48
|
||||
u8 rsvd[9];
|
||||
};
|
||||
|
||||
|
@ -2764,6 +2764,21 @@ bool ice_is_pf_c827(struct ice_hw *hw)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_is_gps_in_netlist
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Check if the GPS generic device is present in the netlist
|
||||
*/
|
||||
bool ice_is_gps_in_netlist(struct ice_hw *hw)
|
||||
{
|
||||
if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_GPS,
|
||||
ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_GPS, NULL))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_aq_list_caps - query function/device capabilities
|
||||
* @hw: pointer to the HW struct
|
||||
|
@ -93,6 +93,7 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
|
||||
struct ice_aqc_get_phy_caps_data *caps,
|
||||
struct ice_sq_cd *cd);
|
||||
bool ice_is_pf_c827(struct ice_hw *hw);
|
||||
bool ice_is_gps_in_netlist(struct ice_hw *hw);
|
||||
int
|
||||
ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx, u8 node_part_number,
|
||||
u16 *node_handle);
|
||||
|
@ -389,6 +389,9 @@ bool ice_gnss_is_gps_present(struct ice_hw *hw)
|
||||
if (!hw->func_caps.ts_func_info.src_tmr_owned)
|
||||
return false;
|
||||
|
||||
if (!ice_is_gps_in_netlist(hw))
|
||||
return false;
|
||||
|
||||
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
|
||||
if (ice_is_e810t(hw)) {
|
||||
int err;
|
||||
|
@ -3989,11 +3989,10 @@ void ice_init_feature_support(struct ice_pf *pf)
|
||||
case ICE_DEV_ID_E810_XXV_QSFP:
|
||||
case ICE_DEV_ID_E810_XXV_SFP:
|
||||
ice_set_feature_support(pf, ICE_F_DSCP);
|
||||
ice_set_feature_support(pf, ICE_F_PTP_EXTTS);
|
||||
if (ice_is_phy_rclk_present(&pf->hw))
|
||||
ice_set_feature_support(pf, ICE_F_PHY_RCLK);
|
||||
/* If we don't own the timer - don't enable other caps */
|
||||
if (!pf->hw.func_caps.ts_func_info.src_tmr_owned)
|
||||
if (!ice_pf_src_tmr_owned(pf))
|
||||
break;
|
||||
if (ice_is_cgu_present(&pf->hw))
|
||||
ice_set_feature_support(pf, ICE_F_CGU);
|
||||
|
@ -3159,7 +3159,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
|
||||
|
||||
ena_mask &= ~PFINT_OICR_TSYN_EVNT_M;
|
||||
|
||||
if (hw->func_caps.ts_func_info.src_tmr_owned) {
|
||||
if (ice_pf_src_tmr_owned(pf)) {
|
||||
/* Save EVENTs from GLTSYN register */
|
||||
pf->ptp.ext_ts_irq |= gltsyn_stat &
|
||||
(GLTSYN_STAT_EVENT0_M |
|
||||
|
@ -436,7 +436,7 @@ static void ice_clear_ptp_clock_index(struct ice_pf *pf)
|
||||
int err;
|
||||
|
||||
/* Do not clear the index if we don't own the timer */
|
||||
if (!hw->func_caps.ts_func_info.src_tmr_owned)
|
||||
if (!ice_pf_src_tmr_owned(pf))
|
||||
return;
|
||||
|
||||
tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
|
||||
@ -1366,6 +1366,7 @@ out_unlock:
|
||||
void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
|
||||
{
|
||||
struct ice_ptp_port *ptp_port;
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
|
||||
if (!test_bit(ICE_FLAG_PTP, pf->flags))
|
||||
return;
|
||||
@ -1380,11 +1381,16 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
|
||||
/* Update cached link status for this port immediately */
|
||||
ptp_port->link_up = linkup;
|
||||
|
||||
/* E810 devices do not need to reconfigure the PHY */
|
||||
if (ice_is_e810(&pf->hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
/* Do not reconfigure E810 PHY */
|
||||
return;
|
||||
|
||||
ice_ptp_port_phy_restart(ptp_port);
|
||||
case ICE_PHY_E822:
|
||||
ice_ptp_port_phy_restart(ptp_port);
|
||||
return;
|
||||
default:
|
||||
dev_warn(ice_pf_to_dev(pf), "%s: Unknown PHY type\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1976,21 +1982,32 @@ ice_ptp_get_syncdevicetime(ktime_t *device,
|
||||
u32 hh_lock, hh_art_ctl;
|
||||
int i;
|
||||
|
||||
/* Get the HW lock */
|
||||
hh_lock = rd32(hw, PFHH_SEM + (PFTSYN_SEM_BYTES * hw->pf_id));
|
||||
#define MAX_HH_HW_LOCK_TRIES 5
|
||||
#define MAX_HH_CTL_LOCK_TRIES 100
|
||||
|
||||
for (i = 0; i < MAX_HH_HW_LOCK_TRIES; i++) {
|
||||
/* Get the HW lock */
|
||||
hh_lock = rd32(hw, PFHH_SEM + (PFTSYN_SEM_BYTES * hw->pf_id));
|
||||
if (hh_lock & PFHH_SEM_BUSY_M) {
|
||||
usleep_range(10000, 15000);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (hh_lock & PFHH_SEM_BUSY_M) {
|
||||
dev_err(ice_pf_to_dev(pf), "PTP failed to get hh lock\n");
|
||||
return -EFAULT;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Program cmd to master timer */
|
||||
ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
|
||||
|
||||
/* Start the ART and device clock sync sequence */
|
||||
hh_art_ctl = rd32(hw, GLHH_ART_CTL);
|
||||
hh_art_ctl = hh_art_ctl | GLHH_ART_CTL_ACTIVE_M;
|
||||
wr32(hw, GLHH_ART_CTL, hh_art_ctl);
|
||||
|
||||
#define MAX_HH_LOCK_TRIES 100
|
||||
|
||||
for (i = 0; i < MAX_HH_LOCK_TRIES; i++) {
|
||||
for (i = 0; i < MAX_HH_CTL_LOCK_TRIES; i++) {
|
||||
/* Wait for sync to complete */
|
||||
hh_art_ctl = rd32(hw, GLHH_ART_CTL);
|
||||
if (hh_art_ctl & GLHH_ART_CTL_ACTIVE_M) {
|
||||
@ -2014,19 +2031,23 @@ ice_ptp_get_syncdevicetime(ktime_t *device,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the master timer */
|
||||
ice_ptp_src_cmd(hw, ICE_PTP_NOP);
|
||||
|
||||
/* Release HW lock */
|
||||
hh_lock = rd32(hw, PFHH_SEM + (PFTSYN_SEM_BYTES * hw->pf_id));
|
||||
hh_lock = hh_lock & ~PFHH_SEM_BUSY_M;
|
||||
wr32(hw, PFHH_SEM + (PFTSYN_SEM_BYTES * hw->pf_id), hh_lock);
|
||||
|
||||
if (i == MAX_HH_LOCK_TRIES)
|
||||
if (i == MAX_HH_CTL_LOCK_TRIES)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_getcrosststamp_e822 - Capture a device cross timestamp
|
||||
* ice_ptp_getcrosststamp_e82x - Capture a device cross timestamp
|
||||
* @info: the driver's PTP info structure
|
||||
* @cts: The memory to fill the cross timestamp info
|
||||
*
|
||||
@ -2034,14 +2055,14 @@ ice_ptp_get_syncdevicetime(ktime_t *device,
|
||||
* clock. Fill the cross timestamp information and report it back to the
|
||||
* caller.
|
||||
*
|
||||
* This is only valid for E822 devices which have support for generating the
|
||||
* cross timestamp via PCIe PTM.
|
||||
* This is only valid for E822 and E823 devices which have support for
|
||||
* generating the cross timestamp via PCIe PTM.
|
||||
*
|
||||
* In order to correctly correlate the ART timestamp back to the TSC time, the
|
||||
* CPU must have X86_FEATURE_TSC_KNOWN_FREQ.
|
||||
*/
|
||||
static int
|
||||
ice_ptp_getcrosststamp_e822(struct ptp_clock_info *info,
|
||||
ice_ptp_getcrosststamp_e82x(struct ptp_clock_info *info,
|
||||
struct system_device_crosststamp *cts)
|
||||
{
|
||||
struct ice_pf *pf = ptp_info_to_pf(info);
|
||||
@ -2246,18 +2267,20 @@ ice_ptp_setup_sma_pins_e810t(struct ice_pf *pf, struct ptp_clock_info *info)
|
||||
static void
|
||||
ice_ptp_setup_pins_e810(struct ice_pf *pf, struct ptp_clock_info *info)
|
||||
{
|
||||
info->n_per_out = N_PER_OUT_E810;
|
||||
|
||||
if (ice_is_feature_supported(pf, ICE_F_PTP_EXTTS))
|
||||
info->n_ext_ts = N_EXT_TS_E810;
|
||||
|
||||
if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL)) {
|
||||
info->n_ext_ts = N_EXT_TS_E810;
|
||||
info->n_per_out = N_PER_OUT_E810T;
|
||||
info->n_pins = NUM_PTP_PINS_E810T;
|
||||
info->verify = ice_verify_pin_e810t;
|
||||
|
||||
/* Complete setup of the SMA pins */
|
||||
ice_ptp_setup_sma_pins_e810t(pf, info);
|
||||
} else if (ice_is_e810t(&pf->hw)) {
|
||||
info->n_ext_ts = N_EXT_TS_NO_SMA_E810T;
|
||||
info->n_per_out = N_PER_OUT_NO_SMA_E810T;
|
||||
} else {
|
||||
info->n_per_out = N_PER_OUT_E810;
|
||||
info->n_ext_ts = N_EXT_TS_E810;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2275,22 +2298,22 @@ ice_ptp_setup_pins_e823(struct ice_pf *pf, struct ptp_clock_info *info)
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_set_funcs_e822 - Set specialized functions for E822 support
|
||||
* ice_ptp_set_funcs_e82x - Set specialized functions for E82x support
|
||||
* @pf: Board private structure
|
||||
* @info: PTP info to fill
|
||||
*
|
||||
* Assign functions to the PTP capabiltiies structure for E822 devices.
|
||||
* Assign functions to the PTP capabiltiies structure for E82x devices.
|
||||
* Functions which operate across all device families should be set directly
|
||||
* in ice_ptp_set_caps. Only add functions here which are distinct for E822
|
||||
* in ice_ptp_set_caps. Only add functions here which are distinct for E82x
|
||||
* devices.
|
||||
*/
|
||||
static void
|
||||
ice_ptp_set_funcs_e822(struct ice_pf *pf, struct ptp_clock_info *info)
|
||||
ice_ptp_set_funcs_e82x(struct ice_pf *pf, struct ptp_clock_info *info)
|
||||
{
|
||||
#ifdef CONFIG_ICE_HWTS
|
||||
if (boot_cpu_has(X86_FEATURE_ART) &&
|
||||
boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
|
||||
info->getcrosststamp = ice_ptp_getcrosststamp_e822;
|
||||
info->getcrosststamp = ice_ptp_getcrosststamp_e82x;
|
||||
#endif /* CONFIG_ICE_HWTS */
|
||||
}
|
||||
|
||||
@ -2324,6 +2347,8 @@ ice_ptp_set_funcs_e810(struct ice_pf *pf, struct ptp_clock_info *info)
|
||||
static void
|
||||
ice_ptp_set_funcs_e823(struct ice_pf *pf, struct ptp_clock_info *info)
|
||||
{
|
||||
ice_ptp_set_funcs_e82x(pf, info);
|
||||
|
||||
info->enable = ice_ptp_gpio_enable_e823;
|
||||
ice_ptp_setup_pins_e823(pf, info);
|
||||
}
|
||||
@ -2351,7 +2376,7 @@ static void ice_ptp_set_caps(struct ice_pf *pf)
|
||||
else if (ice_is_e823(&pf->hw))
|
||||
ice_ptp_set_funcs_e823(pf, info);
|
||||
else
|
||||
ice_ptp_set_funcs_e822(pf, info);
|
||||
ice_ptp_set_funcs_e82x(pf, info);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2474,7 +2499,7 @@ void ice_ptp_reset(struct ice_pf *pf)
|
||||
if (test_bit(ICE_PFR_REQ, pf->state))
|
||||
goto pfr;
|
||||
|
||||
if (!hw->func_caps.ts_func_info.src_tmr_owned)
|
||||
if (!ice_pf_src_tmr_owned(pf))
|
||||
goto reset_ts;
|
||||
|
||||
err = ice_ptp_init_phc(hw);
|
||||
@ -2685,14 +2710,22 @@ static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp)
|
||||
*/
|
||||
static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
|
||||
{
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
|
||||
mutex_init(&ptp_port->ps_lock);
|
||||
|
||||
if (ice_is_e810(&pf->hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
return ice_ptp_init_tx_e810(pf, &ptp_port->tx);
|
||||
case ICE_PHY_E822:
|
||||
kthread_init_delayed_work(&ptp_port->ov_work,
|
||||
ice_ptp_wait_for_offsets);
|
||||
|
||||
kthread_init_delayed_work(&ptp_port->ov_work,
|
||||
ice_ptp_wait_for_offsets);
|
||||
return ice_ptp_init_tx_e822(pf, &ptp_port->tx, ptp_port->port_num);
|
||||
return ice_ptp_init_tx_e822(pf, &ptp_port->tx,
|
||||
ptp_port->port_num);
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2713,10 +2746,12 @@ void ice_ptp_init(struct ice_pf *pf)
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
int err;
|
||||
|
||||
ice_ptp_init_phy_model(hw);
|
||||
|
||||
/* If this function owns the clock hardware, it must allocate and
|
||||
* configure the PTP clock device to represent it.
|
||||
*/
|
||||
if (hw->func_caps.ts_func_info.src_tmr_owned) {
|
||||
if (ice_pf_src_tmr_owned(pf)) {
|
||||
err = ice_ptp_init_owner(pf);
|
||||
if (err)
|
||||
goto err;
|
||||
|
@ -233,7 +233,7 @@ static u64 ice_ptp_read_src_incval(struct ice_hw *hw)
|
||||
*
|
||||
* Prepare the source timer for an upcoming timer sync command.
|
||||
*/
|
||||
static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
|
||||
void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
|
||||
{
|
||||
u32 cmd_val;
|
||||
u8 tmr_idx;
|
||||
@ -242,19 +242,19 @@ static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
|
||||
cmd_val = tmr_idx << SEL_CPK_SRC;
|
||||
|
||||
switch (cmd) {
|
||||
case INIT_TIME:
|
||||
case ICE_PTP_INIT_TIME:
|
||||
cmd_val |= GLTSYN_CMD_INIT_TIME;
|
||||
break;
|
||||
case INIT_INCVAL:
|
||||
case ICE_PTP_INIT_INCVAL:
|
||||
cmd_val |= GLTSYN_CMD_INIT_INCVAL;
|
||||
break;
|
||||
case ADJ_TIME:
|
||||
case ICE_PTP_ADJ_TIME:
|
||||
cmd_val |= GLTSYN_CMD_ADJ_TIME;
|
||||
break;
|
||||
case ADJ_TIME_AT_TIME:
|
||||
case ICE_PTP_ADJ_TIME_AT_TIME:
|
||||
cmd_val |= GLTSYN_CMD_ADJ_INIT_TIME;
|
||||
break;
|
||||
case READ_TIME:
|
||||
case ICE_PTP_READ_TIME:
|
||||
cmd_val |= GLTSYN_CMD_READ_TIME;
|
||||
break;
|
||||
case ICE_PTP_NOP:
|
||||
@ -294,9 +294,9 @@ ice_fill_phy_msg_e822(struct ice_sbq_msg_input *msg, u8 port, u16 offset)
|
||||
{
|
||||
int phy_port, phy, quadtype;
|
||||
|
||||
phy_port = port % ICE_PORTS_PER_PHY;
|
||||
phy = port / ICE_PORTS_PER_PHY;
|
||||
quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_NUM_QUAD_TYPE;
|
||||
phy_port = port % ICE_PORTS_PER_PHY_E822;
|
||||
phy = port / ICE_PORTS_PER_PHY_E822;
|
||||
quadtype = (port / ICE_PORTS_PER_QUAD) % ICE_QUADS_PER_PHY_E822;
|
||||
|
||||
if (quadtype == 0) {
|
||||
msg->msg_addr_low = P_Q0_L(P_0_BASE + offset, phy_port);
|
||||
@ -621,20 +621,25 @@ ice_write_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 val)
|
||||
* Fill a message buffer for accessing a register in a quad shared between
|
||||
* multiple PHYs.
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
ice_fill_quad_msg_e822(struct ice_sbq_msg_input *msg, u8 quad, u16 offset)
|
||||
{
|
||||
u32 addr;
|
||||
|
||||
if (quad >= ICE_MAX_QUAD)
|
||||
return -EINVAL;
|
||||
|
||||
msg->dest_dev = rmn_0;
|
||||
|
||||
if ((quad % ICE_NUM_QUAD_TYPE) == 0)
|
||||
if ((quad % ICE_QUADS_PER_PHY_E822) == 0)
|
||||
addr = Q_0_BASE + offset;
|
||||
else
|
||||
addr = Q_1_BASE + offset;
|
||||
|
||||
msg->msg_addr_low = lower_16_bits(addr);
|
||||
msg->msg_addr_high = upper_16_bits(addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -653,10 +658,10 @@ ice_read_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 *val)
|
||||
struct ice_sbq_msg_input msg = {0};
|
||||
int err;
|
||||
|
||||
if (quad >= ICE_MAX_QUAD)
|
||||
return -EINVAL;
|
||||
err = ice_fill_quad_msg_e822(&msg, quad, offset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ice_fill_quad_msg_e822(&msg, quad, offset);
|
||||
msg.opcode = ice_sbq_msg_rd;
|
||||
|
||||
err = ice_sbq_rw_reg(hw, &msg);
|
||||
@ -687,10 +692,10 @@ ice_write_quad_reg_e822(struct ice_hw *hw, u8 quad, u16 offset, u32 val)
|
||||
struct ice_sbq_msg_input msg = {0};
|
||||
int err;
|
||||
|
||||
if (quad >= ICE_MAX_QUAD)
|
||||
return -EINVAL;
|
||||
err = ice_fill_quad_msg_e822(&msg, quad, offset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ice_fill_quad_msg_e822(&msg, quad, offset);
|
||||
msg.opcode = ice_sbq_msg_wr;
|
||||
msg.data = val;
|
||||
|
||||
@ -754,29 +759,32 @@ ice_read_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp)
|
||||
* @quad: the quad to read from
|
||||
* @idx: the timestamp index to reset
|
||||
*
|
||||
* Clear a timestamp, resetting its valid bit, from the PHY quad block that is
|
||||
* shared between the internal PHYs on the E822 devices.
|
||||
* Read the timestamp out of the quad to clear its timestamp status bit from
|
||||
* the PHY quad block that is shared between the internal PHYs of the E822
|
||||
* devices.
|
||||
*
|
||||
* Note that unlike E810, software cannot directly write to the quad memory
|
||||
* bank registers. E822 relies on the ice_get_phy_tx_tstamp_ready() function
|
||||
* to determine which timestamps are valid. Reading a timestamp auto-clears
|
||||
* the valid bit.
|
||||
*
|
||||
* To directly clear the contents of the timestamp block entirely, discarding
|
||||
* all timestamp data at once, software should instead use
|
||||
* ice_ptp_reset_ts_memory_quad_e822().
|
||||
*
|
||||
* This function should only be called on an idx whose bit is set according to
|
||||
* ice_get_phy_tx_tstamp_ready().
|
||||
*/
|
||||
static int
|
||||
ice_clear_phy_tstamp_e822(struct ice_hw *hw, u8 quad, u8 idx)
|
||||
{
|
||||
u16 lo_addr, hi_addr;
|
||||
u64 unused_tstamp;
|
||||
int err;
|
||||
|
||||
lo_addr = (u16)TS_L(Q_REG_TX_MEMORY_BANK_START, idx);
|
||||
hi_addr = (u16)TS_H(Q_REG_TX_MEMORY_BANK_START, idx);
|
||||
|
||||
err = ice_write_quad_reg_e822(hw, quad, lo_addr, 0);
|
||||
err = ice_read_phy_tstamp_e822(hw, quad, idx, &unused_tstamp);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, err %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ice_write_quad_reg_e822(hw, quad, hi_addr, 0);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, err %d\n",
|
||||
err);
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for quad %u, idx %u, err %d\n",
|
||||
quad, idx, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1151,7 +1159,7 @@ static int ice_ptp_init_phc_e822(struct ice_hw *hw)
|
||||
* @time: Time to initialize the PHY port clocks to
|
||||
*
|
||||
* Program the PHY port registers with a new initial time value. The port
|
||||
* clock will be initialized once the driver issues an INIT_TIME sync
|
||||
* clock will be initialized once the driver issues an ICE_PTP_INIT_TIME sync
|
||||
* command. The time value is the upper 32 bits of the PHY timer, usually in
|
||||
* units of nominal nanoseconds.
|
||||
*/
|
||||
@ -1200,7 +1208,7 @@ exit_err:
|
||||
*
|
||||
* Program the port for an atomic adjustment by writing the Tx and Rx timer
|
||||
* registers. The atomic adjustment won't be completed until the driver issues
|
||||
* an ADJ_TIME command.
|
||||
* an ICE_PTP_ADJ_TIME command.
|
||||
*
|
||||
* Note that time is not in units of nanoseconds. It is in clock time
|
||||
* including the lower sub-nanosecond portion of the port timer.
|
||||
@ -1253,7 +1261,7 @@ exit_err:
|
||||
*
|
||||
* Prepare the PHY ports for an atomic time adjustment by programming the PHY
|
||||
* Tx and Rx port registers. The actual adjustment is completed by issuing an
|
||||
* ADJ_TIME or ADJ_TIME_AT_TIME sync command.
|
||||
* ICE_PTP_ADJ_TIME or ICE_PTP_ADJ_TIME_AT_TIME sync command.
|
||||
*/
|
||||
static int
|
||||
ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj)
|
||||
@ -1288,7 +1296,7 @@ ice_ptp_prep_phy_adj_e822(struct ice_hw *hw, s32 adj)
|
||||
*
|
||||
* Prepare each of the PHY ports for a new increment value by programming the
|
||||
* port's TIMETUS registers. The new increment value will be updated after
|
||||
* issuing an INIT_INCVAL command.
|
||||
* issuing an ICE_PTP_INIT_INCVAL command.
|
||||
*/
|
||||
static int
|
||||
ice_ptp_prep_phy_incval_e822(struct ice_hw *hw, u64 incval)
|
||||
@ -1374,19 +1382,19 @@ ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd
|
||||
tmr_idx = ice_get_ptp_src_clock_index(hw);
|
||||
cmd_val = tmr_idx << SEL_PHY_SRC;
|
||||
switch (cmd) {
|
||||
case INIT_TIME:
|
||||
case ICE_PTP_INIT_TIME:
|
||||
cmd_val |= PHY_CMD_INIT_TIME;
|
||||
break;
|
||||
case INIT_INCVAL:
|
||||
case ICE_PTP_INIT_INCVAL:
|
||||
cmd_val |= PHY_CMD_INIT_INCVAL;
|
||||
break;
|
||||
case ADJ_TIME:
|
||||
case ICE_PTP_ADJ_TIME:
|
||||
cmd_val |= PHY_CMD_ADJ_TIME;
|
||||
break;
|
||||
case READ_TIME:
|
||||
case ICE_PTP_READ_TIME:
|
||||
cmd_val |= PHY_CMD_READ_TIME;
|
||||
break;
|
||||
case ADJ_TIME_AT_TIME:
|
||||
case ICE_PTP_ADJ_TIME_AT_TIME:
|
||||
cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME;
|
||||
break;
|
||||
case ICE_PTP_NOP:
|
||||
@ -2322,8 +2330,8 @@ int ice_phy_cfg_rx_offset_e822(struct ice_hw *hw, u8 port)
|
||||
* @phy_time: on return, the 64bit PHY timer value
|
||||
* @phc_time: on return, the lower 64bits of PHC time
|
||||
*
|
||||
* Issue a READ_TIME timer command to simultaneously capture the PHY and PHC
|
||||
* timer values.
|
||||
* Issue a ICE_PTP_READ_TIME timer command to simultaneously capture the PHY
|
||||
* and PHC timer values.
|
||||
*/
|
||||
static int
|
||||
ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time,
|
||||
@ -2336,15 +2344,15 @@ ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time,
|
||||
|
||||
tmr_idx = ice_get_ptp_src_clock_index(hw);
|
||||
|
||||
/* Prepare the PHC timer for a READ_TIME capture command */
|
||||
ice_ptp_src_cmd(hw, READ_TIME);
|
||||
/* Prepare the PHC timer for a ICE_PTP_READ_TIME capture command */
|
||||
ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
|
||||
|
||||
/* Prepare the PHY timer for a READ_TIME capture command */
|
||||
err = ice_ptp_one_port_cmd(hw, port, READ_TIME);
|
||||
/* Prepare the PHY timer for a ICE_PTP_READ_TIME capture command */
|
||||
err = ice_ptp_one_port_cmd(hw, port, ICE_PTP_READ_TIME);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Issue the sync to start the READ_TIME capture */
|
||||
/* Issue the sync to start the ICE_PTP_READ_TIME capture */
|
||||
ice_ptp_exec_tmr_cmd(hw);
|
||||
|
||||
/* Read the captured PHC time from the shadow time registers */
|
||||
@ -2378,10 +2386,11 @@ ice_read_phy_and_phc_time_e822(struct ice_hw *hw, u8 port, u64 *phy_time,
|
||||
* @port: the PHY port to synchronize
|
||||
*
|
||||
* Perform an adjustment to ensure that the PHY and PHC timers are in sync.
|
||||
* This is done by issuing a READ_TIME command which triggers a simultaneous
|
||||
* read of the PHY timer and PHC timer. Then we use the difference to
|
||||
* calculate an appropriate 2s complement addition to add to the PHY timer in
|
||||
* order to ensure it reads the same value as the primary PHC timer.
|
||||
* This is done by issuing a ICE_PTP_READ_TIME command which triggers a
|
||||
* simultaneous read of the PHY timer and PHC timer. Then we use the
|
||||
* difference to calculate an appropriate 2s complement addition to add
|
||||
* to the PHY timer in order to ensure it reads the same value as the
|
||||
* primary PHC timer.
|
||||
*/
|
||||
static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port)
|
||||
{
|
||||
@ -2411,7 +2420,7 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port)
|
||||
if (err)
|
||||
goto err_unlock;
|
||||
|
||||
err = ice_ptp_one_port_cmd(hw, port, ADJ_TIME);
|
||||
err = ice_ptp_one_port_cmd(hw, port, ICE_PTP_ADJ_TIME);
|
||||
if (err)
|
||||
goto err_unlock;
|
||||
|
||||
@ -2534,7 +2543,7 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ice_ptp_one_port_cmd(hw, port, INIT_INCVAL);
|
||||
err = ice_ptp_one_port_cmd(hw, port, ICE_PTP_INIT_INCVAL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -2562,7 +2571,7 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ice_ptp_one_port_cmd(hw, port, INIT_INCVAL);
|
||||
err = ice_ptp_one_port_cmd(hw, port, ICE_PTP_INIT_INCVAL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -2811,28 +2820,39 @@ ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
|
||||
* @lport: the lport to read from
|
||||
* @idx: the timestamp index to reset
|
||||
*
|
||||
* Clear a timestamp, resetting its valid bit, from the timestamp block of the
|
||||
* external PHY on the E810 device.
|
||||
* Read the timestamp and then forcibly overwrite its value to clear the valid
|
||||
* bit from the timestamp block of the external PHY on the E810 device.
|
||||
*
|
||||
* This function should only be called on an idx whose bit is set according to
|
||||
* ice_get_phy_tx_tstamp_ready().
|
||||
*/
|
||||
static int ice_clear_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx)
|
||||
{
|
||||
u32 lo_addr, hi_addr;
|
||||
u64 unused_tstamp;
|
||||
int err;
|
||||
|
||||
err = ice_read_phy_tstamp_e810(hw, lport, idx, &unused_tstamp);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to read the timestamp register for lport %u, idx %u, err %d\n",
|
||||
lport, idx, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
lo_addr = TS_EXT(LOW_TX_MEMORY_BANK_START, lport, idx);
|
||||
hi_addr = TS_EXT(HIGH_TX_MEMORY_BANK_START, lport, idx);
|
||||
|
||||
err = ice_write_phy_reg_e810(hw, lo_addr, 0);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register, err %d\n",
|
||||
err);
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register for lport %u, idx %u, err %d\n",
|
||||
lport, idx, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ice_write_phy_reg_e810(hw, hi_addr, 0);
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register, err %d\n",
|
||||
err);
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to clear high PTP timestamp register for lport %u, idx %u, err %d\n",
|
||||
lport, idx, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2883,7 +2903,7 @@ static int ice_ptp_init_phc_e810(struct ice_hw *hw)
|
||||
*
|
||||
* Program the PHY port ETH_GLTSYN_SHTIME registers in preparation setting the
|
||||
* initial clock time. The time will not actually be programmed until the
|
||||
* driver issues an INIT_TIME command.
|
||||
* driver issues an ICE_PTP_INIT_TIME command.
|
||||
*
|
||||
* The time value is the upper 32 bits of the PHY timer, usually in units of
|
||||
* nominal nanoseconds.
|
||||
@ -2918,7 +2938,7 @@ static int ice_ptp_prep_phy_time_e810(struct ice_hw *hw, u32 time)
|
||||
*
|
||||
* Prepare the PHY port for an atomic adjustment by programming the PHY
|
||||
* ETH_GLTSYN_SHADJ_L and ETH_GLTSYN_SHADJ_H registers. The actual adjustment
|
||||
* is completed by issuing an ADJ_TIME sync command.
|
||||
* is completed by issuing an ICE_PTP_ADJ_TIME sync command.
|
||||
*
|
||||
* The adjustment value only contains the portion used for the upper 32bits of
|
||||
* the PHY timer, usually in units of nominal nanoseconds. Negative
|
||||
@ -2958,7 +2978,7 @@ static int ice_ptp_prep_phy_adj_e810(struct ice_hw *hw, s32 adj)
|
||||
*
|
||||
* Prepare the PHY port for a new increment value by programming the PHY
|
||||
* ETH_GLTSYN_SHADJ_L and ETH_GLTSYN_SHADJ_H registers. The actual change is
|
||||
* completed by issuing an INIT_INCVAL command.
|
||||
* completed by issuing an ICE_PTP_INIT_INCVAL command.
|
||||
*/
|
||||
static int ice_ptp_prep_phy_incval_e810(struct ice_hw *hw, u64 incval)
|
||||
{
|
||||
@ -3001,19 +3021,19 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
case INIT_TIME:
|
||||
case ICE_PTP_INIT_TIME:
|
||||
cmd_val = GLTSYN_CMD_INIT_TIME;
|
||||
break;
|
||||
case INIT_INCVAL:
|
||||
case ICE_PTP_INIT_INCVAL:
|
||||
cmd_val = GLTSYN_CMD_INIT_INCVAL;
|
||||
break;
|
||||
case ADJ_TIME:
|
||||
case ICE_PTP_ADJ_TIME:
|
||||
cmd_val = GLTSYN_CMD_ADJ_TIME;
|
||||
break;
|
||||
case READ_TIME:
|
||||
case ICE_PTP_READ_TIME:
|
||||
cmd_val = GLTSYN_CMD_READ_TIME;
|
||||
break;
|
||||
case ADJ_TIME_AT_TIME:
|
||||
case ICE_PTP_ADJ_TIME_AT_TIME:
|
||||
cmd_val = GLTSYN_CMD_ADJ_INIT_TIME;
|
||||
break;
|
||||
case ICE_PTP_NOP:
|
||||
@ -3275,6 +3295,21 @@ void ice_ptp_unlock(struct ice_hw *hw)
|
||||
wr32(hw, PFTSYN_SEM + (PFTSYN_SEM_BYTES * hw->pf_id), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_init_phy_model - Initialize hw->phy_model based on device type
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Determine the PHY model for the device, and initialize hw->phy_model
|
||||
* for use by other functions.
|
||||
*/
|
||||
void ice_ptp_init_phy_model(struct ice_hw *hw)
|
||||
{
|
||||
if (ice_is_e810(hw))
|
||||
hw->phy_model = ICE_PHY_E810;
|
||||
else
|
||||
hw->phy_model = ICE_PHY_E822;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ptp_tmr_cmd - Prepare and trigger a timer sync command
|
||||
* @hw: pointer to HW struct
|
||||
@ -3293,10 +3328,17 @@ static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
|
||||
ice_ptp_src_cmd(hw, cmd);
|
||||
|
||||
/* Next, prepare the ports */
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
err = ice_ptp_port_cmd_e810(hw, cmd);
|
||||
else
|
||||
break;
|
||||
case ICE_PHY_E822:
|
||||
err = ice_ptp_port_cmd_e822(hw, cmd);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY ports for timer command %u, err %d\n",
|
||||
cmd, err);
|
||||
@ -3338,14 +3380,21 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
|
||||
|
||||
/* PHY timers */
|
||||
/* Fill Rx and Tx ports and send msg to PHY */
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
err = ice_ptp_prep_phy_time_e810(hw, time & 0xFFFFFFFF);
|
||||
else
|
||||
break;
|
||||
case ICE_PHY_E822:
|
||||
err = ice_ptp_prep_phy_time_e822(hw, time & 0xFFFFFFFF);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return ice_ptp_tmr_cmd(hw, INIT_TIME);
|
||||
return ice_ptp_tmr_cmd(hw, ICE_PTP_INIT_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3358,8 +3407,8 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
|
||||
*
|
||||
* 1) Write the increment value to the source timer shadow registers
|
||||
* 2) Write the increment value to the PHY timer shadow registers
|
||||
* 3) Issue an INIT_INCVAL timer command to synchronously switch both the
|
||||
* source and port timers to the new increment value at the next clock
|
||||
* 3) Issue an ICE_PTP_INIT_INCVAL timer command to synchronously switch both
|
||||
* the source and port timers to the new increment value at the next clock
|
||||
* cycle.
|
||||
*/
|
||||
int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
|
||||
@ -3373,14 +3422,21 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
|
||||
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval));
|
||||
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval));
|
||||
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
err = ice_ptp_prep_phy_incval_e810(hw, incval);
|
||||
else
|
||||
break;
|
||||
case ICE_PHY_E822:
|
||||
err = ice_ptp_prep_phy_incval_e822(hw, incval);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return ice_ptp_tmr_cmd(hw, INIT_INCVAL);
|
||||
return ice_ptp_tmr_cmd(hw, ICE_PTP_INIT_INCVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3414,8 +3470,8 @@ int ice_ptp_write_incval_locked(struct ice_hw *hw, u64 incval)
|
||||
*
|
||||
* 1) Write the adjustment to the source timer shadow registers
|
||||
* 2) Write the adjustment to the PHY timer shadow registers
|
||||
* 3) Issue an ADJ_TIME timer command to synchronously apply the adjustment to
|
||||
* both the source and port timers at the next clock cycle.
|
||||
* 3) Issue an ICE_PTP_ADJ_TIME timer command to synchronously apply the
|
||||
* adjustment to both the source and port timers at the next clock cycle.
|
||||
*/
|
||||
int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
|
||||
{
|
||||
@ -3425,21 +3481,28 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
|
||||
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
|
||||
|
||||
/* Write the desired clock adjustment into the GLTSYN_SHADJ register.
|
||||
* For an ADJ_TIME command, this set of registers represents the value
|
||||
* to add to the clock time. It supports subtraction by interpreting
|
||||
* the value as a 2's complement integer.
|
||||
* For an ICE_PTP_ADJ_TIME command, this set of registers represents
|
||||
* the value to add to the clock time. It supports subtraction by
|
||||
* interpreting the value as a 2's complement integer.
|
||||
*/
|
||||
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0);
|
||||
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj);
|
||||
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
err = ice_ptp_prep_phy_adj_e810(hw, adj);
|
||||
else
|
||||
break;
|
||||
case ICE_PHY_E822:
|
||||
err = ice_ptp_prep_phy_adj_e822(hw, adj);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return ice_ptp_tmr_cmd(hw, ADJ_TIME);
|
||||
return ice_ptp_tmr_cmd(hw, ICE_PTP_ADJ_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3455,10 +3518,14 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
|
||||
*/
|
||||
int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
|
||||
{
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
return ice_read_phy_tstamp_e810(hw, block, idx, tstamp);
|
||||
else
|
||||
case ICE_PHY_E822:
|
||||
return ice_read_phy_tstamp_e822(hw, block, idx, tstamp);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3467,16 +3534,26 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
|
||||
* @block: the block to read from
|
||||
* @idx: the timestamp index to reset
|
||||
*
|
||||
* Clear a timestamp, resetting its valid bit, from the timestamp block. For
|
||||
* E822 devices, the block is the quad to clear from. For E810 devices, the
|
||||
* block is the logical port to clear from.
|
||||
* Clear a timestamp from the timestamp block, discarding its value without
|
||||
* returning it. This resets the memory status bit for the timestamp index
|
||||
* allowing it to be reused for another timestamp in the future.
|
||||
*
|
||||
* For E822 devices, the block number is the PHY quad to clear from. For E810
|
||||
* devices, the block number is the logical port to clear from.
|
||||
*
|
||||
* This function must only be called on a timestamp index whose valid bit is
|
||||
* set according to ice_get_phy_tx_tstamp_ready().
|
||||
*/
|
||||
int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx)
|
||||
{
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
return ice_clear_phy_tstamp_e810(hw, block, idx);
|
||||
else
|
||||
case ICE_PHY_E822:
|
||||
return ice_clear_phy_tstamp_e822(hw, block, idx);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3569,10 +3646,14 @@ int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx)
|
||||
*/
|
||||
void ice_ptp_reset_ts_memory(struct ice_hw *hw)
|
||||
{
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E822:
|
||||
ice_ptp_reset_ts_memory_e822(hw);
|
||||
break;
|
||||
case ICE_PHY_E810:
|
||||
default:
|
||||
return;
|
||||
|
||||
ice_ptp_reset_ts_memory_e822(hw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3591,10 +3672,14 @@ int ice_ptp_init_phc(struct ice_hw *hw)
|
||||
/* Clear event err indications for auxiliary pins */
|
||||
(void)rd32(hw, GLTSYN_STAT(src_idx));
|
||||
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
return ice_ptp_init_phc_e810(hw);
|
||||
else
|
||||
case ICE_PHY_E822:
|
||||
return ice_ptp_init_phc_e822(hw);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3610,12 +3695,17 @@ int ice_ptp_init_phc(struct ice_hw *hw)
|
||||
*/
|
||||
int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready)
|
||||
{
|
||||
if (ice_is_e810(hw))
|
||||
switch (hw->phy_model) {
|
||||
case ICE_PHY_E810:
|
||||
return ice_get_phy_tx_tstamp_ready_e810(hw, block,
|
||||
tstamp_ready);
|
||||
else
|
||||
case ICE_PHY_E822:
|
||||
return ice_get_phy_tx_tstamp_ready_e822(hw, block,
|
||||
tstamp_ready);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,11 +6,11 @@
|
||||
#include <linux/dpll.h>
|
||||
|
||||
enum ice_ptp_tmr_cmd {
|
||||
INIT_TIME,
|
||||
INIT_INCVAL,
|
||||
ADJ_TIME,
|
||||
ADJ_TIME_AT_TIME,
|
||||
READ_TIME,
|
||||
ICE_PTP_INIT_TIME,
|
||||
ICE_PTP_INIT_INCVAL,
|
||||
ICE_PTP_ADJ_TIME,
|
||||
ICE_PTP_ADJ_TIME_AT_TIME,
|
||||
ICE_PTP_READ_TIME,
|
||||
ICE_PTP_NOP,
|
||||
};
|
||||
|
||||
@ -203,6 +203,7 @@ extern const struct ice_vernier_info_e822 e822_vernier[NUM_ICE_PTP_LNK_SPD];
|
||||
u8 ice_get_ptp_src_clock_index(struct ice_hw *hw);
|
||||
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);
|
||||
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);
|
||||
@ -284,6 +285,8 @@ int ice_get_cgu_state(struct ice_hw *hw, u8 dpll_idx,
|
||||
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);
|
||||
|
||||
#define PFTSYN_SEM_BYTES 4
|
||||
|
||||
#define ICE_PTP_CLOCK_INDEX_0 0x00
|
||||
|
@ -822,6 +822,13 @@ struct ice_mbx_data {
|
||||
u16 async_watermark_val;
|
||||
};
|
||||
|
||||
/* PHY model */
|
||||
enum ice_phy_model {
|
||||
ICE_PHY_UNSUP = -1,
|
||||
ICE_PHY_E810 = 1,
|
||||
ICE_PHY_E822,
|
||||
};
|
||||
|
||||
/* Port hardware description */
|
||||
struct ice_hw {
|
||||
u8 __iomem *hw_addr;
|
||||
@ -843,6 +850,7 @@ 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 */
|
||||
|
||||
@ -901,13 +909,13 @@ struct ice_hw {
|
||||
/* INTRL granularity in 1 us */
|
||||
u8 intrl_gran;
|
||||
|
||||
#define ICE_PHY_PER_NAC 1
|
||||
#define ICE_MAX_QUAD 2
|
||||
#define ICE_NUM_QUAD_TYPE 2
|
||||
#define ICE_PORTS_PER_QUAD 4
|
||||
#define ICE_PHY_0_LAST_QUAD 1
|
||||
#define ICE_PORTS_PER_PHY 8
|
||||
#define ICE_NUM_EXTERNAL_PORTS ICE_PORTS_PER_PHY
|
||||
#define ICE_PHY_PER_NAC_E822 1
|
||||
#define ICE_MAX_QUAD 2
|
||||
#define ICE_QUADS_PER_PHY_E822 2
|
||||
#define ICE_PORTS_PER_PHY_E822 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)
|
||||
|
||||
/* Active package version (currently active) */
|
||||
struct ice_pkg_ver active_pkg_ver;
|
||||
|
Loading…
x
Reference in New Issue
Block a user