net: lan743x: Add support for PTP-IO Event Input External Timestamp (extts)
authorRaju Lakkaraju <Raju.Lakkaraju@microchip.com>
Thu, 17 Mar 2022 10:43:09 +0000 (16:13 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Mar 2022 12:53:23 +0000 (12:53 +0000)
PTP-IOs block provides for time stamping PTP-IO input events.
PTP-IOs are numbered from 0 to 11.
When a PTP-IO is enabled by the corresponding bit in the PTP-IO
Capture Configuration Register, a rising or falling edge,
respectively, will capture the 1588 Local Time Counter

Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/microchip/lan743x_main.h
drivers/net/ethernet/microchip/lan743x_ptp.c
drivers/net/ethernet/microchip/lan743x_ptp.h

index d1036a323c522f12ac781f1997d411206c8e6134..9c528705866f46f8fb8e51dd0a8d88f49c0257f2 100644 (file)
 #define PTP_GENERAL_CONFIG_RELOAD_ADD_X_(channel)      (BIT((channel) << 2))
 
 #define PTP_INT_STS                            (0x0A08)
+#define PTP_INT_IO_FE_MASK_                    GENMASK(31, 24)
+#define PTP_INT_IO_FE_SHIFT_                   (24)
+#define PTP_INT_IO_FE_SET_(channel)            BIT(24 + (channel))
+#define PTP_INT_IO_RE_MASK_                    GENMASK(23, 16)
+#define PTP_INT_IO_RE_SHIFT_                   (16)
+#define PTP_INT_IO_RE_SET_(channel)            BIT(16 + (channel))
 #define PTP_INT_EN_SET                         (0x0A0C)
+#define PTP_INT_EN_FE_EN_SET_(channel)         BIT(24 + (channel))
+#define PTP_INT_EN_RE_EN_SET_(channel)         BIT(16 + (channel))
 #define PTP_INT_EN_CLR                         (0x0A10)
+#define PTP_INT_EN_FE_EN_CLR_(channel)         BIT(24 + (channel))
+#define PTP_INT_EN_RE_EN_CLR_(channel)         BIT(16 + (channel))
 #define PTP_INT_BIT_TX_SWTS_ERR_               BIT(13)
 #define PTP_INT_BIT_TX_TS_                     BIT(12)
 #define PTP_INT_BIT_TIMER_B_                   BIT(1)
 #define PTP_CLOCK_TARGET_NS_X(channel)         (0x0A34 + ((channel) << 4))
 #define PTP_CLOCK_TARGET_RELOAD_SEC_X(channel) (0x0A38 + ((channel) << 4))
 #define PTP_CLOCK_TARGET_RELOAD_NS_X(channel)  (0x0A3C + ((channel) << 4))
+#define PTP_LTC_SET_SEC_HI                     (0x0A50)
+#define PTP_LTC_SET_SEC_HI_SEC_47_32_MASK_     GENMASK(15, 0)
+#define PTP_VERSION                            (0x0A54)
+#define PTP_VERSION_TX_UP_MASK_                        GENMASK(31, 24)
+#define PTP_VERSION_TX_LO_MASK_                        GENMASK(23, 16)
+#define PTP_VERSION_RX_UP_MASK_                        GENMASK(15, 8)
+#define PTP_VERSION_RX_LO_MASK_                        GENMASK(7, 0)
+#define PTP_IO_SEL                             (0x0A58)
+#define PTP_IO_SEL_MASK_                       GENMASK(10, 8)
+#define PTP_IO_SEL_SHIFT_                      (8)
 #define PTP_LATENCY                            (0x0A5C)
 #define PTP_LATENCY_TX_SET_(tx_latency)                (((u32)(tx_latency)) << 16)
 #define PTP_LATENCY_RX_SET_(rx_latency)                \
 #define PTP_TX_MSG_HEADER_MSG_TYPE_            (0x000F0000)
 #define PTP_TX_MSG_HEADER_MSG_TYPE_SYNC_       (0x00000000)
 
+#define PTP_TX_CAP_INFO                                (0x0AB8)
+#define PTP_TX_CAP_INFO_TX_CH_MASK_            GENMASK(1, 0)
+#define PTP_TX_DOMAIN                          (0x0ABC)
+#define PTP_TX_DOMAIN_MASK_                    GENMASK(23, 16)
+#define PTP_TX_DOMAIN_RANGE_EN_                        BIT(15)
+#define PTP_TX_DOMAIN_RANGE_MASK_              GENMASK(7, 0)
+#define PTP_TX_SDOID                           (0x0AC0)
+#define PTP_TX_SDOID_MASK_                     GENMASK(23, 16)
+#define PTP_TX_SDOID_RANGE_EN_                 BIT(15)
+#define PTP_TX_SDOID_11_0_MASK_                        GENMASK(7, 0)
+#define PTP_IO_CAP_CONFIG                      (0x0AC4)
+#define PTP_IO_CAP_CONFIG_LOCK_FE_(channel)    BIT(24 + (channel))
+#define PTP_IO_CAP_CONFIG_LOCK_RE_(channel)    BIT(16 + (channel))
+#define PTP_IO_CAP_CONFIG_FE_CAP_EN_(channel)  BIT(8 + (channel))
+#define PTP_IO_CAP_CONFIG_RE_CAP_EN_(channel)  BIT(0 + (channel))
+#define PTP_IO_RE_LTC_SEC_CAP_X                        (0x0AC8)
+#define PTP_IO_RE_LTC_NS_CAP_X                 (0x0ACC)
+#define PTP_IO_FE_LTC_SEC_CAP_X                        (0x0AD0)
+#define PTP_IO_FE_LTC_NS_CAP_X                 (0x0AD4)
+#define PTP_IO_EVENT_OUTPUT_CFG                        (0x0AD8)
+#define PTP_IO_EVENT_OUTPUT_CFG_SEL_(channel)  BIT(16 + (channel))
+#define PTP_IO_EVENT_OUTPUT_CFG_EN_(channel)   BIT(0 + (channel))
+#define PTP_IO_PIN_CFG                         (0x0ADC)
+#define PTP_IO_PIN_CFG_OBUF_TYPE_(channel)     BIT(0 + (channel))
+#define PTP_LTC_RD_SEC_HI                      (0x0AF0)
+#define PTP_LTC_RD_SEC_HI_SEC_47_32_MASK_      GENMASK(15, 0)
+#define PTP_LTC_RD_SEC_LO                      (0x0AF4)
+#define PTP_LTC_RD_NS                          (0x0AF8)
+#define PTP_LTC_RD_NS_29_0_MASK_               GENMASK(29, 0)
+#define PTP_LTC_RD_SUBNS                       (0x0AFC)
+#define PTP_RX_USER_MAC_HI                     (0x0B00)
+#define PTP_RX_USER_MAC_HI_47_32_MASK_         GENMASK(15, 0)
+#define PTP_RX_USER_MAC_LO                     (0x0B04)
+#define PTP_RX_USER_IP_ADDR_0                  (0x0B20)
+#define PTP_RX_USER_IP_ADDR_1                  (0x0B24)
+#define PTP_RX_USER_IP_ADDR_2                  (0x0B28)
+#define PTP_RX_USER_IP_ADDR_3                  (0x0B2C)
+#define PTP_RX_USER_IP_MASK_0                  (0x0B30)
+#define PTP_RX_USER_IP_MASK_1                  (0x0B34)
+#define PTP_RX_USER_IP_MASK_2                  (0x0B38)
+#define PTP_RX_USER_IP_MASK_3                  (0x0B3C)
+#define PTP_TX_USER_MAC_HI                     (0x0B40)
+#define PTP_TX_USER_MAC_HI_47_32_MASK_         GENMASK(15, 0)
+#define PTP_TX_USER_MAC_LO                     (0x0B44)
+#define PTP_TX_USER_IP_ADDR_0                  (0x0B60)
+#define PTP_TX_USER_IP_ADDR_1                  (0x0B64)
+#define PTP_TX_USER_IP_ADDR_2                  (0x0B68)
+#define PTP_TX_USER_IP_ADDR_3                  (0x0B6C)
+#define PTP_TX_USER_IP_MASK_0                  (0x0B70)
+#define PTP_TX_USER_IP_MASK_1                  (0x0B74)
+#define PTP_TX_USER_IP_MASK_2                  (0x0B78)
+#define PTP_TX_USER_IP_MASK_3                  (0x0B7C)
+
 #define DMAC_CFG                               (0xC00)
 #define DMAC_CFG_COAL_EN_                      BIT(16)
 #define DMAC_CFG_CH_ARB_SEL_RX_HIGH_           (0x00000000)
index ec082594bbbd97cea565db90439bc324e8c03633..470d9050df0c165649e07d3b89752a878d1bc901 100644 (file)
@@ -25,6 +25,18 @@ static void lan743x_ptp_clock_set(struct lan743x_adapter *adapter,
                                  u32 seconds, u32 nano_seconds,
                                  u32 sub_nano_seconds);
 
+static int lan743x_get_channel(u32 ch_map)
+{
+       int idx;
+
+       for (idx = 0; idx < 32; idx++) {
+               if (ch_map & (0x1 << idx))
+                       return idx;
+       }
+
+       return -EINVAL;
+}
+
 int lan743x_gpio_init(struct lan743x_adapter *adapter)
 {
        struct lan743x_gpio *gpio = &adapter->gpio;
@@ -179,6 +191,8 @@ static void lan743x_ptp_release_event_ch(struct lan743x_adapter *adapter,
 static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
                                  u32 *seconds, u32 *nano_seconds,
                                  u32 *sub_nano_seconds);
+static void lan743x_ptp_io_clock_get(struct lan743x_adapter *adapter,
+                                    u32 *sec, u32 *nsec, u32 *sub_nsec);
 static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
                                   s64 time_step_ns);
 
@@ -407,7 +421,11 @@ static int lan743x_ptpci_gettime64(struct ptp_clock_info *ptpci,
        u32 nano_seconds = 0;
        u32 seconds = 0;
 
-       lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
+       if (adapter->is_pci11x1x)
+               lan743x_ptp_io_clock_get(adapter, &seconds, &nano_seconds,
+                                        NULL);
+       else
+               lan743x_ptp_clock_get(adapter, &seconds, &nano_seconds, NULL);
        ts->tv_sec = seconds;
        ts->tv_nsec = nano_seconds;
 
@@ -671,6 +689,113 @@ failed:
        return ret;
 }
 
+static void lan743x_ptp_io_extts_off(struct lan743x_adapter *adapter,
+                                    u32 index)
+{
+       struct lan743x_ptp *ptp = &adapter->ptp;
+       struct lan743x_extts *extts;
+       int val;
+
+       extts = &ptp->extts[index];
+       /* PTP Interrupt Enable Clear Register */
+       if (extts->flags & PTP_FALLING_EDGE)
+               val = PTP_INT_EN_FE_EN_CLR_(index);
+       else
+               val = PTP_INT_EN_RE_EN_CLR_(index);
+       lan743x_csr_write(adapter, PTP_INT_EN_CLR, val);
+
+       /* Disables PTP-IO edge lock */
+       val = lan743x_csr_read(adapter, PTP_IO_CAP_CONFIG);
+       if (extts->flags & PTP_FALLING_EDGE) {
+               val &= ~PTP_IO_CAP_CONFIG_LOCK_FE_(index);
+               val &= ~PTP_IO_CAP_CONFIG_FE_CAP_EN_(index);
+       } else {
+               val &= ~PTP_IO_CAP_CONFIG_LOCK_RE_(index);
+               val &= ~PTP_IO_CAP_CONFIG_RE_CAP_EN_(index);
+       }
+       lan743x_csr_write(adapter, PTP_IO_CAP_CONFIG, val);
+
+       /* PTP-IO De-select register */
+       val = lan743x_csr_read(adapter, PTP_IO_SEL);
+       val &= ~PTP_IO_SEL_MASK_;
+       lan743x_csr_write(adapter, PTP_IO_SEL, val);
+
+       /* Clear timestamp */
+       memset(&extts->ts, 0, sizeof(struct timespec64));
+       extts->flags = 0;
+}
+
+static int lan743x_ptp_io_event_cap_en(struct lan743x_adapter *adapter,
+                                      u32 flags, u32 channel)
+{
+       struct lan743x_ptp *ptp = &adapter->ptp;
+       int val;
+
+       if ((flags & PTP_EXTTS_EDGES) ==  PTP_EXTTS_EDGES)
+               return -EOPNOTSUPP;
+
+       mutex_lock(&ptp->command_lock);
+       /* PTP-IO Event Capture Enable */
+       val = lan743x_csr_read(adapter, PTP_IO_CAP_CONFIG);
+       if (flags & PTP_FALLING_EDGE) {
+               val &= ~PTP_IO_CAP_CONFIG_LOCK_RE_(channel);
+               val &= ~PTP_IO_CAP_CONFIG_RE_CAP_EN_(channel);
+               val |= PTP_IO_CAP_CONFIG_LOCK_FE_(channel);
+               val |= PTP_IO_CAP_CONFIG_FE_CAP_EN_(channel);
+       } else {
+               /* Rising eventing as Default */
+               val &= ~PTP_IO_CAP_CONFIG_LOCK_FE_(channel);
+               val &= ~PTP_IO_CAP_CONFIG_FE_CAP_EN_(channel);
+               val |= PTP_IO_CAP_CONFIG_LOCK_RE_(channel);
+               val |= PTP_IO_CAP_CONFIG_RE_CAP_EN_(channel);
+       }
+       lan743x_csr_write(adapter, PTP_IO_CAP_CONFIG, val);
+
+       /* PTP-IO Select */
+       val = lan743x_csr_read(adapter, PTP_IO_SEL);
+       val &= ~PTP_IO_SEL_MASK_;
+       val |= channel << PTP_IO_SEL_SHIFT_;
+       lan743x_csr_write(adapter, PTP_IO_SEL, val);
+
+       /* PTP Interrupt Enable Register */
+       if (flags & PTP_FALLING_EDGE)
+               val = PTP_INT_EN_FE_EN_SET_(channel);
+       else
+               val = PTP_INT_EN_RE_EN_SET_(channel);
+       lan743x_csr_write(adapter, PTP_INT_EN_SET, val);
+
+       mutex_unlock(&ptp->command_lock);
+
+       return 0;
+}
+
+static int lan743x_ptp_io_extts(struct lan743x_adapter *adapter, int on,
+                               struct ptp_extts_request *extts_request)
+{
+       struct lan743x_ptp *ptp = &adapter->ptp;
+       u32 flags = extts_request->flags;
+       u32 index = extts_request->index;
+       struct lan743x_extts *extts;
+       int extts_pin;
+       int ret = 0;
+
+       extts = &ptp->extts[index];
+
+       if (on) {
+               extts_pin = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS, index);
+               if (extts_pin < 0)
+                       return -EBUSY;
+
+               ret = lan743x_ptp_io_event_cap_en(adapter, flags, index);
+               if (!ret)
+                       extts->flags = flags;
+       } else {
+               lan743x_ptp_io_extts_off(adapter, index);
+       }
+
+       return ret;
+}
+
 static int lan743x_ptpci_enable(struct ptp_clock_info *ptpci,
                                struct ptp_clock_request *request, int on)
 {
@@ -682,6 +807,9 @@ static int lan743x_ptpci_enable(struct ptp_clock_info *ptpci,
        if (request) {
                switch (request->type) {
                case PTP_CLK_REQ_EXTTS:
+                       if (request->extts.index < ptpci->n_ext_ts)
+                               return lan743x_ptp_io_extts(adapter, on,
+                                                        &request->extts);
                        return -EINVAL;
                case PTP_CLK_REQ_PEROUT:
                        if (request->perout.index < ptpci->n_per_out)
@@ -715,8 +843,8 @@ static int lan743x_ptpci_verify_pin_config(struct ptp_clock_info *ptp,
        switch (func) {
        case PTP_PF_NONE:
        case PTP_PF_PEROUT:
-               break;
        case PTP_PF_EXTTS:
+               break;
        case PTP_PF_PHYSYNC:
        default:
                result = -1;
@@ -725,6 +853,33 @@ static int lan743x_ptpci_verify_pin_config(struct ptp_clock_info *ptp,
        return result;
 }
 
+static void lan743x_ptp_io_event_clock_get(struct lan743x_adapter *adapter,
+                                          bool fe, u8 channel,
+                                          struct timespec64 *ts)
+{
+       struct lan743x_ptp *ptp = &adapter->ptp;
+       struct lan743x_extts *extts;
+       u32 sec, nsec;
+
+       mutex_lock(&ptp->command_lock);
+       if (fe) {
+               sec = lan743x_csr_read(adapter, PTP_IO_FE_LTC_SEC_CAP_X);
+               nsec = lan743x_csr_read(adapter, PTP_IO_FE_LTC_NS_CAP_X);
+       } else {
+               sec = lan743x_csr_read(adapter, PTP_IO_RE_LTC_SEC_CAP_X);
+               nsec = lan743x_csr_read(adapter, PTP_IO_RE_LTC_NS_CAP_X);
+       }
+
+       mutex_unlock(&ptp->command_lock);
+
+       /* Update Local timestamp */
+       extts = &ptp->extts[channel];
+       extts->ts.tv_sec = sec;
+       extts->ts.tv_nsec = nsec;
+       ts->tv_sec = sec;
+       ts->tv_nsec = nsec;
+}
+
 static long lan743x_ptpci_do_aux_work(struct ptp_clock_info *ptpci)
 {
        struct lan743x_ptp *ptp =
@@ -733,41 +888,121 @@ static long lan743x_ptpci_do_aux_work(struct ptp_clock_info *ptpci)
                container_of(ptp, struct lan743x_adapter, ptp);
        u32 cap_info, cause, header, nsec, seconds;
        bool new_timestamp_available = false;
+       struct ptp_clock_event ptp_event;
+       struct timespec64 ts;
+       int ptp_int_sts;
        int count = 0;
+       int channel;
+       s64 ns;
 
-       while ((count < 100) &&
-              (lan743x_csr_read(adapter, PTP_INT_STS) & PTP_INT_BIT_TX_TS_)) {
+       ptp_int_sts = lan743x_csr_read(adapter, PTP_INT_STS);
+       while ((count < 100) && ptp_int_sts) {
                count++;
-               cap_info = lan743x_csr_read(adapter, PTP_CAP_INFO);
-
-               if (PTP_CAP_INFO_TX_TS_CNT_GET_(cap_info) > 0) {
-                       seconds = lan743x_csr_read(adapter,
-                                                  PTP_TX_EGRESS_SEC);
-                       nsec = lan743x_csr_read(adapter, PTP_TX_EGRESS_NS);
-                       cause = (nsec &
-                                PTP_TX_EGRESS_NS_CAPTURE_CAUSE_MASK_);
-                       header = lan743x_csr_read(adapter,
-                                                 PTP_TX_MSG_HEADER);
-
-                       if (cause == PTP_TX_EGRESS_NS_CAPTURE_CAUSE_SW_) {
-                               nsec &= PTP_TX_EGRESS_NS_TS_NS_MASK_;
-                               lan743x_ptp_tx_ts_enqueue_ts(adapter,
-                                                            seconds, nsec,
-                                                            header);
-                               new_timestamp_available = true;
-                       } else if (cause ==
-                               PTP_TX_EGRESS_NS_CAPTURE_CAUSE_AUTO_) {
-                               netif_err(adapter, drv, adapter->netdev,
-                                         "Auto capture cause not supported\n");
+
+               if (ptp_int_sts & PTP_INT_BIT_TX_TS_) {
+                       cap_info = lan743x_csr_read(adapter, PTP_CAP_INFO);
+
+                       if (PTP_CAP_INFO_TX_TS_CNT_GET_(cap_info) > 0) {
+                               seconds = lan743x_csr_read(adapter,
+                                                          PTP_TX_EGRESS_SEC);
+                               nsec = lan743x_csr_read(adapter,
+                                                       PTP_TX_EGRESS_NS);
+                               cause = (nsec &
+                                        PTP_TX_EGRESS_NS_CAPTURE_CAUSE_MASK_);
+                               header = lan743x_csr_read(adapter,
+                                                         PTP_TX_MSG_HEADER);
+
+                               if (cause ==
+                                   PTP_TX_EGRESS_NS_CAPTURE_CAUSE_SW_) {
+                                       nsec &= PTP_TX_EGRESS_NS_TS_NS_MASK_;
+                                       lan743x_ptp_tx_ts_enqueue_ts(adapter,
+                                                                    seconds,
+                                                                    nsec,
+                                                                    header);
+                                       new_timestamp_available = true;
+                               } else if (cause ==
+                                          PTP_TX_EGRESS_NS_CAPTURE_CAUSE_AUTO_) {
+                                       netif_err(adapter, drv, adapter->netdev,
+                                                 "Auto capture cause not supported\n");
+                               } else {
+                                       netif_warn(adapter, drv, adapter->netdev,
+                                                  "unknown tx timestamp capture cause\n");
+                               }
                        } else {
                                netif_warn(adapter, drv, adapter->netdev,
-                                          "unknown tx timestamp capture cause\n");
+                                          "TX TS INT but no TX TS CNT\n");
                        }
-               } else {
-                       netif_warn(adapter, drv, adapter->netdev,
-                                  "TX TS INT but no TX TS CNT\n");
+                       lan743x_csr_write(adapter, PTP_INT_STS,
+                                         PTP_INT_BIT_TX_TS_);
                }
-               lan743x_csr_write(adapter, PTP_INT_STS, PTP_INT_BIT_TX_TS_);
+
+               if (ptp_int_sts & PTP_INT_IO_FE_MASK_) {
+                       do {
+                               channel = lan743x_get_channel((ptp_int_sts &
+                                                       PTP_INT_IO_FE_MASK_) >>
+                                                       PTP_INT_IO_FE_SHIFT_);
+                               if (channel >= 0 &&
+                                   channel < PCI11X1X_PTP_IO_MAX_CHANNELS) {
+                                       lan743x_ptp_io_event_clock_get(adapter,
+                                                                      true,
+                                                                      channel,
+                                                                      &ts);
+                                       /* PTP Falling Event post */
+                                       ns = timespec64_to_ns(&ts);
+                                       ptp_event.timestamp = ns;
+                                       ptp_event.index = channel;
+                                       ptp_event.type = PTP_CLOCK_EXTTS;
+                                       ptp_clock_event(ptp->ptp_clock,
+                                                       &ptp_event);
+                                       lan743x_csr_write(adapter, PTP_INT_STS,
+                                                         PTP_INT_IO_FE_SET_
+                                                         (channel));
+                                       ptp_int_sts &= ~(1 <<
+                                                        (PTP_INT_IO_FE_SHIFT_ +
+                                                         channel));
+                               } else {
+                                       /* Clear falling event interrupts */
+                                       lan743x_csr_write(adapter, PTP_INT_STS,
+                                                         PTP_INT_IO_FE_MASK_);
+                                       ptp_int_sts &= ~PTP_INT_IO_FE_MASK_;
+                               }
+                       } while (ptp_int_sts & PTP_INT_IO_FE_MASK_);
+               }
+
+               if (ptp_int_sts & PTP_INT_IO_RE_MASK_) {
+                       do {
+                               channel = lan743x_get_channel((ptp_int_sts &
+                                                      PTP_INT_IO_RE_MASK_) >>
+                                                      PTP_INT_IO_RE_SHIFT_);
+                               if (channel >= 0 &&
+                                   channel < PCI11X1X_PTP_IO_MAX_CHANNELS) {
+                                       lan743x_ptp_io_event_clock_get(adapter,
+                                                                      false,
+                                                                      channel,
+                                                                      &ts);
+                                       /* PTP Rising Event post */
+                                       ns = timespec64_to_ns(&ts);
+                                       ptp_event.timestamp = ns;
+                                       ptp_event.index = channel;
+                                       ptp_event.type = PTP_CLOCK_EXTTS;
+                                       ptp_clock_event(ptp->ptp_clock,
+                                                       &ptp_event);
+                                       lan743x_csr_write(adapter, PTP_INT_STS,
+                                                         PTP_INT_IO_RE_SET_
+                                                         (channel));
+                                       ptp_int_sts &= ~(1 <<
+                                                        (PTP_INT_IO_RE_SHIFT_ +
+                                                         channel));
+                               } else {
+                                       /* Clear Rising event interrupt */
+                                       lan743x_csr_write(adapter, PTP_INT_STS,
+                                                         PTP_INT_IO_RE_MASK_);
+                                       ptp_int_sts &= ~PTP_INT_IO_RE_MASK_;
+                               }
+                       } while (ptp_int_sts & PTP_INT_IO_RE_MASK_);
+               }
+
+               ptp_int_sts = lan743x_csr_read(adapter, PTP_INT_STS);
        }
 
        if (new_timestamp_available)
@@ -802,6 +1037,28 @@ static void lan743x_ptp_clock_get(struct lan743x_adapter *adapter,
        mutex_unlock(&ptp->command_lock);
 }
 
+static void lan743x_ptp_io_clock_get(struct lan743x_adapter *adapter,
+                                    u32 *sec, u32 *nsec, u32 *sub_nsec)
+{
+       struct lan743x_ptp *ptp = &adapter->ptp;
+
+       mutex_lock(&ptp->command_lock);
+       lan743x_csr_write(adapter, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_READ_);
+       lan743x_ptp_wait_till_cmd_done(adapter, PTP_CMD_CTL_PTP_CLOCK_READ_);
+
+       if (sec)
+               (*sec) = lan743x_csr_read(adapter, PTP_LTC_RD_SEC_LO);
+
+       if (nsec)
+               (*nsec) = lan743x_csr_read(adapter, PTP_LTC_RD_NS);
+
+       if (sub_nsec)
+               (*sub_nsec) =
+               lan743x_csr_read(adapter, PTP_LTC_RD_SUBNS);
+
+       mutex_unlock(&ptp->command_lock);
+}
+
 static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
                                   s64 time_step_ns)
 {
@@ -815,8 +1072,12 @@ static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
 
        if (time_step_ns >  15000000000LL) {
                /* convert to clock set */
-               lan743x_ptp_clock_get(adapter, &unsigned_seconds,
-                                     &nano_seconds, NULL);
+               if (adapter->is_pci11x1x)
+                       lan743x_ptp_io_clock_get(adapter, &unsigned_seconds,
+                                                &nano_seconds, NULL);
+               else
+                       lan743x_ptp_clock_get(adapter, &unsigned_seconds,
+                                             &nano_seconds, NULL);
                unsigned_seconds += div_u64_rem(time_step_ns, 1000000000LL,
                                                &remainder);
                nano_seconds += remainder;
@@ -831,8 +1092,13 @@ static void lan743x_ptp_clock_step(struct lan743x_adapter *adapter,
                /* convert to clock set */
                time_step_ns = -time_step_ns;
 
-               lan743x_ptp_clock_get(adapter, &unsigned_seconds,
-                                     &nano_seconds, NULL);
+               if (adapter->is_pci11x1x) {
+                       lan743x_ptp_io_clock_get(adapter, &unsigned_seconds,
+                                                &nano_seconds, NULL);
+               } else {
+                       lan743x_ptp_clock_get(adapter, &unsigned_seconds,
+                                             &nano_seconds, NULL);
+               }
                unsigned_seconds -= div_u64_rem(time_step_ns, 1000000000LL,
                                                &remainder);
                nano_seconds_step = remainder;
@@ -1061,6 +1327,8 @@ int lan743x_ptp_open(struct lan743x_adapter *adapter)
                n_pins = LAN7430_N_GPIO;
                break;
        case ID_REV_ID_LAN7431_:
+       case ID_REV_ID_A011_:
+       case ID_REV_ID_A041_:
                n_pins = LAN7431_N_GPIO;
                break;
        default:
@@ -1088,10 +1356,10 @@ int lan743x_ptp_open(struct lan743x_adapter *adapter)
                 adapter->netdev->dev_addr);
        ptp->ptp_clock_info.max_adj = LAN743X_PTP_MAX_FREQ_ADJ_IN_PPB;
        ptp->ptp_clock_info.n_alarm = 0;
-       ptp->ptp_clock_info.n_ext_ts = 0;
+       ptp->ptp_clock_info.n_ext_ts = LAN743X_PTP_N_EXTTS;
        ptp->ptp_clock_info.n_per_out = LAN743X_PTP_N_EVENT_CHAN;
        ptp->ptp_clock_info.n_pins = n_pins;
-       ptp->ptp_clock_info.pps = 0;
+       ptp->ptp_clock_info.pps = LAN743X_PTP_N_PPS;
        ptp->ptp_clock_info.pin_config = ptp->pin_config;
        ptp->ptp_clock_info.adjfine = lan743x_ptpci_adjfine;
        ptp->ptp_clock_info.adjfreq = lan743x_ptpci_adjfreq;
index 7663bf5d2e3300ff16299bc00f3ff431f13d0846..96d3a134e788abff03fc866117abcf2d9b643ed9 100644 (file)
@@ -18,6 +18,9 @@
  */
 #define LAN743X_PTP_N_EVENT_CHAN       2
 #define LAN743X_PTP_N_PEROUT           LAN743X_PTP_N_EVENT_CHAN
+#define LAN743X_PTP_N_EXTTS            4
+#define LAN743X_PTP_N_PPS              0
+#define PCI11X1X_PTP_IO_MAX_CHANNELS   8
 
 struct lan743x_adapter;
 
@@ -60,6 +63,11 @@ struct lan743x_ptp_perout {
        int  gpio_pin;  /* GPIO pin where output appears */
 };
 
+struct lan743x_extts {
+       int flags;
+       struct timespec64 ts;
+};
+
 struct lan743x_ptp {
        int flags;
 
@@ -72,6 +80,7 @@ struct lan743x_ptp {
 
        unsigned long used_event_ch;
        struct lan743x_ptp_perout perout[LAN743X_PTP_N_PEROUT];
+       struct lan743x_extts extts[LAN743X_PTP_N_EXTTS];
 
        bool leds_multiplexed;
        bool led_enabled[LAN7430_N_LED];