The PTP configuration for GMAC3_X differs from the other implementations
in several ways :
 - There's only one external snapshot trigger
 - The snapshot configuration is done through the PTP_TCR register,
   whereas the other dwmac variants have a dedicated ACR (auxiliary
   control reg) for that purpose
 - The layout for the PTP_TCR register also differs, as bits 24/25 are
   used for the snapshot configuration. These bits are reserved on other
   variants.
On GMAC3_X, we also can't discover the number of snapshot triggers
automatically.
The GMAC3_X has one PPS output, however it's configuration isn't
supported yet so report 0 n_per_out for now.
Introduce a dedicated set of ptp_clock_info ops and configuration
parameters to reflect these differences specific to GMAC3_X.
This was tested on dwmac_socfpga.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20241112170658.2388529-5-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
 
 extern const struct ptp_clock_info stmmac_ptp_clock_ops;
+extern const struct ptp_clock_info dwmac1000_ptp_clock_ops;
 
 struct mac_link {
        u32 caps;
 
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
 #define GMAC_EXTHASH_BASE  0x500
 
+/* PTP and timestamping registers */
+
+#define GMAC_PTP_TCR_ATSFC     BIT(24)
+#define GMAC_PTP_TCR_ATSEN0    BIT(25)
+
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
 #endif /* __DWMAC1000_H__ */
 
 #include <linux/io.h>
 #include "stmmac.h"
 #include "stmmac_pcs.h"
+#include "stmmac_ptp.h"
 #include "dwmac1000.h"
 
 static void dwmac1000_core_init(struct mac_device_info *hw,
 
        return 0;
 }
+
+/* DWMAC 1000 ptp_clock_info ops */
+
+int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
+                        struct ptp_clock_request *rq, int on)
+{
+       struct stmmac_priv *priv =
+           container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+       void __iomem *ptpaddr = priv->ptpaddr;
+       int ret = -EOPNOTSUPP;
+       u32 tcr_val;
+
+       switch (rq->type) {
+       case PTP_CLK_REQ_EXTTS:
+               mutex_lock(&priv->aux_ts_lock);
+               tcr_val = readl(ptpaddr + PTP_TCR);
+
+               if (on) {
+                       tcr_val |= GMAC_PTP_TCR_ATSEN0;
+                       tcr_val |= GMAC_PTP_TCR_ATSFC;
+                       priv->plat->flags |= STMMAC_FLAG_EXT_SNAPSHOT_EN;
+               } else {
+                       tcr_val &= ~GMAC_PTP_TCR_ATSEN0;
+                       priv->plat->flags &= ~STMMAC_FLAG_EXT_SNAPSHOT_EN;
+               }
+
+               netdev_dbg(priv->dev, "Auxiliary Snapshot %s.\n",
+                          on ? "enabled" : "disabled");
+               writel(tcr_val, ptpaddr + PTP_TCR);
+
+               /* wait for auxts fifo clear to finish */
+               ret = readl_poll_timeout(ptpaddr + PTP_TCR, tcr_val,
+                                        !(tcr_val & GMAC_PTP_TCR_ATSFC),
+                                        10, 10000);
+
+               mutex_unlock(&priv->aux_ts_lock);
+               break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
 
                .dma = &dwmac100_dma_ops,
                .mac = &dwmac100_ops,
                .hwtimestamp = &stmmac_ptp,
-               .ptp = &stmmac_ptp_clock_ops,
+               .ptp = &dwmac1000_ptp_clock_ops,
                .mode = NULL,
                .tc = NULL,
                .mmc = &dwmac_mmc_ops,
                .dma = &dwmac1000_dma_ops,
                .mac = &dwmac1000_ops,
                .hwtimestamp = &stmmac_ptp,
-               .ptp = &stmmac_ptp_clock_ops,
+               .ptp = &dwmac1000_ptp_clock_ops,
                .mode = NULL,
                .tc = NULL,
                .mmc = &dwmac_mmc_ops,
 
        .getcrosststamp = stmmac_getcrosststamp,
 };
 
+/* structure describing a PTP hardware clock */
+const struct ptp_clock_info dwmac1000_ptp_clock_ops = {
+       .owner = THIS_MODULE,
+       .name = "stmmac ptp",
+       .max_adj = 62500000,
+       .n_alarm = 0,
+       .n_ext_ts = 1,
+       .n_per_out = 0,
+       .n_pins = 0,
+       .pps = 0,
+       .adjfine = stmmac_adjust_freq,
+       .adjtime = stmmac_adjust_time,
+       .gettime64 = stmmac_get_time,
+       .settime64 = stmmac_set_time,
+       .enable = dwmac1000_ptp_enable,
+       .getcrosststamp = stmmac_getcrosststamp,
+};
+
 /**
  * stmmac_ptp_register
  * @priv: driver private structure
 
        AUX_SNAPSHOT3 = 0x80,
 };
 
+struct ptp_clock_info;
+struct ptp_clock_request;
+
+int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
+                        struct ptp_clock_request *rq, int on);
+
 #endif /* __STMMAC_PTP_H__ */