octeontx2-pf: cn10k: add support for new ptp timestamp format
authorNaveen Mamindlapalli <naveenm@marvell.com>
Mon, 21 Feb 2022 06:45:07 +0000 (12:15 +0530)
committerDavid S. Miller <davem@davemloft.net>
Mon, 21 Feb 2022 13:07:48 +0000 (13:07 +0000)
The cn10k hardware ptp timestamp format has been modified primarily
to support 1-step ptp clock. The 64-bit timestamp used by hardware is
split into two 32-bit fields, the upper one holds seconds, the lower
one nanoseconds. A new register (PTP_CLOCK_SEC) has been added that
returns the current seconds value. The nanoseconds register PTP_CLOCK_HI
resets after every second. The cn10k RPM block provides Rx/Tx timestamps
to the NIX block using the new timestamp format. The software can read
the current timestamp in nanoseconds by reading both PTP_CLOCK_SEC &
PTP_CLOCK_HI registers.

This patch provides support for new timestamp format.

Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: Rakesh Babu Saladi <rsaladi2@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/ptp.c
drivers/net/ethernet/marvell/octeontx2/af/ptp.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c

index e682b7b..5b8906f 100644 (file)
@@ -25,6 +25,9 @@
 #define PCI_SUBSYS_DEVID_OCTX2_95XXO_PTP       0xB600
 #define PCI_DEVID_OCTEONTX2_RST                        0xA085
 #define PCI_DEVID_CN10K_PTP                    0xA09E
+#define PCI_SUBSYS_DEVID_CN10K_A_PTP           0xB900
+#define PCI_SUBSYS_DEVID_CNF10K_A_PTP          0xBA00
+#define PCI_SUBSYS_DEVID_CNF10K_B_PTP          0xBC00
 
 #define PCI_PTP_BAR_NO                         0
 
 #define PTP_CLOCK_HI                           0xF10ULL
 #define PTP_CLOCK_COMP                         0xF18ULL
 #define PTP_TIMESTAMP                          0xF20ULL
+#define PTP_CLOCK_SEC                          0xFD0ULL
 
 static struct ptp *first_ptp_block;
 static const struct pci_device_id ptp_id_table[];
 
+static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp)
+{
+       if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
+           ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
+               return true;
+       return false;
+}
+
+static u64 read_ptp_tstmp_sec_nsec(struct ptp *ptp)
+{
+       u64 sec, sec1, nsec;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ptp->ptp_lock, flags);
+       sec = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL;
+       nsec = readq(ptp->reg_base + PTP_CLOCK_HI);
+       sec1 = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL;
+       /* check nsec rollover */
+       if (sec1 > sec) {
+               nsec = readq(ptp->reg_base + PTP_CLOCK_HI);
+               sec = sec1;
+       }
+       spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+
+       return sec * NSEC_PER_SEC + nsec;
+}
+
+static u64 read_ptp_tstmp_nsec(struct ptp *ptp)
+{
+       return readq(ptp->reg_base + PTP_CLOCK_HI);
+}
+
 struct ptp *ptp_get(void)
 {
        struct ptp *ptp = first_ptp_block;
@@ -117,7 +153,7 @@ static int ptp_adjfine(struct ptp *ptp, long scaled_ppm)
 static int ptp_get_clock(struct ptp *ptp, u64 *clk)
 {
        /* Return the current PTP clock */
-       *clk = readq(ptp->reg_base + PTP_CLOCK_HI);
+       *clk = ptp->read_ptp_tstmp(ptp);
 
        return 0;
 }
@@ -214,6 +250,12 @@ static int ptp_probe(struct pci_dev *pdev,
        if (!first_ptp_block)
                first_ptp_block = ptp;
 
+       spin_lock_init(&ptp->ptp_lock);
+       if (is_ptp_tsfmt_sec_nsec(ptp))
+               ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec;
+       else
+               ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec;
+
        return 0;
 
 error_free:
index 1b81a04..95a9551 100644 (file)
@@ -15,6 +15,8 @@
 struct ptp {
        struct pci_dev *pdev;
        void __iomem *reg_base;
+       u64 (*read_ptp_tstmp)(struct ptp *ptp);
+       spinlock_t ptp_lock; /* lock */
        u32 clock_rate;
 };
 
index 7724f17..65e31a2 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/soc/marvell/octeontx2/asm.h>
 #include <net/pkt_cls.h>
 #include <net/devlink.h>
+#include <linux/time64.h>
 
 #include <mbox.h>
 #include <npc.h>
@@ -275,6 +276,8 @@ struct otx2_ptp {
        u64 thresh;
 
        struct ptp_pin_desc extts_config;
+       u64 (*convert_rx_ptp_tstmp)(u64 timestamp);
+       u64 (*convert_tx_ptp_tstmp)(u64 timestamp);
 };
 
 #define OTX2_HW_TIMESTAMP_LEN  8
index 61c2090..fdc2c93 100644 (file)
@@ -294,6 +294,14 @@ int otx2_ptp_init(struct otx2_nic *pfvf)
                goto error;
        }
 
+       if (is_dev_otx2(pfvf->pdev)) {
+               ptp_ptr->convert_rx_ptp_tstmp = &otx2_ptp_convert_rx_timestamp;
+               ptp_ptr->convert_tx_ptp_tstmp = &otx2_ptp_convert_tx_timestamp;
+       } else {
+               ptp_ptr->convert_rx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
+               ptp_ptr->convert_tx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
+       }
+
        pfvf->ptp = ptp_ptr;
 
 error:
index 6ff2842..7ff4192 100644 (file)
@@ -8,6 +8,21 @@
 #ifndef OTX2_PTP_H
 #define OTX2_PTP_H
 
+static inline u64 otx2_ptp_convert_rx_timestamp(u64 timestamp)
+{
+       return be64_to_cpu(*(__be64 *)&timestamp);
+}
+
+static inline u64 otx2_ptp_convert_tx_timestamp(u64 timestamp)
+{
+       return timestamp;
+}
+
+static inline u64 cn10k_ptp_convert_timestamp(u64 timestamp)
+{
+       return ((timestamp >> 32) * NSEC_PER_SEC) + (timestamp & 0xFFFFFFFFUL);
+}
+
 int otx2_ptp_init(struct otx2_nic *pfvf);
 void otx2_ptp_destroy(struct otx2_nic *pfvf);
 
index 7c4068c..c26de15 100644 (file)
@@ -148,6 +148,7 @@ static void otx2_snd_pkt_handler(struct otx2_nic *pfvf,
        if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) {
                timestamp = ((u64 *)sq->timestamps->base)[snd_comp->sqe_id];
                if (timestamp != 1) {
+                       timestamp = pfvf->ptp->convert_tx_ptp_tstmp(timestamp);
                        err = otx2_ptp_tstamp2time(pfvf, timestamp, &tsns);
                        if (!err) {
                                memset(&ts, 0, sizeof(ts));
@@ -167,14 +168,15 @@ static void otx2_snd_pkt_handler(struct otx2_nic *pfvf,
 static void otx2_set_rxtstamp(struct otx2_nic *pfvf,
                              struct sk_buff *skb, void *data)
 {
-       u64 tsns;
+       u64 timestamp, tsns;
        int err;
 
        if (!(pfvf->flags & OTX2_FLAG_RX_TSTAMP_ENABLED))
                return;
 
+       timestamp = pfvf->ptp->convert_rx_ptp_tstmp(*(u64 *)data);
        /* The first 8 bytes is the timestamp */
-       err = otx2_ptp_tstamp2time(pfvf, be64_to_cpu(*(__be64 *)data), &tsns);
+       err = otx2_ptp_tstamp2time(pfvf, timestamp, &tsns);
        if (err)
                return;