OSDN Git Service

net: dsa: mv88e6xxx: Abstract PTP operations
authorAndrew Lunn <andrew@lunn.ch>
Wed, 18 Jul 2018 20:38:20 +0000 (22:38 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 18 Jul 2018 22:05:38 +0000 (15:05 -0700)
The mv88e6165 family supports PTP, but its registers use a different
layout to the currently supported devices. Abstract accessing the PTP
registers into a set of ops, so making space for a second
implementation.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/ptp.c
drivers/net/dsa/mv88e6xxx/ptp.h

index 437cd6e..94939a2 100644 (file)
@@ -3134,6 +3134,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
        .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 = {
@@ -3176,6 +3178,7 @@ 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 = {
@@ -3215,6 +3218,7 @@ 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 = {
@@ -3253,6 +3257,7 @@ 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 = {
@@ -3289,6 +3294,7 @@ 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 = {
@@ -3329,6 +3335,7 @@ 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 = {
@@ -3402,6 +3409,7 @@ static const struct mv88e6xxx_ops mv88e6351_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 = {
@@ -3444,6 +3452,7 @@ 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,
@@ -3488,6 +3497,7 @@ static const struct mv88e6xxx_ops mv88e6390_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 mv88e6390x_ops = {
@@ -3529,6 +3539,7 @@ 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[] = {
index 8ac3fbb..e12a489 100644 (file)
@@ -155,6 +155,7 @@ struct mv88e6xxx_bus_ops;
 struct mv88e6xxx_irq_ops;
 struct mv88e6xxx_gpio_ops;
 struct mv88e6xxx_avb_ops;
+struct mv88e6xxx_ptp_ops;
 
 struct mv88e6xxx_irq {
        u16 masked;
@@ -439,6 +440,9 @@ struct mv88e6xxx_ops {
 
        /* 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 {
@@ -486,6 +490,16 @@ struct mv88e6xxx_avb_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)
index bd85e2c..aaa8f1b 100644 (file)
@@ -50,7 +50,7 @@ static int mv88e6xxx_tai_write(struct mv88e6xxx_chip *chip, int addr, u16 data)
 }
 
 /* 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;
@@ -65,7 +65,7 @@ static int mv88e6xxx_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
        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];
@@ -79,13 +79,13 @@ static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
                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;
@@ -118,7 +118,7 @@ static int mv88e6xxx_config_eventcap(struct mv88e6xxx_chip *chip, int event,
        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);
@@ -232,7 +232,7 @@ static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
        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);
@@ -250,18 +250,18 @@ static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
        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);
        }
@@ -272,20 +272,20 @@ out:
        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) {
@@ -299,6 +299,24 @@ static int mv88e6xxx_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
        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.
  */
@@ -317,6 +335,7 @@ static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
 
 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 */
@@ -330,14 +349,15 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
                         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;
@@ -355,8 +375,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
        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);
@@ -373,7 +393,8 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
 {
        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;
index 10f271a..16a3106 100644 (file)
@@ -87,6 +87,8 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
 #define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip,      \
                                      ptp_clock_info)
 
+extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops;
+
 #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
 
 static inline long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)
@@ -103,6 +105,8 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
 {
 }
 
+static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {};
+
 #endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */
 
 #endif /* _MV88E6XXX_PTP_H */