@@ -177,6 +177,17 @@ static int ice_set_mac_type(struct ice_hw *hw)
case ICE_DEV_ID_E825C_SGMII:
hw->mac_type = ICE_MAC_GENERIC_3K_E825;
break;
+ case ICE_DEV_ID_E830_BACKPLANE:
+ case ICE_DEV_ID_E830_QSFP56:
+ case ICE_DEV_ID_E830_SFP:
+ case ICE_DEV_ID_E830C_BACKPLANE:
+ case ICE_DEV_ID_E830_XXV_BACKPLANE:
+ case ICE_DEV_ID_E830C_QSFP:
+ case ICE_DEV_ID_E830_XXV_QSFP:
+ case ICE_DEV_ID_E830C_SFP:
+ case ICE_DEV_ID_E830_XXV_SFP:
+ hw->mac_type = ICE_MAC_E830;
+ break;
default:
hw->mac_type = ICE_MAC_UNKNOWN;
break;
@@ -245,6 +256,17 @@ bool ice_is_e810t(struct ice_hw *hw)
return false;
}
+/**
+ * ice_is_e830
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if the device is E830 based, false if not.
+ */
+bool ice_is_e830(struct ice_hw *hw)
+{
+ return hw->mac_type == ICE_MAC_E830;
+}
+
/**
* ice_is_e823
* @hw: pointer to the hardware structure
@@ -266,6 +266,7 @@ void ice_print_rollback_msg(struct ice_hw *hw);
bool ice_is_generic_mac(struct ice_hw *hw);
bool ice_is_e810(struct ice_hw *hw);
bool ice_is_e810t(struct ice_hw *hw);
+bool ice_is_e830(struct ice_hw *hw);
bool ice_is_e825c(struct ice_hw *hw);
bool ice_is_e823(struct ice_hw *hw);
int
@@ -15,6 +15,24 @@
#define ICE_DEV_ID_E823L_1GBE 0x124F
/* Intel(R) Ethernet Connection E823-L for QSFP */
#define ICE_DEV_ID_E823L_QSFP 0x151D
+/* Intel(R) Ethernet Controller E830-CC for backplane */
+#define ICE_DEV_ID_E830_BACKPLANE 0x12D1
+/* Intel(R) Ethernet Controller E830-CC for QSFP */
+#define ICE_DEV_ID_E830_QSFP56 0x12D2
+/* Intel(R) Ethernet Controller E830-CC for SFP */
+#define ICE_DEV_ID_E830_SFP 0x12D3
+/* Intel(R) Ethernet Controller E830-C for backplane */
+#define ICE_DEV_ID_E830C_BACKPLANE 0x12D5
+/* Intel(R) Ethernet Controller E830-XXV for backplane */
+#define ICE_DEV_ID_E830_XXV_BACKPLANE 0x12DC
+/* Intel(R) Ethernet Controller E830-C for QSFP */
+#define ICE_DEV_ID_E830C_QSFP 0x12D8
+/* Intel(R) Ethernet Controller E830-XXV for QSFP */
+#define ICE_DEV_ID_E830_XXV_QSFP 0x12DD
+/* Intel(R) Ethernet Controller E830-C for SFP */
+#define ICE_DEV_ID_E830C_SFP 0x12DA
+/* Intel(R) Ethernet Controller E830-XXV for SFP */
+#define ICE_DEV_ID_E830_XXV_SFP 0x12DE
/* Intel(R) Ethernet Controller E810-C for backplane */
#define ICE_DEV_ID_E810C_BACKPLANE 0x1591
/* Intel(R) Ethernet Controller E810-C for QSFP */
@@ -7,6 +7,11 @@
#ifndef _ICE_HW_AUTOGEN_H_
#define _ICE_HW_AUTOGEN_H_
+#define E830_PRTTSYN_TXTIME_H(_i) (0x001E5004 + ((_i) * 64)) /* _i=0...63 */ /* Reset Source: GLOBR */
+#define E830_PRTTSYN_TXTIME_L(_i) (0x001E5000 + ((_i) * 64)) /* _i=0...63 */ /* Reset Source: GLOBR */
+#define E830_PRTMAC_TS_TX_MEM_VALID_L 0x001E2000 /* Reset Source: GLOBR */
+#define E830_PRTMAC_TS_TX_MEM_VALID_H 0x001E2020 /* Reset Source: GLOBR */
+
#define GL_HIDA(_i) (0x00082000 + ((_i) * 4))
#define GL_HIBA(_i) (0x00081000 + ((_i) * 4))
#define GL_HICR 0x00082040
@@ -4690,6 +4690,38 @@ ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
return 0;
}
+/**
+ * ice_read_phy_tstamp_e830 - Read a PHY timestamp out of the external PHY
+ * @hw: pointer to the HW struct
+ * @lport: the lport to read from
+ * @idx: the timestamp index to read
+ * @tstamp: on return, the 40bit timestamp value
+ *
+ * Read a 40bit timestamp value out of the timestamp block of the external PHY
+ * on the E830 device.
+ */
+static enum ice_status
+ice_read_phy_tstamp_e830(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
+{
+ u32 hi_addr = E830_HIGH_TX_MEMORY_BANK(idx, lport);
+ u32 lo_addr = E830_LOW_TX_MEMORY_BANK(idx, lport);
+ u32 lo_val, hi_val, lo;
+ u8 hi;
+
+ lo_val = rd32(hw, lo_addr);
+ hi_val = rd32(hw, hi_addr);
+
+ lo = lo_val;
+ hi = (u8)hi_val;
+
+ /* For E830 devices, the timestamp is reported with the lower 32 bits
+ * in the low register, and the upper 8 bits in the high register.
+ */
+ *tstamp = ((u64)hi) << TS_HIGH_S | ((u64)lo & TS_LOW_M);
+
+ return ICE_SUCCESS;
+}
+
/**
* ice_clear_phy_tstamp_e810 - Clear a timestamp from the external PHY
* @hw: pointer to the HW struct
@@ -4880,6 +4912,31 @@ ice_ptp_prep_phy_incval_e810(struct ice_hw *hw, u64 incval)
return 0;
}
+/**
+ * ice_ptp_write_direct_incval_e830 - Prep PHY port increment value change
+ * @hw: pointer to HW struct
+ * @incval: The new 40bit increment value to prepare
+ *
+ * Prepare the PHY port for a new increment value by programming the PHC
+ * GLTSYN_INCVAL_L and GLTSYN_INCVAL_H registers. The actual change is
+ * completed by FW automatically.
+ */
+static enum ice_status
+ice_ptp_write_direct_incval_e830(struct ice_hw *hw, u64 incval)
+{
+ u32 high, low;
+ u8 tmr_idx;
+
+ tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ low = ICE_LO_DWORD(incval);
+ high = ICE_HI_DWORD(incval);
+
+ wr32(hw, GLTSYN_INCVAL_L(tmr_idx), low);
+ wr32(hw, GLTSYN_INCVAL_H(tmr_idx), high);
+
+ return ICE_SUCCESS;
+}
+
/**
* ice_ptp_prep_phy_adj_target_e810 - Prepare PHY port with adjust target
* @hw: Board private structure
@@ -4920,17 +4977,18 @@ ice_ptp_prep_phy_adj_target_e810(struct ice_hw *hw, u32 target_time)
}
/**
- * ice_ptp_port_cmd_e810 - Prepare all external PHYs for a timer command
+ * ice_ptp_port_cmd - Prepare all external PHYs for a timer command
* @hw: pointer to HW struct
* @cmd: Command to be sent to the port
* @lock_sbq: true if the sideband queue lock must be acquired
+ * @eth_gltsyn_cmd_addr: address for ETH_GLTSYN_CMD register
*
* Prepare the external PHYs connected to this device for a timer sync
* command.
*/
static int
-ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
- bool lock_sbq)
+ice_ptp_port_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
+ bool lock_sbq, u32 eth_gltsyn_cmd_addr)
{
int status;
u32 cmd_val, val;
@@ -4957,7 +5015,8 @@ ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
}
/* Read, modify, write */
- status = ice_read_phy_reg_e810_lp(hw, ETH_GLTSYN_CMD, &val, lock_sbq);
+ status = ice_read_phy_reg_e810_lp(hw, eth_gltsyn_cmd_addr, &val,
+ lock_sbq);
if (status) {
ice_debug(hw, ICE_DBG_PTP, "Failed to read GLTSYN_CMD, status %d\n",
status);
@@ -4968,7 +5027,8 @@ ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
val &= ~TS_CMD_MASK_E810;
val |= cmd_val;
- status = ice_write_phy_reg_e810_lp(hw, ETH_GLTSYN_CMD, val, lock_sbq);
+ status = ice_write_phy_reg_e810_lp(hw, eth_gltsyn_cmd_addr, val,
+ lock_sbq);
if (status) {
ice_debug(hw, ICE_DBG_PTP, "Failed to write back GLTSYN_CMD, status %d\n",
status);
@@ -4978,6 +5038,38 @@ ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
return 0;
}
+/**
+ * ice_ptp_port_cmd_e810 - Prepare all external PHYs for a timer command
+ * @hw: pointer to HW struct
+ * @cmd: Command to be sent to the port
+ * @lock_sbq: true if the sideband queue lock must be acquired
+ *
+ * Prepare the external PHYs connected to this device for a timer sync
+ * command.
+ */
+static enum ice_status
+ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
+ bool lock_sbq)
+{
+ return ice_ptp_port_cmd(hw, cmd, lock_sbq, E810_ETH_GLTSYN_CMD);
+}
+
+/**
+ * ice_ptp_port_cmd_e830 - Prepare all external PHYs for a timer command
+ * @hw: pointer to HW struct
+ * @cmd: Command to be sent to the port
+ * @lock_sbq: true if the sideband queue lock must be acquired
+ *
+ * Prepare the external PHYs connected to this device for a timer sync
+ * command.
+ */
+static enum ice_status
+ice_ptp_port_cmd_e830(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
+ bool lock_sbq)
+{
+ return ice_ptp_port_cmd(hw, cmd, lock_sbq, E830_ETH_GLTSYN_CMD);
+}
+
/* E810T SMA functions
*
* The following functions operate specifically on E810T hardware and are used
@@ -5285,6 +5377,9 @@ static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
case ICE_PHY_ETH56G:
status = ice_ptp_port_cmd_eth56g(hw, cmd, lock_sbq);
break;
+ case ICE_PHY_E830:
+ status = ice_ptp_port_cmd_e830(hw, cmd, lock_sbq);
+ break;
case ICE_PHY_E810:
status = ice_ptp_port_cmd_e810(hw, cmd, lock_sbq);
break;
@@ -5309,6 +5404,32 @@ static int ice_ptp_tmr_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd,
return 0;
}
+/**
+ * ice_ptp_write_direct_phc_time_e830 - Prepare PHY port with initial time
+ * @hw: Board private structure
+ * @time: Time to initialize the PHY port clock to
+ *
+ * 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 ICE_PTP_INIT_TIME command.
+ *
+ * The time value is the upper 32 bits of the PHY timer, usually in units of
+ * nominal nanoseconds.
+ */
+static enum ice_status
+ice_ptp_write_direct_phc_time_e830(struct ice_hw *hw, u64 time)
+{
+ u8 tmr_idx;
+
+ tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+
+ wr32(hw, GLTSYN_TIME_0(tmr_idx), 0);
+ wr32(hw, GLTSYN_TIME_L(tmr_idx), ICE_LO_DWORD(time));
+ wr32(hw, GLTSYN_TIME_H(tmr_idx), ICE_HI_DWORD(time));
+
+ return ICE_SUCCESS;
+}
+
/**
* ice_ptp_init_time - Initialize device time to provided value
* @hw: pointer to HW struct
@@ -5330,6 +5451,10 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
/* Source timers */
+ /* For E830 we don't need to use shadow registers, its automatic */
+ if (ice_is_e830(hw))
+ return ice_ptp_write_direct_phc_time_e830(hw, time);
+
wr32(hw, GLTSYN_SHTIME_L(tmr_idx), ICE_LO_DWORD(time));
wr32(hw, GLTSYN_SHTIME_H(tmr_idx), ICE_HI_DWORD(time));
wr32(hw, GLTSYN_SHTIME_0(tmr_idx), 0);
@@ -5377,6 +5502,10 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ /* For E830 we don't need to use shadow registers, its automatic */
+ if (ice_is_e830(hw))
+ return ice_ptp_write_direct_incval_e830(hw, incval);
+
/* Shadow Adjust */
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), ICE_LO_DWORD(incval));
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), ICE_HI_DWORD(incval));
@@ -5456,6 +5585,9 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj, bool lock_sbq)
case ICE_PHY_ETH56G:
status = ice_ptp_prep_phy_adj_eth56g(hw, adj, lock_sbq);
break;
+ case ICE_PHY_E830:
+ /* E830 sync PHYs automatically after setting GLTSYN_SHADJ */
+ return ICE_SUCCESS;
case ICE_PHY_E810:
status = ice_ptp_prep_phy_adj_e810(hw, adj, lock_sbq);
break;
@@ -5571,6 +5703,8 @@ ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
case ICE_PHY_ETH56G:
status = ice_read_phy_tstamp_eth56g(hw, block, idx, tstamp);
break;
+ case ICE_PHY_E830:
+ return ice_read_phy_tstamp_e830(hw, block, idx, tstamp);
case ICE_PHY_E810:
status = ice_read_phy_tstamp_e810(hw, block, idx, tstamp);
break;
@@ -482,7 +482,9 @@ int ice_ptp_init_phy_cfg(struct ice_hw *hw);
#define ETH_GLTSYN_SHADJ_H(_i) (0x0300037C + ((_i) * 32))
/* E810 timer command register */
-#define ETH_GLTSYN_CMD 0x03000344
+#define E810_ETH_GLTSYN_CMD 0x03000344
+/* E830 timer command register */
+#define E830_ETH_GLTSYN_CMD 0x00088814
/* Source timer incval macros */
#define INCVAL_HIGH_M 0xFF
@@ -522,6 +524,11 @@ int ice_ptp_init_phy_cfg(struct ice_hw *hw);
#define LOW_TX_MEMORY_BANK_START 0x03090000
#define HIGH_TX_MEMORY_BANK_START 0x03090004
+#define E830_LOW_TX_MEMORY_BANK(slot, port) \
+ (E830_PRTTSYN_TXTIME_L(slot) + 0x8 * (port))
+#define E830_HIGH_TX_MEMORY_BANK(slot, port) \
+ (E830_PRTTSYN_TXTIME_H(slot) + 0x8 * (port))
+
/* E810T PCA9575 IO controller registers */
#define ICE_PCA9575_P0_IN 0x0
#define ICE_PCA9575_P1_IN 0x1
@@ -204,6 +204,7 @@ enum ice_set_fc_aq_failures {
enum ice_mac_type {
ICE_MAC_UNKNOWN = 0,
ICE_MAC_E810,
+ ICE_MAC_E830,
ICE_MAC_GENERIC,
ICE_MAC_GENERIC_3K,
ICE_MAC_GENERIC_3K_E825,
@@ -1233,6 +1234,7 @@ enum ice_phy_cfg {
ICE_PHY_E810 = 1,
ICE_PHY_E822,
ICE_PHY_ETH56G,
+ ICE_PHY_E830,
};
/* Port hardware description */