Lines Matching full:ptp
2 /* Marvell PTP driver
16 #include "ptp.h"
19 #define DRV_NAME "Marvell PTP Driver"
67 #define is_rev_A0(ptp) (((ptp)->pdev->revision & 0x0F) == 0x0) argument
68 #define is_rev_A1(ptp) (((ptp)->pdev->revision & 0x0F) == 0x1) argument
70 /* PTP atomic update operation type */
77 static struct ptp *first_ptp_block;
80 static bool is_ptp_dev_cnf10ka(struct ptp *ptp) in is_ptp_dev_cnf10ka() argument
82 return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP; in is_ptp_dev_cnf10ka()
85 static bool is_ptp_dev_cn10ka(struct ptp *ptp) in is_ptp_dev_cn10ka() argument
87 return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP; in is_ptp_dev_cn10ka()
90 static bool cn10k_ptp_errata(struct ptp *ptp) in cn10k_ptp_errata() argument
92 if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) && in cn10k_ptp_errata()
93 (is_rev_A0(ptp) || is_rev_A1(ptp))) in cn10k_ptp_errata()
101 struct ptp *ptp = rvu->ptp; in is_tstmp_atomic_update_supported() local
109 if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) && in is_tstmp_atomic_update_supported()
110 (is_rev_A0(ptp) || is_rev_A1(ptp))) in is_tstmp_atomic_update_supported()
118 struct ptp *ptp = container_of(hrtimer, struct ptp, hrtimer); in ptp_reset_thresh() local
124 delta_ns = ktime_to_ns(ktime_sub(curr_ts, ptp->last_ts)); in ptp_reset_thresh()
126 /* if the ptp clock value has crossed 0.5 seconds, in ptp_reset_thresh()
130 ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI); in ptp_reset_thresh()
134 writeq(500000000, ptp->reg_base + PTP_PPS_THRESH_HI); in ptp_reset_thresh()
139 ptp->last_ts = curr_ts; in ptp_reset_thresh()
144 static void ptp_hrtimer_start(struct ptp *ptp, ktime_t start_ns) in ptp_hrtimer_start() argument
149 hrtimer_start(&ptp->hrtimer, period_ns, HRTIMER_MODE_REL); in ptp_hrtimer_start()
150 ptp->last_ts = ktime_get(); in ptp_hrtimer_start()
153 static u64 read_ptp_tstmp_sec_nsec(struct ptp *ptp) in read_ptp_tstmp_sec_nsec() argument
158 spin_lock_irqsave(&ptp->ptp_lock, flags); in read_ptp_tstmp_sec_nsec()
159 sec = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL; in read_ptp_tstmp_sec_nsec()
160 nsec = readq(ptp->reg_base + PTP_CLOCK_HI); in read_ptp_tstmp_sec_nsec()
161 sec1 = readq(ptp->reg_base + PTP_CLOCK_SEC) & 0xFFFFFFFFUL; in read_ptp_tstmp_sec_nsec()
164 nsec = readq(ptp->reg_base + PTP_CLOCK_HI); in read_ptp_tstmp_sec_nsec()
167 spin_unlock_irqrestore(&ptp->ptp_lock, flags); in read_ptp_tstmp_sec_nsec()
172 static u64 read_ptp_tstmp_nsec(struct ptp *ptp) in read_ptp_tstmp_nsec() argument
174 return readq(ptp->reg_base + PTP_CLOCK_HI); in read_ptp_tstmp_nsec()
199 /* check whether ptp nanosecond counter rolls over early */ in ptp_calc_adjusted_comp()
215 /* speed up the ptp clock to account for nanoseconds lost */ in ptp_calc_adjusted_comp()
220 /* slow down the ptp clock to not rollover early */ in ptp_calc_adjusted_comp()
229 struct ptp *ptp_get(void) in ptp_get()
231 struct ptp *ptp = first_ptp_block; in ptp_get() local
233 /* Check PTP block is present in hardware */ in ptp_get()
236 /* Check driver is bound to PTP block */ in ptp_get()
237 if (!ptp) in ptp_get()
238 ptp = ERR_PTR(-EPROBE_DEFER); in ptp_get()
239 else if (!IS_ERR(ptp)) in ptp_get()
240 pci_dev_get(ptp->pdev); in ptp_get()
242 return ptp; in ptp_get()
245 void ptp_put(struct ptp *ptp) in ptp_put() argument
247 if (!ptp) in ptp_put()
250 pci_dev_put(ptp->pdev); in ptp_put()
253 static void ptp_atomic_update(struct ptp *ptp, u64 timestamp) in ptp_atomic_update() argument
258 writeq(timestamp, ptp->reg_base + PTP_NANO_TIMESTAMP); in ptp_atomic_update()
259 writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP); in ptp_atomic_update()
261 ptp->reg_base + PTP_SEC_TIMESTAMP); in ptp_atomic_update()
265 writeq(nxt_rollover_set, ptp->reg_base + PTP_NXT_ROLLOVER_SET); in ptp_atomic_update()
266 writeq(curr_rollover_set, ptp->reg_base + PTP_CURR_ROLLOVER_SET); in ptp_atomic_update()
269 regval = readq(ptp->reg_base + PTP_CLOCK_CFG); in ptp_atomic_update()
272 writeq(regval, ptp->reg_base + PTP_CLOCK_CFG); in ptp_atomic_update()
275 static void ptp_atomic_adjtime(struct ptp *ptp, s64 delta) in ptp_atomic_adjtime() argument
290 ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI); in ptp_atomic_adjtime()
299 ptp_atomic_update(ptp, ptp_clock_hi); in ptp_atomic_adjtime()
301 writeq(delta, ptp->reg_base + PTP_NANO_TIMESTAMP); in ptp_atomic_adjtime()
302 writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP); in ptp_atomic_adjtime()
305 regval = readq(ptp->reg_base + PTP_CLOCK_CFG); in ptp_atomic_adjtime()
308 writeq(regval, ptp->reg_base + PTP_CLOCK_CFG); in ptp_atomic_adjtime()
312 static int ptp_adjfine(struct ptp *ptp, long scaled_ppm) in ptp_adjfine() argument
324 /* The hardware adds the clock compensation value to the PTP clock in ptp_adjfine()
343 if (cn10k_ptp_errata(ptp)) { in ptp_adjfine()
345 freq_adj = (ptp->clock_rate * ppb) / 1000000000ULL; in ptp_adjfine()
346 freq = neg_adj ? ptp->clock_rate + freq_adj : ptp->clock_rate - freq_adj; in ptp_adjfine()
349 comp = ((u64)1000000000ull << 32) / ptp->clock_rate; in ptp_adjfine()
354 writeq(comp, ptp->reg_base + PTP_CLOCK_COMP); in ptp_adjfine()
359 static int ptp_get_clock(struct ptp *ptp, u64 *clk) in ptp_get_clock() argument
361 /* Return the current PTP clock */ in ptp_get_clock()
362 *clk = ptp->read_ptp_tstmp(ptp); in ptp_get_clock()
369 struct ptp *ptp = rvu->ptp; in ptp_start() local
374 if (!ptp) in ptp_start()
377 pdev = ptp->pdev; in ptp_start()
380 dev_err(&pdev->dev, "PTP input clock cannot be zero\n"); in ptp_start()
385 ptp->clock_rate = sclk * 1000000; in ptp_start()
389 writeq(0, ptp->reg_base + PTP_NANO_TIMESTAMP); in ptp_start()
390 writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP); in ptp_start()
391 writeq(0, ptp->reg_base + PTP_SEC_TIMESTAMP); in ptp_start()
392 writeq(0, ptp->reg_base + PTP_CURR_ROLLOVER_SET); in ptp_start()
393 writeq(0x3b9aca00, ptp->reg_base + PTP_NXT_ROLLOVER_SET); in ptp_start()
394 writeq(0x3b9aca00, ptp->reg_base + PTP_SEC_ROLLOVER); in ptp_start()
397 /* Enable PTP clock */ in ptp_start()
398 clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); in ptp_start()
401 ptp->clock_rate = ext_clk_freq; in ptp_start()
402 /* Set GPIO as PTP clock source */ in ptp_start()
415 writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); in ptp_start()
416 clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); in ptp_start()
419 writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); in ptp_start()
421 if (cn10k_ptp_errata(ptp)) in ptp_start()
422 clock_comp = ptp_calc_adjusted_comp(ptp->clock_rate); in ptp_start()
424 clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate; in ptp_start()
427 writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP); in ptp_start()
430 static int ptp_get_tstmp(struct ptp *ptp, u64 *clk) in ptp_get_tstmp() argument
434 if (is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) { in ptp_get_tstmp()
435 timestamp = readq(ptp->reg_base + PTP_TIMESTAMP); in ptp_get_tstmp()
438 *clk = readq(ptp->reg_base + PTP_TIMESTAMP); in ptp_get_tstmp()
444 static int ptp_set_thresh(struct ptp *ptp, u64 thresh) in ptp_set_thresh() argument
446 if (!cn10k_ptp_errata(ptp)) in ptp_set_thresh()
447 writeq(thresh, ptp->reg_base + PTP_PPS_THRESH_HI); in ptp_set_thresh()
452 static int ptp_config_hrtimer(struct ptp *ptp, int on) in ptp_config_hrtimer() argument
457 ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI); in ptp_config_hrtimer()
458 ptp_hrtimer_start(ptp, (ktime_t)ptp_clock_hi); in ptp_config_hrtimer()
460 if (hrtimer_active(&ptp->hrtimer)) in ptp_config_hrtimer()
461 hrtimer_cancel(&ptp->hrtimer); in ptp_config_hrtimer()
467 static int ptp_pps_on(struct ptp *ptp, int on, u64 period) in ptp_pps_on() argument
471 clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); in ptp_pps_on()
473 if (cn10k_ptp_errata(ptp) && period != NSEC_PER_SEC) { in ptp_pps_on()
474 dev_err(&ptp->pdev->dev, "Supports max period value as 1 second\n"); in ptp_pps_on()
479 dev_err(&ptp->pdev->dev, "Supports max period as 8 seconds\n"); in ptp_pps_on()
484 writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); in ptp_pps_on()
486 writeq(0, ptp->reg_base + PTP_PPS_THRESH_HI); in ptp_pps_on()
487 writeq(0, ptp->reg_base + PTP_PPS_THRESH_LO); in ptp_pps_on()
491 writeq(((u64)period << 32), ptp->reg_base + PTP_PPS_HI_INCR); in ptp_pps_on()
492 writeq(((u64)period << 32), ptp->reg_base + PTP_PPS_LO_INCR); in ptp_pps_on()
495 writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); in ptp_pps_on()
498 if (on && cn10k_ptp_errata(ptp)) { in ptp_pps_on()
506 ptp->clock_period = NSEC_PER_SEC / ptp->clock_rate; in ptp_pps_on()
507 writeq((0x1dcd6500ULL - ptp->clock_period) << 32, in ptp_pps_on()
508 ptp->reg_base + PTP_PPS_LO_INCR); in ptp_pps_on()
511 if (cn10k_ptp_errata(ptp)) in ptp_pps_on()
512 ptp_config_hrtimer(ptp, on); in ptp_pps_on()
520 struct ptp *ptp; in ptp_probe() local
523 ptp = kzalloc(sizeof(*ptp), GFP_KERNEL); in ptp_probe()
524 if (!ptp) { in ptp_probe()
529 ptp->pdev = pdev; in ptp_probe()
539 ptp->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO]; in ptp_probe()
541 pci_set_drvdata(pdev, ptp); in ptp_probe()
543 first_ptp_block = ptp; in ptp_probe()
545 spin_lock_init(&ptp->ptp_lock); in ptp_probe()
546 if (cn10k_ptp_errata(ptp)) { in ptp_probe()
547 ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec; in ptp_probe()
548 hrtimer_init(&ptp->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); in ptp_probe()
549 ptp->hrtimer.function = ptp_reset_thresh; in ptp_probe()
551 ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec; in ptp_probe()
557 kfree(ptp); in ptp_probe()
574 struct ptp *ptp = pci_get_drvdata(pdev); in ptp_remove() local
577 if (IS_ERR_OR_NULL(ptp)) in ptp_remove()
580 if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer)) in ptp_remove()
581 hrtimer_cancel(&ptp->hrtimer); in ptp_remove()
583 /* Disable PTP clock */ in ptp_remove()
584 clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); in ptp_remove()
586 writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); in ptp_remove()
587 kfree(ptp); in ptp_remove()
625 /* This function is the PTP mailbox handler invoked when in rvu_mbox_handler_ptp_op()
627 * It is used by netdev driver to get the PTP clock and to set in rvu_mbox_handler_ptp_op()
629 * notion of whether the driver is bound to ptp device below in rvu_mbox_handler_ptp_op()
632 if (!rvu->ptp) in rvu_mbox_handler_ptp_op()
637 err = ptp_adjfine(rvu->ptp, req->scaled_ppm); in rvu_mbox_handler_ptp_op()
640 err = ptp_get_clock(rvu->ptp, &rsp->clk); in rvu_mbox_handler_ptp_op()
643 err = ptp_get_tstmp(rvu->ptp, &rsp->clk); in rvu_mbox_handler_ptp_op()
646 err = ptp_set_thresh(rvu->ptp, req->thresh); in rvu_mbox_handler_ptp_op()
649 err = ptp_pps_on(rvu->ptp, req->pps_on, req->period); in rvu_mbox_handler_ptp_op()
652 ptp_atomic_adjtime(rvu->ptp, req->delta); in rvu_mbox_handler_ptp_op()
655 ptp_atomic_update(rvu->ptp, (u64)req->clk); in rvu_mbox_handler_ptp_op()
668 if (!rvu->ptp) in rvu_mbox_handler_ptp_get_cap()