diff mbox series

[net-next] octeontx2-pf: Use PTP HW timestamp counter atomic update feature

Message ID 20230804093014.2729634-1-saikrishnag@marvell.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net-next] octeontx2-pf: Use PTP HW timestamp counter atomic update feature | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 9 this patch: 9
netdev/cc_maintainers warning 2 maintainers not CCed: lcherian@marvell.com jerinj@marvell.com
netdev/build_clang success Errors and warnings before: 1351 this patch: 1351
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1368 this patch: 1368
netdev/checkpatch warning WARNING: line length of 81 exceeds 80 columns WARNING: line length of 82 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 91 exceeds 80 columns WARNING: line length of 92 exceeds 80 columns WARNING: line length of 93 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline fail Was 0 now: 1

Commit Message

Sai Krishna Gajula Aug. 4, 2023, 9:30 a.m. UTC
Some of the newer silicon versions in CN10K series supports a feature
where in the current PTP timestamp in HW can be updated atomically
without losing any cpu cycles unlike read/modify/write register.
This patch uses this feature so that PTP accuracy can be improved
while adjusting the master offset in HW. There is no need for SW
timecounter when using this feature. So removed references to SW
timecounter wherever appropriate.

Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
---
 .../net/ethernet/marvell/octeontx2/af/mbox.h  |  12 ++
 .../net/ethernet/marvell/octeontx2/af/ptp.c   | 161 ++++++++++++++--
 .../net/ethernet/marvell/octeontx2/af/ptp.h   |   2 +-
 .../net/ethernet/marvell/octeontx2/af/rvu.c   |   2 +-
 .../net/ethernet/marvell/octeontx2/af/rvu.h   |  12 ++
 .../marvell/octeontx2/nic/otx2_common.h       |   1 +
 .../ethernet/marvell/octeontx2/nic/otx2_ptp.c | 177 ++++++++++++++----
 7 files changed, 313 insertions(+), 54 deletions(-)

Comments

Simon Horman Aug. 5, 2023, 11:33 a.m. UTC | #1
On Fri, Aug 04, 2023 at 03:00:14PM +0530, Sai Krishna wrote:
> Some of the newer silicon versions in CN10K series supports a feature
> where in the current PTP timestamp in HW can be updated atomically
> without losing any cpu cycles unlike read/modify/write register.
> This patch uses this feature so that PTP accuracy can be improved
> while adjusting the master offset in HW. There is no need for SW
> timecounter when using this feature. So removed references to SW
> timecounter wherever appropriate.
> 
> Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
> Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
> Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>

...

>  struct npc_get_field_status_req {
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c

...

>  
> -static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp)
> +static inline bool is_tstmp_atomic_update_supported(struct rvu *rvu)

Hi Sai,

Please avoid using the inline keyword for functions in .c files.
Unless there is a demonstrable advantage to doing so it should
be left up to the compiler to inline or not.

...
Sai Krishna Gajula Aug. 7, 2023, 6:41 a.m. UTC | #2
> -----Original Message-----
> From: Simon Horman <horms@kernel.org>
> Sent: Saturday, August 5, 2023 5:04 PM
> To: Sai Krishna Gajula <saikrishnag@marvell.com>
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; Sunil Kovvuri Goutham <sgoutham@marvell.com>;
> Geethasowjanya Akula <gakula@marvell.com>; Subbaraya Sundeep Bhatta
> <sbhatta@marvell.com>; Hariprasad Kelam <hkelam@marvell.com>;
> richardcochran@gmail.com; Naveen Mamindlapalli
> <naveenm@marvell.com>
> Subject: Re: [net-next PATCH] octeontx2-pf: Use PTP HW timestamp
> counter atomic update feature
> 
> On Fri, Aug 04, 2023 at 03:00:14PM +0530, Sai Krishna wrote:
> > Some of the newer silicon versions in CN10K series supports a feature
> > where in the current PTP timestamp in HW can be updated atomically
> > without losing any cpu cycles unlike read/modify/write register.
> > This patch uses this feature so that PTP accuracy can be improved
> > while adjusting the master offset in HW. There is no need for SW
> > timecounter when using this feature. So removed references to SW
> > timecounter wherever appropriate.
> >
> > Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
> > Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
> > Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
> 
> ...
> 
> >  struct npc_get_field_status_req {
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
> > b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
> 
> ...
> 
> >
> > -static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp)
> > +static inline bool is_tstmp_atomic_update_supported(struct rvu *rvu)
> 
> Hi Sai,
> 
> Please avoid using the inline keyword for functions in .c files.
> Unless there is a demonstrable advantage to doing so it should be left up to
> the compiler to inline or not.

Ok, will remove inline keyword and submit V2 patch.

Thanks,
Sai
> 
> ...
> 
> --
> pw-bot: changes-requested
Kalesh Anakkur Purayil Aug. 7, 2023, 7:54 a.m. UTC | #3
On Fri, Aug 4, 2023 at 3:00 PM Sai Krishna <saikrishnag@marvell.com> wrote:

> Some of the newer silicon versions in CN10K series supports a feature
> where in the current PTP timestamp in HW can be updated atomically
> without losing any cpu cycles unlike read/modify/write register.
> This patch uses this feature so that PTP accuracy can be improved
> while adjusting the master offset in HW. There is no need for SW
> timecounter when using this feature. So removed references to SW
> timecounter wherever appropriate.
>
> Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
> Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
> Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
> ---
>  .../net/ethernet/marvell/octeontx2/af/mbox.h  |  12 ++
>  .../net/ethernet/marvell/octeontx2/af/ptp.c   | 161 ++++++++++++++--
>  .../net/ethernet/marvell/octeontx2/af/ptp.h   |   2 +-
>  .../net/ethernet/marvell/octeontx2/af/rvu.c   |   2 +-
>  .../net/ethernet/marvell/octeontx2/af/rvu.h   |  12 ++
>  .../marvell/octeontx2/nic/otx2_common.h       |   1 +
>  .../ethernet/marvell/octeontx2/nic/otx2_ptp.c | 177 ++++++++++++++----
>  7 files changed, 313 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> index a8f3c8faf8af..407c220840d9 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
> @@ -136,6 +136,7 @@ M(GET_HW_CAP,               0x008, get_hw_cap,
> msg_req, get_hw_cap_rsp)     \
>  M(LMTST_TBL_SETUP,     0x00a, lmtst_tbl_setup, lmtst_tbl_setup_req,    \
>                                 msg_rsp)                                \
>  M(SET_VF_PERM,         0x00b, set_vf_perm, set_vf_perm, msg_rsp)       \
> +M(PTP_GET_CAP,         0x00c, ptp_get_cap, msg_req, ptp_get_cap_rsp)   \
>  /* CGX mbox IDs (range 0x200 - 0x3FF) */                               \
>  M(CGX_START_RXTX,      0x200, cgx_start_rxtx, msg_req, msg_rsp)        \
>  M(CGX_STOP_RXTX,       0x201, cgx_stop_rxtx, msg_req, msg_rsp)         \
> @@ -1437,6 +1438,12 @@ struct npc_get_kex_cfg_rsp {
>         u8 mkex_pfl_name[MKEX_NAME_LEN];
>  };
>
> +struct ptp_get_cap_rsp {
> +       struct mbox_msghdr hdr;
> +#define        PTP_CAP_HW_ATOMIC_UPDATE BIT_ULL(0)
> +       u64 cap;
> +};
> +
>  struct flow_msg {
>         unsigned char dmac[6];
>         unsigned char smac[6];
> @@ -1567,6 +1574,8 @@ enum ptp_op {
>         PTP_OP_GET_TSTMP = 2,
>         PTP_OP_SET_THRESH = 3,
>         PTP_OP_EXTTS_ON = 4,
> +       PTP_OP_ADJTIME = 5,
> +       PTP_OP_SET_CLOCK = 6,
>  };
>
>  struct ptp_req {
> @@ -1575,11 +1584,14 @@ struct ptp_req {
>         s64 scaled_ppm;
>         u64 thresh;
>         int extts_on;
> +       s64 delta;
> +       u64 clk;
>  };
>
>  struct ptp_rsp {
>         struct mbox_msghdr hdr;
>         u64 clk;
> +       u64 tsc;
>  };
>
>  struct npc_get_field_status_req {
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
> b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
> index c55c2c441a1a..70256372bec6 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
> @@ -12,9 +12,9 @@
>  #include <linux/hrtimer.h>
>  #include <linux/ktime.h>
>
> -#include "ptp.h"
>  #include "mbox.h"
>  #include "rvu.h"
> +#include "ptp.h"
>
>  #define DRV_NAME                               "Marvell PTP Driver"
>
> @@ -40,6 +40,7 @@
>  #define PTP_CLOCK_CFG_TSTMP_EDGE               BIT_ULL(9)
>  #define PTP_CLOCK_CFG_TSTMP_EN                 BIT_ULL(8)
>  #define PTP_CLOCK_CFG_TSTMP_IN_MASK            GENMASK_ULL(15, 10)
> +#define PTP_CLOCK_CFG_ATOMIC_OP_MASK           GENMASK_ULL(28, 26)
>  #define PTP_CLOCK_CFG_PPS_EN                   BIT_ULL(30)
>  #define PTP_CLOCK_CFG_PPS_INV                  BIT_ULL(31)
>
> @@ -53,36 +54,70 @@
>  #define PTP_TIMESTAMP                          0xF20ULL
>  #define PTP_CLOCK_SEC                          0xFD0ULL
>  #define PTP_SEC_ROLLOVER                       0xFD8ULL
> +/* Atomic update related CSRs */
> +#define PTP_FRNS_TIMESTAMP                     0xFE0ULL
> +#define PTP_NXT_ROLLOVER_SET                   0xFE8ULL
> +#define PTP_CURR_ROLLOVER_SET                  0xFF0ULL
> +#define PTP_NANO_TIMESTAMP                     0xFF8ULL
> +#define PTP_SEC_TIMESTAMP                      0x1000ULL
>
>  #define CYCLE_MULT                             1000
>
> +/* PTP atomic update operation type */
> +enum atomic_opcode {
> +       ATOMIC_SET = 1,
> +       ATOMIC_INC = 3,
> +       ATOMIC_DEC = 4
> +};
> +
>  static struct ptp *first_ptp_block;
>  static const struct pci_device_id ptp_id_table[];
>
> -static bool is_ptp_dev_cnf10kb(struct ptp *ptp)
> +static bool is_ptp_dev_cnf10ka(struct ptp *ptp)
>  {
> -       return ptp->pdev->subsystem_device ==
> PCI_SUBSYS_DEVID_CNF10K_B_PTP;
> +       return (ptp->pdev->subsystem_device ==
> PCI_SUBSYS_DEVID_CNF10K_A_PTP) ? true : false;
>
[Kalesh]: Isn't it enough?
return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP;

>  }
>
> -static bool is_ptp_dev_cn10k(struct ptp *ptp)
> +static bool is_ptp_dev_cn10ka(struct ptp *ptp)
>  {
> -       return ptp->pdev->device == PCI_DEVID_CN10K_PTP;
> +       return (ptp->pdev->subsystem_device ==
> PCI_SUBSYS_DEVID_CN10K_A_PTP) ? true : false;
>
[Kalesh]: Same as above

>  }
>
>  static bool cn10k_ptp_errata(struct ptp *ptp)
>  {
> -       if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
> -           ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
> +       if ((is_ptp_dev_cn10ka(ptp) &&
> +            ((ptp->pdev->revision & 0x0F) == 0x0 || (ptp->pdev->revision
> & 0x0F) == 0x1)) ||
> +           (is_ptp_dev_cnf10ka(ptp) &&
> +            ((ptp->pdev->revision & 0x0F) == 0x0 || (ptp->pdev->revision
> & 0x0F) == 0x1)))
>                 return true;
> +
>         return false;
>  }
>
> -static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp)
> +static inline bool is_tstmp_atomic_update_supported(struct rvu *rvu)
>  {
> -       if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
> -           ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
> +       struct ptp *ptp = rvu->ptp;
> +       struct pci_dev *pdev;
> +
> +       if (is_rvu_otx2(rvu))
> +               return false;
> +
> +       pdev = ptp->pdev;
> +
> +       /* On older silicon variants of CN10K, atomic update feature
> +        * is not available.
> +        */
> +       if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP &&
> +            (pdev->revision & 0x0F) == 0x0) ||
> +            (pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP &&
> +            (pdev->revision & 0x0F) == 0x1) ||
> +            (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP &&
> +            (pdev->revision & 0x0F) == 0x0) ||
> +            (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP &&
> +            (pdev->revision & 0x0F) == 0x1))
> +               return false;
> +       else
>
[Kalesh]: No need of else here.

>                 return true;
> -       return false;
>  }
>
>  static enum hrtimer_restart ptp_reset_thresh(struct hrtimer *hrtimer)
> @@ -222,6 +257,65 @@ void ptp_put(struct ptp *ptp)
>         pci_dev_put(ptp->pdev);
>  }
>
> +static void ptp_atomic_update(struct ptp *ptp, u64 timestamp)
> +{
> +       u64 regval, curr_rollover_set, nxt_rollover_set;
> +
> +       /* First setup NSECs and SECs */
> +       writeq(timestamp, ptp->reg_base + PTP_NANO_TIMESTAMP);
> +       writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
> +       writeq(timestamp / NSEC_PER_SEC,
> +              ptp->reg_base + PTP_SEC_TIMESTAMP);
> +
> +       nxt_rollover_set = roundup(timestamp, NSEC_PER_SEC);
> +       curr_rollover_set = nxt_rollover_set - NSEC_PER_SEC;
> +       writeq(nxt_rollover_set, ptp->reg_base + PTP_NXT_ROLLOVER_SET);
> +       writeq(curr_rollover_set, ptp->reg_base + PTP_CURR_ROLLOVER_SET);
> +
> +       /* Now, initiate atomic update */
> +       regval = readq(ptp->reg_base + PTP_CLOCK_CFG);
> +       regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
> +       regval |= (ATOMIC_SET << 26);
> +       writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);
> +}
> +
> +static void ptp_atomic_adjtime(struct ptp *ptp, s64 delta)
> +{
> +       bool neg_adj = false, atomic_inc_dec = false;
> +       u64 regval, ptp_clock_hi;
> +
> +       if (delta < 0) {
> +               delta = -delta;
> +               neg_adj = true;
> +       }
> +
> +       /* use atomic inc/dec when delta < 1 second */
> +       if (delta < NSEC_PER_SEC)
> +               atomic_inc_dec = true;
> +
> +       if (!atomic_inc_dec) {
> +               ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI);
> +               if (neg_adj) {
> +                       if (ptp_clock_hi > delta)
> +                               ptp_clock_hi -= delta;
> +                       else
> +                               ptp_clock_hi = delta - ptp_clock_hi;
> +               } else {
> +                       ptp_clock_hi += delta;
> +               }
> +               ptp_atomic_update(ptp, ptp_clock_hi);
> +       } else {
> +               writeq(delta, ptp->reg_base + PTP_NANO_TIMESTAMP);
> +               writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
> +
> +               /* initiate atomic inc/dec */
> +               regval = readq(ptp->reg_base + PTP_CLOCK_CFG);
> +               regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
> +               regval |= neg_adj ? (ATOMIC_DEC << 26) : (ATOMIC_INC <<
> 26);
> +               writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);
> +       }
> +}
> +
>  static int ptp_adjfine(struct ptp *ptp, long scaled_ppm)
>  {
>         bool neg_adj = false;
> @@ -277,8 +371,9 @@ static int ptp_get_clock(struct ptp *ptp, u64 *clk)
>         return 0;
>  }
>
> -void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
> +void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts)
>  {
> +       struct ptp *ptp = rvu->ptp;
>         struct pci_dev *pdev;
>         u64 clock_comp;
>         u64 clock_cfg;
> @@ -297,8 +392,14 @@ void ptp_start(struct ptp *ptp, u64 sclk, u32
> ext_clk_freq, u32 extts)
>         ptp->clock_rate = sclk * 1000000;
>
>         /* Program the seconds rollover value to 1 second */
> -       if (is_ptp_dev_cnf10kb(ptp))
> +       if (is_tstmp_atomic_update_supported(rvu)) {
> +               writeq(0, ptp->reg_base + PTP_NANO_TIMESTAMP);
> +               writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
> +               writeq(0, ptp->reg_base + PTP_SEC_TIMESTAMP);
> +               writeq(0, ptp->reg_base + PTP_CURR_ROLLOVER_SET);
> +               writeq(0x3b9aca00, ptp->reg_base + PTP_NXT_ROLLOVER_SET);
>                 writeq(0x3b9aca00, ptp->reg_base + PTP_SEC_ROLLOVER);
> +       }
>
>         /* Enable PTP clock */
>         clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
> @@ -320,6 +421,10 @@ void ptp_start(struct ptp *ptp, u64 sclk, u32
> ext_clk_freq, u32 extts)
>         clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
>         clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV;
>         writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
> +       clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
> +       clock_cfg &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
> +       clock_cfg |= (ATOMIC_SET << 26);
> +       writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
>
>         /* Set 50% duty cycle for 1Hz output */
>         writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_HI_INCR);
> @@ -350,7 +455,7 @@ static int ptp_get_tstmp(struct ptp *ptp, u64 *clk)
>  {
>         u64 timestamp;
>
> -       if (is_ptp_dev_cn10k(ptp)) {
> +       if (is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) {
>                 timestamp = readq(ptp->reg_base + PTP_TIMESTAMP);
>                 *clk = (timestamp >> 32) * NSEC_PER_SEC + (timestamp &
> 0xFFFFFFFF);
>         } else {
> @@ -414,14 +519,12 @@ static int ptp_probe(struct pci_dev *pdev,
>                 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;
> -
>         if (cn10k_ptp_errata(ptp)) {
> +               ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec;
>                 hrtimer_init(&ptp->hrtimer, CLOCK_MONOTONIC,
> HRTIMER_MODE_REL);
>                 ptp->hrtimer.function = ptp_reset_thresh;
> +       } else {
> +               ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec;
>         }
>
>         return 0;
> @@ -521,6 +624,12 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct
> ptp_req *req,
>         case PTP_OP_EXTTS_ON:
>                 err = ptp_extts_on(rvu->ptp, req->extts_on);
>                 break;
> +       case PTP_OP_ADJTIME:
> +               ptp_atomic_adjtime(rvu->ptp, req->delta);
> +               break;
> +       case PTP_OP_SET_CLOCK:
> +               ptp_atomic_update(rvu->ptp, (u64)req->clk);
> +               break;
>         default:
>                 err = -EINVAL;
>                 break;
> @@ -528,3 +637,17 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct
> ptp_req *req,
>
>         return err;
>  }
> +
> +int rvu_mbox_handler_ptp_get_cap(struct rvu *rvu, struct msg_req *req,
> +                                struct ptp_get_cap_rsp *rsp)
> +{
> +       if (!rvu->ptp)
> +               return -ENODEV;
> +
> +       if (is_tstmp_atomic_update_supported(rvu))
> +               rsp->cap |= PTP_CAP_HW_ATOMIC_UPDATE;
> +       else
> +               rsp->cap &= ~BIT_ULL_MASK(0);
> +
> +       return 0;
> +}
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
> b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
> index b9d92abc3844..0268a5e0b8bc 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
> @@ -25,7 +25,7 @@ struct ptp {
>
>  struct ptp *ptp_get(void);
>  void ptp_put(struct ptp *ptp);
> -void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts);
> +void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts);
>
>  extern struct pci_driver ptp_driver;
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
> b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
> index 73df2d564545..22c395c7d040 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
> @@ -3322,7 +3322,7 @@ static int rvu_probe(struct pci_dev *pdev, const
> struct pci_device_id *id)
>         mutex_init(&rvu->rswitch.switch_lock);
>
>         if (rvu->fwdata)
> -               ptp_start(rvu->ptp, rvu->fwdata->sclk,
> rvu->fwdata->ptp_ext_clk_rate,
> +               ptp_start(rvu, rvu->fwdata->sclk,
> rvu->fwdata->ptp_ext_clk_rate,
>                           rvu->fwdata->ptp_ext_tstamp);
>
>         return 0;
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
> b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
> index e8e65fd7888d..c4d999ef5ab4 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
> @@ -17,6 +17,7 @@
>  #include "mbox.h"
>  #include "npc.h"
>  #include "rvu_reg.h"
> +#include "ptp.h"
>
>  /* PCI device IDs */
>  #define        PCI_DEVID_OCTEONTX2_RVU_AF              0xA065
> @@ -26,6 +27,7 @@
>  #define PCI_SUBSYS_DEVID_98XX                  0xB100
>  #define PCI_SUBSYS_DEVID_96XX                  0xB200
>  #define PCI_SUBSYS_DEVID_CN10K_A              0xB900
> +#define PCI_SUBSYS_DEVID_CNF10K_A             0xBA00
>  #define PCI_SUBSYS_DEVID_CNF10K_B              0xBC00
>  #define PCI_SUBSYS_DEVID_CN10K_B               0xBD00
>
> @@ -634,6 +636,16 @@ static inline bool is_rvu_otx2(struct rvu *rvu)
>                 midr == PCI_REVISION_ID_95XXMM || midr ==
> PCI_REVISION_ID_95XXO);
>  }
>
> +static inline bool is_cnf10ka_a0(struct rvu *rvu)
> +{
> +       struct pci_dev *pdev = rvu->pdev;
> +
> +       if (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A &&
> +           (pdev->revision & 0x0F) == 0x0)
> +               return true;
> +       return false;
> +}
> +
>  static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu)
>  {
>         u64 npc_const3;
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> index 25e99fd2e3fd..ee37235e6f09 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> @@ -326,6 +326,7 @@ struct otx2_ptp {
>         struct ptp_pin_desc extts_config;
>         u64 (*convert_rx_ptp_tstmp)(u64 timestamp);
>         u64 (*convert_tx_ptp_tstmp)(u64 timestamp);
> +       u64 (*ptp_tstamp2nsec)(const struct timecounter *time_counter, u64
> timestamp);
>         struct delayed_work synctstamp_work;
>         u64 tstamp;
>         u32 base_ns;
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
> index 896b2f9bac34..839d7a07939d 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
> @@ -10,6 +10,62 @@
>  #include "otx2_common.h"
>  #include "otx2_ptp.h"
>
> +static bool is_tstmp_atomic_update_supported(struct otx2_ptp *ptp)
> +{
> +       struct ptp_get_cap_rsp *rsp;
> +       struct msg_req *req;
> +       int err;
> +
> +       if (!ptp->nic)
> +               return 0;
>
[Kalesh]: return false; same comment applies for below 2 returns.

> +
> +       mutex_lock(&ptp->nic->mbox.lock);
> +       req = otx2_mbox_alloc_msg_ptp_get_cap(&ptp->nic->mbox);
> +       if (!req)
> +               return 0;
> +
> +       err = otx2_sync_mbox_msg(&ptp->nic->mbox);
> +       if (err)
> +               return 0;
> +
> +       rsp = (struct ptp_get_cap_rsp
> *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
> +                                                         &req->hdr);
> +       mutex_unlock(&ptp->nic->mbox.lock);
> +
> +       if (IS_ERR(rsp))
> +               return false;
> +
> +       if (rsp->cap & PTP_CAP_HW_ATOMIC_UPDATE)
> +               return true;
> +
> +       return false;
> +}
> +
> +static int otx2_ptp_hw_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
> +{
> +       struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
> +                                           ptp_info);
> +       struct otx2_nic *pfvf = ptp->nic;
> +       struct ptp_req *req;
> +       int rc;
> +
> +       if (!ptp->nic)
> +               return -ENODEV;
> +
> +       mutex_lock(&pfvf->mbox.lock);
> +       req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
> +       if (!req) {
> +               mutex_unlock(&pfvf->mbox.lock);
> +               return -ENOMEM;
> +       }
> +       req->op = PTP_OP_ADJTIME;
> +       req->delta = delta;
> +       rc = otx2_sync_mbox_msg(&ptp->nic->mbox);
> +       mutex_unlock(&pfvf->mbox.lock);
> +
> +       return rc;
> +}
> +
>  static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp)
>  {
>         struct ptp_req *req;
> @@ -37,6 +93,49 @@ static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp)
>         return rsp->clk;
>  }
>
> +static int otx2_ptp_hw_gettime(struct ptp_clock_info *ptp_info,
> +                              struct timespec64 *ts)
> +{
> +       struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
> +                                           ptp_info);
> +       u64 tstamp;
> +
> +       tstamp = otx2_ptp_get_clock(ptp);
> +
> +       *ts = ns_to_timespec64(tstamp);
> +       return 0;
> +}
> +
> +static int otx2_ptp_hw_settime(struct ptp_clock_info *ptp_info,
> +                              const struct timespec64 *ts)
> +{
> +       struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
> +                                           ptp_info);
> +       struct otx2_nic *pfvf = ptp->nic;
> +       struct ptp_req *req;
> +       u64 nsec;
> +       int rc;
> +
> +       if (!ptp->nic)
> +               return -ENODEV;
> +
> +       nsec = timespec64_to_ns(ts);
> +
> +       mutex_lock(&pfvf->mbox.lock);
> +       req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
> +       if (!req) {
> +               mutex_unlock(&pfvf->mbox.lock);
> +               return -ENOMEM;
> +       }
> +
> +       req->op = PTP_OP_SET_CLOCK;
> +       req->clk = nsec;
> +       rc = otx2_sync_mbox_msg(&ptp->nic->mbox);
> +       mutex_unlock(&pfvf->mbox.lock);
> +
> +       return rc;
> +}
> +
>  static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long
> scaled_ppm)
>  {
>         struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
> @@ -124,21 +223,15 @@ static u64 ptp_tstmp_read(struct otx2_ptp *ptp)
>         return rsp->clk;
>  }
>
> -static void otx2_get_ptpclock(struct otx2_ptp *ptp, u64 *tstamp)
> -{
> -       struct otx2_nic *pfvf = ptp->nic;
> -
> -       mutex_lock(&pfvf->mbox.lock);
> -       *tstamp = timecounter_read(&ptp->time_counter);
> -       mutex_unlock(&pfvf->mbox.lock);
> -}
> -
> -static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
> +static int otx2_ptp_tc_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
>  {
>         struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
>                                             ptp_info);
>         struct otx2_nic *pfvf = ptp->nic;
>
> +       if (!ptp->nic)
> +               return -ENODEV;
> +
>         mutex_lock(&pfvf->mbox.lock);
>         timecounter_adjtime(&ptp->time_counter, delta);
>         mutex_unlock(&pfvf->mbox.lock);
> @@ -146,32 +239,33 @@ static int otx2_ptp_adjtime(struct ptp_clock_info
> *ptp_info, s64 delta)
>         return 0;
>  }
>
> -static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info,
> -                           struct timespec64 *ts)
> +static int otx2_ptp_tc_gettime(struct ptp_clock_info *ptp_info,
> +                              struct timespec64 *ts)
>  {
>         struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
>                                             ptp_info);
>         u64 tstamp;
>
> -       otx2_get_ptpclock(ptp, &tstamp);
> +       mutex_lock(&ptp->nic->mbox.lock);
> +       tstamp = timecounter_read(&ptp->time_counter);
> +       mutex_unlock(&ptp->nic->mbox.lock);
>         *ts = ns_to_timespec64(tstamp);
>
>         return 0;
>  }
>
> -static int otx2_ptp_settime(struct ptp_clock_info *ptp_info,
> -                           const struct timespec64 *ts)
> +static int otx2_ptp_tc_settime(struct ptp_clock_info *ptp_info,
> +                              const struct timespec64 *ts)
>  {
>         struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
>                                             ptp_info);
> -       struct otx2_nic *pfvf = ptp->nic;
>         u64 nsec;
>
>         nsec = timespec64_to_ns(ts);
>
> -       mutex_lock(&pfvf->mbox.lock);
> +       mutex_lock(&ptp->nic->mbox.lock);
>         timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec);
> -       mutex_unlock(&pfvf->mbox.lock);
> +       mutex_unlock(&ptp->nic->mbox.lock);
>
>         return 0;
>  }
> @@ -190,6 +284,12 @@ static int otx2_ptp_verify_pin(struct ptp_clock_info
> *ptp, unsigned int pin,
>         return 0;
>  }
>
> +static u64 otx2_ptp_hw_tstamp2time(const struct timecounter
> *time_counter, u64 tstamp)
> +{
> +       /* On HW which supports atomic updates, timecounter is not
> initialized */
> +       return tstamp;
> +}
> +
>  static void otx2_ptp_extts_check(struct work_struct *work)
>  {
>         struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
> @@ -204,7 +304,7 @@ static void otx2_ptp_extts_check(struct work_struct
> *work)
>         if (tstmp != ptp->last_extts) {
>                 event.type = PTP_CLOCK_EXTTS;
>                 event.index = 0;
> -               event.timestamp = timecounter_cyc2time(&ptp->time_counter,
> tstmp);
> +               event.timestamp = ptp->ptp_tstamp2nsec(&ptp->time_counter,
> tstmp);
>                 ptp_clock_event(ptp->ptp_clock, &event);
>                 new_thresh = tstmp % 500000000;
>                 if (ptp->thresh != new_thresh) {
> @@ -229,7 +329,7 @@ static void otx2_sync_tstamp(struct work_struct *work)
>         tstamp = otx2_ptp_get_clock(ptp);
>         mutex_unlock(&pfvf->mbox.lock);
>
> -       ptp->tstamp = timecounter_cyc2time(&pfvf->ptp->time_counter,
> tstamp);
> +       ptp->tstamp = ptp->ptp_tstamp2nsec(&ptp->time_counter, tstamp);
>         ptp->base_ns = tstamp % NSEC_PER_SEC;
>
>         schedule_delayed_work(&ptp->synctstamp_work,
> msecs_to_jiffies(250));
> @@ -302,15 +402,6 @@ int otx2_ptp_init(struct otx2_nic *pfvf)
>
>         ptp_ptr->nic = pfvf;
>
> -       cc = &ptp_ptr->cycle_counter;
> -       cc->read = ptp_cc_read;
> -       cc->mask = CYCLECOUNTER_MASK(64);
> -       cc->mult = 1;
> -       cc->shift = 0;
> -
> -       timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
> -                        ktime_to_ns(ktime_get_real()));
> -
>         snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->
> extts_config.name), "TSTAMP");
>         ptp_ptr->extts_config.index = 0;
>         ptp_ptr->extts_config.func = PTP_PF_NONE;
> @@ -324,13 +415,33 @@ int otx2_ptp_init(struct otx2_nic *pfvf)
>                 .pps            = 0,
>                 .pin_config     = &ptp_ptr->extts_config,
>                 .adjfine        = otx2_ptp_adjfine,
> -               .adjtime        = otx2_ptp_adjtime,
> -               .gettime64      = otx2_ptp_gettime,
> -               .settime64      = otx2_ptp_settime,
>                 .enable         = otx2_ptp_enable,
>                 .verify         = otx2_ptp_verify_pin,
>         };
>
> +       /* Check whether hardware supports atomic updates to timestamp */
> +       if (is_tstmp_atomic_update_supported(ptp_ptr)) {
> +               ptp_ptr->ptp_info.adjtime = otx2_ptp_hw_adjtime;
> +               ptp_ptr->ptp_info.gettime64 = otx2_ptp_hw_gettime;
> +               ptp_ptr->ptp_info.settime64 = otx2_ptp_hw_settime;
> +
> +               ptp_ptr->ptp_tstamp2nsec = otx2_ptp_hw_tstamp2time;
> +       } else {
> +               ptp_ptr->ptp_info.adjtime = otx2_ptp_tc_adjtime;
> +               ptp_ptr->ptp_info.gettime64 = otx2_ptp_tc_gettime;
> +               ptp_ptr->ptp_info.settime64 = otx2_ptp_tc_settime;
> +
> +               cc = &ptp_ptr->cycle_counter;
> +               cc->read = ptp_cc_read;
> +               cc->mask = CYCLECOUNTER_MASK(64);
> +               cc->mult = 1;
> +               cc->shift = 0;
> +               ptp_ptr->ptp_tstamp2nsec = timecounter_cyc2time;
> +
> +               timecounter_init(&ptp_ptr->time_counter,
> &ptp_ptr->cycle_counter,
> +                                ktime_to_ns(ktime_get_real()));
> +       }
> +
>         INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check);
>
>         ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info,
> pfvf->dev);
> @@ -387,7 +498,7 @@ int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64
> tstamp, u64 *tsns)
>         if (!pfvf->ptp)
>                 return -ENODEV;
>
> -       *tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
> +       *tsns = pfvf->ptp->ptp_tstamp2nsec(&pfvf->ptp->time_counter,
> tstamp);
>
>         return 0;
>  }
> --
> 2.25.1
>
>
>
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index a8f3c8faf8af..407c220840d9 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -136,6 +136,7 @@  M(GET_HW_CAP,		0x008, get_hw_cap, msg_req, get_hw_cap_rsp)	\
 M(LMTST_TBL_SETUP,	0x00a, lmtst_tbl_setup, lmtst_tbl_setup_req,    \
 				msg_rsp)				\
 M(SET_VF_PERM,		0x00b, set_vf_perm, set_vf_perm, msg_rsp)	\
+M(PTP_GET_CAP,		0x00c, ptp_get_cap, msg_req, ptp_get_cap_rsp)	\
 /* CGX mbox IDs (range 0x200 - 0x3FF) */				\
 M(CGX_START_RXTX,	0x200, cgx_start_rxtx, msg_req, msg_rsp)	\
 M(CGX_STOP_RXTX,	0x201, cgx_stop_rxtx, msg_req, msg_rsp)		\
@@ -1437,6 +1438,12 @@  struct npc_get_kex_cfg_rsp {
 	u8 mkex_pfl_name[MKEX_NAME_LEN];
 };
 
+struct ptp_get_cap_rsp {
+	struct mbox_msghdr hdr;
+#define        PTP_CAP_HW_ATOMIC_UPDATE BIT_ULL(0)
+	u64 cap;
+};
+
 struct flow_msg {
 	unsigned char dmac[6];
 	unsigned char smac[6];
@@ -1567,6 +1574,8 @@  enum ptp_op {
 	PTP_OP_GET_TSTMP = 2,
 	PTP_OP_SET_THRESH = 3,
 	PTP_OP_EXTTS_ON = 4,
+	PTP_OP_ADJTIME = 5,
+	PTP_OP_SET_CLOCK = 6,
 };
 
 struct ptp_req {
@@ -1575,11 +1584,14 @@  struct ptp_req {
 	s64 scaled_ppm;
 	u64 thresh;
 	int extts_on;
+	s64 delta;
+	u64 clk;
 };
 
 struct ptp_rsp {
 	struct mbox_msghdr hdr;
 	u64 clk;
+	u64 tsc;
 };
 
 struct npc_get_field_status_req {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
index c55c2c441a1a..70256372bec6 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
@@ -12,9 +12,9 @@ 
 #include <linux/hrtimer.h>
 #include <linux/ktime.h>
 
-#include "ptp.h"
 #include "mbox.h"
 #include "rvu.h"
+#include "ptp.h"
 
 #define DRV_NAME				"Marvell PTP Driver"
 
@@ -40,6 +40,7 @@ 
 #define PTP_CLOCK_CFG_TSTMP_EDGE		BIT_ULL(9)
 #define PTP_CLOCK_CFG_TSTMP_EN			BIT_ULL(8)
 #define PTP_CLOCK_CFG_TSTMP_IN_MASK		GENMASK_ULL(15, 10)
+#define PTP_CLOCK_CFG_ATOMIC_OP_MASK		GENMASK_ULL(28, 26)
 #define PTP_CLOCK_CFG_PPS_EN			BIT_ULL(30)
 #define PTP_CLOCK_CFG_PPS_INV			BIT_ULL(31)
 
@@ -53,36 +54,70 @@ 
 #define PTP_TIMESTAMP				0xF20ULL
 #define PTP_CLOCK_SEC				0xFD0ULL
 #define PTP_SEC_ROLLOVER			0xFD8ULL
+/* Atomic update related CSRs */
+#define PTP_FRNS_TIMESTAMP			0xFE0ULL
+#define PTP_NXT_ROLLOVER_SET			0xFE8ULL
+#define PTP_CURR_ROLLOVER_SET			0xFF0ULL
+#define PTP_NANO_TIMESTAMP			0xFF8ULL
+#define PTP_SEC_TIMESTAMP			0x1000ULL
 
 #define CYCLE_MULT				1000
 
+/* PTP atomic update operation type */
+enum atomic_opcode {
+	ATOMIC_SET = 1,
+	ATOMIC_INC = 3,
+	ATOMIC_DEC = 4
+};
+
 static struct ptp *first_ptp_block;
 static const struct pci_device_id ptp_id_table[];
 
-static bool is_ptp_dev_cnf10kb(struct ptp *ptp)
+static bool is_ptp_dev_cnf10ka(struct ptp *ptp)
 {
-	return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_PTP;
+	return (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP) ? true : false;
 }
 
-static bool is_ptp_dev_cn10k(struct ptp *ptp)
+static bool is_ptp_dev_cn10ka(struct ptp *ptp)
 {
-	return ptp->pdev->device == PCI_DEVID_CN10K_PTP;
+	return (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP) ? true : false;
 }
 
 static bool cn10k_ptp_errata(struct ptp *ptp)
 {
-	if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
-	    ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
+	if ((is_ptp_dev_cn10ka(ptp) &&
+	     ((ptp->pdev->revision & 0x0F) == 0x0 || (ptp->pdev->revision & 0x0F) == 0x1)) ||
+	    (is_ptp_dev_cnf10ka(ptp) &&
+	     ((ptp->pdev->revision & 0x0F) == 0x0 || (ptp->pdev->revision & 0x0F) == 0x1)))
 		return true;
+
 	return false;
 }
 
-static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp)
+static inline bool is_tstmp_atomic_update_supported(struct rvu *rvu)
 {
-	if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
-	    ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
+	struct ptp *ptp = rvu->ptp;
+	struct pci_dev *pdev;
+
+	if (is_rvu_otx2(rvu))
+		return false;
+
+	pdev = ptp->pdev;
+
+	/* On older silicon variants of CN10K, atomic update feature
+	 * is not available.
+	 */
+	if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP &&
+	     (pdev->revision & 0x0F) == 0x0) ||
+	     (pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP &&
+	     (pdev->revision & 0x0F) == 0x1) ||
+	     (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP &&
+	     (pdev->revision & 0x0F) == 0x0) ||
+	     (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP &&
+	     (pdev->revision & 0x0F) == 0x1))
+		return false;
+	else
 		return true;
-	return false;
 }
 
 static enum hrtimer_restart ptp_reset_thresh(struct hrtimer *hrtimer)
@@ -222,6 +257,65 @@  void ptp_put(struct ptp *ptp)
 	pci_dev_put(ptp->pdev);
 }
 
+static void ptp_atomic_update(struct ptp *ptp, u64 timestamp)
+{
+	u64 regval, curr_rollover_set, nxt_rollover_set;
+
+	/* First setup NSECs and SECs */
+	writeq(timestamp, ptp->reg_base + PTP_NANO_TIMESTAMP);
+	writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
+	writeq(timestamp / NSEC_PER_SEC,
+	       ptp->reg_base + PTP_SEC_TIMESTAMP);
+
+	nxt_rollover_set = roundup(timestamp, NSEC_PER_SEC);
+	curr_rollover_set = nxt_rollover_set - NSEC_PER_SEC;
+	writeq(nxt_rollover_set, ptp->reg_base + PTP_NXT_ROLLOVER_SET);
+	writeq(curr_rollover_set, ptp->reg_base + PTP_CURR_ROLLOVER_SET);
+
+	/* Now, initiate atomic update */
+	regval = readq(ptp->reg_base + PTP_CLOCK_CFG);
+	regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
+	regval |= (ATOMIC_SET << 26);
+	writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);
+}
+
+static void ptp_atomic_adjtime(struct ptp *ptp, s64 delta)
+{
+	bool neg_adj = false, atomic_inc_dec = false;
+	u64 regval, ptp_clock_hi;
+
+	if (delta < 0) {
+		delta = -delta;
+		neg_adj = true;
+	}
+
+	/* use atomic inc/dec when delta < 1 second */
+	if (delta < NSEC_PER_SEC)
+		atomic_inc_dec = true;
+
+	if (!atomic_inc_dec) {
+		ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI);
+		if (neg_adj) {
+			if (ptp_clock_hi > delta)
+				ptp_clock_hi -= delta;
+			else
+				ptp_clock_hi = delta - ptp_clock_hi;
+		} else {
+			ptp_clock_hi += delta;
+		}
+		ptp_atomic_update(ptp, ptp_clock_hi);
+	} else {
+		writeq(delta, ptp->reg_base + PTP_NANO_TIMESTAMP);
+		writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
+
+		/* initiate atomic inc/dec */
+		regval = readq(ptp->reg_base + PTP_CLOCK_CFG);
+		regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
+		regval |= neg_adj ? (ATOMIC_DEC << 26) : (ATOMIC_INC << 26);
+		writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);
+	}
+}
+
 static int ptp_adjfine(struct ptp *ptp, long scaled_ppm)
 {
 	bool neg_adj = false;
@@ -277,8 +371,9 @@  static int ptp_get_clock(struct ptp *ptp, u64 *clk)
 	return 0;
 }
 
-void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
+void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts)
 {
+	struct ptp *ptp = rvu->ptp;
 	struct pci_dev *pdev;
 	u64 clock_comp;
 	u64 clock_cfg;
@@ -297,8 +392,14 @@  void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
 	ptp->clock_rate = sclk * 1000000;
 
 	/* Program the seconds rollover value to 1 second */
-	if (is_ptp_dev_cnf10kb(ptp))
+	if (is_tstmp_atomic_update_supported(rvu)) {
+		writeq(0, ptp->reg_base + PTP_NANO_TIMESTAMP);
+		writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
+		writeq(0, ptp->reg_base + PTP_SEC_TIMESTAMP);
+		writeq(0, ptp->reg_base + PTP_CURR_ROLLOVER_SET);
+		writeq(0x3b9aca00, ptp->reg_base + PTP_NXT_ROLLOVER_SET);
 		writeq(0x3b9aca00, ptp->reg_base + PTP_SEC_ROLLOVER);
+	}
 
 	/* Enable PTP clock */
 	clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
@@ -320,6 +421,10 @@  void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
 	clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
 	clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV;
 	writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
+	clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
+	clock_cfg &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
+	clock_cfg |= (ATOMIC_SET << 26);
+	writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
 
 	/* Set 50% duty cycle for 1Hz output */
 	writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_HI_INCR);
@@ -350,7 +455,7 @@  static int ptp_get_tstmp(struct ptp *ptp, u64 *clk)
 {
 	u64 timestamp;
 
-	if (is_ptp_dev_cn10k(ptp)) {
+	if (is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) {
 		timestamp = readq(ptp->reg_base + PTP_TIMESTAMP);
 		*clk = (timestamp >> 32) * NSEC_PER_SEC + (timestamp & 0xFFFFFFFF);
 	} else {
@@ -414,14 +519,12 @@  static int ptp_probe(struct pci_dev *pdev,
 		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;
-
 	if (cn10k_ptp_errata(ptp)) {
+		ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec;
 		hrtimer_init(&ptp->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 		ptp->hrtimer.function = ptp_reset_thresh;
+	} else {
+		ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec;
 	}
 
 	return 0;
@@ -521,6 +624,12 @@  int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,
 	case PTP_OP_EXTTS_ON:
 		err = ptp_extts_on(rvu->ptp, req->extts_on);
 		break;
+	case PTP_OP_ADJTIME:
+		ptp_atomic_adjtime(rvu->ptp, req->delta);
+		break;
+	case PTP_OP_SET_CLOCK:
+		ptp_atomic_update(rvu->ptp, (u64)req->clk);
+		break;
 	default:
 		err = -EINVAL;
 		break;
@@ -528,3 +637,17 @@  int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,
 
 	return err;
 }
+
+int rvu_mbox_handler_ptp_get_cap(struct rvu *rvu, struct msg_req *req,
+				 struct ptp_get_cap_rsp *rsp)
+{
+	if (!rvu->ptp)
+		return -ENODEV;
+
+	if (is_tstmp_atomic_update_supported(rvu))
+		rsp->cap |= PTP_CAP_HW_ATOMIC_UPDATE;
+	else
+		rsp->cap &= ~BIT_ULL_MASK(0);
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
index b9d92abc3844..0268a5e0b8bc 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
@@ -25,7 +25,7 @@  struct ptp {
 
 struct ptp *ptp_get(void);
 void ptp_put(struct ptp *ptp);
-void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts);
+void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts);
 
 extern struct pci_driver ptp_driver;
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 73df2d564545..22c395c7d040 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -3322,7 +3322,7 @@  static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	mutex_init(&rvu->rswitch.switch_lock);
 
 	if (rvu->fwdata)
-		ptp_start(rvu->ptp, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate,
+		ptp_start(rvu, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate,
 			  rvu->fwdata->ptp_ext_tstamp);
 
 	return 0;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index e8e65fd7888d..c4d999ef5ab4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -17,6 +17,7 @@ 
 #include "mbox.h"
 #include "npc.h"
 #include "rvu_reg.h"
+#include "ptp.h"
 
 /* PCI device IDs */
 #define	PCI_DEVID_OCTEONTX2_RVU_AF		0xA065
@@ -26,6 +27,7 @@ 
 #define PCI_SUBSYS_DEVID_98XX                  0xB100
 #define PCI_SUBSYS_DEVID_96XX                  0xB200
 #define PCI_SUBSYS_DEVID_CN10K_A	       0xB900
+#define PCI_SUBSYS_DEVID_CNF10K_A	       0xBA00
 #define PCI_SUBSYS_DEVID_CNF10K_B              0xBC00
 #define PCI_SUBSYS_DEVID_CN10K_B               0xBD00
 
@@ -634,6 +636,16 @@  static inline bool is_rvu_otx2(struct rvu *rvu)
 		midr == PCI_REVISION_ID_95XXMM || midr == PCI_REVISION_ID_95XXO);
 }
 
+static inline bool is_cnf10ka_a0(struct rvu *rvu)
+{
+	struct pci_dev *pdev = rvu->pdev;
+
+	if (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A &&
+	    (pdev->revision & 0x0F) == 0x0)
+		return true;
+	return false;
+}
+
 static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu)
 {
 	u64 npc_const3;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 25e99fd2e3fd..ee37235e6f09 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -326,6 +326,7 @@  struct otx2_ptp {
 	struct ptp_pin_desc extts_config;
 	u64 (*convert_rx_ptp_tstmp)(u64 timestamp);
 	u64 (*convert_tx_ptp_tstmp)(u64 timestamp);
+	u64 (*ptp_tstamp2nsec)(const struct timecounter *time_counter, u64 timestamp);
 	struct delayed_work synctstamp_work;
 	u64 tstamp;
 	u32 base_ns;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
index 896b2f9bac34..839d7a07939d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
@@ -10,6 +10,62 @@ 
 #include "otx2_common.h"
 #include "otx2_ptp.h"
 
+static bool is_tstmp_atomic_update_supported(struct otx2_ptp *ptp)
+{
+	struct ptp_get_cap_rsp *rsp;
+	struct msg_req *req;
+	int err;
+
+	if (!ptp->nic)
+		return 0;
+
+	mutex_lock(&ptp->nic->mbox.lock);
+	req = otx2_mbox_alloc_msg_ptp_get_cap(&ptp->nic->mbox);
+	if (!req)
+		return 0;
+
+	err = otx2_sync_mbox_msg(&ptp->nic->mbox);
+	if (err)
+		return 0;
+
+	rsp = (struct ptp_get_cap_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
+							  &req->hdr);
+	mutex_unlock(&ptp->nic->mbox.lock);
+
+	if (IS_ERR(rsp))
+		return false;
+
+	if (rsp->cap & PTP_CAP_HW_ATOMIC_UPDATE)
+		return true;
+
+	return false;
+}
+
+static int otx2_ptp_hw_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
+{
+	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
+					    ptp_info);
+	struct otx2_nic *pfvf = ptp->nic;
+	struct ptp_req *req;
+	int rc;
+
+	if (!ptp->nic)
+		return -ENODEV;
+
+	mutex_lock(&pfvf->mbox.lock);
+	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
+	if (!req) {
+		mutex_unlock(&pfvf->mbox.lock);
+		return -ENOMEM;
+	}
+	req->op = PTP_OP_ADJTIME;
+	req->delta = delta;
+	rc = otx2_sync_mbox_msg(&ptp->nic->mbox);
+	mutex_unlock(&pfvf->mbox.lock);
+
+	return rc;
+}
+
 static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp)
 {
 	struct ptp_req *req;
@@ -37,6 +93,49 @@  static u64 otx2_ptp_get_clock(struct otx2_ptp *ptp)
 	return rsp->clk;
 }
 
+static int otx2_ptp_hw_gettime(struct ptp_clock_info *ptp_info,
+			       struct timespec64 *ts)
+{
+	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
+					    ptp_info);
+	u64 tstamp;
+
+	tstamp = otx2_ptp_get_clock(ptp);
+
+	*ts = ns_to_timespec64(tstamp);
+	return 0;
+}
+
+static int otx2_ptp_hw_settime(struct ptp_clock_info *ptp_info,
+			       const struct timespec64 *ts)
+{
+	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
+					    ptp_info);
+	struct otx2_nic *pfvf = ptp->nic;
+	struct ptp_req *req;
+	u64 nsec;
+	int rc;
+
+	if (!ptp->nic)
+		return -ENODEV;
+
+	nsec = timespec64_to_ns(ts);
+
+	mutex_lock(&pfvf->mbox.lock);
+	req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
+	if (!req) {
+		mutex_unlock(&pfvf->mbox.lock);
+		return -ENOMEM;
+	}
+
+	req->op = PTP_OP_SET_CLOCK;
+	req->clk = nsec;
+	rc = otx2_sync_mbox_msg(&ptp->nic->mbox);
+	mutex_unlock(&pfvf->mbox.lock);
+
+	return rc;
+}
+
 static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
 {
 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
@@ -124,21 +223,15 @@  static u64 ptp_tstmp_read(struct otx2_ptp *ptp)
 	return rsp->clk;
 }
 
-static void otx2_get_ptpclock(struct otx2_ptp *ptp, u64 *tstamp)
-{
-	struct otx2_nic *pfvf = ptp->nic;
-
-	mutex_lock(&pfvf->mbox.lock);
-	*tstamp = timecounter_read(&ptp->time_counter);
-	mutex_unlock(&pfvf->mbox.lock);
-}
-
-static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
+static int otx2_ptp_tc_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
 {
 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
 					    ptp_info);
 	struct otx2_nic *pfvf = ptp->nic;
 
+	if (!ptp->nic)
+		return -ENODEV;
+
 	mutex_lock(&pfvf->mbox.lock);
 	timecounter_adjtime(&ptp->time_counter, delta);
 	mutex_unlock(&pfvf->mbox.lock);
@@ -146,32 +239,33 @@  static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
 	return 0;
 }
 
-static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info,
-			    struct timespec64 *ts)
+static int otx2_ptp_tc_gettime(struct ptp_clock_info *ptp_info,
+			       struct timespec64 *ts)
 {
 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
 					    ptp_info);
 	u64 tstamp;
 
-	otx2_get_ptpclock(ptp, &tstamp);
+	mutex_lock(&ptp->nic->mbox.lock);
+	tstamp = timecounter_read(&ptp->time_counter);
+	mutex_unlock(&ptp->nic->mbox.lock);
 	*ts = ns_to_timespec64(tstamp);
 
 	return 0;
 }
 
-static int otx2_ptp_settime(struct ptp_clock_info *ptp_info,
-			    const struct timespec64 *ts)
+static int otx2_ptp_tc_settime(struct ptp_clock_info *ptp_info,
+			       const struct timespec64 *ts)
 {
 	struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
 					    ptp_info);
-	struct otx2_nic *pfvf = ptp->nic;
 	u64 nsec;
 
 	nsec = timespec64_to_ns(ts);
 
-	mutex_lock(&pfvf->mbox.lock);
+	mutex_lock(&ptp->nic->mbox.lock);
 	timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec);
-	mutex_unlock(&pfvf->mbox.lock);
+	mutex_unlock(&ptp->nic->mbox.lock);
 
 	return 0;
 }
@@ -190,6 +284,12 @@  static int otx2_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
 	return 0;
 }
 
+static u64 otx2_ptp_hw_tstamp2time(const struct timecounter *time_counter, u64 tstamp)
+{
+	/* On HW which supports atomic updates, timecounter is not initialized */
+	return tstamp;
+}
+
 static void otx2_ptp_extts_check(struct work_struct *work)
 {
 	struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
@@ -204,7 +304,7 @@  static void otx2_ptp_extts_check(struct work_struct *work)
 	if (tstmp != ptp->last_extts) {
 		event.type = PTP_CLOCK_EXTTS;
 		event.index = 0;
-		event.timestamp = timecounter_cyc2time(&ptp->time_counter, tstmp);
+		event.timestamp = ptp->ptp_tstamp2nsec(&ptp->time_counter, tstmp);
 		ptp_clock_event(ptp->ptp_clock, &event);
 		new_thresh = tstmp % 500000000;
 		if (ptp->thresh != new_thresh) {
@@ -229,7 +329,7 @@  static void otx2_sync_tstamp(struct work_struct *work)
 	tstamp = otx2_ptp_get_clock(ptp);
 	mutex_unlock(&pfvf->mbox.lock);
 
-	ptp->tstamp = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
+	ptp->tstamp = ptp->ptp_tstamp2nsec(&ptp->time_counter, tstamp);
 	ptp->base_ns = tstamp % NSEC_PER_SEC;
 
 	schedule_delayed_work(&ptp->synctstamp_work, msecs_to_jiffies(250));
@@ -302,15 +402,6 @@  int otx2_ptp_init(struct otx2_nic *pfvf)
 
 	ptp_ptr->nic = pfvf;
 
-	cc = &ptp_ptr->cycle_counter;
-	cc->read = ptp_cc_read;
-	cc->mask = CYCLECOUNTER_MASK(64);
-	cc->mult = 1;
-	cc->shift = 0;
-
-	timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
-			 ktime_to_ns(ktime_get_real()));
-
 	snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->extts_config.name), "TSTAMP");
 	ptp_ptr->extts_config.index = 0;
 	ptp_ptr->extts_config.func = PTP_PF_NONE;
@@ -324,13 +415,33 @@  int otx2_ptp_init(struct otx2_nic *pfvf)
 		.pps            = 0,
 		.pin_config     = &ptp_ptr->extts_config,
 		.adjfine        = otx2_ptp_adjfine,
-		.adjtime        = otx2_ptp_adjtime,
-		.gettime64      = otx2_ptp_gettime,
-		.settime64      = otx2_ptp_settime,
 		.enable         = otx2_ptp_enable,
 		.verify         = otx2_ptp_verify_pin,
 	};
 
+	/* Check whether hardware supports atomic updates to timestamp */
+	if (is_tstmp_atomic_update_supported(ptp_ptr)) {
+		ptp_ptr->ptp_info.adjtime = otx2_ptp_hw_adjtime;
+		ptp_ptr->ptp_info.gettime64 = otx2_ptp_hw_gettime;
+		ptp_ptr->ptp_info.settime64 = otx2_ptp_hw_settime;
+
+		ptp_ptr->ptp_tstamp2nsec = otx2_ptp_hw_tstamp2time;
+	} else {
+		ptp_ptr->ptp_info.adjtime = otx2_ptp_tc_adjtime;
+		ptp_ptr->ptp_info.gettime64 = otx2_ptp_tc_gettime;
+		ptp_ptr->ptp_info.settime64 = otx2_ptp_tc_settime;
+
+		cc = &ptp_ptr->cycle_counter;
+		cc->read = ptp_cc_read;
+		cc->mask = CYCLECOUNTER_MASK(64);
+		cc->mult = 1;
+		cc->shift = 0;
+		ptp_ptr->ptp_tstamp2nsec = timecounter_cyc2time;
+
+		timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
+				 ktime_to_ns(ktime_get_real()));
+	}
+
 	INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check);
 
 	ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev);
@@ -387,7 +498,7 @@  int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns)
 	if (!pfvf->ptp)
 		return -ENODEV;
 
-	*tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
+	*tsns = pfvf->ptp->ptp_tstamp2nsec(&pfvf->ptp->time_counter, tstamp);
 
 	return 0;
 }