From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B6E33454EF; Tue, 25 Jun 2024 13:18:54 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B3190427C9; Tue, 25 Jun 2024 13:16:29 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) by mails.dpdk.org (Postfix) with ESMTP id 75BD442DB1 for ; Tue, 25 Jun 2024 13:15:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1719314146; x=1750850146; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FxQ9qCQVdErdCnrT4iCjkg9WTxzzt4z4RRvqMvN3pQs=; b=BZ86r6BKTd1RxYfzPtNFIbwYsHJJbqJ4MeRLrclfrPi/BNvhKluFZtpw vF9hru0DiOswXab40X0H+fImY6kfctv0OCxjT/L2ODmyCDWJgBHkO84dX eHHGyi+Z3IlMpQ4oIk5dvSGCO7MUUsfi8X/rvz4mHd1xlRIdEXJCGN9ge 0wnO1OMfUDT9uYJQi+EQhQUlFYiPNHNeMeH4FGKUtembytXeKnm/iEsJC J0yR8r0xeotgWEpvBPYWZrGoPOFlTD9GQ8n7tNyJnKeCsGlJKwtj5bFUk Mc0fCBK7j4TPVk9JP7Um/CwDyQwq/jhyBHg8kwqGxHst8XpSexiutWrgz w==; X-CSE-ConnectionGUID: HidZgZ9VSM6ZROFhUJQ+6Q== X-CSE-MsgGUID: xUCru/O/RemRzw78k4gjFA== X-IronPort-AV: E=McAfee;i="6700,10204,11113"; a="16080133" X-IronPort-AV: E=Sophos;i="6.08,263,1712646000"; d="scan'208";a="16080133" Received: from orviesa009.jf.intel.com ([10.64.159.149]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jun 2024 04:15:46 -0700 X-CSE-ConnectionGUID: xhOZKEc+T+aPnAo86Br/CA== X-CSE-MsgGUID: Eeaw0LCQRzyjxzEDgts7aw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,263,1712646000"; d="scan'208";a="43719060" Received: from unknown (HELO silpixa00401119.ir.intel.com) ([10.55.129.167]) by orviesa009.jf.intel.com with ESMTP; 25 Jun 2024 04:15:45 -0700 From: Anatoly Burakov To: dev@dpdk.org Cc: Michal Michalik , bruce.richardson@intel.com, ian.stokes@intel.com Subject: [PATCH v3 028/129] net/ice/base: implement initial PTP support for E830 Date: Tue, 25 Jun 2024 12:12:33 +0100 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Michal Michalik The new series of devices supported by ice driver are E830 devices. This hardware supports the PTP feature very similar to E810 devices. The main difference besides some other register addresses is that in E830 we are able to read the TX timestamps memory directly from BARs (in E810 we used SBQ to read those). Note some workaround code for E830 functions and defines are added at this point but a full E830 Patch will add full functionality at a later stage. Signed-off-by: Michal Michalik Signed-off-by: Ian Stokes --- drivers/net/ice/base/ice_common.c | 22 ++++ drivers/net/ice/base/ice_common.h | 1 + drivers/net/ice/base/ice_devids.h | 18 ++++ drivers/net/ice/base/ice_hw_autogen.h | 5 + drivers/net/ice/base/ice_ptp_hw.c | 144 +++++++++++++++++++++++++- drivers/net/ice/base/ice_ptp_hw.h | 9 +- drivers/net/ice/base/ice_type.h | 2 + 7 files changed, 195 insertions(+), 6 deletions(-) diff --git a/drivers/net/ice/base/ice_common.c b/drivers/net/ice/base/ice_common.c index 50c8a1b472..16107317d3 100644 --- a/drivers/net/ice/base/ice_common.c +++ b/drivers/net/ice/base/ice_common.c @@ -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 diff --git a/drivers/net/ice/base/ice_common.h b/drivers/net/ice/base/ice_common.h index 18cbe590c6..ecfe55bd3a 100644 --- a/drivers/net/ice/base/ice_common.h +++ b/drivers/net/ice/base/ice_common.h @@ -265,6 +265,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 diff --git a/drivers/net/ice/base/ice_devids.h b/drivers/net/ice/base/ice_devids.h index 19478d2db1..49d642372a 100644 --- a/drivers/net/ice/base/ice_devids.h +++ b/drivers/net/ice/base/ice_devids.h @@ -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 */ diff --git a/drivers/net/ice/base/ice_hw_autogen.h b/drivers/net/ice/base/ice_hw_autogen.h index 5215d71c70..fde5f9d86f 100644 --- a/drivers/net/ice/base/ice_hw_autogen.h +++ b/drivers/net/ice/base/ice_hw_autogen.h @@ -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 diff --git a/drivers/net/ice/base/ice_ptp_hw.c b/drivers/net/ice/base/ice_ptp_hw.c index e83f4d5357..85c2cbb3ed 100644 --- a/drivers/net/ice/base/ice_ptp_hw.c +++ b/drivers/net/ice/base/ice_ptp_hw.c @@ -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 int +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 int +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 int +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 int +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 int +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 0; 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; diff --git a/drivers/net/ice/base/ice_ptp_hw.h b/drivers/net/ice/base/ice_ptp_hw.h index e2fb716186..7095c20209 100644 --- a/drivers/net/ice/base/ice_ptp_hw.h +++ b/drivers/net/ice/base/ice_ptp_hw.h @@ -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 diff --git a/drivers/net/ice/base/ice_type.h b/drivers/net/ice/base/ice_type.h index 48f892bfd3..99eb758eeb 100644 --- a/drivers/net/ice/base/ice_type.h +++ b/drivers/net/ice/base/ice_type.h @@ -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 */ -- 2.43.0