if (lan966x->ptp_irq)
                devm_free_irq(lan966x->dev, lan966x->ptp_irq, lan966x);
+
+       if (lan966x->ptp_ext_irq)
+               devm_free_irq(lan966x->dev, lan966x->ptp_ext_irq, lan966x);
 }
 
 static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
                lan966x->fdma = true;
        }
 
+       if (lan966x->ptp) {
+               lan966x->ptp_ext_irq = platform_get_irq_byname(pdev, "ptp-ext");
+               if (lan966x->ptp_ext_irq > 0) {
+                       err = devm_request_threaded_irq(&pdev->dev,
+                                                       lan966x->ptp_ext_irq, NULL,
+                                                       lan966x_ptp_ext_irq_handler,
+                                                       IRQF_ONESHOT,
+                                                       "ptp-ext irq", lan966x);
+                       if (err)
+                               return dev_err_probe(&pdev->dev, err,
+                                                    "Unable to use ptp-ext irq");
+               }
+       }
+
        /* init switch */
        lan966x_init(lan966x);
        lan966x_stats_init(lan966x);
 
        return IRQ_HANDLED;
 }
 
+irqreturn_t lan966x_ptp_ext_irq_handler(int irq, void *args)
+{
+       struct lan966x *lan966x = args;
+       struct lan966x_phc *phc;
+       unsigned long flags;
+       u64 time = 0;
+       time64_t s;
+       int pin, i;
+       s64 ns;
+
+       if (!(lan_rd(lan966x, PTP_PIN_INTR)))
+               return IRQ_NONE;
+
+       /* Go through all domains and see which pin generated the interrupt */
+       for (i = 0; i < LAN966X_PHC_COUNT; ++i) {
+               struct ptp_clock_event ptp_event = {0};
+
+               phc = &lan966x->phc[i];
+               pin = ptp_find_pin_unlocked(phc->clock, PTP_PF_EXTTS, 0);
+               if (pin == -1)
+                       continue;
+
+               if (!(lan_rd(lan966x, PTP_PIN_INTR) & BIT(pin)))
+                       continue;
+
+               spin_lock_irqsave(&lan966x->ptp_clock_lock, flags);
+
+               /* Enable to get the new interrupt.
+                * By writing 1 it clears the bit
+                */
+               lan_wr(BIT(pin), lan966x, PTP_PIN_INTR);
+
+               /* Get current time */
+               s = lan_rd(lan966x, PTP_TOD_SEC_MSB(pin));
+               s <<= 32;
+               s |= lan_rd(lan966x, PTP_TOD_SEC_LSB(pin));
+               ns = lan_rd(lan966x, PTP_TOD_NSEC(pin));
+               ns &= PTP_TOD_NSEC_TOD_NSEC;
+
+               spin_unlock_irqrestore(&lan966x->ptp_clock_lock, flags);
+
+               if ((ns & 0xFFFFFFF0) == 0x3FFFFFF0) {
+                       s--;
+                       ns &= 0xf;
+                       ns += 999999984;
+               }
+               time = ktime_set(s, ns);
+
+               ptp_event.index = pin;
+               ptp_event.timestamp = time;
+               ptp_event.type = PTP_CLOCK_EXTTS;
+               ptp_clock_event(phc->clock, &ptp_event);
+       }
+
+       return IRQ_HANDLED;
+}
+
 static int lan966x_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
        struct lan966x_phc *phc = container_of(ptp, struct lan966x_phc, info);
        switch (func) {
        case PTP_PF_NONE:
        case PTP_PF_PEROUT:
+       case PTP_PF_EXTTS:
                break;
        default:
                return -1;
                if (ptp == info)
                        continue;
 
-               if (info->pin_config[pin].func == PTP_PF_PEROUT)
+               if (info->pin_config[pin].func == PTP_PF_PEROUT ||
+                   info->pin_config[pin].func == PTP_PF_EXTTS)
                        return -1;
        }
 
        return 0;
 }
 
+static int lan966x_ptp_extts(struct ptp_clock_info *ptp,
+                            struct ptp_clock_request *rq, int on)
+{
+       struct lan966x_phc *phc = container_of(ptp, struct lan966x_phc, info);
+       struct lan966x *lan966x = phc->lan966x;
+       unsigned long flags;
+       int pin;
+       u32 val;
+
+       if (lan966x->ptp_ext_irq <= 0)
+               return -EOPNOTSUPP;
+
+       /* Reject requests with unsupported flags */
+       if (rq->extts.flags & ~(PTP_ENABLE_FEATURE |
+                               PTP_RISING_EDGE |
+                               PTP_STRICT_FLAGS))
+               return -EOPNOTSUPP;
+
+       pin = ptp_find_pin(phc->clock, PTP_PF_EXTTS, rq->extts.index);
+       if (pin == -1 || pin >= LAN966X_PHC_PINS_NUM)
+               return -EINVAL;
+
+       spin_lock_irqsave(&lan966x->ptp_clock_lock, flags);
+       lan_rmw(PTP_PIN_CFG_PIN_ACTION_SET(PTP_PIN_ACTION_SAVE) |
+               PTP_PIN_CFG_PIN_SYNC_SET(on ? 3 : 0) |
+               PTP_PIN_CFG_PIN_DOM_SET(phc->index) |
+               PTP_PIN_CFG_PIN_SELECT_SET(pin),
+               PTP_PIN_CFG_PIN_ACTION |
+               PTP_PIN_CFG_PIN_SYNC |
+               PTP_PIN_CFG_PIN_DOM |
+               PTP_PIN_CFG_PIN_SELECT,
+               lan966x, PTP_PIN_CFG(pin));
+
+       val = lan_rd(lan966x, PTP_PIN_INTR_ENA);
+       if (on)
+               val |= BIT(pin);
+       else
+               val &= ~BIT(pin);
+       lan_wr(val, lan966x, PTP_PIN_INTR_ENA);
+
+       spin_unlock_irqrestore(&lan966x->ptp_clock_lock, flags);
+
+       return 0;
+}
+
 static int lan966x_ptp_enable(struct ptp_clock_info *ptp,
                              struct ptp_clock_request *rq, int on)
 {
        switch (rq->type) {
        case PTP_CLK_REQ_PEROUT:
                return lan966x_ptp_perout(ptp, rq, on);
+       case PTP_CLK_REQ_EXTTS:
+               return lan966x_ptp_extts(ptp, rq, on);
        default:
                return -EOPNOTSUPP;
        }
        .verify         = lan966x_ptp_verify,
        .enable         = lan966x_ptp_enable,
        .n_per_out      = LAN966X_PHC_PINS_NUM,
+       .n_ext_ts       = LAN966X_PHC_PINS_NUM,
        .n_pins         = LAN966X_PHC_PINS_NUM,
 };