unsigned int estsel;
        unsigned int fpesel;
        unsigned int tbssel;
+       /* Numbers of Auxiliary Snapshot Inputs */
+       unsigned int aux_snapshot_n;
 };
 
 /* RX Buffer size must be multiple of 4/8/16 bytes */
 
 #include "dwmac-intel.h"
 #include "dwmac4.h"
 #include "stmmac.h"
+#include "stmmac_ptp.h"
 
 #define INTEL_MGBE_ADHOC_ADDR  0x15
 #define INTEL_MGBE_XPCS_ADDR   0x16
        writel(gpio_value, priv->ioaddr + GMAC_GPIO_STATUS);
 }
 
+static void get_arttime(struct mii_bus *mii, int intel_adhoc_addr,
+                       u64 *art_time)
+{
+       u64 ns;
+
+       ns = mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE3);
+       ns <<= GMAC4_ART_TIME_SHIFT;
+       ns |= mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE2);
+       ns <<= GMAC4_ART_TIME_SHIFT;
+       ns |= mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE1);
+       ns <<= GMAC4_ART_TIME_SHIFT;
+       ns |= mdiobus_read(mii, intel_adhoc_addr, PMC_ART_VALUE0);
+
+       *art_time = ns;
+}
+
+static int intel_crosststamp(ktime_t *device,
+                            struct system_counterval_t *system,
+                            void *ctx)
+{
+       struct intel_priv_data *intel_priv;
+
+       struct stmmac_priv *priv = (struct stmmac_priv *)ctx;
+       void __iomem *ptpaddr = priv->ptpaddr;
+       void __iomem *ioaddr = priv->hw->pcsr;
+       unsigned long flags;
+       u64 art_time = 0;
+       u64 ptp_time = 0;
+       u32 num_snapshot;
+       u32 gpio_value;
+       u32 acr_value;
+       int ret;
+       u32 v;
+       int i;
+
+       if (!boot_cpu_has(X86_FEATURE_ART))
+               return -EOPNOTSUPP;
+
+       intel_priv = priv->plat->bsp_priv;
+
+       /* Enable Internal snapshot trigger */
+       acr_value = readl(ptpaddr + PTP_ACR);
+       acr_value &= ~PTP_ACR_MASK;
+       switch (priv->plat->int_snapshot_num) {
+       case AUX_SNAPSHOT0:
+               acr_value |= PTP_ACR_ATSEN0;
+               break;
+       case AUX_SNAPSHOT1:
+               acr_value |= PTP_ACR_ATSEN1;
+               break;
+       case AUX_SNAPSHOT2:
+               acr_value |= PTP_ACR_ATSEN2;
+               break;
+       case AUX_SNAPSHOT3:
+               acr_value |= PTP_ACR_ATSEN3;
+               break;
+       default:
+               return -EINVAL;
+       }
+       writel(acr_value, ptpaddr + PTP_ACR);
+
+       /* Clear FIFO */
+       acr_value = readl(ptpaddr + PTP_ACR);
+       acr_value |= PTP_ACR_ATSFC;
+       writel(acr_value, ptpaddr + PTP_ACR);
+
+       /* Trigger Internal snapshot signal
+        * Create a rising edge by just toggle the GPO1 to low
+        * and back to high.
+        */
+       gpio_value = readl(ioaddr + GMAC_GPIO_STATUS);
+       gpio_value &= ~GMAC_GPO1;
+       writel(gpio_value, ioaddr + GMAC_GPIO_STATUS);
+       gpio_value |= GMAC_GPO1;
+       writel(gpio_value, ioaddr + GMAC_GPIO_STATUS);
+
+       /* Poll for time sync operation done */
+       ret = readl_poll_timeout(priv->ioaddr + GMAC_INT_STATUS, v,
+                                (v & GMAC_INT_TSIE), 100, 10000);
+
+       if (ret == -ETIMEDOUT) {
+               pr_err("%s: Wait for time sync operation timeout\n", __func__);
+               return ret;
+       }
+
+       num_snapshot = (readl(ioaddr + GMAC_TIMESTAMP_STATUS) &
+                       GMAC_TIMESTAMP_ATSNS_MASK) >>
+                       GMAC_TIMESTAMP_ATSNS_SHIFT;
+
+       /* Repeat until the timestamps are from the FIFO last segment */
+       for (i = 0; i < num_snapshot; i++) {
+               spin_lock_irqsave(&priv->ptp_lock, flags);
+               stmmac_get_ptptime(priv, ptpaddr, &ptp_time);
+               *device = ns_to_ktime(ptp_time);
+               spin_unlock_irqrestore(&priv->ptp_lock, flags);
+               get_arttime(priv->mii, intel_priv->mdio_adhoc_addr, &art_time);
+               *system = convert_art_to_tsc(art_time);
+       }
+
+       return 0;
+}
+
 static void common_default_data(struct plat_stmmacenet_data *plat)
 {
        plat->clk_csr = 2;      /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
        plat->mdio_bus_data->phy_mask = 1 << INTEL_MGBE_ADHOC_ADDR;
        plat->mdio_bus_data->phy_mask |= 1 << INTEL_MGBE_XPCS_ADDR;
 
+       plat->int_snapshot_num = AUX_SNAPSHOT1;
+
+       plat->has_crossts = true;
+       plat->crosststamp = intel_crosststamp;
+
        return 0;
 }
 
 
 #define GMAC_L4_ADDR(reg)              (0x904 + (reg) * 0x30)
 #define GMAC_L3_ADDR0(reg)             (0x910 + (reg) * 0x30)
 #define GMAC_L3_ADDR1(reg)             (0x914 + (reg) * 0x30)
+#define GMAC_TIMESTAMP_STATUS          0x00000b20
 
 /* RX Queues Routing */
 #define GMAC_RXQCTRL_AVCPQ_MASK                GENMASK(2, 0)
 #define GMAC_INT_PCS_PHYIS             BIT(3)
 #define GMAC_INT_PMT_EN                        BIT(4)
 #define GMAC_INT_LPI_EN                        BIT(5)
+#define GMAC_INT_TSIE                  BIT(12)
 
 #define        GMAC_PCS_IRQ_DEFAULT    (GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK | \
                                 GMAC_INT_PCS_ANE)
 #define GMAC_HW_RXFIFOSIZE             GENMASK(4, 0)
 
 /* MAC HW features2 bitmap */
+#define GMAC_HW_FEAT_AUXSNAPNUM                GENMASK(30, 28)
 #define GMAC_HW_FEAT_PPSOUTNUM         GENMASK(26, 24)
 #define GMAC_HW_FEAT_TXCHCNT           GENMASK(21, 18)
 #define GMAC_HW_FEAT_RXCHCNT           GENMASK(15, 12)
 #define GMAC_L4DP0_SHIFT               16
 #define GMAC_L4SP0                     GENMASK(15, 0)
 
+/* MAC Timestamp Status */
+#define GMAC_TIMESTAMP_AUXTSTRIG       BIT(2)
+#define GMAC_TIMESTAMP_ATSNS_MASK      GENMASK(29, 25)
+#define GMAC_TIMESTAMP_ATSNS_SHIFT     25
+
 /*  MTL registers */
 #define MTL_OPERATION_MODE             0x00000c00
 #define MTL_FRPE                       BIT(15)
 
 
        /* IEEE 1588-2002 */
        dma_cap->time_stamp = 0;
+       /* Number of Auxiliary Snapshot Inputs */
+       dma_cap->aux_snapshot_n = (hw_cap & GMAC_HW_FEAT_AUXSNAPNUM) >> 28;
 
        /* MAC HW feature3 */
        hw_cap = readl(ioaddr + GMAC_HW_FEATURE3);
 
        int (*adjust_systime) (void __iomem *ioaddr, u32 sec, u32 nsec,
                               int add_sub, int gmac4);
        void (*get_systime) (void __iomem *ioaddr, u64 *systime);
+       void (*get_ptptime)(void __iomem *ioaddr, u64 *ptp_time);
 };
 
 #define stmmac_config_hw_tstamping(__priv, __args...) \
        stmmac_do_callback(__priv, ptp, adjust_systime, __args)
 #define stmmac_get_systime(__priv, __args...) \
        stmmac_do_void_callback(__priv, ptp, get_systime, __args)
+#define stmmac_get_ptptime(__priv, __args...) \
+       stmmac_do_void_callback(__priv, ptp, get_ptptime, __args)
 
 /* Helpers to manage the descriptors for chain and ring modes */
 struct stmmac_mode_ops {
 
                *systime = ns;
 }
 
+static void get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
+{
+       u64 ns;
+
+       ns = readl(ptpaddr + PTP_ATNR);
+       ns += readl(ptpaddr + PTP_ATSR) * NSEC_PER_SEC;
+
+       *ptp_time = ns;
+}
+
 const struct stmmac_hwtimestamp stmmac_ptp = {
        .config_hw_tstamping = config_hw_tstamping,
        .init_systime = init_systime,
        .config_addend = config_addend,
        .adjust_systime = adjust_systime,
        .get_systime = get_systime,
+       .get_ptptime = get_ptptime,
 };
 
 *******************************************************************************/
 #include "stmmac.h"
 #include "stmmac_ptp.h"
+#include "dwmac4.h"
 
 /**
  * stmmac_adjust_freq
        return ret;
 }
 
+/**
+ * stmmac_get_syncdevicetime
+ * @device: current device time
+ * @system: system counter value read synchronously with device time
+ * @ctx: context provided by timekeeping code
+ * Description: Read device and system clock simultaneously and return the
+ * corrected clock values in ns.
+ **/
+static int stmmac_get_syncdevicetime(ktime_t *device,
+                                    struct system_counterval_t *system,
+                                    void *ctx)
+{
+       struct stmmac_priv *priv = (struct stmmac_priv *)ctx;
+
+       if (priv->plat->crosststamp)
+               return priv->plat->crosststamp(device, system, ctx);
+       else
+               return -EOPNOTSUPP;
+}
+
+static int stmmac_getcrosststamp(struct ptp_clock_info *ptp,
+                                struct system_device_crosststamp *xtstamp)
+{
+       struct stmmac_priv *priv =
+               container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+
+       return get_device_system_crosststamp(stmmac_get_syncdevicetime,
+                                            priv, NULL, xtstamp);
+}
+
 /* structure describing a PTP hardware clock */
 static struct ptp_clock_info stmmac_ptp_clock_ops = {
        .owner = THIS_MODULE,
        .gettime64 = stmmac_get_time,
        .settime64 = stmmac_set_time,
        .enable = stmmac_enable,
+       .getcrosststamp = stmmac_getcrosststamp,
 };
 
 /**
 
 #define        PTP_STSUR       0x10    /* System Time – Seconds Update Reg */
 #define        PTP_STNSUR      0x14    /* System Time – Nanoseconds Update Reg */
 #define        PTP_TAR         0x18    /* Timestamp Addend Reg */
+#define        PTP_ACR         0x40    /* Auxiliary Control Reg */
+#define        PTP_ATNR        0x48    /* Auxiliary Timestamp - Nanoseconds Reg */
+#define        PTP_ATSR        0x4c    /* Auxiliary Timestamp - Seconds Reg */
 
 #define        PTP_STNSUR_ADDSUB_SHIFT 31
 #define        PTP_DIGITAL_ROLLOVER_MODE       0x3B9ACA00      /* 10e9-1 ns */
 #define        PTP_SSIR_SSINC_MASK             0xff
 #define        GMAC4_PTP_SSIR_SSINC_SHIFT      16
 
+/* Auxiliary Control defines */
+#define        PTP_ACR_ATSFC           BIT(0)  /* Auxiliary Snapshot FIFO Clear */
+#define        PTP_ACR_ATSEN0          BIT(4)  /* Auxiliary Snapshot 0 Enable */
+#define        PTP_ACR_ATSEN1          BIT(5)  /* Auxiliary Snapshot 1 Enable */
+#define        PTP_ACR_ATSEN2          BIT(6)  /* Auxiliary Snapshot 2 Enable */
+#define        PTP_ACR_ATSEN3          BIT(7)  /* Auxiliary Snapshot 3 Enable */
+#define        PTP_ACR_MASK            GENMASK(7, 4)   /* Aux Snapshot Mask */
+#define        PMC_ART_VALUE0          0x01    /* PMC_ART[15:0] timer value */
+#define        PMC_ART_VALUE1          0x02    /* PMC_ART[31:16] timer value */
+#define        PMC_ART_VALUE2          0x03    /* PMC_ART[47:32] timer value */
+#define        PMC_ART_VALUE3          0x04    /* PMC_ART[63:48] timer value */
+#define        GMAC4_ART_TIME_SHIFT    16      /* ART TIME 16-bits shift */
+
+enum aux_snapshot {
+       AUX_SNAPSHOT0 = 0x10,
+       AUX_SNAPSHOT1 = 0x20,
+       AUX_SNAPSHOT2 = 0x40,
+       AUX_SNAPSHOT3 = 0x80,
+};
+
 #endif /* __STMMAC_PTP_H__ */
 
        void (*exit)(struct platform_device *pdev, void *priv);
        struct mac_device_info *(*setup)(void *priv);
        int (*clks_config)(void *priv, bool enabled);
+       int (*crosststamp)(ktime_t *device, struct system_counterval_t *system,
+                          void *ctx);
        void *bsp_priv;
        struct clk *stmmac_clk;
        struct clk *pclk;
        u8 vlan_fail_q;
        unsigned int eee_usecs_rate;
        struct pci_dev *pdev;
+       bool has_crossts;
+       int int_snapshot_num;
 };
 #endif