net: stmmac: Introduce dwmac1000 timestamping operations
authorMaxime Chevallier <maxime.chevallier@bootlin.com>
Tue, 12 Nov 2024 17:06:53 +0000 (18:06 +0100)
committerJakub Kicinski <kuba@kernel.org>
Thu, 14 Nov 2024 02:52:13 +0000 (18:52 -0800)
In GMAC3_X, the timestamping configuration differs from GMAC4 in the
layout of the registers accessed to grab the number of snapshots in FIFO
as well as the register offset to grab the aux snapshot timestamp.

Introduce dedicated ops to configure timestamping on dwmac100 and
dwmac1000. The latency correction doesn't seem to exist on GMAC3, so its
corresponding operation isn't populated.

Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20241112170658.2388529-6-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/hwif.c
drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h

index 6f68a6b298c9afd10498a19350eaeac8b07a3bf4..1367fa5c9b8ea3a8ed5fa26274147a01b6948563 100644 (file)
@@ -549,6 +549,7 @@ extern const struct stmmac_desc_ops ndesc_ops;
 struct mac_device_info;
 
 extern const struct stmmac_hwtimestamp stmmac_ptp;
+extern const struct stmmac_hwtimestamp dwmac1000_ptp;
 extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
 
 extern const struct ptp_clock_info stmmac_ptp_clock_ops;
index 01eafeb1272fa8fa79ced6df21ab4a1557d44daa..600fea8f712fd65bbb0c60a6f4464be6a5c04c3c 100644 (file)
@@ -331,8 +331,15 @@ enum rtc_control {
 
 /* PTP and timestamping registers */
 
+#define GMAC3_X_ATSNS       GENMASK(19, 16)
+#define GMAC3_X_ATSNS_SHIFT 16
+
 #define GMAC_PTP_TCR_ATSFC     BIT(24)
 #define GMAC_PTP_TCR_ATSEN0    BIT(25)
 
+#define GMAC3_X_TIMESTAMP_STATUS       0x28
+#define GMAC_PTP_ATNR  0x30
+#define GMAC_PTP_ATSR  0x34
+
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
 #endif /* __DWMAC1000_H__ */
index a14509d88fe74d72e1802cdc661ad5a6abd0f01f..73bba4fdc2e4caaf711c8fd27fc5be705757608a 100644 (file)
@@ -553,6 +553,46 @@ int dwmac1000_setup(struct stmmac_priv *priv)
        return 0;
 }
 
+/* DWMAC 1000 HW Timestaming ops */
+
+void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
+{
+       u64 ns;
+
+       ns = readl(ptpaddr + GMAC_PTP_ATNR);
+       ns += readl(ptpaddr + GMAC_PTP_ATSR) * NSEC_PER_SEC;
+
+       *ptp_time = ns;
+}
+
+void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv)
+{
+       struct ptp_clock_event event;
+       u32 ts_status, num_snapshot;
+       unsigned long flags;
+       u64 ptp_time;
+       int i;
+
+       /* Clears the timestamp interrupt */
+       ts_status = readl(priv->ptpaddr + GMAC3_X_TIMESTAMP_STATUS);
+
+       if (!(priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN))
+               return;
+
+       num_snapshot = (ts_status & GMAC3_X_ATSNS) >> GMAC3_X_ATSNS_SHIFT;
+
+       for (i = 0; i < num_snapshot; i++) {
+               read_lock_irqsave(&priv->ptp_lock, flags);
+               stmmac_get_ptptime(priv, priv->ptpaddr, &ptp_time);
+               read_unlock_irqrestore(&priv->ptp_lock, flags);
+
+               event.type = PTP_CLOCK_EXTTS;
+               event.index = 0;
+               event.timestamp = ptp_time;
+               ptp_clock_event(priv->ptp_clock, &event);
+       }
+}
+
 /* DWMAC 1000 ptp_clock_info ops */
 
 int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
index 1f508843fb5a120e3f6e82d2645a939c108a34d1..a72d336a835080b337faff42f94bba20eff66cee 100644 (file)
@@ -134,7 +134,7 @@ static const struct stmmac_hwif_entry {
                .desc = NULL,
                .dma = &dwmac100_dma_ops,
                .mac = &dwmac100_ops,
-               .hwtimestamp = &stmmac_ptp,
+               .hwtimestamp = &dwmac1000_ptp,
                .ptp = &dwmac1000_ptp_clock_ops,
                .mode = NULL,
                .tc = NULL,
@@ -153,7 +153,7 @@ static const struct stmmac_hwif_entry {
                .desc = NULL,
                .dma = &dwmac1000_dma_ops,
                .mac = &dwmac1000_ops,
-               .hwtimestamp = &stmmac_ptp,
+               .hwtimestamp = &dwmac1000_ptp,
                .ptp = &dwmac1000_ptp_clock_ops,
                .mode = NULL,
                .tc = NULL,
index 5ef52ef2698fbe934dfad2917d95fa5c8ecc61a5..a94829ef8cfb4442be1576965ed69624f12cb8f1 100644 (file)
@@ -269,3 +269,14 @@ const struct stmmac_hwtimestamp stmmac_ptp = {
        .timestamp_interrupt = timestamp_interrupt,
        .hwtstamp_correct_latency = hwtstamp_correct_latency,
 };
+
+const struct stmmac_hwtimestamp dwmac1000_ptp = {
+       .config_hw_tstamping = config_hw_tstamping,
+       .init_systime = init_systime,
+       .config_sub_second_increment = config_sub_second_increment,
+       .config_addend = config_addend,
+       .adjust_systime = adjust_systime,
+       .get_systime = get_systime,
+       .get_ptptime = dwmac1000_get_ptptime,
+       .timestamp_interrupt = dwmac1000_timestamp_interrupt,
+};
index fa46118553110cc4e3834349caf79800055b6d35..4cc70480ce0f0d0485fa1dc2053d0b35d1348f8d 100644 (file)
@@ -96,8 +96,12 @@ enum aux_snapshot {
 
 struct ptp_clock_info;
 struct ptp_clock_request;
+struct stmmac_priv;
 
 int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
                         struct ptp_clock_request *rq, int on);
 
+void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time);
+void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv);
+
 #endif /* __STMMAC_PTP_H__ */