From nobody Mon Feb 9 09:32:39 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 59979339B49 for ; Tue, 27 Jan 2026 09:07:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769504834; cv=none; b=GNz8M7w3qbUt3Kqpb3m2rkD391Lsm841IqcqGFGW/LGs9idtktOq27RWTJcQcC1i5tjRLDEzcnpa8WrRjEyPFEGuQkALiC3zjI1ZUJra+fZ1eSK6gu+qldx+NSuXDcN4T0ZWRmpejgQQ5M4qUDjqet05cH6RxdfhQ6/UWEJAF5c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769504834; c=relaxed/simple; bh=64Arvmq2sRvqqzk2dsreHnPXzxrgRZpUINVBCX1caPU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dtb0DXUtV5FVjQ2LYjRLKTwhypfV67dX2Wn/yKxbl2hdzRkEf48MOW9A1dcwLlNPbZv9p7BA+Js6VnKZJ8CzKljJs+9QGwl1Nta1pu8HPenGnc5wWeB8DN0tc7rJcsRAVuSs/gqyl7wxKSYfsPQritl6XiAINH/zjQhl3lhTJjE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=x7iLdS1c; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="x7iLdS1c" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 74BCD1A2A6D; Tue, 27 Jan 2026 09:07:08 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 498CD606F5; Tue, 27 Jan 2026 09:07:08 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id E3AD0119A8686; Tue, 27 Jan 2026 10:07:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1769504827; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=sTdHB09lzT72JQy4mNi+vIBCm0pWIK7KzixDxNqCtKE=; b=x7iLdS1cZK0YtkexNBOUUJc+a6UM7h9+LdPRU0VlNE8QFnanwPvHEo58H3NOWiHyR2Nusc sXK3iOIJqyelNbtZdDLx/XIETrStIo4hDLAdXpMC1EHWivQm/dIXEqdxYtCpJx/nsutrzX GBz8jGA3XdiRp2d935ueHfLlnKFJl4IMigd1TnwdoXFs5KMgBqRFmmhNoRU+MV5mwCp8wi ZEnvq4+bbj1BajLeBAAh6QilXYrzuaZUKayiS1kE61OCKnTLvCQgZokaBxQZoM7mYyfCmI QihmenqwLU6JNUs/S1/trw5HuLaYD+l+xcFq4Fsb73benBM1czl8AARY00xFkQ== From: "Bastien Curutchet (Schneider Electric)" Date: Tue, 27 Jan 2026 10:06:50 +0100 Subject: [PATCH net-next v4 8/8] net: dsa: microchip: Add two-step PTP support for KSZ8463 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260127-ksz8463-ptp-v4-8-652e021aae86@bootlin.com> References: <20260127-ksz8463-ptp-v4-0-652e021aae86@bootlin.com> In-Reply-To: <20260127-ksz8463-ptp-v4-0-652e021aae86@bootlin.com> To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Simon Horman Cc: Pascal Eberhard , =?utf-8?q?Miqu=C3=A8l_Raynal?= , Thomas Petazzoni , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, "Bastien Curutchet (Schneider Electric)" X-Mailer: b4 0.14.2 X-Last-TLS-Session-Version: TLSv1.3 The KSZ8463 switch supports PTP but it's not supported by driver. Add L2 two-step PTP support for the KSZ8463. IPv4 and IPv6 layers aren't supported. Neither is one-step PTP. The pdelay_req and pdelay_resp timestamps share one interrupt bit status. So introduce last_tx_is_pdelayresp to keep track of the last sent event type. Use it to retrieve the relevant timestamp when the interrupt is caught. Signed-off-by: Bastien Curutchet (Schneider Electric) --- drivers/net/dsa/microchip/ksz8.c | 9 ++---- drivers/net/dsa/microchip/ksz8_reg.h | 1 + drivers/net/dsa/microchip/ksz_common.c | 1 + drivers/net/dsa/microchip/ksz_common.h | 1 + drivers/net/dsa/microchip/ksz_ptp.c | 52 ++++++++++++++++++++++++++---= ---- drivers/net/dsa/microchip/ksz_ptp_reg.h | 4 +++ 6 files changed, 51 insertions(+), 17 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/k= sz8.c index a05527899b8bab6d53509ba38c58101b79e98ee5..f4dfdbd52b9daeab8a0134fb09c= f4c960d9d9409 100644 --- a/drivers/net/dsa/microchip/ksz8.c +++ b/drivers/net/dsa/microchip/ksz8.c @@ -143,9 +143,9 @@ int ksz8_reset_switch(struct ksz_device *dev) KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, false); } else if (ksz_is_ksz8463(dev)) { ksz_cfg(dev, KSZ8463_REG_SW_RESET, - KSZ8463_GLOBAL_SOFTWARE_RESET, true); + KSZ8463_GLOBAL_SOFTWARE_RESET | KSZ8463_PTP_SOFTWARE_RESET, true); ksz_cfg(dev, KSZ8463_REG_SW_RESET, - KSZ8463_GLOBAL_SOFTWARE_RESET, false); + KSZ8463_GLOBAL_SOFTWARE_RESET | KSZ8463_PTP_SOFTWARE_RESET, false); } else { /* reset switch */ ksz_write8(dev, REG_POWER_MANAGEMENT_1, @@ -1763,10 +1763,7 @@ void ksz8_config_cpu_port(struct dsa_switch *ds) COPPER_RECEIVE_ADJUSTMENT, 0); } =20 - /* Turn off PTP function as the switch's proprietary way of - * handling timestamp is not supported in current Linux PTP - * stack implementation. - */ + /* Turn off PTP function as the switch enables it by default */ regmap_update_bits(ksz_regmap_16(dev), KSZ8463_PTP_MSG_CONF1, PTP_ENABLE, 0); diff --git a/drivers/net/dsa/microchip/ksz8_reg.h b/drivers/net/dsa/microch= ip/ksz8_reg.h index 332408567b473c141c3695328a524f257f2cfc70..0558740ae57738fa7e4a8f3f429= 254033c54af12 100644 --- a/drivers/net/dsa/microchip/ksz8_reg.h +++ b/drivers/net/dsa/microchip/ksz8_reg.h @@ -765,6 +765,7 @@ #define KSZ8463_REG_SW_RESET 0x126 =20 #define KSZ8463_GLOBAL_SOFTWARE_RESET BIT(0) +#define KSZ8463_PTP_SOFTWARE_RESET BIT(2) =20 #define KSZ8463_PTP_CLK_CTRL 0x600 =20 diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/micro= chip/ksz_common.c index 5141343d2f40bbd380c0b52f6919b842fb71a8fd..55e3fa4791078cb099e236e6e5a= 29515727ed8ab 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1512,6 +1512,7 @@ const struct ksz_chip_data ksz_switch_chips[] =3D { .supports_mii =3D {false, false, true}, .supports_rmii =3D {false, false, true}, .internal_phy =3D {true, true, false}, + .ptp_capable =3D true, }, =20 [KSZ8563] =3D { diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/micro= chip/ksz_common.h index dfbc3d13daca8d7a8b9d3ffe6a7c1ec9927863f2..1fface82086eed87749d4702b04= 6fcab313663e9 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -150,6 +150,7 @@ struct ksz_port { struct kernel_hwtstamp_config tstamp_config; bool hwts_tx_en; bool hwts_rx_en; + bool last_tx_is_pdelayresp; struct ksz_irq ptpirq; struct ksz_ptp_irq ptpmsg_irq[3]; ktime_t tstamp_msg; diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchi= p/ksz_ptp.c index 7eb033157f226b1169bc184d71569328e9a20a5b..a86d087b4c0d05120ba532a221e= 66bc704d1dfb5 100644 --- a/drivers/net/dsa/microchip/ksz_ptp.c +++ b/drivers/net/dsa/microchip/ksz_ptp.c @@ -308,15 +308,20 @@ int ksz_get_ts_info(struct dsa_switch *ds, int port, = struct kernel_ethtool_ts_in SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; =20 - ts->tx_types =3D BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ONESTEP_P2P); + ts->tx_types =3D BIT(HWTSTAMP_TX_OFF); =20 - if (is_lan937x(dev)) + if (!ksz_is_ksz8463(dev)) + ts->tx_types |=3D BIT(HWTSTAMP_TX_ONESTEP_P2P); + + if (is_lan937x(dev) || ksz_is_ksz8463(dev)) ts->tx_types |=3D BIT(HWTSTAMP_TX_ON); =20 ts->rx_filters =3D BIT(HWTSTAMP_FILTER_NONE) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); + BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT); + if (!ksz_is_ksz8463(dev)) { + ts->rx_filters |=3D BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); + } =20 ts->phc_index =3D ptp_clock_index(ptp_data->clock); =20 @@ -353,6 +358,9 @@ static int ksz_set_hwtstamp_config(struct ksz_device *d= ev, prt->hwts_tx_en =3D false; break; case HWTSTAMP_TX_ONESTEP_P2P: + if (ksz_is_ksz8463(dev)) + return -ERANGE; + prt->ptpmsg_irq[KSZ_SYNC_MSG].ts_en =3D false; prt->ptpmsg_irq[KSZ_XDREQ_MSG].ts_en =3D true; prt->ptpmsg_irq[KSZ_PDRES_MSG].ts_en =3D false; @@ -364,14 +372,19 @@ static int ksz_set_hwtstamp_config(struct ksz_device = *dev, =20 break; case HWTSTAMP_TX_ON: - if (!is_lan937x(dev)) + if (!is_lan937x(dev) && !ksz_is_ksz8463(dev)) return -ERANGE; =20 - prt->ptpmsg_irq[KSZ_SYNC_MSG].ts_en =3D true; - prt->ptpmsg_irq[KSZ_XDREQ_MSG].ts_en =3D true; - prt->ptpmsg_irq[KSZ_PDRES_MSG].ts_en =3D true; - prt->hwts_tx_en =3D true; + if (ksz_is_ksz8463(dev)) { + prt->ptpmsg_irq[KSZ8463_SYNC_MSG].ts_en =3D true; + prt->ptpmsg_irq[KSZ8463_XDREQ_PDRES_MSG].ts_en =3D true; + } else { + prt->ptpmsg_irq[KSZ_SYNC_MSG].ts_en =3D true; + prt->ptpmsg_irq[KSZ_XDREQ_MSG].ts_en =3D true; + prt->ptpmsg_irq[KSZ_PDRES_MSG].ts_en =3D true; + } =20 + prt->hwts_tx_en =3D true; ret =3D ksz_rmw16(dev, regs[PTP_MSG_CONF1], PTP_1STEP, 0); if (ret) return ret; @@ -387,6 +400,8 @@ static int ksz_set_hwtstamp_config(struct ksz_device *d= ev, break; case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + if (ksz_is_ksz8463(dev)) + return -ERANGE; config->rx_filter =3D HWTSTAMP_FILTER_PTP_V2_L4_EVENT; prt->hwts_rx_en =3D true; break; @@ -397,6 +412,8 @@ static int ksz_set_hwtstamp_config(struct ksz_device *d= ev, break; case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: + if (ksz_is_ksz8463(dev)) + return -ERANGE; config->rx_filter =3D HWTSTAMP_FILTER_PTP_V2_EVENT; prt->hwts_rx_en =3D true; break; @@ -518,6 +535,8 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port,= struct sk_buff *skb) if (!hdr) return; =20 + prt->last_tx_is_pdelayresp =3D false; + ptp_msg_type =3D ptp_get_msgtype(hdr, type); =20 switch (ptp_msg_type) { @@ -528,6 +547,7 @@ void ksz_port_txtstamp(struct dsa_switch *ds, int port,= struct sk_buff *skb) case PTP_MSGTYPE_PDELAY_REQ: break; case PTP_MSGTYPE_PDELAY_RESP: + prt->last_tx_is_pdelayresp =3D true; if (prt->tstamp_config.tx_type =3D=3D HWTSTAMP_TX_ONESTEP_P2P) { KSZ_SKB_CB(skb)->ptp_type =3D type; KSZ_SKB_CB(skb)->update_correction =3D true; @@ -972,7 +992,17 @@ void ksz_ptp_clock_unregister(struct dsa_switch *ds) =20 static int ksz_read_ts(struct ksz_port *port, u16 reg, u32 *ts) { - return ksz_read32(port->ksz_dev, reg, ts); + u16 ts_reg =3D reg; + + /** + * On KSZ8463 DREQ and DRESP timestamps share one interrupt line + * so we have to check the nature of the latest event sent to know + * where the timestamp is located + */ + if (ksz_is_ksz8463(port->ksz_dev) && port->last_tx_is_pdelayresp) + ts_reg +=3D KSZ8463_DRESP_TS_OFFSET; + + return ksz_read32(port->ksz_dev, ts_reg, ts); } =20 static irqreturn_t ksz_ptp_msg_thread_fn(int irq, void *dev_id) diff --git a/drivers/net/dsa/microchip/ksz_ptp_reg.h b/drivers/net/dsa/micr= ochip/ksz_ptp_reg.h index e80fb4bd1a0e970ba3570374d3dc82c8e2cc15b4..ac9d0f2b348b0469abbeed0e645= fe8ef441d35fb 100644 --- a/drivers/net/dsa/microchip/ksz_ptp_reg.h +++ b/drivers/net/dsa/microchip/ksz_ptp_reg.h @@ -125,6 +125,10 @@ #define KSZ8463_REG_PORT_SYNC_TS 0x064C #define KSZ8463_REG_PORT_DRESP_TS 0x0650 =20 +#define KSZ8463_DRESP_TS_OFFSET (KSZ8463_REG_PORT_DRESP_TS - KSZ8463_REG_= PORT_DREQ_TS) +#define KSZ8463_SYNC_MSG 0 +#define KSZ8463_XDREQ_PDRES_MSG 1 + #define REG_PTP_PORT_TX_INT_STATUS__2 0x0C14 #define REG_PTP_PORT_TX_INT_ENABLE__2 0x0C16 =20 --=20 2.52.0