Lines Matching +full:ptp +full:- +full:ref

1 // SPDX-License-Identifier: GPL-2.0+
7 * https://github.com/microchip-ung/sparx-5_reginfo
30 * (1/1000000)/((2^-59)/X) in sparx5_ptp_get_1ppm()
35 switch (sparx5->coreclock) { in sparx5_ptp_get_1ppm()
60 switch (sparx5->coreclock) { in sparx5_ptp_get_nominal_value()
85 struct sparx5 *sparx5 = port->sparx5; in sparx5_ptp_hwtstamp_set()
88 /* For now don't allow to run ptp on ports that are part of a bridge, in sparx5_ptp_hwtstamp_set()
93 if (test_bit(port->portno, sparx5->bridge_mask)) in sparx5_ptp_hwtstamp_set()
94 return -EINVAL; in sparx5_ptp_hwtstamp_set()
96 switch (cfg->tx_type) { in sparx5_ptp_hwtstamp_set()
98 port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP; in sparx5_ptp_hwtstamp_set()
101 port->ptp_cmd = IFH_REW_OP_ONE_STEP_PTP; in sparx5_ptp_hwtstamp_set()
104 port->ptp_cmd = IFH_REW_OP_NOOP; in sparx5_ptp_hwtstamp_set()
107 return -ERANGE; in sparx5_ptp_hwtstamp_set()
110 switch (cfg->rx_filter) { in sparx5_ptp_hwtstamp_set()
127 cfg->rx_filter = HWTSTAMP_FILTER_ALL; in sparx5_ptp_hwtstamp_set()
130 return -ERANGE; in sparx5_ptp_hwtstamp_set()
134 mutex_lock(&sparx5->ptp_lock); in sparx5_ptp_hwtstamp_set()
135 phc = &sparx5->phc[SPARX5_PHC_PORT]; in sparx5_ptp_hwtstamp_set()
136 phc->hwtstamp_config = *cfg; in sparx5_ptp_hwtstamp_set()
137 mutex_unlock(&sparx5->ptp_lock); in sparx5_ptp_hwtstamp_set()
145 struct sparx5 *sparx5 = port->sparx5; in sparx5_ptp_hwtstamp_get()
148 phc = &sparx5->phc[SPARX5_PHC_PORT]; in sparx5_ptp_hwtstamp_get()
149 *cfg = phc->hwtstamp_config; in sparx5_ptp_hwtstamp_get()
159 if (port->ptp_cmd == IFH_REW_OP_NOOP) { in sparx5_ptp_classify()
190 if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) { in sparx5_ptp_classify()
212 spin_lock_irqsave(&port->tx_skbs.lock, flags); in sparx5_ptp_txtstamp_old_release()
213 skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) { in sparx5_ptp_txtstamp_old_release()
214 if time_after(SPARX5_SKB_CB(skb)->jiffies + SPARX5_PTP_TIMEOUT, in sparx5_ptp_txtstamp_old_release()
218 __skb_unlink(skb, &port->tx_skbs); in sparx5_ptp_txtstamp_old_release()
221 spin_unlock_irqrestore(&port->tx_skbs.lock, flags); in sparx5_ptp_txtstamp_old_release()
227 struct sparx5 *sparx5 = port->sparx5; in sparx5_ptp_txtstamp_request()
232 SPARX5_SKB_CB(skb)->rew_op = rew_op; in sparx5_ptp_txtstamp_request()
233 SPARX5_SKB_CB(skb)->pdu_type = pdu_type; in sparx5_ptp_txtstamp_request()
234 SPARX5_SKB_CB(skb)->pdu_w16_offset = pdu_w16_offset; in sparx5_ptp_txtstamp_request()
241 spin_lock_irqsave(&sparx5->ptp_ts_id_lock, flags); in sparx5_ptp_txtstamp_request()
242 if (sparx5->ptp_skbs == SPARX5_MAX_PTP_ID) { in sparx5_ptp_txtstamp_request()
243 spin_unlock_irqrestore(&sparx5->ptp_ts_id_lock, flags); in sparx5_ptp_txtstamp_request()
244 return -EBUSY; in sparx5_ptp_txtstamp_request()
247 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; in sparx5_ptp_txtstamp_request()
249 skb_queue_tail(&port->tx_skbs, skb); in sparx5_ptp_txtstamp_request()
250 SPARX5_SKB_CB(skb)->ts_id = port->ts_id; in sparx5_ptp_txtstamp_request()
251 SPARX5_SKB_CB(skb)->jiffies = jiffies; in sparx5_ptp_txtstamp_request()
253 sparx5->ptp_skbs++; in sparx5_ptp_txtstamp_request()
254 port->ts_id++; in sparx5_ptp_txtstamp_request()
255 if (port->ts_id == SPARX5_MAX_PTP_ID) in sparx5_ptp_txtstamp_request()
256 port->ts_id = 0; in sparx5_ptp_txtstamp_request()
258 spin_unlock_irqrestore(&sparx5->ptp_ts_id_lock, flags); in sparx5_ptp_txtstamp_request()
266 struct sparx5 *sparx5 = port->sparx5; in sparx5_ptp_txtstamp_release()
269 spin_lock_irqsave(&sparx5->ptp_ts_id_lock, flags); in sparx5_ptp_txtstamp_release()
270 port->ts_id--; in sparx5_ptp_txtstamp_release()
271 sparx5->ptp_skbs--; in sparx5_ptp_txtstamp_release()
272 skb_unlink(skb, &port->tx_skbs); in sparx5_ptp_txtstamp_release()
273 spin_unlock_irqrestore(&sparx5->ptp_ts_id_lock, flags); in sparx5_ptp_txtstamp_release()
280 /* Read current PTP time to get seconds */ in sparx5_get_hwtimestamp()
281 const struct sparx5_consts *consts = sparx5->data->consts; in sparx5_get_hwtimestamp()
285 spin_lock_irqsave(&sparx5->ptp_clock_lock, flags); in sparx5_get_hwtimestamp()
293 sparx5, PTP_PTP_PIN_CFG(consts->tod_pin)); in sparx5_get_hwtimestamp()
295 ts->tv_sec = spx5_rd(sparx5, PTP_PTP_TOD_SEC_LSB(consts->tod_pin)); in sparx5_get_hwtimestamp()
296 curr_nsec = spx5_rd(sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin)); in sparx5_get_hwtimestamp()
298 ts->tv_nsec = nsec; in sparx5_get_hwtimestamp()
302 ts->tv_sec--; in sparx5_get_hwtimestamp()
304 spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags); in sparx5_get_hwtimestamp()
312 while (budget--) { in sparx5_ptp_irq_handler()
336 port = sparx5->ports[txport]; in sparx5_ptp_irq_handler()
360 spin_lock_irqsave(&port->tx_skbs.lock, flags); in sparx5_ptp_irq_handler()
361 skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) { in sparx5_ptp_irq_handler()
362 if (SPARX5_SKB_CB(skb)->ts_id != id) in sparx5_ptp_irq_handler()
365 __skb_unlink(skb, &port->tx_skbs); in sparx5_ptp_irq_handler()
369 spin_unlock_irqrestore(&port->tx_skbs.lock, flags); in sparx5_ptp_irq_handler()
379 spin_lock(&sparx5->ptp_ts_id_lock); in sparx5_ptp_irq_handler()
380 sparx5->ptp_skbs--; in sparx5_ptp_irq_handler()
381 spin_unlock(&sparx5->ptp_ts_id_lock); in sparx5_ptp_irq_handler()
396 static int sparx5_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) in sparx5_ptp_adjfine() argument
398 struct sparx5_phc *phc = container_of(ptp, struct sparx5_phc, info); in sparx5_ptp_adjfine()
399 struct sparx5 *sparx5 = phc->sparx5; in sparx5_ptp_adjfine()
403 u64 ref; in sparx5_ptp_adjfine() local
410 scaled_ppm = -scaled_ppm; in sparx5_ptp_adjfine()
419 ref = sparx5_ptp_get_1ppm(sparx5) * (scaled_ppm >> 16); in sparx5_ptp_adjfine()
420 ref += (sparx5_ptp_get_1ppm(sparx5) * (0xffff & scaled_ppm)) >> 16; in sparx5_ptp_adjfine()
421 tod_inc = neg_adj ? tod_inc - ref : tod_inc + ref; in sparx5_ptp_adjfine()
423 spin_lock_irqsave(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_adjfine()
425 spx5_rmw(PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS_SET(1 << BIT(phc->index)), in sparx5_ptp_adjfine()
430 PTP_CLK_PER_CFG(phc->index, 0)); in sparx5_ptp_adjfine()
432 PTP_CLK_PER_CFG(phc->index, 1)); in sparx5_ptp_adjfine()
438 spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_adjfine()
443 static int sparx5_ptp_settime64(struct ptp_clock_info *ptp, in sparx5_ptp_settime64() argument
446 struct sparx5_phc *phc = container_of(ptp, struct sparx5_phc, info); in sparx5_ptp_settime64()
447 struct sparx5 *sparx5 = phc->sparx5; in sparx5_ptp_settime64()
451 consts = sparx5->data->consts; in sparx5_ptp_settime64()
453 spin_lock_irqsave(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_settime64()
457 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc->index) | in sparx5_ptp_settime64()
462 sparx5, PTP_PTP_PIN_CFG(consts->tod_pin)); in sparx5_ptp_settime64()
465 spx5_wr(PTP_PTP_TOD_SEC_MSB_PTP_TOD_SEC_MSB_SET(upper_32_bits(ts->tv_sec)), in sparx5_ptp_settime64()
466 sparx5, PTP_PTP_TOD_SEC_MSB(consts->tod_pin)); in sparx5_ptp_settime64()
467 spx5_wr(lower_32_bits(ts->tv_sec), in sparx5_ptp_settime64()
468 sparx5, PTP_PTP_TOD_SEC_LSB(consts->tod_pin)); in sparx5_ptp_settime64()
469 spx5_wr(ts->tv_nsec, sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin)); in sparx5_ptp_settime64()
473 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc->index) | in sparx5_ptp_settime64()
478 sparx5, PTP_PTP_PIN_CFG(consts->tod_pin)); in sparx5_ptp_settime64()
480 spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_settime64()
485 int sparx5_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts) in sparx5_ptp_gettime64() argument
487 struct sparx5_phc *phc = container_of(ptp, struct sparx5_phc, info); in sparx5_ptp_gettime64()
488 struct sparx5 *sparx5 = phc->sparx5; in sparx5_ptp_gettime64()
494 consts = sparx5->data->consts; in sparx5_ptp_gettime64()
496 spin_lock_irqsave(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_gettime64()
499 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc->index) | in sparx5_ptp_gettime64()
504 sparx5, PTP_PTP_PIN_CFG(consts->tod_pin)); in sparx5_ptp_gettime64()
506 s = spx5_rd(sparx5, PTP_PTP_TOD_SEC_MSB(consts->tod_pin)); in sparx5_ptp_gettime64()
508 s |= spx5_rd(sparx5, PTP_PTP_TOD_SEC_LSB(consts->tod_pin)); in sparx5_ptp_gettime64()
509 ns = spx5_rd(sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin)); in sparx5_ptp_gettime64()
512 spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_gettime64()
516 s--; in sparx5_ptp_gettime64()
525 static int sparx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) in sparx5_ptp_adjtime() argument
527 struct sparx5_phc *phc = container_of(ptp, struct sparx5_phc, info); in sparx5_ptp_adjtime()
528 struct sparx5 *sparx5 = phc->sparx5; in sparx5_ptp_adjtime()
531 consts = sparx5->data->consts; in sparx5_ptp_adjtime()
533 if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) { in sparx5_ptp_adjtime()
536 spin_lock_irqsave(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_adjtime()
540 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc->index) | in sparx5_ptp_adjtime()
545 sparx5, PTP_PTP_PIN_CFG(consts->tod_pin)); in sparx5_ptp_adjtime()
548 sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin)); in sparx5_ptp_adjtime()
552 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc->index) | in sparx5_ptp_adjtime()
557 sparx5, PTP_PTP_PIN_CFG(consts->tod_pin)); in sparx5_ptp_adjtime()
559 spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags); in sparx5_ptp_adjtime()
565 sparx5_ptp_gettime64(ptp, &ts); in sparx5_ptp_adjtime()
570 sparx5_ptp_settime64(ptp, &ts); in sparx5_ptp_adjtime()
578 .name = "sparx5 ptp",
590 struct sparx5_phc *phc = &sparx5->phc[index]; in sparx5_ptp_phc_init()
592 phc->info = *clock_info; in sparx5_ptp_phc_init()
593 phc->clock = ptp_clock_register(&phc->info, sparx5->dev); in sparx5_ptp_phc_init()
594 if (IS_ERR(phc->clock)) in sparx5_ptp_phc_init()
595 return PTR_ERR(phc->clock); in sparx5_ptp_phc_init()
597 phc->index = index; in sparx5_ptp_phc_init()
598 phc->sparx5 = sparx5; in sparx5_ptp_phc_init()
600 /* PTP Rx stamping is always enabled. */ in sparx5_ptp_phc_init()
601 phc->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; in sparx5_ptp_phc_init()
612 if (!sparx5->ptp) in sparx5_ptp_init()
621 spin_lock_init(&sparx5->ptp_clock_lock); in sparx5_ptp_init()
622 spin_lock_init(&sparx5->ptp_ts_id_lock); in sparx5_ptp_init()
623 mutex_init(&sparx5->ptp_lock); in sparx5_ptp_init()
647 for (i = 0; i < sparx5->data->consts->n_ports; i++) { in sparx5_ptp_init()
648 port = sparx5->ports[i]; in sparx5_ptp_init()
652 skb_queue_head_init(&port->tx_skbs); in sparx5_ptp_init()
663 for (i = 0; i < sparx5->data->consts->n_ports; i++) { in sparx5_ptp_deinit()
664 port = sparx5->ports[i]; in sparx5_ptp_deinit()
668 skb_queue_purge(&port->tx_skbs); in sparx5_ptp_deinit()
672 ptp_clock_unregister(sparx5->phc[i].clock); in sparx5_ptp_deinit()
683 if (!sparx5->ptp) in sparx5_ptp_rxtstamp()
686 phc = &sparx5->phc[SPARX5_PHC_PORT]; in sparx5_ptp_rxtstamp()
687 sparx5_ptp_gettime64(&phc->info, &ts); in sparx5_ptp_rxtstamp()
690 ts.tv_sec--; in sparx5_ptp_rxtstamp()
695 shhwtstamps->hwtstamp = full_ts_in_ns; in sparx5_ptp_rxtstamp()