Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Marvell PTP driver
0003  *
0004  * Copyright (C) 2020 Marvell.
0005  *
0006  */
0007 
0008 #include <linux/bitfield.h>
0009 #include <linux/device.h>
0010 #include <linux/module.h>
0011 #include <linux/pci.h>
0012 
0013 #include "ptp.h"
0014 #include "mbox.h"
0015 #include "rvu.h"
0016 
0017 #define DRV_NAME                "Marvell PTP Driver"
0018 
0019 #define PCI_DEVID_OCTEONTX2_PTP         0xA00C
0020 #define PCI_SUBSYS_DEVID_OCTX2_98xx_PTP     0xB100
0021 #define PCI_SUBSYS_DEVID_OCTX2_96XX_PTP     0xB200
0022 #define PCI_SUBSYS_DEVID_OCTX2_95XX_PTP     0xB300
0023 #define PCI_SUBSYS_DEVID_OCTX2_95XXN_PTP    0xB400
0024 #define PCI_SUBSYS_DEVID_OCTX2_95MM_PTP     0xB500
0025 #define PCI_SUBSYS_DEVID_OCTX2_95XXO_PTP    0xB600
0026 #define PCI_DEVID_OCTEONTX2_RST         0xA085
0027 #define PCI_DEVID_CN10K_PTP         0xA09E
0028 #define PCI_SUBSYS_DEVID_CN10K_A_PTP        0xB900
0029 #define PCI_SUBSYS_DEVID_CNF10K_A_PTP       0xBA00
0030 #define PCI_SUBSYS_DEVID_CNF10K_B_PTP       0xBC00
0031 
0032 #define PCI_PTP_BAR_NO              0
0033 
0034 #define PTP_CLOCK_CFG               0xF00ULL
0035 #define PTP_CLOCK_CFG_PTP_EN            BIT_ULL(0)
0036 #define PTP_CLOCK_CFG_EXT_CLK_EN        BIT_ULL(1)
0037 #define PTP_CLOCK_CFG_EXT_CLK_IN_MASK       GENMASK_ULL(7, 2)
0038 #define PTP_CLOCK_CFG_TSTMP_EDGE        BIT_ULL(9)
0039 #define PTP_CLOCK_CFG_TSTMP_EN          BIT_ULL(8)
0040 #define PTP_CLOCK_CFG_TSTMP_IN_MASK     GENMASK_ULL(15, 10)
0041 #define PTP_CLOCK_CFG_PPS_EN            BIT_ULL(30)
0042 #define PTP_CLOCK_CFG_PPS_INV           BIT_ULL(31)
0043 
0044 #define PTP_PPS_HI_INCR             0xF60ULL
0045 #define PTP_PPS_LO_INCR             0xF68ULL
0046 #define PTP_PPS_THRESH_HI           0xF58ULL
0047 
0048 #define PTP_CLOCK_LO                0xF08ULL
0049 #define PTP_CLOCK_HI                0xF10ULL
0050 #define PTP_CLOCK_COMP              0xF18ULL
0051 #define PTP_TIMESTAMP               0xF20ULL
0052 #define PTP_CLOCK_SEC               0xFD0ULL
0053 
0054 #define CYCLE_MULT              1000
0055 
0056 static struct ptp *first_ptp_block;
0057 static const struct pci_device_id ptp_id_table[];
0058 
0059 static bool cn10k_ptp_errata(struct ptp *ptp)
0060 {
0061     if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
0062         ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
0063         return true;
0064     return false;
0065 }
0066 
0067 static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp)
0068 {
0069     if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
0070         ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
0071         return true;
0072     return false;
0073 }
0074 
0075 static u64 read_ptp_tstmp_sec_nsec(struct ptp *ptp)
0076 {
0077     u64 sec, sec1, nsec;
0078     unsigned long flags;
0079 
0080     spin_lock_irqsave(&ptp->ptp_lock, flags);
0081     sec = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL;
0082     nsec = readq(ptp->reg_base + PTP_CLOCK_HI);
0083     sec1 = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL;
0084     /* check nsec rollover */
0085     if (sec1 > sec) {
0086         nsec = readq(ptp->reg_base + PTP_CLOCK_HI);
0087         sec = sec1;
0088     }
0089     spin_unlock_irqrestore(&ptp->ptp_lock, flags);
0090 
0091     return sec * NSEC_PER_SEC + nsec;
0092 }
0093 
0094 static u64 read_ptp_tstmp_nsec(struct ptp *ptp)
0095 {
0096     return readq(ptp->reg_base + PTP_CLOCK_HI);
0097 }
0098 
0099 static u64 ptp_calc_adjusted_comp(u64 ptp_clock_freq)
0100 {
0101     u64 comp, adj = 0, cycles_per_sec, ns_drift = 0;
0102     u32 ptp_clock_nsec, cycle_time;
0103     int cycle;
0104 
0105     /* Errata:
0106      * Issue #1: At the time of 1 sec rollover of the nano-second counter,
0107      * the nano-second counter is set to 0. However, it should be set to
0108      * (existing counter_value - 10^9).
0109      *
0110      * Issue #2: The nano-second counter rolls over at 0x3B9A_C9FF.
0111      * It should roll over at 0x3B9A_CA00.
0112      */
0113 
0114     /* calculate ptp_clock_comp value */
0115     comp = ((u64)1000000000ULL << 32) / ptp_clock_freq;
0116     /* use CYCLE_MULT to avoid accuracy loss due to integer arithmetic */
0117     cycle_time = NSEC_PER_SEC * CYCLE_MULT / ptp_clock_freq;
0118     /* cycles per sec */
0119     cycles_per_sec = ptp_clock_freq;
0120 
0121     /* check whether ptp nanosecond counter rolls over early */
0122     cycle = cycles_per_sec - 1;
0123     ptp_clock_nsec = (cycle * comp) >> 32;
0124     while (ptp_clock_nsec < NSEC_PER_SEC) {
0125         if (ptp_clock_nsec == 0x3B9AC9FF)
0126             goto calc_adj_comp;
0127         cycle++;
0128         ptp_clock_nsec = (cycle * comp) >> 32;
0129     }
0130     /* compute nanoseconds lost per second when nsec counter rolls over */
0131     ns_drift = ptp_clock_nsec - NSEC_PER_SEC;
0132     /* calculate ptp_clock_comp adjustment */
0133     if (ns_drift > 0) {
0134         adj = comp * ns_drift;
0135         adj = adj / 1000000000ULL;
0136     }
0137     /* speed up the ptp clock to account for nanoseconds lost */
0138     comp += adj;
0139     return comp;
0140 
0141 calc_adj_comp:
0142     /* slow down the ptp clock to not rollover early */
0143     adj = comp * cycle_time;
0144     adj = adj / 1000000000ULL;
0145     adj = adj / CYCLE_MULT;
0146     comp -= adj;
0147 
0148     return comp;
0149 }
0150 
0151 struct ptp *ptp_get(void)
0152 {
0153     struct ptp *ptp = first_ptp_block;
0154 
0155     /* Check PTP block is present in hardware */
0156     if (!pci_dev_present(ptp_id_table))
0157         return ERR_PTR(-ENODEV);
0158     /* Check driver is bound to PTP block */
0159     if (!ptp)
0160         ptp = ERR_PTR(-EPROBE_DEFER);
0161     else
0162         pci_dev_get(ptp->pdev);
0163 
0164     return ptp;
0165 }
0166 
0167 void ptp_put(struct ptp *ptp)
0168 {
0169     if (!ptp)
0170         return;
0171 
0172     pci_dev_put(ptp->pdev);
0173 }
0174 
0175 static int ptp_adjfine(struct ptp *ptp, long scaled_ppm)
0176 {
0177     bool neg_adj = false;
0178     u32 freq, freq_adj;
0179     u64 comp, adj;
0180     s64 ppb;
0181 
0182     if (scaled_ppm < 0) {
0183         neg_adj = true;
0184         scaled_ppm = -scaled_ppm;
0185     }
0186 
0187     /* The hardware adds the clock compensation value to the PTP clock
0188      * on every coprocessor clock cycle. Typical convention is that it
0189      * represent number of nanosecond betwen each cycle. In this
0190      * convention compensation value is in 64 bit fixed-point
0191      * representation where upper 32 bits are number of nanoseconds
0192      * and lower is fractions of nanosecond.
0193      * The scaled_ppm represent the ratio in "parts per million" by which
0194      * the compensation value should be corrected.
0195      * To calculate new compenstation value we use 64bit fixed point
0196      * arithmetic on following formula
0197      * comp = tbase + tbase * scaled_ppm / (1M * 2^16)
0198      * where tbase is the basic compensation value calculated
0199      * initialy in the probe function.
0200      */
0201     /* convert scaled_ppm to ppb */
0202     ppb = 1 + scaled_ppm;
0203     ppb *= 125;
0204     ppb >>= 13;
0205 
0206     if (cn10k_ptp_errata(ptp)) {
0207         /* calculate the new frequency based on ppb */
0208         freq_adj = (ptp->clock_rate * ppb) / 1000000000ULL;
0209         freq = neg_adj ? ptp->clock_rate + freq_adj : ptp->clock_rate - freq_adj;
0210         comp = ptp_calc_adjusted_comp(freq);
0211     } else {
0212         comp = ((u64)1000000000ull << 32) / ptp->clock_rate;
0213         adj = comp * ppb;
0214         adj = div_u64(adj, 1000000000ull);
0215         comp = neg_adj ? comp - adj : comp + adj;
0216     }
0217     writeq(comp, ptp->reg_base + PTP_CLOCK_COMP);
0218 
0219     return 0;
0220 }
0221 
0222 static int ptp_get_clock(struct ptp *ptp, u64 *clk)
0223 {
0224     /* Return the current PTP clock */
0225     *clk = ptp->read_ptp_tstmp(ptp);
0226 
0227     return 0;
0228 }
0229 
0230 void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
0231 {
0232     struct pci_dev *pdev;
0233     u64 clock_comp;
0234     u64 clock_cfg;
0235 
0236     if (!ptp)
0237         return;
0238 
0239     pdev = ptp->pdev;
0240 
0241     if (!sclk) {
0242         dev_err(&pdev->dev, "PTP input clock cannot be zero\n");
0243         return;
0244     }
0245 
0246     /* sclk is in MHz */
0247     ptp->clock_rate = sclk * 1000000;
0248 
0249     /* Enable PTP clock */
0250     clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
0251 
0252     if (ext_clk_freq) {
0253         ptp->clock_rate = ext_clk_freq;
0254         /* Set GPIO as PTP clock source */
0255         clock_cfg &= ~PTP_CLOCK_CFG_EXT_CLK_IN_MASK;
0256         clock_cfg |= PTP_CLOCK_CFG_EXT_CLK_EN;
0257     }
0258 
0259     if (extts) {
0260         clock_cfg |= PTP_CLOCK_CFG_TSTMP_EDGE;
0261         /* Set GPIO as timestamping source */
0262         clock_cfg &= ~PTP_CLOCK_CFG_TSTMP_IN_MASK;
0263         clock_cfg |= PTP_CLOCK_CFG_TSTMP_EN;
0264     }
0265 
0266     clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
0267     clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV;
0268     writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
0269 
0270     /* Set 50% duty cycle for 1Hz output */
0271     writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_HI_INCR);
0272     writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_LO_INCR);
0273 
0274     if (cn10k_ptp_errata(ptp))
0275         clock_comp = ptp_calc_adjusted_comp(ptp->clock_rate);
0276     else
0277         clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate;
0278 
0279     /* Initial compensation value to start the nanosecs counter */
0280     writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP);
0281 }
0282 
0283 static int ptp_get_tstmp(struct ptp *ptp, u64 *clk)
0284 {
0285     *clk = readq(ptp->reg_base + PTP_TIMESTAMP);
0286 
0287     return 0;
0288 }
0289 
0290 static int ptp_set_thresh(struct ptp *ptp, u64 thresh)
0291 {
0292     writeq(thresh, ptp->reg_base + PTP_PPS_THRESH_HI);
0293 
0294     return 0;
0295 }
0296 
0297 static int ptp_probe(struct pci_dev *pdev,
0298              const struct pci_device_id *ent)
0299 {
0300     struct device *dev = &pdev->dev;
0301     struct ptp *ptp;
0302     int err;
0303 
0304     ptp = devm_kzalloc(dev, sizeof(*ptp), GFP_KERNEL);
0305     if (!ptp) {
0306         err = -ENOMEM;
0307         goto error;
0308     }
0309 
0310     ptp->pdev = pdev;
0311 
0312     err = pcim_enable_device(pdev);
0313     if (err)
0314         goto error_free;
0315 
0316     err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
0317     if (err)
0318         goto error_free;
0319 
0320     ptp->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
0321 
0322     pci_set_drvdata(pdev, ptp);
0323     if (!first_ptp_block)
0324         first_ptp_block = ptp;
0325 
0326     spin_lock_init(&ptp->ptp_lock);
0327     if (is_ptp_tsfmt_sec_nsec(ptp))
0328         ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec;
0329     else
0330         ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec;
0331 
0332     return 0;
0333 
0334 error_free:
0335     devm_kfree(dev, ptp);
0336 
0337 error:
0338     /* For `ptp_get()` we need to differentiate between the case
0339      * when the core has not tried to probe this device and the case when
0340      * the probe failed.  In the later case we pretend that the
0341      * initialization was successful and keep the error in
0342      * `dev->driver_data`.
0343      */
0344     pci_set_drvdata(pdev, ERR_PTR(err));
0345     if (!first_ptp_block)
0346         first_ptp_block = ERR_PTR(err);
0347 
0348     return 0;
0349 }
0350 
0351 static void ptp_remove(struct pci_dev *pdev)
0352 {
0353     struct ptp *ptp = pci_get_drvdata(pdev);
0354     u64 clock_cfg;
0355 
0356     if (IS_ERR_OR_NULL(ptp))
0357         return;
0358 
0359     /* Disable PTP clock */
0360     clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
0361     clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
0362     writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
0363 }
0364 
0365 static const struct pci_device_id ptp_id_table[] = {
0366     { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
0367              PCI_VENDOR_ID_CAVIUM,
0368              PCI_SUBSYS_DEVID_OCTX2_98xx_PTP) },
0369     { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
0370              PCI_VENDOR_ID_CAVIUM,
0371              PCI_SUBSYS_DEVID_OCTX2_96XX_PTP) },
0372     { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
0373              PCI_VENDOR_ID_CAVIUM,
0374              PCI_SUBSYS_DEVID_OCTX2_95XX_PTP) },
0375     { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
0376              PCI_VENDOR_ID_CAVIUM,
0377              PCI_SUBSYS_DEVID_OCTX2_95XXN_PTP) },
0378     { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
0379              PCI_VENDOR_ID_CAVIUM,
0380              PCI_SUBSYS_DEVID_OCTX2_95MM_PTP) },
0381     { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
0382              PCI_VENDOR_ID_CAVIUM,
0383              PCI_SUBSYS_DEVID_OCTX2_95XXO_PTP) },
0384     { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_PTP) },
0385     { 0, }
0386 };
0387 
0388 struct pci_driver ptp_driver = {
0389     .name = DRV_NAME,
0390     .id_table = ptp_id_table,
0391     .probe = ptp_probe,
0392     .remove = ptp_remove,
0393 };
0394 
0395 int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,
0396                 struct ptp_rsp *rsp)
0397 {
0398     int err = 0;
0399 
0400     /* This function is the PTP mailbox handler invoked when
0401      * called by AF consumers/netdev drivers via mailbox mechanism.
0402      * It is used by netdev driver to get the PTP clock and to set
0403      * frequency adjustments. Since mailbox can be called without
0404      * notion of whether the driver is bound to ptp device below
0405      * validation is needed as first step.
0406      */
0407     if (!rvu->ptp)
0408         return -ENODEV;
0409 
0410     switch (req->op) {
0411     case PTP_OP_ADJFINE:
0412         err = ptp_adjfine(rvu->ptp, req->scaled_ppm);
0413         break;
0414     case PTP_OP_GET_CLOCK:
0415         err = ptp_get_clock(rvu->ptp, &rsp->clk);
0416         break;
0417     case PTP_OP_GET_TSTMP:
0418         err = ptp_get_tstmp(rvu->ptp, &rsp->clk);
0419         break;
0420     case PTP_OP_SET_THRESH:
0421         err = ptp_set_thresh(rvu->ptp, req->thresh);
0422         break;
0423     default:
0424         err = -EINVAL;
0425         break;
0426     }
0427 
0428     return err;
0429 }