.vtu_getnext = mv88e6390_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
        .serdes_power = mv88e6390_serdes_power,
+       .avb_ops = &mv88e6390_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6240_ops = {
        .serdes_power = mv88e6352_serdes_power,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6352_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6290_ops = {
        .serdes_power = mv88e6390_serdes_power,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6390_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6320_ops = {
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6352_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6321_ops = {
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6352_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6341_ops = {
        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6390_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6350_ops = {
        .vtu_getnext = mv88e6352_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
        .avb_ops = &mv88e6352_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6352_ops = {
        .serdes_power = mv88e6352_serdes_power,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6352_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
        .serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
        .serdes_get_strings = mv88e6352_serdes_get_strings,
        .serdes_get_stats = mv88e6352_serdes_get_stats,
        .serdes_power = mv88e6390_serdes_power,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6390_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_ops mv88e6390x_ops = {
        .serdes_power = mv88e6390_serdes_power,
        .gpio_ops = &mv88e6352_gpio_ops,
        .avb_ops = &mv88e6390_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
 };
 
 static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 
 struct mv88e6xxx_irq_ops;
 struct mv88e6xxx_gpio_ops;
 struct mv88e6xxx_avb_ops;
+struct mv88e6xxx_ptp_ops;
 
 struct mv88e6xxx_irq {
        u16 masked;
 
        /* Remote Management Unit operations */
        int (*rmu_disable)(struct mv88e6xxx_chip *chip);
+
+       /* Precision Time Protocol operations */
+       const struct mv88e6xxx_ptp_ops *ptp_ops;
 };
 
 struct mv88e6xxx_irq_ops {
        int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
 };
 
+struct mv88e6xxx_ptp_ops {
+       u64 (*clock_read)(const struct cyclecounter *cc);
+       int (*ptp_enable)(struct ptp_clock_info *ptp,
+                         struct ptp_clock_request *rq, int on);
+       int (*ptp_verify)(struct ptp_clock_info *ptp, unsigned int pin,
+                         enum ptp_pin_function func, unsigned int chan);
+       void (*event_work)(struct work_struct *ugly);
+       int n_ext_ts;
+};
+
 #define STATS_TYPE_PORT                BIT(0)
 #define STATS_TYPE_BANK0       BIT(1)
 #define STATS_TYPE_BANK1       BIT(2)
 
 }
 
 /* TODO: places where this are called should be using pinctrl */
-static int mv88e6xxx_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
+static int mv88e6352_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
                                   int func, int input)
 {
        int err;
        return chip->info->ops->gpio_ops->set_pctl(chip, pin, func);
 }
 
-static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
+static u64 mv88e6352_ptp_clock_read(const struct cyclecounter *cc)
 {
        struct mv88e6xxx_chip *chip = cc_to_chip(cc);
        u16 phc_time[2];
                return ((u32)phc_time[1] << 16) | phc_time[0];
 }
 
-/* mv88e6xxx_config_eventcap - configure TAI event capture
+/* mv88e6352_config_eventcap - configure TAI event capture
  * @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
  * @rising: zero for falling-edge trigger, else rising-edge trigger
  *
  * This will also reset the capture sequence counter.
  */
-static int mv88e6xxx_config_eventcap(struct mv88e6xxx_chip *chip, int event,
+static int mv88e6352_config_eventcap(struct mv88e6xxx_chip *chip, int event,
                                     int rising)
 {
        u16 global_config;
        return err;
 }
 
-static void mv88e6xxx_tai_event_work(struct work_struct *ugly)
+static void mv88e6352_tai_event_work(struct work_struct *ugly)
 {
        struct delayed_work *dw = to_delayed_work(ugly);
        struct mv88e6xxx_chip *chip = dw_tai_event_to_chip(dw);
        return 0;
 }
 
-static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
+static int mv88e6352_ptp_enable_extts(struct mv88e6xxx_chip *chip,
                                      struct ptp_clock_request *rq, int on)
 {
        int rising = (rq->extts.flags & PTP_RISING_EDGE);
        if (on) {
                func = MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ;
 
-               err = mv88e6xxx_set_gpio_func(chip, pin, func, true);
+               err = mv88e6352_set_gpio_func(chip, pin, func, true);
                if (err)
                        goto out;
 
                schedule_delayed_work(&chip->tai_event_work,
                                      TAI_EVENT_WORK_INTERVAL);
 
-               err = mv88e6xxx_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
+               err = mv88e6352_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
        } else {
                func = MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO;
 
-               err = mv88e6xxx_set_gpio_func(chip, pin, func, true);
+               err = mv88e6352_set_gpio_func(chip, pin, func, true);
 
                cancel_delayed_work_sync(&chip->tai_event_work);
        }
        return err;
 }
 
-static int mv88e6xxx_ptp_enable(struct ptp_clock_info *ptp,
+static int mv88e6352_ptp_enable(struct ptp_clock_info *ptp,
                                struct ptp_clock_request *rq, int on)
 {
        struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
 
        switch (rq->type) {
        case PTP_CLK_REQ_EXTTS:
-               return mv88e6xxx_ptp_enable_extts(chip, rq, on);
+               return mv88e6352_ptp_enable_extts(chip, rq, on);
        default:
                return -EOPNOTSUPP;
        }
 }
 
-static int mv88e6xxx_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
+static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
                                enum ptp_pin_function func, unsigned int chan)
 {
        switch (func) {
        return 0;
 }
 
+const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
+       .clock_read = mv88e6352_ptp_clock_read,
+       .ptp_enable = mv88e6352_ptp_enable,
+       .ptp_verify = mv88e6352_ptp_verify,
+       .event_work = mv88e6352_tai_event_work,
+       .n_ext_ts = 1,
+};
+
+static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
+{
+       struct mv88e6xxx_chip *chip = cc_to_chip(cc);
+
+       if (chip->info->ops->ptp_ops->clock_read)
+               return chip->info->ops->ptp_ops->clock_read(cc);
+
+       return 0;
+}
+
 /* With a 125MHz input clock, the 32-bit timestamp counter overflows in ~34.3
  * seconds; this task forces periodic reads so that we don't miss any.
  */
 
 int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
 {
+       const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
        int i;
 
        /* Set up the cycle counter */
                         ktime_to_ns(ktime_get_real()));
 
        INIT_DELAYED_WORK(&chip->overflow_work, mv88e6xxx_ptp_overflow_check);
-       INIT_DELAYED_WORK(&chip->tai_event_work, mv88e6xxx_tai_event_work);
+       if (ptp_ops->event_work)
+               INIT_DELAYED_WORK(&chip->tai_event_work, ptp_ops->event_work);
 
        chip->ptp_clock_info.owner = THIS_MODULE;
        snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
                 dev_name(chip->dev));
        chip->ptp_clock_info.max_adj    = 1000000;
 
-       chip->ptp_clock_info.n_ext_ts   = 1;
+       chip->ptp_clock_info.n_ext_ts   = ptp_ops->n_ext_ts;
        chip->ptp_clock_info.n_per_out  = 0;
        chip->ptp_clock_info.n_pins     = mv88e6xxx_num_gpio(chip);
        chip->ptp_clock_info.pps        = 0;
        chip->ptp_clock_info.adjtime    = mv88e6xxx_ptp_adjtime;
        chip->ptp_clock_info.gettime64  = mv88e6xxx_ptp_gettime;
        chip->ptp_clock_info.settime64  = mv88e6xxx_ptp_settime;
-       chip->ptp_clock_info.enable     = mv88e6xxx_ptp_enable;
-       chip->ptp_clock_info.verify     = mv88e6xxx_ptp_verify;
+       chip->ptp_clock_info.enable     = ptp_ops->ptp_enable;
+       chip->ptp_clock_info.verify     = ptp_ops->ptp_verify;
        chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work;
 
        chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev);
 {
        if (chip->ptp_clock) {
                cancel_delayed_work_sync(&chip->overflow_work);
-               cancel_delayed_work_sync(&chip->tai_event_work);
+               if (chip->info->ops->ptp_ops->event_work)
+                       cancel_delayed_work_sync(&chip->tai_event_work);
 
                ptp_clock_unregister(chip->ptp_clock);
                chip->ptp_clock = NULL;