netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v7 0/5] Add rds ptp library for Microchip phys
@ 2024-12-13 12:13 Divya Koppera
  2024-12-13 12:13 ` [PATCH net-next v7 1/5] net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp library Divya Koppera
                   ` (4 more replies)
  0 siblings, 5 replies; 19+ messages in thread
From: Divya Koppera @ 2024-12-13 12:13 UTC (permalink / raw)
  To: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

Adds support for rds ptp library in Microchip phys, where rds is internal
code name for ptp IP or hardware. This library will be re-used in
Microchip phys where same ptp hardware is used. Register base addresses
and mmd may changes, due to which base addresses and mmd is made variable
in this library.

Divya Koppera (5):
  net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp
    library
  net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  net: phy: Kconfig: Add rds ptp library support and 1588 optional flag
    in Microchip phys
  net: phy: Makefile: Add makefile support for rds ptp in Microchip phys
  net: phy: microchip_t1 : Add initialization of ptp for lan887x

 drivers/net/phy/Kconfig             |    9 +-
 drivers/net/phy/Makefile            |    1 +
 drivers/net/phy/microchip_rds_ptp.c | 1008 +++++++++++++++++++++++++++
 drivers/net/phy/microchip_rds_ptp.h |  219 ++++++
 drivers/net/phy/microchip_t1.c      |   41 +-
 5 files changed, 1274 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/phy/microchip_rds_ptp.c
 create mode 100644 drivers/net/phy/microchip_rds_ptp.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH net-next v7 1/5] net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp library
  2024-12-13 12:13 [PATCH net-next v7 0/5] Add rds ptp library for Microchip phys Divya Koppera
@ 2024-12-13 12:13 ` Divya Koppera
  2024-12-17 15:05   ` Andrew Lunn
  2024-12-13 12:14 ` [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys Divya Koppera
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 19+ messages in thread
From: Divya Koppera @ 2024-12-13 12:13 UTC (permalink / raw)
  To: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

This rds ptp header file will cover ptp macros for future phys in
Microchip where addresses will be same but base offset and mmd address
may changes.

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Divya Koppera <divya.koppera@microchip.com>
---
v6 -> v7
- No changes

v5 -> v6
- Renamed header file name, macros and function names to
  reflect ptp hardware code name.

v4 -> v5
- Reduced scope of config PTP Macro check to APIs

v3 -> v4
- Re-ordered mchp_ptp_clock structure.

v2 -> v3
- No changes

v1 -> v2
- Fixed sparse warnings and compilation errors/warnings reported by kernel
  test robot
---
 drivers/net/phy/microchip_rds_ptp.h | 219 ++++++++++++++++++++++++++++
 1 file changed, 219 insertions(+)
 create mode 100644 drivers/net/phy/microchip_rds_ptp.h

diff --git a/drivers/net/phy/microchip_rds_ptp.h b/drivers/net/phy/microchip_rds_ptp.h
new file mode 100644
index 000000000000..ffcf1e56184f
--- /dev/null
+++ b/drivers/net/phy/microchip_rds_ptp.h
@@ -0,0 +1,219 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright (C) 2024 Microchip Technology
+ */
+
+#ifndef _MICROCHIP_RDS_PTP_H
+#define _MICROCHIP_RDS_PTP_H
+
+#include <linux/ptp_clock_kernel.h>
+#include <linux/ptp_clock.h>
+#include <linux/ptp_classify.h>
+#include <linux/net_tstamp.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#define MCHP_RDS_PTP_CMD_CTL(b)			((b) + 0x0)
+#define MCHP_RDS_PTP_CMD_CTL_LTC_STEP_NSEC	BIT(6)
+#define MCHP_RDS_PTP_CMD_CTL_LTC_STEP_SEC	BIT(5)
+#define MCHP_RDS_PTP_CMD_CTL_CLOCK_LOAD		BIT(4)
+#define MCHP_RDS_PTP_CMD_CTL_CLOCK_READ		BIT(3)
+#define MCHP_RDS_PTP_CMD_CTL_EN			BIT(1)
+#define MCHP_RDS_PTP_CMD_CTL_DIS		BIT(0)
+
+#define MCHP_RDS_PTP_REF_CLK_CFG(b)		((b) + 0x2)
+#define MCHP_RDS_PTP_REF_CLK_SRC_250MHZ		0x0
+#define MCHP_RDS_PTP_REF_CLK_PERIOD_OVERRIDE	BIT(9)
+#define MCHP_RDS_PTP_REF_CLK_PERIOD		4
+#define MCHP_RDS_PTP_REF_CLK_CFG_SET	(MCHP_RDS_PTP_REF_CLK_SRC_250MHZ |\
+					 MCHP_RDS_PTP_REF_CLK_PERIOD_OVERRIDE |\
+					 MCHP_RDS_PTP_REF_CLK_PERIOD)
+
+#define MCHP_RDS_PTP_LTC_SEC_HI(b)		((b) + 0x5)
+#define MCHP_RDS_PTP_LTC_SEC_MID(b)		((b) + 0x6)
+#define MCHP_RDS_PTP_LTC_SEC_LO(b)		((b) + 0x7)
+#define MCHP_RDS_PTP_LTC_NS_HI(b)		((b) + 0x8)
+#define MCHP_RDS_PTP_LTC_NS_LO(b)		((b) + 0x9)
+#define MCHP_RDS_PTP_LTC_RATE_ADJ_HI(b)		((b) + 0xc)
+#define MCHP_RDS_PTP_LTC_RATE_ADJ_HI_DIR	BIT(15)
+#define MCHP_RDS_PTP_LTC_RATE_ADJ_LO(b)		((b) + 0xd)
+#define MCHP_RDS_PTP_STEP_ADJ_HI(b)		((b) + 0x12)
+#define MCHP_RDS_PTP_STEP_ADJ_HI_DIR		BIT(15)
+#define MCHP_RDS_PTP_STEP_ADJ_LO(b)		((b) + 0x13)
+#define MCHP_RDS_PTP_LTC_READ_SEC_HI(b)		((b) + 0x29)
+#define MCHP_RDS_PTP_LTC_READ_SEC_MID(b)	((b) + 0x2a)
+#define MCHP_RDS_PTP_LTC_READ_SEC_LO(b)		((b) + 0x2b)
+#define MCHP_RDS_PTP_LTC_READ_NS_HI(b)		((b) + 0x2c)
+#define MCHP_RDS_PTP_LTC_READ_NS_LO(b)		((b) + 0x2d)
+#define MCHP_RDS_PTP_OP_MODE(b)			((b) + 0x41)
+#define MCHP_RDS_PTP_OP_MODE_DIS		0
+#define MCHP_RDS_PTP_OP_MODE_STANDALONE		1
+#define MCHP_RDS_PTP_LATENCY_CORRECTION_CTL(b)	((b) + 0x44)
+#define MCHP_RDS_PTP_PREDICTOR_EN		BIT(6)
+#define MCHP_RDS_PTP_TX_PRED_DIS		BIT(1)
+#define MCHP_RDS_PTP_RX_PRED_DIS		BIT(0)
+#define MCHP_RDS_PTP_LATENCY_SETTING		(MCHP_RDS_PTP_PREDICTOR_EN | \
+						 MCHP_RDS_PTP_TX_PRED_DIS | \
+						 MCHP_RDS_PTP_RX_PRED_DIS)
+
+#define MCHP_RDS_PTP_INT_EN(b)			((b) + 0x0)
+#define MCHP_RDS_PTP_INT_STS(b)			((b) + 0x01)
+#define MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN		BIT(3)
+#define MCHP_RDS_PTP_INT_TX_TS_EN		BIT(2)
+#define MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN		BIT(1)
+#define MCHP_RDS_PTP_INT_RX_TS_EN		BIT(0)
+#define MCHP_RDS_PTP_INT_ALL_MSK	(MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN | \
+					 MCHP_RDS_PTP_INT_TX_TS_EN | \
+					 MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN |\
+					 MCHP_RDS_PTP_INT_RX_TS_EN)
+
+#define MCHP_RDS_PTP_CAP_INFO(b)		((b) + 0x2e)
+#define MCHP_RDS_PTP_TX_TS_CNT(v)		(((v) & GENMASK(11, 8)) >> 8)
+#define MCHP_RDS_PTP_RX_TS_CNT(v)		((v) & GENMASK(3, 0))
+
+#define MCHP_RDS_PTP_RX_PARSE_CONFIG(b)		((b) + 0x42)
+#define MCHP_RDS_PTP_RX_PARSE_L2_ADDR_EN(b)	((b) + 0x44)
+#define MCHP_RDS_PTP_RX_PARSE_IPV4_ADDR_EN(b)	((b) + 0x45)
+
+#define MCHP_RDS_PTP_RX_TIMESTAMP_CONFIG(b)	((b) + 0x4e)
+#define MCHP_RDS_PTP_RX_TIMESTAMP_CONFIG_PTP_FCS_DIS BIT(0)
+
+#define MCHP_RDS_PTP_RX_VERSION(b)		((b) + 0x48)
+#define MCHP_RDS_PTP_RX_TIMESTAMP_EN(b)		((b) + 0x4d)
+
+#define MCHP_RDS_PTP_RX_INGRESS_NS_HI(b)	((b) + 0x54)
+#define MCHP_RDS_PTP_RX_INGRESS_NS_HI_TS_VALID	BIT(15)
+
+#define MCHP_RDS_PTP_RX_INGRESS_NS_LO(b)	((b) + 0x55)
+#define MCHP_RDS_PTP_RX_INGRESS_SEC_HI(b)	((b) + 0x56)
+#define MCHP_RDS_PTP_RX_INGRESS_SEC_LO(b)	((b) + 0x57)
+#define MCHP_RDS_PTP_RX_MSG_HDR2(b)		((b) + 0x59)
+
+#define MCHP_RDS_PTP_TX_PARSE_CONFIG(b)		((b) + 0x82)
+#define MCHP_RDS_PTP_PARSE_CONFIG_LAYER2_EN	BIT(0)
+#define MCHP_RDS_PTP_PARSE_CONFIG_IPV4_EN	BIT(1)
+#define MCHP_RDS_PTP_PARSE_CONFIG_IPV6_EN	BIT(2)
+
+#define MCHP_RDS_PTP_TX_PARSE_L2_ADDR_EN(b)	((b) + 0x84)
+#define MCHP_RDS_PTP_TX_PARSE_IPV4_ADDR_EN(b)	((b) + 0x85)
+
+#define MCHP_RDS_PTP_TX_VERSION(b)		((b) + 0x88)
+#define MCHP_RDS_PTP_MAX_VERSION(x)		(((x) & GENMASK(7, 0)) << 8)
+#define MCHP_RDS_PTP_MIN_VERSION(x)		((x) & GENMASK(7, 0))
+
+#define MCHP_RDS_PTP_TX_TIMESTAMP_EN(b)		((b) + 0x8d)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_SYNC		BIT(0)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_DREQ		BIT(1)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_PDREQ		BIT(2)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_PDRES		BIT(3)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_ALL	(MCHP_RDS_PTP_TIMESTAMP_EN_SYNC |\
+					 MCHP_RDS_PTP_TIMESTAMP_EN_DREQ |\
+					 MCHP_RDS_PTP_TIMESTAMP_EN_PDREQ |\
+					 MCHP_RDS_PTP_TIMESTAMP_EN_PDRES)
+
+#define MCHP_RDS_PTP_TX_TIMESTAMP_CONFIG(b)	((b) + 0x8e)
+#define MCHP_RDS_PTP_TX_TIMESTAMP_CONFIG_PTP_FCS_DIS BIT(0)
+
+#define MCHP_RDS_PTP_TX_MOD(b)			((b) + 0x8f)
+#define MCHP_RDS_PTP_TX_MOD_PTP_SYNC_TS_INSERT	BIT(12)
+#define MCHP_RDS_PTP_TX_MOD_PTP_FU_TS_INSERT	BIT(11)
+
+#define MCHP_RDS_PTP_TX_EGRESS_NS_HI(b)		((b) + 0x94)
+#define MCHP_RDS_PTP_TX_EGRESS_NS_HI_TS_VALID	BIT(15)
+
+#define MCHP_RDS_PTP_TX_EGRESS_NS_LO(b)		((b) + 0x95)
+#define MCHP_RDS_PTP_TX_EGRESS_SEC_HI(b)	((b) + 0x96)
+#define MCHP_RDS_PTP_TX_EGRESS_SEC_LO(b)	((b) + 0x97)
+#define MCHP_RDS_PTP_TX_MSG_HDR2(b)		((b) + 0x99)
+
+#define MCHP_RDS_PTP_TSU_GEN_CONFIG(b)		((b) + 0xc0)
+#define MCHP_RDS_PTP_TSU_GEN_CFG_TSU_EN		BIT(0)
+
+#define MCHP_RDS_PTP_TSU_HARD_RESET(b)		((b) + 0xc1)
+#define MCHP_RDS_PTP_TSU_HARDRESET		BIT(0)
+
+/* Represents 1ppm adjustment in 2^32 format with
+ * each nsec contains 4 clock cycles in 250MHz.
+ * The value is calculated as following: (1/1000000)/((2^-32)/4)
+ */
+#define MCHP_RDS_PTP_1PPM_FORMAT		17179
+#define MCHP_RDS_PTP_FIFO_SIZE			8
+#define MCHP_RDS_PTP_MAX_ADJ			31249999
+
+#define BASE_CLK(p)		((p)->clk_base_addr)
+#define BASE_PORT(p)		((p)->port_base_addr)
+#define PTP_MMD(p)		((p)->mmd)
+
+enum mchp_rds_ptp_fifo_dir {
+	MCHP_RDS_PTP_INGRESS_FIFO,
+	MCHP_RDS_PTP_EGRESS_FIFO
+};
+
+struct mchp_rds_ptp_clock {
+	struct mii_timestamper mii_ts;
+	struct phy_device *phydev;
+	struct ptp_clock *ptp_clock;
+
+	struct sk_buff_head tx_queue;
+	struct sk_buff_head rx_queue;
+	struct list_head rx_ts_list;
+
+	struct ptp_clock_info caps;
+
+	/* Lock for Rx ts fifo */
+	spinlock_t rx_ts_lock;
+	int hwts_tx_type;
+
+	enum hwtstamp_rx_filters rx_filter;
+	int layer;
+	int version;
+	u16 port_base_addr;
+	u16 clk_base_addr;
+
+	/* Lock for phc */
+	struct mutex ptp_lock;
+	u8 mmd;
+};
+
+struct mchp_rds_ptp_rx_ts {
+	struct list_head list;
+	u32 seconds;
+	u32 nsec;
+	u16 seq_id;
+};
+
+#if IS_ENABLED(CONFIG_MICROCHIP_PHY_RDS_PTP)
+
+struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device *phydev, u8 mmd,
+					      u16 clk_base, u16 port_base);
+
+int mchp_rds_ptp_top_config_intr(struct mchp_rds_ptp_clock *clock,
+				 u16 reg, u16 val, bool enable);
+
+irqreturn_t mchp_rds_ptp_handle_interrupt(struct mchp_rds_ptp_clock *clock);
+
+#else
+
+static inline struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device
+							    *phydev, u8 mmd,
+							    u16 clk_base,
+							    u16 port_base)
+{
+	return NULL;
+}
+
+static inline int mchp_rds_ptp_top_config_intr(struct mchp_rds_ptp_clock *clock,
+					       u16 reg, u16 val, bool enable)
+{
+	return 0;
+}
+
+static inline irqreturn_t mchp_rds_ptp_handle_interrupt(struct
+							mchp_rds_ptp_clock
+							* clock)
+{
+	return IRQ_NONE;
+}
+
+#endif //CONFIG_MICROCHIP_PHY_RDS_PTP
+
+#endif //_MICROCHIP_RDS_PTP_H
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  2024-12-13 12:13 [PATCH net-next v7 0/5] Add rds ptp library for Microchip phys Divya Koppera
  2024-12-13 12:13 ` [PATCH net-next v7 1/5] net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp library Divya Koppera
@ 2024-12-13 12:14 ` Divya Koppera
  2024-12-18  3:22   ` Jakub Kicinski
  2024-12-18  3:25   ` Jakub Kicinski
  2024-12-13 12:14 ` [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in " Divya Koppera
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 19+ messages in thread
From: Divya Koppera @ 2024-12-13 12:14 UTC (permalink / raw)
  To: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

Add rds ptp library for Microchip phys
1-step and 2-step modes are supported, over Ethernet and UDP(ipv4, ipv6)

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Divya Koppera <divya.koppera@microchip.com>
---
v6 -> v7
- Enabling ptp interrupt is moved to proper place.
- Moved skb purge to flush fifo function and removed redundant code.

v5 -> v6
- Renamed file name, macros, function names.
- Moved initialization of ptp_lock to avoid race condition.

v4 -> v5
- No changes

v3 -> v4
- Fixed coccicheck errors

v2 -> v3
- Moved to kmalloc from kzalloc
- Fixed sparse errors related to cast from restricted __be16

v1 -> v2
- Removed redundant memsets
- Moved to standard comparision than memcmp for u16
- Fixed sparse/smatch warnings reported by kernel test robot
- Added spinlock to shared code
- Moved redundant part of code out of spinlock protected area
---
 drivers/net/phy/microchip_rds_ptp.c | 1008 +++++++++++++++++++++++++++
 1 file changed, 1008 insertions(+)
 create mode 100644 drivers/net/phy/microchip_rds_ptp.c

diff --git a/drivers/net/phy/microchip_rds_ptp.c b/drivers/net/phy/microchip_rds_ptp.c
new file mode 100644
index 000000000000..2817acbbb45d
--- /dev/null
+++ b/drivers/net/phy/microchip_rds_ptp.c
@@ -0,0 +1,1008 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2024 Microchip Technology
+
+#include "microchip_rds_ptp.h"
+
+static int mchp_rds_ptp_flush_fifo(struct mchp_rds_ptp_clock *clock,
+				   enum mchp_rds_ptp_fifo_dir dir)
+{
+	struct phy_device *phydev = clock->phydev;
+	int rc;
+
+	if (dir == MCHP_RDS_PTP_EGRESS_FIFO)
+		skb_queue_purge(&clock->tx_queue);
+	else
+		skb_queue_purge(&clock->rx_queue);
+
+	for (int i = 0; i < MCHP_RDS_PTP_FIFO_SIZE; ++i) {
+		rc = phy_read_mmd(phydev, PTP_MMD(clock),
+				  dir == MCHP_RDS_PTP_EGRESS_FIFO ?
+				  MCHP_RDS_PTP_TX_MSG_HDR2(BASE_PORT(clock)) :
+				  MCHP_RDS_PTP_RX_MSG_HDR2(BASE_PORT(clock)));
+		if (rc < 0)
+			return rc;
+	}
+	return phy_read_mmd(phydev, PTP_MMD(clock),
+			    MCHP_RDS_PTP_INT_STS(BASE_PORT(clock)));
+}
+
+static int mchp_rds_ptp_config_intr(struct mchp_rds_ptp_clock *clock,
+				    bool enable)
+{
+	struct phy_device *phydev = clock->phydev;
+
+	/* Enable  or disable ptp interrupts */
+	return phy_write_mmd(phydev, PTP_MMD(clock),
+			     MCHP_RDS_PTP_INT_EN(BASE_PORT(clock)),
+			     enable ? MCHP_RDS_PTP_INT_ALL_MSK : 0);
+}
+
+static void mchp_rds_ptp_txtstamp(struct mii_timestamper *mii_ts,
+				  struct sk_buff *skb, int type)
+{
+	struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
+						      struct mchp_rds_ptp_clock,
+						      mii_ts);
+
+	switch (clock->hwts_tx_type) {
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		if (ptp_msg_is_sync(skb, type)) {
+			kfree_skb(skb);
+			return;
+		}
+		fallthrough;
+	case HWTSTAMP_TX_ON:
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+		skb_queue_tail(&clock->tx_queue, skb);
+		break;
+	case HWTSTAMP_TX_OFF:
+	default:
+		kfree_skb(skb);
+		break;
+	}
+}
+
+static bool mchp_rds_ptp_get_sig_rx(struct sk_buff *skb, u16 *sig)
+{
+	struct ptp_header *ptp_header;
+	int type;
+
+	skb_push(skb, ETH_HLEN);
+	type = ptp_classify_raw(skb);
+	if (type == PTP_CLASS_NONE)
+		return false;
+
+	ptp_header = ptp_parse_header(skb, type);
+	if (!ptp_header)
+		return false;
+
+	skb_pull_inline(skb, ETH_HLEN);
+
+	*sig = (__force u16)(ntohs(ptp_header->sequence_id));
+
+	return true;
+}
+
+static bool mchp_rds_ptp_match_skb(struct mchp_rds_ptp_clock *clock,
+				   struct mchp_rds_ptp_rx_ts *rx_ts)
+{
+	struct skb_shared_hwtstamps *shhwtstamps;
+	struct sk_buff *skb, *skb_tmp;
+	unsigned long flags;
+	bool rc = false;
+	u16 skb_sig;
+
+	spin_lock_irqsave(&clock->rx_queue.lock, flags);
+	skb_queue_walk_safe(&clock->rx_queue, skb, skb_tmp) {
+		if (!mchp_rds_ptp_get_sig_rx(skb, &skb_sig))
+			continue;
+
+		if (skb_sig != rx_ts->seq_id)
+			continue;
+
+		__skb_unlink(skb, &clock->rx_queue);
+
+		rc = true;
+		break;
+	}
+	spin_unlock_irqrestore(&clock->rx_queue.lock, flags);
+
+	if (rc) {
+		shhwtstamps = skb_hwtstamps(skb);
+		shhwtstamps->hwtstamp = ktime_set(rx_ts->seconds, rx_ts->nsec);
+		netif_rx(skb);
+	}
+
+	return rc;
+}
+
+static void mchp_rds_ptp_match_rx_ts(struct mchp_rds_ptp_clock *clock,
+				     struct mchp_rds_ptp_rx_ts *rx_ts)
+{
+	unsigned long flags;
+
+	/* If we failed to match the skb add it to the queue for when
+	 * the frame will come
+	 */
+	if (!mchp_rds_ptp_match_skb(clock, rx_ts)) {
+		spin_lock_irqsave(&clock->rx_ts_lock, flags);
+		list_add(&rx_ts->list, &clock->rx_ts_list);
+		spin_unlock_irqrestore(&clock->rx_ts_lock, flags);
+	} else {
+		kfree(rx_ts);
+	}
+}
+
+static void mchp_rds_ptp_match_rx_skb(struct mchp_rds_ptp_clock *clock,
+				      struct sk_buff *skb)
+{
+	struct mchp_rds_ptp_rx_ts *rx_ts, *tmp, *rx_ts_var = NULL;
+	struct skb_shared_hwtstamps *shhwtstamps;
+	unsigned long flags;
+	u16 skb_sig;
+
+	if (!mchp_rds_ptp_get_sig_rx(skb, &skb_sig))
+		return;
+
+	/* Iterate over all RX timestamps and match it with the received skbs */
+	spin_lock_irqsave(&clock->rx_ts_lock, flags);
+	list_for_each_entry_safe(rx_ts, tmp, &clock->rx_ts_list, list) {
+		/* Check if we found the signature we were looking for. */
+		if (skb_sig != rx_ts->seq_id)
+			continue;
+
+		shhwtstamps = skb_hwtstamps(skb);
+		shhwtstamps->hwtstamp = ktime_set(rx_ts->seconds, rx_ts->nsec);
+		netif_rx(skb);
+
+		rx_ts_var = rx_ts;
+
+		break;
+	}
+	spin_unlock_irqrestore(&clock->rx_ts_lock, flags);
+
+	if (rx_ts_var) {
+		list_del(&rx_ts_var->list);
+		kfree(rx_ts_var);
+	} else {
+		skb_queue_tail(&clock->rx_queue, skb);
+	}
+}
+
+static bool mchp_rds_ptp_rxtstamp(struct mii_timestamper *mii_ts,
+				  struct sk_buff *skb, int type)
+{
+	struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
+						      struct mchp_rds_ptp_clock,
+						      mii_ts);
+
+	if (clock->rx_filter == HWTSTAMP_FILTER_NONE ||
+	    type == PTP_CLASS_NONE)
+		return false;
+
+	if ((type & clock->version) == 0 || (type & clock->layer) == 0)
+		return false;
+
+	/* Here if match occurs skb is sent to application, If not skb is added
+	 * to queue and sending skb to application will get handled when
+	 * interrupt occurs i.e., it get handles in interrupt handler. By
+	 * any means skb will reach the application so we should not return
+	 * false here if skb doesn't matches.
+	 */
+	mchp_rds_ptp_match_rx_skb(clock, skb);
+
+	return true;
+}
+
+static int mchp_rds_ptp_hwtstamp(struct mii_timestamper *mii_ts,
+				 struct kernel_hwtstamp_config *config,
+				 struct netlink_ext_ack *extack)
+{
+	struct mchp_rds_ptp_clock *clock =
+				container_of(mii_ts, struct mchp_rds_ptp_clock,
+					     mii_ts);
+	struct phy_device *phydev = clock->phydev;
+	struct mchp_rds_ptp_rx_ts *rx_ts, *tmp;
+	int txcfg = 0, rxcfg = 0;
+	unsigned long flags;
+	int rc;
+
+	clock->hwts_tx_type = config->tx_type;
+	clock->rx_filter = config->rx_filter;
+
+	switch (config->rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		clock->layer = 0;
+		clock->version = 0;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		clock->layer = PTP_CLASS_L4;
+		clock->version = PTP_CLASS_V2;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+		clock->layer = PTP_CLASS_L2;
+		clock->version = PTP_CLASS_V2;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		clock->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
+		clock->version = PTP_CLASS_V2;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	/* Setup parsing of the frames and enable the timestamping for ptp
+	 * frames
+	 */
+	if (clock->layer & PTP_CLASS_L2) {
+		rxcfg = MCHP_RDS_PTP_PARSE_CONFIG_LAYER2_EN;
+		txcfg = MCHP_RDS_PTP_PARSE_CONFIG_LAYER2_EN;
+	}
+	if (clock->layer & PTP_CLASS_L4) {
+		rxcfg |= MCHP_RDS_PTP_PARSE_CONFIG_IPV4_EN |
+			 MCHP_RDS_PTP_PARSE_CONFIG_IPV6_EN;
+		txcfg |= MCHP_RDS_PTP_PARSE_CONFIG_IPV4_EN |
+			 MCHP_RDS_PTP_PARSE_CONFIG_IPV6_EN;
+	}
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_RX_PARSE_CONFIG(BASE_PORT(clock)),
+			   rxcfg);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TX_PARSE_CONFIG(BASE_PORT(clock)),
+			   txcfg);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_RX_TIMESTAMP_EN(BASE_PORT(clock)),
+			   MCHP_RDS_PTP_TIMESTAMP_EN_ALL);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TX_TIMESTAMP_EN(BASE_PORT(clock)),
+			   MCHP_RDS_PTP_TIMESTAMP_EN_ALL);
+	if (rc < 0)
+		return rc;
+
+	if (clock->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC)
+		/* Enable / disable of the TX timestamp in the SYNC frames */
+		rc = phy_modify_mmd(phydev, PTP_MMD(clock),
+				    MCHP_RDS_PTP_TX_MOD(BASE_PORT(clock)),
+				    MCHP_RDS_PTP_TX_MOD_PTP_SYNC_TS_INSERT,
+				    MCHP_RDS_PTP_TX_MOD_PTP_SYNC_TS_INSERT);
+	else
+		rc = phy_modify_mmd(phydev, PTP_MMD(clock),
+				    MCHP_RDS_PTP_TX_MOD(BASE_PORT(clock)),
+				    MCHP_RDS_PTP_TX_MOD_PTP_SYNC_TS_INSERT,
+				(u16)~MCHP_RDS_PTP_TX_MOD_PTP_SYNC_TS_INSERT);
+
+	if (rc < 0)
+		return rc;
+
+	/* In case of multiple starts and stops, these needs to be cleared */
+	spin_lock_irqsave(&clock->rx_ts_lock, flags);
+	list_for_each_entry_safe(rx_ts, tmp, &clock->rx_ts_list, list) {
+		list_del(&rx_ts->list);
+		kfree(rx_ts);
+	}
+	spin_unlock_irqrestore(&clock->rx_ts_lock, flags);
+
+	rc = mchp_rds_ptp_flush_fifo(clock, MCHP_RDS_PTP_INGRESS_FIFO);
+	if (rc < 0)
+		return rc;
+
+	rc = mchp_rds_ptp_flush_fifo(clock, MCHP_RDS_PTP_EGRESS_FIFO);
+	if (rc < 0)
+		return rc;
+
+	/* Now enable the timestamping interrupts */
+	rc = mchp_rds_ptp_config_intr(clock,
+				      config->rx_filter !=
+				      HWTSTAMP_FILTER_NONE);
+
+	return rc < 0 ? rc : 0;
+}
+
+static int mchp_rds_ptp_ts_info(struct mii_timestamper *mii_ts,
+				struct kernel_ethtool_ts_info *info)
+{
+	struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
+						      struct mchp_rds_ptp_clock,
+						      mii_ts);
+
+	info->phc_index =
+		clock->ptp_clock ? ptp_clock_index(clock->ptp_clock) : -1;
+	if (info->phc_index == -1)
+		return 0;
+
+	info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+				SOF_TIMESTAMPING_RX_HARDWARE |
+				SOF_TIMESTAMPING_RAW_HARDWARE;
+
+	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
+			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
+
+	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
+
+	return 0;
+}
+
+static int mchp_rds_ptp_ltc_adjtime(struct ptp_clock_info *info, s64 delta)
+{
+	struct mchp_rds_ptp_clock *clock = container_of(info,
+						      struct mchp_rds_ptp_clock,
+						      caps);
+	struct phy_device *phydev = clock->phydev;
+	struct timespec64 ts;
+	bool add = true;
+	int rc = 0;
+	u32 nsec;
+	s32 sec;
+
+	/* The HW allows up to 15 sec to adjust the time, but here we limit to
+	 * 10 sec the adjustment. The reason is, in case the adjustment is 14
+	 * sec and 999999999 nsec, then we add 8ns to compensate the actual
+	 * increment so the value can be bigger than 15 sec. Therefore limit the
+	 * possible adjustments so we will not have these corner cases
+	 */
+	if (delta > 10000000000LL || delta < -10000000000LL) {
+		/* The timeadjustment is too big, so fall back using set time */
+		u64 now;
+
+		info->gettime64(info, &ts);
+
+		now = ktime_to_ns(timespec64_to_ktime(ts));
+		ts = ns_to_timespec64(now + delta);
+
+		info->settime64(info, &ts);
+		return 0;
+	}
+	sec = div_u64_rem(abs(delta), NSEC_PER_SEC, &nsec);
+	if (delta < 0 && nsec != 0) {
+		/* It is not allowed to adjust low the nsec part, therefore
+		 * subtract more from second part and add to nanosecond such
+		 * that would roll over, so the second part will increase
+		 */
+		sec--;
+		nsec = NSEC_PER_SEC - nsec;
+	}
+
+	/* Calculate the adjustments and the direction */
+	if (delta < 0)
+		add = false;
+
+	if (nsec > 0) {
+		/* add 8 ns to cover the likely normal increment */
+		nsec += 8;
+
+		if (nsec >= NSEC_PER_SEC) {
+			/* carry into seconds */
+			sec++;
+			nsec -= NSEC_PER_SEC;
+		}
+	}
+
+	mutex_lock(&clock->ptp_lock);
+	if (sec) {
+		sec = abs(sec);
+
+		rc = phy_write_mmd(phydev, PTP_MMD(clock),
+				   MCHP_RDS_PTP_STEP_ADJ_LO(BASE_CLK(clock)),
+				   sec);
+		if (rc < 0)
+			goto out_unlock;
+
+		rc = phy_set_bits_mmd(phydev, PTP_MMD(clock),
+				      MCHP_RDS_PTP_STEP_ADJ_HI(BASE_CLK(clock)),
+				      ((add ? MCHP_RDS_PTP_STEP_ADJ_HI_DIR :
+					0) | ((sec >> 16) & GENMASK(13, 0))));
+		if (rc < 0)
+			goto out_unlock;
+
+		rc = phy_set_bits_mmd(phydev, PTP_MMD(clock),
+				      MCHP_RDS_PTP_CMD_CTL(BASE_CLK(clock)),
+				      MCHP_RDS_PTP_CMD_CTL_LTC_STEP_SEC);
+		if (rc < 0)
+			goto out_unlock;
+	}
+
+	if (nsec) {
+		rc = phy_write_mmd(phydev, PTP_MMD(clock),
+				   MCHP_RDS_PTP_STEP_ADJ_LO(BASE_CLK(clock)),
+				   nsec & GENMASK(15, 0));
+		if (rc < 0)
+			goto out_unlock;
+
+		rc = phy_write_mmd(phydev, PTP_MMD(clock),
+				   MCHP_RDS_PTP_STEP_ADJ_HI(BASE_CLK(clock)),
+				   (nsec >> 16) & GENMASK(13, 0));
+		if (rc < 0)
+			goto out_unlock;
+
+		rc = phy_set_bits_mmd(phydev, PTP_MMD(clock),
+				      MCHP_RDS_PTP_CMD_CTL(BASE_CLK(clock)),
+				      MCHP_RDS_PTP_CMD_CTL_LTC_STEP_NSEC);
+	}
+
+out_unlock:
+	mutex_unlock(&clock->ptp_lock);
+
+	return rc;
+}
+
+static int mchp_rds_ptp_ltc_adjfine(struct ptp_clock_info *info,
+				    long scaled_ppm)
+{
+	struct mchp_rds_ptp_clock *clock = container_of(info,
+						      struct mchp_rds_ptp_clock,
+						      caps);
+	struct phy_device *phydev = clock->phydev;
+	u16 rate_lo, rate_hi;
+	bool faster = true;
+	u32 rate;
+	int rc;
+
+	if (!scaled_ppm)
+		return 0;
+
+	if (scaled_ppm < 0) {
+		scaled_ppm = -scaled_ppm;
+		faster = false;
+	}
+
+	rate = MCHP_RDS_PTP_1PPM_FORMAT * (upper_16_bits(scaled_ppm));
+	rate += (MCHP_RDS_PTP_1PPM_FORMAT * (lower_16_bits(scaled_ppm))) >> 16;
+
+	rate_lo = rate & GENMASK(15, 0);
+	rate_hi = (rate >> 16) & GENMASK(13, 0);
+
+	if (faster)
+		rate_hi |= MCHP_RDS_PTP_LTC_RATE_ADJ_HI_DIR;
+
+	mutex_lock(&clock->ptp_lock);
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LTC_RATE_ADJ_HI(BASE_CLK(clock)),
+			   rate_hi);
+	if (rc < 0)
+		goto error;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LTC_RATE_ADJ_LO(BASE_CLK(clock)),
+			   rate_lo);
+	if (rc > 0)
+		rc = 0;
+error:
+	mutex_unlock(&clock->ptp_lock);
+
+	return rc;
+}
+
+static int mchp_rds_ptp_ltc_gettime64(struct ptp_clock_info *info,
+				      struct timespec64 *ts)
+{
+	struct mchp_rds_ptp_clock *clock = container_of(info,
+						      struct mchp_rds_ptp_clock,
+						      caps);
+	struct phy_device *phydev = clock->phydev;
+	time64_t secs;
+	int rc = 0;
+	s64 nsecs;
+
+	mutex_lock(&clock->ptp_lock);
+	/* Set read bit to 1 to save current values of 1588 local time counter
+	 * into PTP LTC seconds and nanoseconds registers.
+	 */
+	rc = phy_set_bits_mmd(phydev, PTP_MMD(clock),
+			      MCHP_RDS_PTP_CMD_CTL(BASE_CLK(clock)),
+			      MCHP_RDS_PTP_CMD_CTL_CLOCK_READ);
+	if (rc < 0)
+		goto out_unlock;
+
+	/* Get LTC clock values */
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_LTC_READ_SEC_HI(BASE_CLK(clock)));
+	if (rc < 0)
+		goto out_unlock;
+	secs = rc << 16;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_LTC_READ_SEC_MID(BASE_CLK(clock)));
+	if (rc < 0)
+		goto out_unlock;
+	secs |= rc;
+	secs <<= 16;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_LTC_READ_SEC_LO(BASE_CLK(clock)));
+	if (rc < 0)
+		goto out_unlock;
+	secs |= rc;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_LTC_READ_NS_HI(BASE_CLK(clock)));
+	if (rc < 0)
+		goto out_unlock;
+	nsecs = (rc & GENMASK(13, 0));
+	nsecs <<= 16;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_LTC_READ_NS_LO(BASE_CLK(clock)));
+	if (rc < 0)
+		goto out_unlock;
+	nsecs |= rc;
+
+	set_normalized_timespec64(ts, secs, nsecs);
+
+	if (rc > 0)
+		rc = 0;
+out_unlock:
+	mutex_unlock(&clock->ptp_lock);
+
+	return rc;
+}
+
+static int mchp_rds_ptp_ltc_settime64(struct ptp_clock_info *info,
+				      const struct timespec64 *ts)
+{
+	struct mchp_rds_ptp_clock *clock = container_of(info,
+						      struct mchp_rds_ptp_clock,
+						      caps);
+	struct phy_device *phydev = clock->phydev;
+	int rc;
+
+	mutex_lock(&clock->ptp_lock);
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LTC_SEC_LO(BASE_CLK(clock)),
+			   lower_16_bits(ts->tv_sec));
+	if (rc < 0)
+		goto out_unlock;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LTC_SEC_MID(BASE_CLK(clock)),
+			   upper_16_bits(ts->tv_sec));
+	if (rc < 0)
+		goto out_unlock;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LTC_SEC_HI(BASE_CLK(clock)),
+			   upper_32_bits(ts->tv_sec) & GENMASK(15, 0));
+	if (rc < 0)
+		goto out_unlock;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LTC_NS_LO(BASE_CLK(clock)),
+			   lower_16_bits(ts->tv_nsec));
+	if (rc < 0)
+		goto out_unlock;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LTC_NS_HI(BASE_CLK(clock)),
+			   upper_16_bits(ts->tv_nsec) & GENMASK(13, 0));
+	if (rc < 0)
+		goto out_unlock;
+
+	/* Set load bit to 1 to write PTP LTC seconds and nanoseconds
+	 * registers to 1588 local time counter.
+	 */
+	rc = phy_set_bits_mmd(phydev, PTP_MMD(clock),
+			      MCHP_RDS_PTP_CMD_CTL(BASE_CLK(clock)),
+			      MCHP_RDS_PTP_CMD_CTL_CLOCK_LOAD);
+	if (rc > 0)
+		rc = 0;
+out_unlock:
+	mutex_unlock(&clock->ptp_lock);
+
+	return rc;
+}
+
+static bool mchp_rds_ptp_get_sig_tx(struct sk_buff *skb, u16 *sig)
+{
+	struct ptp_header *ptp_header;
+	int type;
+
+	type = ptp_classify_raw(skb);
+	if (type == PTP_CLASS_NONE)
+		return false;
+
+	ptp_header = ptp_parse_header(skb, type);
+	if (!ptp_header)
+		return false;
+
+	*sig = (__force u16)(ntohs(ptp_header->sequence_id));
+
+	return true;
+}
+
+static void mchp_rds_ptp_match_tx_skb(struct mchp_rds_ptp_clock *clock,
+				      u32 seconds, u32 nsec, u16 seq_id)
+{
+	struct skb_shared_hwtstamps shhwtstamps;
+	struct sk_buff *skb, *skb_tmp;
+	unsigned long flags;
+	bool rc = false;
+	u16 skb_sig;
+
+	spin_lock_irqsave(&clock->tx_queue.lock, flags);
+	skb_queue_walk_safe(&clock->tx_queue, skb, skb_tmp) {
+		if (!mchp_rds_ptp_get_sig_tx(skb, &skb_sig))
+			continue;
+
+		if (skb_sig != seq_id)
+			continue;
+
+		__skb_unlink(skb, &clock->tx_queue);
+		rc = true;
+		break;
+	}
+	spin_unlock_irqrestore(&clock->tx_queue.lock, flags);
+
+	if (rc) {
+		shhwtstamps.hwtstamp = ktime_set(seconds, nsec);
+		skb_complete_tx_timestamp(skb, &shhwtstamps);
+	}
+}
+
+static struct mchp_rds_ptp_rx_ts
+		       *mchp_rds_ptp_get_rx_ts(struct mchp_rds_ptp_clock *clock)
+{
+	struct phy_device *phydev = clock->phydev;
+	struct mchp_rds_ptp_rx_ts *rx_ts = NULL;
+	u32 sec, nsec;
+	int rc;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_RX_INGRESS_NS_HI(BASE_PORT(clock)));
+	if (rc < 0)
+		goto error;
+	if (!(rc & MCHP_RDS_PTP_RX_INGRESS_NS_HI_TS_VALID)) {
+		phydev_err(phydev, "RX Timestamp is not valid!\n");
+		goto error;
+	}
+	nsec = (rc & GENMASK(13, 0)) << 16;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_RX_INGRESS_NS_LO(BASE_PORT(clock)));
+	if (rc < 0)
+		goto error;
+	nsec |= rc;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_RX_INGRESS_SEC_HI(BASE_PORT(clock)));
+	if (rc < 0)
+		goto error;
+	sec = rc << 16;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_RX_INGRESS_SEC_LO(BASE_PORT(clock)));
+	if (rc < 0)
+		goto error;
+	sec |= rc;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_RX_MSG_HDR2(BASE_PORT(clock)));
+	if (rc < 0)
+		goto error;
+
+	rx_ts = kmalloc(sizeof(*rx_ts), GFP_KERNEL);
+	if (!rx_ts)
+		return NULL;
+
+	rx_ts->seconds = sec;
+	rx_ts->nsec = nsec;
+	rx_ts->seq_id = rc;
+
+error:
+	return rx_ts;
+}
+
+static void mchp_rds_ptp_process_rx_ts(struct mchp_rds_ptp_clock *clock)
+{
+	struct phy_device *phydev = clock->phydev;
+	int caps;
+
+	do {
+		struct mchp_rds_ptp_rx_ts *rx_ts;
+
+		rx_ts = mchp_rds_ptp_get_rx_ts(clock);
+		if (rx_ts)
+			mchp_rds_ptp_match_rx_ts(clock, rx_ts);
+
+		caps = phy_read_mmd(phydev, PTP_MMD(clock),
+				    MCHP_RDS_PTP_CAP_INFO(BASE_PORT(clock)));
+		if (caps < 0)
+			return;
+	} while (MCHP_RDS_PTP_RX_TS_CNT(caps) > 0);
+}
+
+static bool mchp_rds_ptp_get_tx_ts(struct mchp_rds_ptp_clock *clock,
+				   u32 *sec, u32 *nsec, u16 *seq)
+{
+	struct phy_device *phydev = clock->phydev;
+	int rc;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_TX_EGRESS_NS_HI(BASE_PORT(clock)));
+	if (rc < 0)
+		return false;
+	if (!(rc & MCHP_RDS_PTP_TX_EGRESS_NS_HI_TS_VALID))
+		return false;
+	*nsec = (rc & GENMASK(13, 0)) << 16;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_TX_EGRESS_NS_LO(BASE_PORT(clock)));
+	if (rc < 0)
+		return false;
+	*nsec = *nsec | rc;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_TX_EGRESS_SEC_HI(BASE_PORT(clock)));
+	if (rc < 0)
+		return false;
+	*sec = rc << 16;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_TX_EGRESS_SEC_LO(BASE_PORT(clock)));
+	if (rc < 0)
+		return false;
+	*sec = *sec | rc;
+
+	rc = phy_read_mmd(phydev, PTP_MMD(clock),
+			  MCHP_RDS_PTP_TX_MSG_HDR2(BASE_PORT(clock)));
+	if (rc < 0)
+		return false;
+
+	*seq = rc;
+
+	return true;
+}
+
+static void mchp_rds_ptp_process_tx_ts(struct mchp_rds_ptp_clock *clock)
+{
+	struct phy_device *phydev = clock->phydev;
+	int caps;
+
+	do {
+		u32 sec, nsec;
+		u16 seq;
+
+		if (mchp_rds_ptp_get_tx_ts(clock, &sec, &nsec, &seq))
+			mchp_rds_ptp_match_tx_skb(clock, sec, nsec, seq);
+
+		caps = phy_read_mmd(phydev, PTP_MMD(clock),
+				    MCHP_RDS_PTP_CAP_INFO(BASE_PORT(clock)));
+		if (caps < 0)
+			return;
+	} while (MCHP_RDS_PTP_TX_TS_CNT(caps) > 0);
+}
+
+int mchp_rds_ptp_top_config_intr(struct mchp_rds_ptp_clock *clock,
+				 u16 reg, u16 val, bool clear)
+{
+	struct phy_device *phydev = clock->phydev;
+
+	if (clear)
+		return phy_clear_bits_mmd(phydev, PTP_MMD(clock), reg, val);
+	else
+		return phy_set_bits_mmd(phydev, PTP_MMD(clock), reg, val);
+}
+EXPORT_SYMBOL_GPL(mchp_rds_ptp_top_config_intr);
+
+irqreturn_t mchp_rds_ptp_handle_interrupt(struct mchp_rds_ptp_clock *clock)
+{
+	struct phy_device *phydev;
+	int irq_sts;
+
+	/* To handle rogue interrupt scenarios */
+	if (!clock)
+		return IRQ_NONE;
+
+	phydev = clock->phydev;
+	do {
+		irq_sts = phy_read_mmd(phydev, PTP_MMD(clock),
+				       MCHP_RDS_PTP_INT_STS(BASE_PORT(clock)));
+		if (irq_sts < 0)
+			return IRQ_NONE;
+
+		if (irq_sts & MCHP_RDS_PTP_INT_RX_TS_EN)
+			mchp_rds_ptp_process_rx_ts(clock);
+
+		if (irq_sts & MCHP_RDS_PTP_INT_TX_TS_EN)
+			mchp_rds_ptp_process_tx_ts(clock);
+
+		if (irq_sts & MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN)
+			mchp_rds_ptp_flush_fifo(clock,
+						MCHP_RDS_PTP_EGRESS_FIFO);
+
+		if (irq_sts & MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN)
+			mchp_rds_ptp_flush_fifo(clock,
+						MCHP_RDS_PTP_INGRESS_FIFO);
+	} while (irq_sts & (MCHP_RDS_PTP_INT_RX_TS_EN |
+			    MCHP_RDS_PTP_INT_TX_TS_EN |
+			    MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN |
+			    MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN));
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(mchp_rds_ptp_handle_interrupt);
+
+static int mchp_rds_ptp_init(struct mchp_rds_ptp_clock *clock)
+{
+	struct phy_device *phydev = clock->phydev;
+	int rc;
+
+	/* Disable PTP */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_CMD_CTL(BASE_CLK(clock)),
+			   MCHP_RDS_PTP_CMD_CTL_DIS);
+	if (rc < 0)
+		return rc;
+
+	/* Disable TSU */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TSU_GEN_CONFIG(BASE_PORT(clock)), 0);
+	if (rc < 0)
+		return rc;
+
+	/* Clear PTP interrupt status registers */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TSU_HARD_RESET(BASE_PORT(clock)),
+			   MCHP_RDS_PTP_TSU_HARDRESET);
+	if (rc < 0)
+		return rc;
+
+	/* Predictor enable */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_LATENCY_CORRECTION_CTL(BASE_CLK(clock)),
+			   MCHP_RDS_PTP_LATENCY_SETTING);
+	if (rc < 0)
+		return rc;
+
+	/* Configure PTP operational mode */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_OP_MODE(BASE_CLK(clock)),
+			   MCHP_RDS_PTP_OP_MODE_STANDALONE);
+	if (rc < 0)
+		return rc;
+
+	/* Reference clock configuration */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_REF_CLK_CFG(BASE_CLK(clock)),
+			   MCHP_RDS_PTP_REF_CLK_CFG_SET);
+	if (rc < 0)
+		return rc;
+
+	/* Classifier configurations */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_RX_PARSE_CONFIG(BASE_PORT(clock)), 0);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TX_PARSE_CONFIG(BASE_PORT(clock)), 0);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TX_PARSE_L2_ADDR_EN(BASE_PORT(clock)),
+			   0);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_RX_PARSE_L2_ADDR_EN(BASE_PORT(clock)),
+			   0);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_RX_PARSE_IPV4_ADDR_EN(BASE_PORT(clock)),
+			   0);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TX_PARSE_IPV4_ADDR_EN(BASE_PORT(clock)),
+			   0);
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_RX_VERSION(BASE_PORT(clock)),
+			   MCHP_RDS_PTP_MAX_VERSION(0xff) |
+			   MCHP_RDS_PTP_MIN_VERSION(0x0));
+	if (rc < 0)
+		return rc;
+
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TX_VERSION(BASE_PORT(clock)),
+			   MCHP_RDS_PTP_MAX_VERSION(0xff) |
+			   MCHP_RDS_PTP_MIN_VERSION(0x0));
+	if (rc < 0)
+		return rc;
+
+	/* Enable TSU */
+	rc = phy_write_mmd(phydev, PTP_MMD(clock),
+			   MCHP_RDS_PTP_TSU_GEN_CONFIG(BASE_PORT(clock)),
+			   MCHP_RDS_PTP_TSU_GEN_CFG_TSU_EN);
+	if (rc < 0)
+		return rc;
+
+	/* Enable PTP */
+	return phy_write_mmd(phydev, PTP_MMD(clock),
+			     MCHP_RDS_PTP_CMD_CTL(BASE_CLK(clock)),
+			     MCHP_RDS_PTP_CMD_CTL_EN);
+}
+
+struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device *phydev, u8 mmd,
+					      u16 clk_base_addr,
+					      u16 port_base_addr)
+{
+	struct mchp_rds_ptp_clock *clock;
+	int rc;
+
+	clock = devm_kzalloc(&phydev->mdio.dev, sizeof(*clock), GFP_KERNEL);
+	if (!clock)
+		return ERR_PTR(-ENOMEM);
+
+	clock->port_base_addr	= port_base_addr;
+	clock->clk_base_addr	= clk_base_addr;
+	clock->mmd		= mmd;
+
+	mutex_init(&clock->ptp_lock);
+	/* Register PTP clock */
+	clock->caps.owner          = THIS_MODULE;
+	snprintf(clock->caps.name, 30, "%s", phydev->drv->name);
+	clock->caps.max_adj        = MCHP_RDS_PTP_MAX_ADJ;
+	clock->caps.n_ext_ts       = 0;
+	clock->caps.pps            = 0;
+	clock->caps.adjfine        = mchp_rds_ptp_ltc_adjfine;
+	clock->caps.adjtime        = mchp_rds_ptp_ltc_adjtime;
+	clock->caps.gettime64      = mchp_rds_ptp_ltc_gettime64;
+	clock->caps.settime64      = mchp_rds_ptp_ltc_settime64;
+	clock->ptp_clock = ptp_clock_register(&clock->caps,
+					      &phydev->mdio.dev);
+	if (IS_ERR(clock->ptp_clock))
+		return ERR_PTR(-EINVAL);
+
+	/* Initialize the SW */
+	skb_queue_head_init(&clock->tx_queue);
+	skb_queue_head_init(&clock->rx_queue);
+	INIT_LIST_HEAD(&clock->rx_ts_list);
+	spin_lock_init(&clock->rx_ts_lock);
+
+	clock->mii_ts.rxtstamp = mchp_rds_ptp_rxtstamp;
+	clock->mii_ts.txtstamp = mchp_rds_ptp_txtstamp;
+	clock->mii_ts.hwtstamp = mchp_rds_ptp_hwtstamp;
+	clock->mii_ts.ts_info = mchp_rds_ptp_ts_info;
+
+	phydev->mii_ts = &clock->mii_ts;
+
+	/* Timestamp selected by default to keep legacy API */
+	phydev->default_timestamp = true;
+
+	clock->phydev = phydev;
+
+	rc = mchp_rds_ptp_init(clock);
+	if (rc < 0)
+		return ERR_PTR(rc);
+
+	return clock;
+}
+EXPORT_SYMBOL_GPL(mchp_rds_ptp_probe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MICROCHIP PHY RDS PTP driver");
+MODULE_AUTHOR("Divya Koppera");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in Microchip phys
  2024-12-13 12:13 [PATCH net-next v7 0/5] Add rds ptp library for Microchip phys Divya Koppera
  2024-12-13 12:13 ` [PATCH net-next v7 1/5] net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp library Divya Koppera
  2024-12-13 12:14 ` [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys Divya Koppera
@ 2024-12-13 12:14 ` Divya Koppera
  2024-12-17 15:06   ` Andrew Lunn
  2024-12-18  3:14   ` Jakub Kicinski
  2024-12-13 12:14 ` [PATCH net-next v7 4/5] net: phy: Makefile: Add makefile support for rds ptp " Divya Koppera
  2024-12-13 12:14 ` [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x Divya Koppera
  4 siblings, 2 replies; 19+ messages in thread
From: Divya Koppera @ 2024-12-13 12:14 UTC (permalink / raw)
  To: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

Add ptp library support in Kconfig
As some of Microchip T1 phys support ptp, add dependency
of 1588 optional flag in Kconfig

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Divya Koppera <divya.koppera@microchip.com>
---
v6 -> v7
- No changes

v5 -> v6
- Renamed the config name to reflect ptp hardware used.

v4 -> v5
Addressed below review comments.
- Indentation fix
- Changed dependency check to if check for PTP_1588_CLOCK_OPTIONAL

v1 -> v2 -> v3 -> v4
- No changes
---
 drivers/net/phy/Kconfig | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 15828f4710a9..4ff6f5474397 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -287,8 +287,15 @@ config MICROCHIP_PHY
 
 config MICROCHIP_T1_PHY
 	tristate "Microchip T1 PHYs"
+	select MICROCHIP_PHY_RDS_PTP if NETWORK_PHY_TIMESTAMPING && \
+				  PTP_1588_CLOCK_OPTIONAL
 	help
-	  Supports the LAN87XX PHYs.
+	  Supports the LAN8XXX PHYs.
+
+config MICROCHIP_PHY_RDS_PTP
+	tristate "Microchip PHY RDS PTP"
+	help
+	  Currently supports LAN887X T1 PHY
 
 config MICROSEMI_PHY
 	tristate "Microsemi PHYs"
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net-next v7 4/5] net: phy: Makefile: Add makefile support for rds ptp in Microchip phys
  2024-12-13 12:13 [PATCH net-next v7 0/5] Add rds ptp library for Microchip phys Divya Koppera
                   ` (2 preceding siblings ...)
  2024-12-13 12:14 ` [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in " Divya Koppera
@ 2024-12-13 12:14 ` Divya Koppera
  2024-12-17 15:09   ` Andrew Lunn
  2024-12-13 12:14 ` [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x Divya Koppera
  4 siblings, 1 reply; 19+ messages in thread
From: Divya Koppera @ 2024-12-13 12:14 UTC (permalink / raw)
  To: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

Add makefile support for rds ptp library.

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Divya Koppera <divya.koppera@microchip.com>
---
v6 -> v7
- No changes

v5 -> v6
- Renamed config name and object file name to reflect ptp hardware code name.

v1 -> v5
- No changes
---
 drivers/net/phy/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e6145153e837..e32600f3e4f1 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o
 obj-$(CONFIG_MICREL_PHY)	+= micrel.o
 obj-$(CONFIG_MICROCHIP_PHY)	+= microchip.o
 obj-$(CONFIG_MICROCHIP_T1_PHY)	+= microchip_t1.o
+obj-$(CONFIG_MICROCHIP_PHY_RDS_PTP)	+= microchip_rds_ptp.o
 obj-$(CONFIG_MICROCHIP_T1S_PHY) += microchip_t1s.o
 obj-$(CONFIG_MICROSEMI_PHY)	+= mscc/
 obj-$(CONFIG_MOTORCOMM_PHY)	+= motorcomm.o
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x
  2024-12-13 12:13 [PATCH net-next v7 0/5] Add rds ptp library for Microchip phys Divya Koppera
                   ` (3 preceding siblings ...)
  2024-12-13 12:14 ` [PATCH net-next v7 4/5] net: phy: Makefile: Add makefile support for rds ptp " Divya Koppera
@ 2024-12-13 12:14 ` Divya Koppera
  2024-12-17 15:11   ` Andrew Lunn
  2024-12-18  3:13   ` Jakub Kicinski
  4 siblings, 2 replies; 19+ messages in thread
From: Divya Koppera @ 2024-12-13 12:14 UTC (permalink / raw)
  To: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

Add initialization of ptp for lan887x.

Signed-off-by: Divya Koppera <divya.koppera@microchip.com>
---
v6 -> v7
- No changes

v5 -> v6
- Renamed ptp functions and macros.

v2 -> v5
- No changes

v1 -> v2
Fixed below review comment
  Added ptp support only if interrupts are supported as interrupts are mandatory
  for ptp.
---
 drivers/net/phy/microchip_t1.c | 41 +++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index b17bf6708003..73f28463bc35 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -10,11 +10,15 @@
 #include <linux/ethtool.h>
 #include <linux/ethtool_netlink.h>
 #include <linux/bitfield.h>
+#include "microchip_rds_ptp.h"
 
 #define PHY_ID_LAN87XX				0x0007c150
 #define PHY_ID_LAN937X				0x0007c180
 #define PHY_ID_LAN887X				0x0007c1f0
 
+#define MCHP_RDS_PTP_LTC_BASE_ADDR		0xe000
+#define MCHP_RDS_PTP_PORT_BASE_ADDR	    (MCHP_RDS_PTP_LTC_BASE_ADDR + 0x800)
+
 /* External Register Control Register */
 #define LAN87XX_EXT_REG_CTL                     (0x14)
 #define LAN87XX_EXT_REG_CTL_RD_CTL              (0x1000)
@@ -229,6 +233,7 @@
 
 #define LAN887X_INT_STS				0xf000
 #define LAN887X_INT_MSK				0xf001
+#define LAN887X_INT_MSK_P1588_MOD_INT_MSK	BIT(3)
 #define LAN887X_INT_MSK_T1_PHY_INT_MSK		BIT(2)
 #define LAN887X_INT_MSK_LINK_UP_MSK		BIT(1)
 #define LAN887X_INT_MSK_LINK_DOWN_MSK		BIT(0)
@@ -319,6 +324,8 @@ struct lan887x_regwr_map {
 
 struct lan887x_priv {
 	u64 stats[ARRAY_SIZE(lan887x_hw_stats)];
+	struct mchp_rds_ptp_clock *clock;
+	bool init_done;
 };
 
 static int lan937x_dsp_workaround(struct phy_device *phydev, u16 ereg, u8 bank)
@@ -1269,8 +1276,19 @@ static int lan887x_get_features(struct phy_device *phydev)
 
 static int lan887x_phy_init(struct phy_device *phydev)
 {
+	struct lan887x_priv *priv = phydev->priv;
 	int ret;
 
+	if (!priv->init_done && phy_interrupt_is_valid(phydev)) {
+		priv->clock = mchp_rds_ptp_probe(phydev, MDIO_MMD_VEND1,
+						 MCHP_RDS_PTP_LTC_BASE_ADDR,
+						 MCHP_RDS_PTP_PORT_BASE_ADDR);
+		if (IS_ERR(priv->clock))
+			return PTR_ERR(priv->clock);
+
+		priv->init_done = true;
+	}
+
 	/* Clear loopback */
 	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
 				 LAN887X_MIS_CFG_REG2,
@@ -1470,6 +1488,7 @@ static int lan887x_probe(struct phy_device *phydev)
 	if (!priv)
 		return -ENOMEM;
 
+	priv->init_done = false;
 	phydev->priv = priv;
 
 	return lan887x_phy_setup(phydev);
@@ -1518,6 +1537,7 @@ static void lan887x_get_strings(struct phy_device *phydev, u8 *data)
 
 static int lan887x_config_intr(struct phy_device *phydev)
 {
+	struct lan887x_priv *priv = phydev->priv;
 	int rc;
 
 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
@@ -1537,12 +1557,24 @@ static int lan887x_config_intr(struct phy_device *phydev)
 
 		rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
 	}
+	if (rc < 0)
+		return rc;
 
-	return rc < 0 ? rc : 0;
+	if (phy_is_default_hwtstamp(phydev)) {
+		return mchp_rds_ptp_top_config_intr(priv->clock,
+					LAN887X_INT_MSK,
+					LAN887X_INT_MSK_P1588_MOD_INT_MSK,
+					(phydev->interrupts ==
+					 PHY_INTERRUPT_ENABLED));
+	}
+
+	return 0;
 }
 
 static irqreturn_t lan887x_handle_interrupt(struct phy_device *phydev)
 {
+	struct lan887x_priv *priv = phydev->priv;
+	int rc = IRQ_NONE;
 	int irq_status;
 
 	irq_status = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
@@ -1553,10 +1585,13 @@ static irqreturn_t lan887x_handle_interrupt(struct phy_device *phydev)
 
 	if (irq_status & LAN887X_MX_CHIP_TOP_LINK_MSK) {
 		phy_trigger_machine(phydev);
-		return IRQ_HANDLED;
+		rc = IRQ_HANDLED;
 	}
 
-	return IRQ_NONE;
+	if (irq_status & LAN887X_INT_MSK_P1588_MOD_INT_MSK)
+		rc = mchp_rds_ptp_handle_interrupt(priv->clock);
+
+	return rc;
 }
 
 static int lan887x_cd_reset(struct phy_device *phydev,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 1/5] net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp library
  2024-12-13 12:13 ` [PATCH net-next v7 1/5] net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp library Divya Koppera
@ 2024-12-17 15:05   ` Andrew Lunn
  0 siblings, 0 replies; 19+ messages in thread
From: Andrew Lunn @ 2024-12-17 15:05 UTC (permalink / raw)
  To: Divya Koppera
  Cc: arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem, edumazet,
	kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

On Fri, Dec 13, 2024 at 05:43:59PM +0530, Divya Koppera wrote:
> This rds ptp header file will cover ptp macros for future phys in
> Microchip where addresses will be same but base offset and mmd address
> may changes.
> 
> Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
> Signed-off-by: Divya Koppera <divya.koppera@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in Microchip phys
  2024-12-13 12:14 ` [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in " Divya Koppera
@ 2024-12-17 15:06   ` Andrew Lunn
  2024-12-18  3:14   ` Jakub Kicinski
  1 sibling, 0 replies; 19+ messages in thread
From: Andrew Lunn @ 2024-12-17 15:06 UTC (permalink / raw)
  To: Divya Koppera
  Cc: arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem, edumazet,
	kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

On Fri, Dec 13, 2024 at 05:44:01PM +0530, Divya Koppera wrote:
> Add ptp library support in Kconfig
> As some of Microchip T1 phys support ptp, add dependency
> of 1588 optional flag in Kconfig
> 
> Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
> Signed-off-by: Divya Koppera <divya.koppera@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 4/5] net: phy: Makefile: Add makefile support for rds ptp in Microchip phys
  2024-12-13 12:14 ` [PATCH net-next v7 4/5] net: phy: Makefile: Add makefile support for rds ptp " Divya Koppera
@ 2024-12-17 15:09   ` Andrew Lunn
  0 siblings, 0 replies; 19+ messages in thread
From: Andrew Lunn @ 2024-12-17 15:09 UTC (permalink / raw)
  To: Divya Koppera
  Cc: arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem, edumazet,
	kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

> @@ -80,6 +80,7 @@ obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o
>  obj-$(CONFIG_MICREL_PHY)	+= micrel.o
>  obj-$(CONFIG_MICROCHIP_PHY)	+= microchip.o
>  obj-$(CONFIG_MICROCHIP_T1_PHY)	+= microchip_t1.o
> +obj-$(CONFIG_MICROCHIP_PHY_RDS_PTP)	+= microchip_rds_ptp.o
>  obj-$(CONFIG_MICROCHIP_T1S_PHY) += microchip_t1s.o
>  obj-$(CONFIG_MICROSEMI_PHY)	+= mscc/
>  obj-$(CONFIG_MOTORCOMM_PHY)	+= motorcomm.o

If you need to respin, please insert this library in alphabetic
order. But it is O.k. as is if there is no need to respin.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x
  2024-12-13 12:14 ` [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x Divya Koppera
@ 2024-12-17 15:11   ` Andrew Lunn
  2024-12-18  3:13   ` Jakub Kicinski
  1 sibling, 0 replies; 19+ messages in thread
From: Andrew Lunn @ 2024-12-17 15:11 UTC (permalink / raw)
  To: Divya Koppera
  Cc: arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem, edumazet,
	kuba, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

On Fri, Dec 13, 2024 at 05:44:03PM +0530, Divya Koppera wrote:
> Add initialization of ptp for lan887x.
> 
> Signed-off-by: Divya Koppera <divya.koppera@microchip.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x
  2024-12-13 12:14 ` [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x Divya Koppera
  2024-12-17 15:11   ` Andrew Lunn
@ 2024-12-18  3:13   ` Jakub Kicinski
  2024-12-18 12:03     ` Divya.Koppera
  1 sibling, 1 reply; 19+ messages in thread
From: Jakub Kicinski @ 2024-12-18  3:13 UTC (permalink / raw)
  To: Divya Koppera
  Cc: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

On Fri, 13 Dec 2024 17:44:03 +0530 Divya Koppera wrote:
>  static int lan887x_phy_init(struct phy_device *phydev)
>  {
> +	struct lan887x_priv *priv = phydev->priv;
>  	int ret;
>  
> +	if (!priv->init_done && phy_interrupt_is_valid(phydev)) {
> +		priv->clock = mchp_rds_ptp_probe(phydev, MDIO_MMD_VEND1,
> +						 MCHP_RDS_PTP_LTC_BASE_ADDR,
> +						 MCHP_RDS_PTP_PORT_BASE_ADDR);
> +		if (IS_ERR(priv->clock))
> +			return PTR_ERR(priv->clock);
> +
> +		priv->init_done = true;
> +	}

If this only has to happen once, why not call mchp_rds_ptp_probe() from
lan887x_probe() ? If there is some inherent reason the function needs 
to be protected from multiple calls maybe it's better to let
mchp_rds_ptp_probe() handle that case ?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in Microchip phys
  2024-12-13 12:14 ` [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in " Divya Koppera
  2024-12-17 15:06   ` Andrew Lunn
@ 2024-12-18  3:14   ` Jakub Kicinski
  1 sibling, 0 replies; 19+ messages in thread
From: Jakub Kicinski @ 2024-12-18  3:14 UTC (permalink / raw)
  To: Divya Koppera
  Cc: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

On Fri, 13 Dec 2024 17:44:01 +0530 Divya Koppera wrote:
>  config MICROCHIP_T1_PHY
>  	tristate "Microchip T1 PHYs"
> +	select MICROCHIP_PHY_RDS_PTP if NETWORK_PHY_TIMESTAMPING && \
> +				  PTP_1588_CLOCK_OPTIONAL
>  	help
> -	  Supports the LAN87XX PHYs.
> +	  Supports the LAN8XXX PHYs.
> +
> +config MICROCHIP_PHY_RDS_PTP
> +	tristate "Microchip PHY RDS PTP"

Since you're selecting this symbol you can hide it from the user.
Remove the string after tristate.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  2024-12-13 12:14 ` [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys Divya Koppera
@ 2024-12-18  3:22   ` Jakub Kicinski
  2024-12-18  3:47     ` Richard Cochran
  2024-12-18  3:25   ` Jakub Kicinski
  1 sibling, 1 reply; 19+ messages in thread
From: Jakub Kicinski @ 2024-12-18  3:22 UTC (permalink / raw)
  To: Divya Koppera
  Cc: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

On Fri, 13 Dec 2024 17:44:00 +0530 Divya Koppera wrote:
> +
> +static int mchp_rds_ptp_ts_info(struct mii_timestamper *mii_ts,
> +				struct kernel_ethtool_ts_info *info)
> +{
> +	struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
> +						      struct mchp_rds_ptp_clock,
> +						      mii_ts);
> +
> +	info->phc_index =
> +		clock->ptp_clock ? ptp_clock_index(clock->ptp_clock) : -1;

under what condition can the clock be NULL?

> +	if (info->phc_index == -1)
> +		return 0;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  2024-12-13 12:14 ` [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys Divya Koppera
  2024-12-18  3:22   ` Jakub Kicinski
@ 2024-12-18  3:25   ` Jakub Kicinski
  1 sibling, 0 replies; 19+ messages in thread
From: Jakub Kicinski @ 2024-12-18  3:25 UTC (permalink / raw)
  To: Divya Koppera
  Cc: andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

On Fri, 13 Dec 2024 17:44:00 +0530 Divya Koppera wrote:
> +	rc = phy_write_mmd(phydev, PTP_MMD(clock),
> +			   MCHP_RDS_PTP_TX_PARSE_CONFIG(BASE_PORT(clock)),
> +			   txcfg);

You should probably wrap phy_{read,write}_mmd() into small helpers
which do the BASE_PORT() thing, and PTP_MMD() thing.
Just pass the offset (like MCHP_RDS_PTP_TX_PARSE_CONFIG).

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  2024-12-18  3:22   ` Jakub Kicinski
@ 2024-12-18  3:47     ` Richard Cochran
  2024-12-18  3:57       ` Jakub Kicinski
  0 siblings, 1 reply; 19+ messages in thread
From: Richard Cochran @ 2024-12-18  3:47 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Divya Koppera, andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1,
	linux, davem, edumazet, pabeni, netdev, linux-kernel,
	vadim.fedorenko

On Tue, Dec 17, 2024 at 07:22:46PM -0800, Jakub Kicinski wrote:
> On Fri, 13 Dec 2024 17:44:00 +0530 Divya Koppera wrote:
> > +
> > +static int mchp_rds_ptp_ts_info(struct mii_timestamper *mii_ts,
> > +				struct kernel_ethtool_ts_info *info)
> > +{
> > +	struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
> > +						      struct mchp_rds_ptp_clock,
> > +						      mii_ts);
> > +
> > +	info->phc_index =
> > +		clock->ptp_clock ? ptp_clock_index(clock->ptp_clock) : -1;
> 
> under what condition can the clock be NULL?

ptp_clock_register() can return PTR_ERR or null.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  2024-12-18  3:47     ` Richard Cochran
@ 2024-12-18  3:57       ` Jakub Kicinski
  2024-12-18  4:41         ` Richard Cochran
  2024-12-18 10:52         ` Divya.Koppera
  0 siblings, 2 replies; 19+ messages in thread
From: Jakub Kicinski @ 2024-12-18  3:57 UTC (permalink / raw)
  To: Richard Cochran
  Cc: Divya Koppera, andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1,
	linux, davem, edumazet, pabeni, netdev, linux-kernel,
	vadim.fedorenko

On Tue, 17 Dec 2024 19:47:14 -0800 Richard Cochran wrote:
> > > +static int mchp_rds_ptp_ts_info(struct mii_timestamper *mii_ts,
> > > +				struct kernel_ethtool_ts_info *info)
> > > +{
> > > +	struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
> > > +						      struct mchp_rds_ptp_clock,
> > > +						      mii_ts);
> > > +
> > > +	info->phc_index =
> > > +		clock->ptp_clock ? ptp_clock_index(clock->ptp_clock) : -1;  
> > 
> > under what condition can the clock be NULL?  
> 
> ptp_clock_register() can return PTR_ERR or null.

Fair point. Since this is a PTP library module, and an optional one
(patch 1 has empty wrappers for its API) - can we make it depend
on PTP being configured in?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  2024-12-18  3:57       ` Jakub Kicinski
@ 2024-12-18  4:41         ` Richard Cochran
  2024-12-18 10:52         ` Divya.Koppera
  1 sibling, 0 replies; 19+ messages in thread
From: Richard Cochran @ 2024-12-18  4:41 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Divya Koppera, andrew, arun.ramadoss, UNGLinuxDriver, hkallweit1,
	linux, davem, edumazet, pabeni, netdev, linux-kernel,
	vadim.fedorenko

On Tue, Dec 17, 2024 at 07:57:55PM -0800, Jakub Kicinski wrote:

> Fair point. Since this is a PTP library module, and an optional one
> (patch 1 has empty wrappers for its API) - can we make it depend
> on PTP being configured in?

Sounds okay to me.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys
  2024-12-18  3:57       ` Jakub Kicinski
  2024-12-18  4:41         ` Richard Cochran
@ 2024-12-18 10:52         ` Divya.Koppera
  1 sibling, 0 replies; 19+ messages in thread
From: Divya.Koppera @ 2024-12-18 10:52 UTC (permalink / raw)
  To: kuba, richardcochran
  Cc: andrew, Arun.Ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, pabeni, netdev, linux-kernel, vadim.fedorenko

Hi Jakub,

Thanks for the review.

> -----Original Message-----
> From: Jakub Kicinski <kuba@kernel.org>
> Sent: Wednesday, December 18, 2024 9:28 AM
> To: Richard Cochran <richardcochran@gmail.com>
> Cc: Divya Koppera - I30481 <Divya.Koppera@microchip.com>;
> andrew@lunn.ch; Arun Ramadoss - I17769
> <Arun.Ramadoss@microchip.com>; UNGLinuxDriver
> <UNGLinuxDriver@microchip.com>; hkallweit1@gmail.com;
> linux@armlinux.org.uk; davem@davemloft.net; edumazet@google.com;
> pabeni@redhat.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
> vadim.fedorenko@linux.dev
> Subject: Re: [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds
> ptp library for Microchip phys
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> On Tue, 17 Dec 2024 19:47:14 -0800 Richard Cochran wrote:
> > > > +static int mchp_rds_ptp_ts_info(struct mii_timestamper *mii_ts,
> > > > +                         struct kernel_ethtool_ts_info *info) {
> > > > +struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
> > > > +                                               struct mchp_rds_ptp_clock,
> > > > +                                               mii_ts);
> > > > +
> > > > + info->phc_index =
> > > > +         clock->ptp_clock ? ptp_clock_index(clock->ptp_clock) :
> > > > + -1;
> > >
> > > under what condition can the clock be NULL?
> >
> > ptp_clock_register() can return PTR_ERR or null.
> 
> Fair point. Since this is a PTP library module, and an optional one (patch 1 has
> empty wrappers for its API) - can we make it depend on PTP being configured
> in?

Null check is not handled for ptp_clock_register. If that is done there, this is redundant.

Will fix this in next revision.

Thanks,
Divya

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x
  2024-12-18  3:13   ` Jakub Kicinski
@ 2024-12-18 12:03     ` Divya.Koppera
  0 siblings, 0 replies; 19+ messages in thread
From: Divya.Koppera @ 2024-12-18 12:03 UTC (permalink / raw)
  To: kuba
  Cc: andrew, Arun.Ramadoss, UNGLinuxDriver, hkallweit1, linux, davem,
	edumazet, pabeni, netdev, linux-kernel, richardcochran,
	vadim.fedorenko

Hi Jakub,

> -----Original Message-----
> From: Jakub Kicinski <kuba@kernel.org>
> Sent: Wednesday, December 18, 2024 8:44 AM
> To: Divya Koppera - I30481 <Divya.Koppera@microchip.com>
> Cc: andrew@lunn.ch; Arun Ramadoss - I17769
> <Arun.Ramadoss@microchip.com>; UNGLinuxDriver
> <UNGLinuxDriver@microchip.com>; hkallweit1@gmail.com;
> linux@armlinux.org.uk; davem@davemloft.net; edumazet@google.com;
> pabeni@redhat.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
> richardcochran@gmail.com; vadim.fedorenko@linux.dev
> Subject: Re: [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization
> of ptp for lan887x
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> On Fri, 13 Dec 2024 17:44:03 +0530 Divya Koppera wrote:
> >  static int lan887x_phy_init(struct phy_device *phydev)  {
> > +     struct lan887x_priv *priv = phydev->priv;
> >       int ret;
> >
> > +     if (!priv->init_done && phy_interrupt_is_valid(phydev)) {
> > +             priv->clock = mchp_rds_ptp_probe(phydev, MDIO_MMD_VEND1,
> > +                                              MCHP_RDS_PTP_LTC_BASE_ADDR,
> > +                                              MCHP_RDS_PTP_PORT_BASE_ADDR);
> > +             if (IS_ERR(priv->clock))
> > +                     return PTR_ERR(priv->clock);
> > +
> > +             priv->init_done = true;
> > +     }
> 
> If this only has to happen once, why not call mchp_rds_ptp_probe() from
> lan887x_probe() ? If there is some inherent reason the function needs to be
> protected from multiple calls maybe it's better to let
> mchp_rds_ptp_probe() handle that case ?

Valid phy interrupt irq number will be available during phy init procedure. Hence, we are calling ptp probe in phy init as
interrupts are mandatorily enabled for ptp to work.

Thanks,
Divya


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2024-12-18 12:03 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-13 12:13 [PATCH net-next v7 0/5] Add rds ptp library for Microchip phys Divya Koppera
2024-12-13 12:13 ` [PATCH net-next v7 1/5] net: phy: microchip_rds_ptp: Add header file for Microchip rds ptp library Divya Koppera
2024-12-17 15:05   ` Andrew Lunn
2024-12-13 12:14 ` [PATCH net-next v7 2/5] net: phy: microchip_rds_ptp : Add rds ptp library for Microchip phys Divya Koppera
2024-12-18  3:22   ` Jakub Kicinski
2024-12-18  3:47     ` Richard Cochran
2024-12-18  3:57       ` Jakub Kicinski
2024-12-18  4:41         ` Richard Cochran
2024-12-18 10:52         ` Divya.Koppera
2024-12-18  3:25   ` Jakub Kicinski
2024-12-13 12:14 ` [PATCH net-next v7 3/5] net: phy: Kconfig: Add rds ptp library support and 1588 optional flag in " Divya Koppera
2024-12-17 15:06   ` Andrew Lunn
2024-12-18  3:14   ` Jakub Kicinski
2024-12-13 12:14 ` [PATCH net-next v7 4/5] net: phy: Makefile: Add makefile support for rds ptp " Divya Koppera
2024-12-17 15:09   ` Andrew Lunn
2024-12-13 12:14 ` [PATCH net-next v7 5/5] net: phy: microchip_t1 : Add initialization of ptp for lan887x Divya Koppera
2024-12-17 15:11   ` Andrew Lunn
2024-12-18  3:13   ` Jakub Kicinski
2024-12-18 12:03     ` Divya.Koppera

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).