net: dsa: mv88e6xxx: Add hwtimestamp support for the 6165
authorAndrew Lunn <andrew@lunn.ch>
Wed, 18 Jul 2018 20:38:25 +0000 (22:38 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 18 Jul 2018 22:05:38 +0000 (15:05 -0700)
The 6165 family supports a more restricted version of hardware time
stamps. Only L2 PTP is supported. All ports have to use the same
EtherType, and transport spec configuration. PTP can only be
enabled/disabled globally, not per port.

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.h
drivers/net/dsa/mv88e6xxx/hwtstamp.c
drivers/net/dsa/mv88e6xxx/hwtstamp.h
drivers/net/dsa/mv88e6xxx/ptp.c
drivers/net/dsa/mv88e6xxx/ptp.h

index 432e7e8..6aa6197 100644 (file)
@@ -274,6 +274,7 @@ struct mv88e6xxx_chip {
        struct ptp_pin_desc     pin_config[MV88E6XXX_MAX_GPIO];
        u16 trig_config;
        u16 evcap_config;
+       u16 enable_count;
 
        /* Per-port timestamping resources. */
        struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
@@ -499,6 +500,8 @@ struct mv88e6xxx_ptp_ops {
        void (*event_work)(struct work_struct *ugly);
        int (*port_enable)(struct mv88e6xxx_chip *chip, int port);
        int (*port_disable)(struct mv88e6xxx_chip *chip, int port);
+       int (*global_enable)(struct mv88e6xxx_chip *chip);
+       int (*global_disable)(struct mv88e6xxx_chip *chip);
        int n_ext_ts;
        int arr0_sts_reg;
        int arr1_sts_reg;
index 0307704..01e60a8 100644 (file)
@@ -51,6 +51,15 @@ static int mv88e6xxx_ptp_write(struct mv88e6xxx_chip *chip, int addr,
        return chip->info->ops->avb_ops->ptp_write(chip, addr, data);
 }
 
+static int mv88e6xxx_ptp_read(struct mv88e6xxx_chip *chip, int addr,
+                             u16 *data)
+{
+       if (!chip->info->ops->avb_ops->ptp_read)
+               return -EOPNOTSUPP;
+
+       return chip->info->ops->avb_ops->ptp_read(chip, addr, data, 1);
+}
+
 /* TX_TSTAMP_TIMEOUT: This limits the time spent polling for a TX
  * timestamp. When working properly, hardware will produce a timestamp
  * within 1ms. Software may enounter delays due to MDIO contention, so
@@ -144,11 +153,17 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
 
        mutex_lock(&chip->reg_lock);
        if (tstamp_enable) {
+               chip->enable_count += 1;
+               if (chip->enable_count == 1 && ptp_ops->global_enable)
+                       ptp_ops->global_enable(chip);
                if (ptp_ops->port_enable)
                        ptp_ops->port_enable(chip, port);
        } else {
                if (ptp_ops->port_disable)
                        ptp_ops->port_disable(chip, port);
+               chip->enable_count -= 1;
+               if (chip->enable_count == 0 && ptp_ops->global_disable)
+                       ptp_ops->global_disable(chip);
        }
        mutex_unlock(&chip->reg_lock);
 
@@ -516,6 +531,33 @@ bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
        return true;
 }
 
+int mv88e6165_global_disable(struct mv88e6xxx_chip *chip)
+{
+       u16 val;
+       int err;
+
+       err = mv88e6xxx_ptp_read(chip, MV88E6165_PTP_CFG, &val);
+       if (err)
+               return err;
+       val |= MV88E6165_PTP_CFG_DISABLE_PTP;
+
+       return mv88e6xxx_ptp_write(chip, MV88E6165_PTP_CFG, val);
+}
+
+int mv88e6165_global_enable(struct mv88e6xxx_chip *chip)
+{
+       u16 val;
+       int err;
+
+       err = mv88e6xxx_ptp_read(chip, MV88E6165_PTP_CFG, &val);
+       if (err)
+               return err;
+
+       val &= ~(MV88E6165_PTP_CFG_DISABLE_PTP | MV88E6165_PTP_CFG_TSPEC_MASK);
+
+       return mv88e6xxx_ptp_write(chip, MV88E6165_PTP_CFG, val);
+}
+
 int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port)
 {
        return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
@@ -546,6 +588,7 @@ static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)
 
 int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
 {
+       const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
        int err;
        int i;
 
@@ -556,6 +599,13 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
                        return err;
        }
 
+       /* Disable PTP globally */
+       if (ptp_ops->global_disable) {
+               err = ptp_ops->global_disable(chip);
+               if (err)
+                       return err;
+       }
+
        /* MV88E6XXX_PTP_MSG_TYPE is a mask of PTP message types to
         * timestamp. This affects all ports that have timestamping enabled,
         * but the timestamp config is per-port; thus we configure all events
index 3e60105..b9a7266 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "chip.h"
 
-/* Global PTP registers */
+/* Global 6352 PTP registers */
 /* Offset 0x00: PTP EtherType */
 #define MV88E6XXX_PTP_ETHERTYPE        0x00
 
 /* Offset 0x02: Timestamp Arrival Capture Pointers */
 #define MV88E6XXX_PTP_TS_ARRIVAL_PTR   0x02
 
+/* Offset 0x05: PTP Global Configuration */
+#define MV88E6165_PTP_CFG                      0x05
+#define MV88E6165_PTP_CFG_TSPEC_MASK           0xf000
+#define MV88E6165_PTP_CFG_DISABLE_TS_OVERWRITE BIT(1)
+#define MV88E6165_PTP_CFG_DISABLE_PTP          BIT(0)
+
 /* Offset 0x07: PTP Global Configuration */
 #define MV88E6341_PTP_CFG                      0x07
 #define MV88E6341_PTP_CFG_UPDATE               0x8000
@@ -46,7 +52,7 @@
 /* Offset 0x08: PTP Interrupt Status */
 #define MV88E6XXX_PTP_IRQ_STATUS       0x08
 
-/* Per-Port PTP Registers */
+/* Per-Port 6352 PTP Registers */
 /* Offset 0x00: PTP Configuration 0 */
 #define MV88E6XXX_PORT_PTP_CFG0                                0x00
 #define MV88E6XXX_PORT_PTP_CFG0_TSPEC_SHIFT            12
@@ -125,6 +131,8 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip);
 void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip);
 int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port);
 int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port);
+int mv88e6165_global_enable(struct mv88e6xxx_chip *chip);
+int mv88e6165_global_disable(struct mv88e6xxx_chip *chip);
 
 #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
 
index bc4efa7..4b336d8 100644 (file)
@@ -339,6 +339,18 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
 
 const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
        .clock_read = mv88e6165_ptp_clock_read,
+       .global_enable = mv88e6165_global_enable,
+       .global_disable = mv88e6165_global_disable,
+       .arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS,
+       .arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS,
+       .dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS,
+       .rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
 };
 
 static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
index 979eecc..747f90b 100644 (file)
@@ -81,6 +81,7 @@
 /* Offset 0x00: Ether Type */
 #define MV88E6XXX_PTP_GC_ETYPE                 0x00
 
+/* 6165 Global Control Registers */
 /* Offset 0x01: Message ID */
 #define MV88E6XXX_PTP_GC_MESSAGE_ID            0x01
 
 #define MV88E6XXX_PTP_GC_TIME_LO               0x09
 #define MV88E6XXX_PTP_GC_TIME_HI               0x0A
 
+/* 6165 Per Port Registers */
+/* Offset 0: Arrival Time 0 Status */
+#define MV88E6165_PORT_PTP_ARR0_STS    0x00
+
+/* Offset 0x01/0x02: PTP Arrival 0 Time */
+#define MV88E6165_PORT_PTP_ARR0_TIME_LO        0x01
+#define MV88E6165_PORT_PTP_ARR0_TIME_HI        0x02
+
+/* Offset 0x03: PTP Arrival 0 Sequence ID */
+#define MV88E6165_PORT_PTP_ARR0_SEQID  0x03
+
+/* Offset 0x04: PTP Arrival 1 Status */
+#define MV88E6165_PORT_PTP_ARR1_STS    0x04
+
+/* Offset 0x05/0x6E: PTP Arrival 1 Time */
+#define MV88E6165_PORT_PTP_ARR1_TIME_LO        0x05
+#define MV88E6165_PORT_PTP_ARR1_TIME_HI        0x06
+
+/* Offset 0x07: PTP Arrival 1 Sequence ID */
+#define MV88E6165_PORT_PTP_ARR1_SEQID  0x07
+
+/* Offset 0x08: PTP Departure Status */
+#define MV88E6165_PORT_PTP_DEP_STS     0x08
+
+/* Offset 0x09/0x0a: PTP Deperture Time */
+#define MV88E6165_PORT_PTP_DEP_TIME_LO 0x09
+#define MV88E6165_PORT_PTP_DEP_TIME_HI 0x0a
+
+/* Offset 0x0b: PTP Departure Sequence ID */
+#define MV88E6165_PORT_PTP_DEP_SEQID   0x0b
+
+/* Offset 0x0d: Port Status */
+#define MV88E6164_PORT_STATUS          0x0d
+
 #ifdef CONFIG_NET_DSA_MV88E6XXX_PTP
 
 long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp);