From: Sukhdeep Singh Extend the aq_hw_ops interface with new function pointers required for PTP support on AQC113: - enable_ptp: enable/disable PTP counter with clock selection - hw_ring_tx_ptp_get_ts: read TX timestamp from descriptor writeback - hw_tx_ptp_ring_init/hw_rx_ptp_ring_init: per-ring PTP initialization - hw_get_clk_sel: query active TSG clock selection Update existing hw_ops signatures to support AQC113 dual-clock architecture: - hw_gpio_pulse: add clk_sel and hightime parameters - hw_extts_gpio_enable: add channel parameter Add PTP-related hardware defines: - AQ_HW_TXD_CTL_TS_EN/TS_TSG0 for TX descriptor timestamp control - AQ2_HW_PTP_COUNTER_HZ for AQC113 TSG clock frequency - AQ_HW_PTP_IRQS for PTP interrupt vector accounting - PTP enable flags (L2/L4) and TSG clock selection constants Add request_ts and clk_sel bitfields to aq_ring_buff_s for per-packet TX timestamp request tracking. Update hw_atl_b0.c (AQC107) implementations: - Adapt gpio_pulse and extts_gpio_enable to new signatures - Add TX descriptor timestamp bits for AQC113 when ANTIGUA chip feature is detected Signed-off-by: Sukhdeep Singh --- .../net/ethernet/aquantia/atlantic/aq_hw.h | 34 +++++++++++++++++-- .../net/ethernet/aquantia/atlantic/aq_ptp.c | 4 +-- .../net/ethernet/aquantia/atlantic/aq_ring.h | 4 ++- .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 15 ++++++-- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 04fb87d4e56d..e3bacad08b93 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -19,6 +19,9 @@ #define AQ_HW_MAC_COUNTER_HZ 312500000ll #define AQ_HW_PHY_COUNTER_HZ 160000000ll +#define AQ_HW_TXD_CTL_TS_EN 0x40000000U +#define AQ_HW_TXD_CTL_TS_TSG0 0x80000000U + enum aq_tc_mode { AQ_TC_MODE_INVALID = -1, AQ_TC_MODE_8TCS, @@ -38,6 +41,8 @@ enum aq_tc_mode { #define AQ_FRAC_PER_NS 0x100000000LL +#define AQ2_HW_PTP_COUNTER_HZ 156250000ll + /* Used for rate to Mbps conversion */ #define AQ_MBPS_DIVISOR 125000 /* 1000000 / 8 */ @@ -109,6 +114,7 @@ struct aq_stats_s { #define AQ_HW_IRQ_MSIX 3U #define AQ_HW_SERVICE_IRQS 1U +#define AQ_HW_PTP_IRQS 1U #define AQ_HW_POWER_STATE_D0 0U #define AQ_HW_POWER_STATE_D3 3U @@ -157,6 +163,15 @@ enum aq_priv_flags { AQ_HW_LOOPBACK_PHYEXT_SYS, }; +enum { + AQ_HW_PTP_DISABLE = 0, + AQ_HW_PTP_L2_ENABLE = BIT(1), + AQ_HW_PTP_L4_ENABLE = BIT(2), +}; + +#define ATL_TSG_CLOCK_SEL_0 0 +#define ATL_TSG_CLOCK_SEL_1 1 + #define AQ_HW_LOOPBACK_MASK (BIT(AQ_HW_LOOPBACK_DMA_SYS) |\ BIT(AQ_HW_LOOPBACK_PKT_SYS) |\ BIT(AQ_HW_LOOPBACK_DMA_NET) |\ @@ -198,6 +213,7 @@ struct aq_hw_s { u32 rpc_tid; struct hw_atl_utils_fw_rpc rpc; s64 ptp_clk_offset; + s8 clk_select; u16 phy_id; void *priv; }; @@ -325,11 +341,15 @@ struct aq_hw_ops { int (*hw_ts_to_sys_clock)(struct aq_hw_s *self, u64 ts, u64 *time); - int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index, u64 start, - u32 period); + int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index, + u32 clk_sel, u64 start, + u32 period, u32 hightime); int (*hw_extts_gpio_enable)(struct aq_hw_s *self, u32 index, - u32 enable); + u32 channel, int enable); + + void (*enable_ptp)(struct aq_hw_s *self, unsigned int param, + int enable); int (*hw_get_sync_ts)(struct aq_hw_s *self, u64 *ts); @@ -339,6 +359,14 @@ struct aq_hw_ops { int (*extract_hwts)(struct aq_hw_s *self, u8 *p, unsigned int len, u64 *timestamp); + u64 (*hw_ring_tx_ptp_get_ts)(struct aq_ring_s *ring); + + int (*hw_tx_ptp_ring_init)(struct aq_hw_s *self, + struct aq_ring_s *aq_ring); + int (*hw_rx_ptp_ring_init)(struct aq_hw_s *self, + struct aq_ring_s *aq_ring); + u32 (*hw_get_clk_sel)(struct aq_hw_s *self); + int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc); int (*hw_set_loopback)(struct aq_hw_s *self, u32 mode, bool enable); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c index 9df8918216f6..7486a28d7ff8 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c @@ -380,7 +380,7 @@ static int aq_ptp_hw_pin_conf(struct aq_nic_s *aq_nic, u32 pin_index, u64 start, */ mutex_lock(&aq_nic->fwreq_mutex); aq_nic->aq_hw_ops->hw_gpio_pulse(aq_nic->aq_hw, pin_index, - start, (u32)period); + 0, start, (u32)period, 0); mutex_unlock(&aq_nic->fwreq_mutex); return 0; @@ -454,7 +454,7 @@ static void aq_ptp_extts_pin_ctrl(struct aq_ptp_s *aq_ptp) if (aq_nic->aq_hw_ops->hw_extts_gpio_enable) aq_nic->aq_hw_ops->hw_extts_gpio_enable(aq_nic->aq_hw, 0, - enable); + 0, enable); } static int aq_ptp_extts_pin_configure(struct ptp_clock_info *ptp, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h index d627ace850ff..e578fe04d22c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h @@ -85,7 +85,9 @@ struct __packed aq_ring_buff_s { u32 is_error:1; u32 is_vlan:1; u32 is_lro:1; - u32 rsvd3:3; + u32 request_ts:1; + u32 clk_sel:1; + u32 rsvd3:1; u16 eop_index; u16 rsvd4; }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index c7895bfb2ecf..6c25ad264b19 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -736,6 +736,15 @@ int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_s *ring, txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_WB; is_gso = false; is_vlan = false; + + if (ATL_HW_IS_CHIP_FEATURE(self, ANTIGUA) && + unlikely(buff->request_ts)) { + txd->ctl |= AQ_HW_TXD_CTL_TS_EN; + if (buff->clk_sel != ATL_TSG_CLOCK_SEL_1) + txd->ctl |= AQ_HW_TXD_CTL_TS_TSG0; + /* The only DD+TS is required */ + txd->ctl &= ~HW_ATL_B0_TXD_CTL_CMD_WB; + } } } ring->sw_tail = aq_ring_next_dx(ring, ring->sw_tail); @@ -1323,8 +1332,8 @@ static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb) return self->aq_fw_ops->send_fw_request(self, &fwreq, size); } -static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index, - u64 start, u32 period) +static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index, u32 clk_sel, + u64 start, u32 period, u32 hightime) { struct hw_fw_request_iface fwreq; size_t size; @@ -1342,7 +1351,7 @@ static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index, } static int hw_atl_b0_extts_gpio_enable(struct aq_hw_s *self, u32 index, - u32 enable) + u32 channel, int enable) { /* Enable/disable Sync1588 GPIO Timestamping */ aq_phy_write_reg(self, MDIO_MMD_PCS, 0xc611, enable ? 0x71 : 0); -- 2.43.0