This adds PTP support for the MV88E6250 family.

Signed-off-by: Hubert Feurstein <h.feurst...@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c |  4 ++
 drivers/net/dsa/mv88e6xxx/chip.h |  4 ++
 drivers/net/dsa/mv88e6xxx/ptp.c  | 73 ++++++++++++++++++++++----------
 3 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c2fb4ea66434..58e298cc90e0 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3514,6 +3514,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
        .reset = mv88e6250_g1_reset,
        .vtu_getnext = mv88e6250_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
+       .avb_ops = &mv88e6352_avb_ops,
+       .ptp_ops = &mv88e6352_ptp_ops,
        .phylink_validate = mv88e6065_phylink_validate,
 };
 
@@ -4333,6 +4335,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .atu_move_port_mask = 0xf,
                .dual_chip = true,
                .tag_protocol = DSA_TAG_PROTO_DSA,
+               .ptp_support = true,
                .ops = &mv88e6250_ops,
        },
 
@@ -4354,6 +4357,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .atu_move_port_mask = 0xf,
                .dual_chip = true,
                .tag_protocol = DSA_TAG_PROTO_DSA,
+               .ptp_support = true,
                .ops = &mv88e6250_ops,
        },
 
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 720cace3db4e..64872251e479 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -273,6 +273,10 @@ struct mv88e6xxx_chip {
        u16 trig_config;
        u16 evcap_config;
        u16 enable_count;
+       u32 ptp_cc_shift;
+       u32 ptp_cc_mult;
+       u32 ptp_cc_mult_num;
+       u32 ptp_cc_mult_dem;
 
        /* Per-port timestamping resources. */
        struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
index 768d256f7c9f..51cdf4712517 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.c
+++ b/drivers/net/dsa/mv88e6xxx/ptp.c
@@ -15,11 +15,38 @@
 #include "hwtstamp.h"
 #include "ptp.h"
 
-/* Raw timestamps are in units of 8-ns clock periods. */
-#define CC_SHIFT       28
-#define CC_MULT                (8 << CC_SHIFT)
-#define CC_MULT_NUM    (1 << 9)
-#define CC_MULT_DEM    15625ULL
+/* The adjfine API clamps ppb between [-32,768,000, 32,768,000], and
+ * therefore scaled_ppm between [-2,147,483,648, 2,147,483,647].
+ * Set the maximum supported ppb to a round value smaller than the maximum.
+ *
+ * Percentually speaking, this is a +/- 0.032x adjustment of the
+ * free-running counter (0.968x to 1.032x).
+ */
+#define MV88E6XXX_MAX_ADJ_PPB  32000000
+
+/* Family MV88E6250:
+ * Raw timestamps are in units of 10-ns clock periods.
+ *
+ * clkadj = scaled_ppm * 10*2^28 / (10^6 * 2^16)
+ * simplifies to
+ * clkadj = scaled_ppm * 2^7 / 5^5
+ */
+#define MV88E6250_CC_SHIFT     28
+#define MV88E6250_CC_MULT      (10 << MV88E6250_CC_SHIFT)
+#define MV88E6250_CC_MULT_NUM  (1 << 7)
+#define MV88E6250_CC_MULT_DEM  3125ULL
+
+/* Other families:
+ * Raw timestamps are in units of 8-ns clock periods.
+ *
+ * clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16)
+ * simplifies to
+ * clkadj = scaled_ppm * 2^9 / 5^6
+ */
+#define MV88E6XXX_CC_SHIFT     28
+#define MV88E6XXX_CC_MULT      (8 << MV88E6XXX_CC_SHIFT)
+#define MV88E6XXX_CC_MULT_NUM  (1 << 9)
+#define MV88E6XXX_CC_MULT_DEM  15625ULL
 
 #define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
 
@@ -179,24 +206,14 @@ static void mv88e6352_tai_event_work(struct work_struct 
*ugly)
 static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
        struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
-       int neg_adj = 0;
-       u32 diff, mult;
-       u64 adj;
+       s64 adj;
 
-       if (scaled_ppm < 0) {
-               neg_adj = 1;
-               scaled_ppm = -scaled_ppm;
-       }
-       mult = CC_MULT;
-       adj = CC_MULT_NUM;
-       adj *= scaled_ppm;
-       diff = div_u64(adj, CC_MULT_DEM);
+       adj = (s64)scaled_ppm * chip->ptp_cc_mult_num;
+       adj = div_s64(adj, chip->ptp_cc_mult_dem);
 
        mv88e6xxx_reg_lock(chip);
-
        timecounter_read(&chip->tstamp_tc);
-       chip->tstamp_cc.mult = neg_adj ? mult - diff : mult + diff;
-
+       chip->tstamp_cc.mult = chip->ptp_cc_mult + adj;
        mv88e6xxx_reg_unlock(chip);
 
        return 0;
@@ -380,12 +397,24 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
        const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
        int i;
 
+       if (chip->info->family == MV88E6XXX_FAMILY_6250) {
+               chip->ptp_cc_shift      = MV88E6250_CC_SHIFT;
+               chip->ptp_cc_mult       = MV88E6250_CC_MULT;
+               chip->ptp_cc_mult_num   = MV88E6250_CC_MULT_NUM;
+               chip->ptp_cc_mult_dem   = MV88E6250_CC_MULT_DEM;
+       } else {
+               chip->ptp_cc_shift      = MV88E6XXX_CC_SHIFT;
+               chip->ptp_cc_mult       = MV88E6XXX_CC_MULT;
+               chip->ptp_cc_mult_num   = MV88E6XXX_CC_MULT_NUM;
+               chip->ptp_cc_mult_dem   = MV88E6XXX_CC_MULT_DEM;
+       }
+
        /* Set up the cycle counter */
        memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
        chip->tstamp_cc.read    = mv88e6xxx_ptp_clock_read;
        chip->tstamp_cc.mask    = CYCLECOUNTER_MASK(32);
-       chip->tstamp_cc.mult    = CC_MULT;
-       chip->tstamp_cc.shift   = CC_SHIFT;
+       chip->tstamp_cc.mult    = chip->ptp_cc_mult;
+       chip->tstamp_cc.shift   = chip->ptp_cc_shift;
 
        timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
                         ktime_to_ns(ktime_get_real()));
@@ -397,7 +426,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
        chip->ptp_clock_info.owner = THIS_MODULE;
        snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
                 "%s", dev_name(chip->dev));
-       chip->ptp_clock_info.max_adj    = 1000000;
 
        chip->ptp_clock_info.n_ext_ts   = ptp_ops->n_ext_ts;
        chip->ptp_clock_info.n_per_out  = 0;
@@ -413,6 +441,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
        }
        chip->ptp_clock_info.pin_config = chip->pin_config;
 
+       chip->ptp_clock_info.max_adj    = MV88E6XXX_MAX_ADJ_PPB;
        chip->ptp_clock_info.adjfine    = mv88e6xxx_ptp_adjfine;
        chip->ptp_clock_info.adjtime    = mv88e6xxx_ptp_adjtime;
        chip->ptp_clock_info.gettime64  = mv88e6xxx_ptp_gettime;
-- 
2.22.0

Reply via email to