Lines Matching +full:ns +full:- +full:config

1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
3 /* Copyright (c) 1999 - 2025 Intel Corporation. */
37 u64 ns; in wx_ptp_timecounter_cyc2time() local
40 seq = read_seqbegin(&wx->hw_tc_lock); in wx_ptp_timecounter_cyc2time()
41 ns = timecounter_cyc2time(&wx->hw_tc, timestamp); in wx_ptp_timecounter_cyc2time()
42 } while (read_seqretry(&wx->hw_tc_lock, seq)); in wx_ptp_timecounter_cyc2time()
44 return ns; in wx_ptp_timecounter_cyc2time()
71 incval = READ_ONCE(wx->base_incval); in wx_ptp_adjfine()
74 mask = (wx->mac.type == wx_mac_em) ? 0x7FFFFFF : 0xFFFFFF; in wx_ptp_adjfine()
76 if (wx->mac.type != wx_mac_em) in wx_ptp_adjfine()
89 write_seqlock_irqsave(&wx->hw_tc_lock, flags); in wx_ptp_adjtime()
90 timecounter_adjtime(&wx->hw_tc, delta); in wx_ptp_adjtime()
91 write_sequnlock_irqrestore(&wx->hw_tc_lock, flags); in wx_ptp_adjtime()
93 if (wx->ptp_setup_sdp) in wx_ptp_adjtime()
94 wx->ptp_setup_sdp(wx); in wx_ptp_adjtime()
104 u64 ns, stamp; in wx_ptp_gettimex64() local
107 ns = wx_ptp_timecounter_cyc2time(wx, stamp); in wx_ptp_gettimex64()
108 *ts = ns_to_timespec64(ns); in wx_ptp_gettimex64()
118 u64 ns; in wx_ptp_settime64() local
120 ns = timespec64_to_ns(ts); in wx_ptp_settime64()
122 write_seqlock_irqsave(&wx->hw_tc_lock, flags); in wx_ptp_settime64()
123 timecounter_init(&wx->hw_tc, &wx->hw_cc, ns); in wx_ptp_settime64()
124 write_sequnlock_irqrestore(&wx->hw_tc_lock, flags); in wx_ptp_settime64()
126 if (wx->ptp_setup_sdp) in wx_ptp_settime64()
127 wx->ptp_setup_sdp(wx); in wx_ptp_settime64()
133 * wx_ptp_clear_tx_timestamp - utility function to clear Tx timestamp state
143 if (wx->ptp_tx_skb) { in wx_ptp_clear_tx_timestamp()
144 dev_kfree_skb_any(wx->ptp_tx_skb); in wx_ptp_clear_tx_timestamp()
145 wx->ptp_tx_skb = NULL; in wx_ptp_clear_tx_timestamp()
147 clear_bit_unlock(WX_STATE_PTP_TX_IN_PROGRESS, wx->state); in wx_ptp_clear_tx_timestamp()
151 * wx_ptp_convert_to_hwtstamp - convert register value to hw timestamp
171 u64 ns; in wx_ptp_convert_to_hwtstamp() local
173 ns = wx_ptp_timecounter_cyc2time(wx, timestamp); in wx_ptp_convert_to_hwtstamp()
174 hwtstamp->hwtstamp = ns_to_ktime(ns); in wx_ptp_convert_to_hwtstamp()
178 * wx_ptp_tx_hwtstamp - utility function which checks for TX time stamp
181 * if the timestamp is valid, we convert it into the timecounter ns
188 struct sk_buff *skb = wx->ptp_tx_skb; in wx_ptp_tx_hwtstamp()
196 wx->ptp_tx_skb = NULL; in wx_ptp_tx_hwtstamp()
197 clear_bit_unlock(WX_STATE_PTP_TX_IN_PROGRESS, wx->state); in wx_ptp_tx_hwtstamp()
200 wx->tx_hwtstamp_pkts++; in wx_ptp_tx_hwtstamp()
208 if (!wx->ptp_tx_skb) { in wx_ptp_tx_hwtstamp_work()
220 return -1; in wx_ptp_tx_hwtstamp_work()
224 * wx_ptp_overflow_check - watchdog task to detect SYSTIME overflow
235 bool timeout = time_is_before_jiffies(wx->last_overflow_check + in wx_ptp_overflow_check()
241 write_seqlock_irqsave(&wx->hw_tc_lock, flags); in wx_ptp_overflow_check()
242 timecounter_read(&wx->hw_tc); in wx_ptp_overflow_check()
243 write_sequnlock_irqrestore(&wx->hw_tc_lock, flags); in wx_ptp_overflow_check()
245 wx->last_overflow_check = jiffies; in wx_ptp_overflow_check()
250 * wx_ptp_rx_hang - detect error case when Rx timestamp registers latched
271 wx->last_rx_ptp_check = jiffies; in wx_ptp_rx_hang()
276 rx_event = wx->last_rx_ptp_check; in wx_ptp_rx_hang()
277 for (n = 0; n < wx->num_rx_queues; n++) { in wx_ptp_rx_hang()
278 rx_ring = wx->rx_ring[n]; in wx_ptp_rx_hang()
279 if (time_after(rx_ring->last_rx_timestamp, rx_event)) in wx_ptp_rx_hang()
280 rx_event = rx_ring->last_rx_timestamp; in wx_ptp_rx_hang()
286 wx->last_rx_ptp_check = jiffies; in wx_ptp_rx_hang()
288 wx->rx_hwtstamp_cleared++; in wx_ptp_rx_hang()
289 dev_warn(&wx->pdev->dev, "clearing RX Timestamp hang"); in wx_ptp_rx_hang()
294 * wx_ptp_tx_hang - detect error case where Tx timestamp never finishes
299 bool timeout = time_is_before_jiffies(wx->ptp_tx_start + in wx_ptp_tx_hang()
302 if (!wx->ptp_tx_skb) in wx_ptp_tx_hang()
305 if (!test_bit(WX_STATE_PTP_TX_IN_PROGRESS, wx->state)) in wx_ptp_tx_hang()
314 wx->tx_hwtstamp_timeouts++; in wx_ptp_tx_hang()
315 dev_warn(&wx->pdev->dev, "clearing Tx timestamp hang\n"); in wx_ptp_tx_hang()
328 wx->flags))) in wx_ptp_do_aux_work()
337 struct cyclecounter *cc = &wx->hw_cc; in wx_ptp_trigger_calc()
339 u64 ns = 0; in wx_ptp_trigger_calc() local
343 write_seqlock_irqsave(&wx->hw_tc_lock, flags); in wx_ptp_trigger_calc()
344 ns = timecounter_read(&wx->hw_tc); in wx_ptp_trigger_calc()
345 wx->pps_edge_start = wx->hw_tc.cycle_last; in wx_ptp_trigger_calc()
346 write_sequnlock_irqrestore(&wx->hw_tc_lock, flags); in wx_ptp_trigger_calc()
347 wx->pps_edge_end = wx->pps_edge_start; in wx_ptp_trigger_calc()
350 div_u64_rem(ns, WX_NS_PER_SEC, &rem); in wx_ptp_trigger_calc()
355 rem = (WX_NS_PER_SEC - rem); in wx_ptp_trigger_calc()
358 wx->pps_edge_start += div_u64(((u64)rem << cc->shift), cc->mult); in wx_ptp_trigger_calc()
359 wx->pps_edge_end += div_u64(((u64)(rem + wx->pps_width) << in wx_ptp_trigger_calc()
360 cc->shift), cc->mult); in wx_ptp_trigger_calc()
362 return (ns + rem); in wx_ptp_trigger_calc()
367 struct cyclecounter *cc = &wx->hw_cc; in wx_ptp_setup_sdp()
371 if (wx->pps_width >= WX_NS_PER_SEC) { in wx_ptp_setup_sdp()
373 return -EINVAL; in wx_ptp_setup_sdp()
380 if (!test_bit(WX_FLAG_PTP_PPS_ENABLED, wx->flags)) { in wx_ptp_setup_sdp()
381 if (wx->pps_enabled) { in wx_ptp_setup_sdp()
382 wx->pps_enabled = false; in wx_ptp_setup_sdp()
388 wx->pps_enabled = true; in wx_ptp_setup_sdp()
390 wx_set_pps(wx, wx->pps_enabled, nsec, wx->pps_edge_start); in wx_ptp_setup_sdp()
394 wr32ptp(wx, WX_TSC_1588_TRGT_L(0), (u32)wx->pps_edge_start); in wx_ptp_setup_sdp()
395 wr32ptp(wx, WX_TSC_1588_TRGT_H(0), (u32)(wx->pps_edge_start >> 32)); in wx_ptp_setup_sdp()
396 wr32ptp(wx, WX_TSC_1588_TRGT_L(1), (u32)wx->pps_edge_end); in wx_ptp_setup_sdp()
397 wr32ptp(wx, WX_TSC_1588_TRGT_H(1), (u32)(wx->pps_edge_end >> 32)); in wx_ptp_setup_sdp()
406 wx->sec_to_cc = div_u64(((u64)WX_NS_PER_SEC << cc->shift), cc->mult); in wx_ptp_setup_sdp()
422 if (rq->type != PTP_CLK_REQ_PEROUT || !wx->ptp_setup_sdp) in wx_ptp_feature_enable()
423 return -EOPNOTSUPP; in wx_ptp_feature_enable()
426 if (rq->perout.flags & ~(PTP_PEROUT_DUTY_CYCLE | in wx_ptp_feature_enable()
428 return -EOPNOTSUPP; in wx_ptp_feature_enable()
430 if (rq->perout.phase.sec || rq->perout.phase.nsec) { in wx_ptp_feature_enable()
432 return -EINVAL; in wx_ptp_feature_enable()
435 if (rq->perout.period.sec != 1 || rq->perout.period.nsec) { in wx_ptp_feature_enable()
437 return -EINVAL; in wx_ptp_feature_enable()
440 if (rq->perout.flags & PTP_PEROUT_DUTY_CYCLE) { in wx_ptp_feature_enable()
443 ts_on.tv_sec = rq->perout.on.sec; in wx_ptp_feature_enable()
444 ts_on.tv_nsec = rq->perout.on.nsec; in wx_ptp_feature_enable()
445 wx->pps_width = timespec64_to_ns(&ts_on); in wx_ptp_feature_enable()
447 wx->pps_width = 120000000; in wx_ptp_feature_enable()
451 set_bit(WX_FLAG_PTP_PPS_ENABLED, wx->flags); in wx_ptp_feature_enable()
453 clear_bit(WX_FLAG_PTP_PPS_ENABLED, wx->flags); in wx_ptp_feature_enable()
455 return wx->ptp_setup_sdp(wx); in wx_ptp_feature_enable()
466 if (!wx->ptp_clock) in wx_ptp_check_pps_event()
479 wr32ptp(wx, WX_TSC_1588_TRGT_L(0), (u32)wx->pps_edge_start); in wx_ptp_check_pps_event()
480 wr32ptp(wx, WX_TSC_1588_TRGT_H(0), (u32)(wx->pps_edge_start >> 32)); in wx_ptp_check_pps_event()
481 wr32ptp(wx, WX_TSC_1588_TRGT_L(1), (u32)wx->pps_edge_end); in wx_ptp_check_pps_event()
482 wr32ptp(wx, WX_TSC_1588_TRGT_H(1), (u32)(wx->pps_edge_end >> 32)); in wx_ptp_check_pps_event()
491 struct net_device *netdev = wx->netdev; in wx_ptp_create_clock()
495 if (!IS_ERR_OR_NULL(wx->ptp_clock)) in wx_ptp_create_clock()
498 snprintf(wx->ptp_caps.name, sizeof(wx->ptp_caps.name), in wx_ptp_create_clock()
499 "%s", netdev->name); in wx_ptp_create_clock()
500 wx->ptp_caps.owner = THIS_MODULE; in wx_ptp_create_clock()
501 wx->ptp_caps.n_alarm = 0; in wx_ptp_create_clock()
502 wx->ptp_caps.n_ext_ts = 0; in wx_ptp_create_clock()
503 wx->ptp_caps.pps = 0; in wx_ptp_create_clock()
504 wx->ptp_caps.adjfine = wx_ptp_adjfine; in wx_ptp_create_clock()
505 wx->ptp_caps.adjtime = wx_ptp_adjtime; in wx_ptp_create_clock()
506 wx->ptp_caps.gettimex64 = wx_ptp_gettimex64; in wx_ptp_create_clock()
507 wx->ptp_caps.settime64 = wx_ptp_settime64; in wx_ptp_create_clock()
508 wx->ptp_caps.do_aux_work = wx_ptp_do_aux_work; in wx_ptp_create_clock()
509 switch (wx->mac.type) { in wx_ptp_create_clock()
512 wx->ptp_caps.max_adj = 250000000; in wx_ptp_create_clock()
513 wx->ptp_caps.n_per_out = 1; in wx_ptp_create_clock()
514 wx->ptp_setup_sdp = wx_ptp_setup_sdp; in wx_ptp_create_clock()
515 wx->ptp_caps.enable = wx_ptp_feature_enable; in wx_ptp_create_clock()
518 wx->ptp_caps.max_adj = 250000000; in wx_ptp_create_clock()
519 wx->ptp_caps.n_per_out = 0; in wx_ptp_create_clock()
520 wx->ptp_setup_sdp = NULL; in wx_ptp_create_clock()
523 wx->ptp_caps.max_adj = 500000000; in wx_ptp_create_clock()
524 wx->ptp_caps.n_per_out = 1; in wx_ptp_create_clock()
525 wx->ptp_setup_sdp = wx_ptp_setup_sdp; in wx_ptp_create_clock()
526 wx->ptp_caps.enable = wx_ptp_feature_enable; in wx_ptp_create_clock()
529 return -EOPNOTSUPP; in wx_ptp_create_clock()
532 wx->ptp_clock = ptp_clock_register(&wx->ptp_caps, &wx->pdev->dev); in wx_ptp_create_clock()
533 if (IS_ERR(wx->ptp_clock)) { in wx_ptp_create_clock()
534 err = PTR_ERR(wx->ptp_clock); in wx_ptp_create_clock()
535 wx->ptp_clock = NULL; in wx_ptp_create_clock()
538 } else if (wx->ptp_clock) { in wx_ptp_create_clock()
539 dev_info(&wx->pdev->dev, "registered PHC device on %s\n", in wx_ptp_create_clock()
540 netdev->name); in wx_ptp_create_clock()
547 wx->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; in wx_ptp_create_clock()
548 wx->tstamp_config.tx_type = HWTSTAMP_TX_OFF; in wx_ptp_create_clock()
554 struct kernel_hwtstamp_config *config) in wx_ptp_set_timestamp_mode() argument
563 memcpy(flags, wx->flags, sizeof(wx->flags)); in wx_ptp_set_timestamp_mode()
565 switch (config->tx_type) { in wx_ptp_set_timestamp_mode()
572 return -ERANGE; in wx_ptp_set_timestamp_mode()
575 switch (config->rx_filter) { in wx_ptp_set_timestamp_mode()
605 config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; in wx_ptp_set_timestamp_mode()
615 config->rx_filter = HWTSTAMP_FILTER_NONE; in wx_ptp_set_timestamp_mode()
616 return -ERANGE; in wx_ptp_set_timestamp_mode()
646 memcpy(wx->flags, flags, sizeof(wx->flags)); in wx_ptp_set_timestamp_mode()
664 switch (wx->mac.type) { in wx_ptp_link_speed_adjust()
678 switch (wx->speed) { in wx_ptp_link_speed_adjust()
700 * wx_ptp_reset_cyclecounter - create the cycle counter from hw
720 * they do not properly function if the overflow point isn't 2^N-1. in wx_ptp_reset_cyclecounter()
734 WRITE_ONCE(wx->base_incval, incval); in wx_ptp_reset_cyclecounter()
736 mask = (wx->mac.type == wx_mac_em) ? 0x7FFFFFF : 0xFFFFFF; in wx_ptp_reset_cyclecounter()
738 if (wx->mac.type != wx_mac_em) in wx_ptp_reset_cyclecounter()
745 write_seqlock_irqsave(&wx->hw_tc_lock, flags); in wx_ptp_reset_cyclecounter()
746 memcpy(&wx->hw_cc, &cc, sizeof(wx->hw_cc)); in wx_ptp_reset_cyclecounter()
747 write_sequnlock_irqrestore(&wx->hw_tc_lock, flags); in wx_ptp_reset_cyclecounter()
756 wx_ptp_set_timestamp_mode(wx, &wx->tstamp_config); in wx_ptp_reset()
763 write_seqlock_irqsave(&wx->hw_tc_lock, flags); in wx_ptp_reset()
764 timecounter_init(&wx->hw_tc, &wx->hw_cc, in wx_ptp_reset()
766 write_sequnlock_irqrestore(&wx->hw_tc_lock, flags); in wx_ptp_reset()
768 wx->last_overflow_check = jiffies; in wx_ptp_reset()
769 ptp_schedule_worker(wx->ptp_clock, HZ); in wx_ptp_reset()
772 * registers reset, (re-)enable the Clock out feature in wx_ptp_reset()
774 if (wx->ptp_setup_sdp) in wx_ptp_reset()
775 wx->ptp_setup_sdp(wx); in wx_ptp_reset()
784 seqlock_init(&wx->hw_tc_lock); in wx_ptp_init()
786 /* obtain a ptp clock device, or re-use an existing device */ in wx_ptp_init()
790 wx->tx_hwtstamp_pkts = 0; in wx_ptp_init()
791 wx->tx_hwtstamp_timeouts = 0; in wx_ptp_init()
792 wx->tx_hwtstamp_skipped = 0; in wx_ptp_init()
793 wx->tx_hwtstamp_errors = 0; in wx_ptp_init()
794 wx->rx_hwtstamp_cleared = 0; in wx_ptp_init()
799 set_bit(WX_STATE_PTP_RUNNING, wx->state); in wx_ptp_init()
804 * wx_ptp_suspend - stop ptp work items
813 if (!test_and_clear_bit(WX_STATE_PTP_RUNNING, wx->state)) in wx_ptp_suspend()
816 clear_bit(WX_FLAG_PTP_PPS_ENABLED, wx->flags); in wx_ptp_suspend()
817 if (wx->ptp_setup_sdp) in wx_ptp_suspend()
818 wx->ptp_setup_sdp(wx); in wx_ptp_suspend()
825 * wx_ptp_stop - destroy the ptp_clock device
837 if (wx->ptp_clock) { in wx_ptp_stop()
838 ptp_clock_unregister(wx->ptp_clock); in wx_ptp_stop()
839 wx->ptp_clock = NULL; in wx_ptp_stop()
840 dev_info(&wx->pdev->dev, "removed PHC on %s\n", wx->netdev->name); in wx_ptp_stop()
846 * wx_ptp_rx_hwtstamp - utility function which checks for RX time stamp
850 * if the timestamp is valid, we convert it into the timecounter ns
878 return -EINVAL; in wx_hwtstamp_get()
880 *cfg = wx->tstamp_config; in wx_hwtstamp_get()
894 return -EINVAL; in wx_hwtstamp_set()
901 memcpy(&wx->tstamp_config, cfg, sizeof(wx->tstamp_config)); in wx_hwtstamp_set()