1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
4 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
6 * The Sparx5 Chip Register Model can be browsed at this location:
7 * https://github.com/microchip-ung/sparx-5_reginfo
9 #include <linux/ptp_classify.h>
11 #include "sparx5_main_regs.h"
12 #include "sparx5_main.h"
14 #define TOD_ACC_PIN 0x4
17 PTP_PIN_ACTION_IDLE
= 0,
25 static u64
sparx5_ptp_get_1ppm(struct sparx5
*sparx5
)
27 /* Represents 1ppm adjustment in 2^59 format with 1.59687500000(625)
28 * 1.99609375000(500), 3.99218750000(250) as reference
29 * The value is calculated as following:
30 * (1/1000000)/((2^-59)/X)
35 switch (sparx5
->coreclock
) {
36 case SPX5_CORE_CLOCK_250MHZ
:
39 case SPX5_CORE_CLOCK_328MHZ
:
42 case SPX5_CORE_CLOCK_500MHZ
:
45 case SPX5_CORE_CLOCK_625MHZ
:
49 WARN(1, "Invalid core clock");
56 static u64
sparx5_ptp_get_nominal_value(struct sparx5
*sparx5
)
60 switch (sparx5
->coreclock
) {
61 case SPX5_CORE_CLOCK_250MHZ
:
62 res
= 0x1FF0000000000000;
64 case SPX5_CORE_CLOCK_328MHZ
:
65 res
= 0x18604697DD0F9B5B;
67 case SPX5_CORE_CLOCK_500MHZ
:
68 res
= 0x0FF8000000000000;
70 case SPX5_CORE_CLOCK_625MHZ
:
71 res
= 0x0CC6666666666666;
74 WARN(1, "Invalid core clock");
81 int sparx5_ptp_hwtstamp_set(struct sparx5_port
*port
,
82 struct kernel_hwtstamp_config
*cfg
,
83 struct netlink_ext_ack
*extack
)
85 struct sparx5
*sparx5
= port
->sparx5
;
86 struct sparx5_phc
*phc
;
88 /* For now don't allow to run ptp on ports that are part of a bridge,
89 * because in case of transparent clock the HW will still forward the
90 * frames, so there would be duplicate frames
93 if (test_bit(port
->portno
, sparx5
->bridge_mask
))
96 switch (cfg
->tx_type
) {
98 port
->ptp_cmd
= IFH_REW_OP_TWO_STEP_PTP
;
100 case HWTSTAMP_TX_ONESTEP_SYNC
:
101 port
->ptp_cmd
= IFH_REW_OP_ONE_STEP_PTP
;
103 case HWTSTAMP_TX_OFF
:
104 port
->ptp_cmd
= IFH_REW_OP_NOOP
;
110 switch (cfg
->rx_filter
) {
111 case HWTSTAMP_FILTER_NONE
:
113 case HWTSTAMP_FILTER_ALL
:
114 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT
:
115 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC
:
116 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ
:
117 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT
:
118 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC
:
119 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ
:
120 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT
:
121 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC
:
122 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ
:
123 case HWTSTAMP_FILTER_PTP_V2_EVENT
:
124 case HWTSTAMP_FILTER_PTP_V2_SYNC
:
125 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ
:
126 case HWTSTAMP_FILTER_NTP_ALL
:
127 cfg
->rx_filter
= HWTSTAMP_FILTER_ALL
;
133 /* Commit back the result & save it */
134 mutex_lock(&sparx5
->ptp_lock
);
135 phc
= &sparx5
->phc
[SPARX5_PHC_PORT
];
136 phc
->hwtstamp_config
= *cfg
;
137 mutex_unlock(&sparx5
->ptp_lock
);
142 void sparx5_ptp_hwtstamp_get(struct sparx5_port
*port
,
143 struct kernel_hwtstamp_config
*cfg
)
145 struct sparx5
*sparx5
= port
->sparx5
;
146 struct sparx5_phc
*phc
;
148 phc
= &sparx5
->phc
[SPARX5_PHC_PORT
];
149 *cfg
= phc
->hwtstamp_config
;
152 static void sparx5_ptp_classify(struct sparx5_port
*port
, struct sk_buff
*skb
,
153 u8
*rew_op
, u8
*pdu_type
, u8
*pdu_w16_offset
)
155 struct ptp_header
*header
;
159 if (port
->ptp_cmd
== IFH_REW_OP_NOOP
) {
160 *rew_op
= IFH_REW_OP_NOOP
;
161 *pdu_type
= IFH_PDU_TYPE_NONE
;
166 type
= ptp_classify_raw(skb
);
167 if (type
== PTP_CLASS_NONE
) {
168 *rew_op
= IFH_REW_OP_NOOP
;
169 *pdu_type
= IFH_PDU_TYPE_NONE
;
174 header
= ptp_parse_header(skb
, type
);
176 *rew_op
= IFH_REW_OP_NOOP
;
177 *pdu_type
= IFH_PDU_TYPE_NONE
;
183 if (type
& PTP_CLASS_L2
)
184 *pdu_type
= IFH_PDU_TYPE_PTP
;
185 if (type
& PTP_CLASS_IPV4
)
186 *pdu_type
= IFH_PDU_TYPE_IPV4_UDP_PTP
;
187 if (type
& PTP_CLASS_IPV6
)
188 *pdu_type
= IFH_PDU_TYPE_IPV6_UDP_PTP
;
190 if (port
->ptp_cmd
== IFH_REW_OP_TWO_STEP_PTP
) {
191 *rew_op
= IFH_REW_OP_TWO_STEP_PTP
;
195 /* If it is sync and run 1 step then set the correct operation,
196 * otherwise run as 2 step
198 msgtype
= ptp_get_msgtype(header
, type
);
199 if ((msgtype
& 0xf) == 0) {
200 *rew_op
= IFH_REW_OP_ONE_STEP_PTP
;
204 *rew_op
= IFH_REW_OP_TWO_STEP_PTP
;
207 static void sparx5_ptp_txtstamp_old_release(struct sparx5_port
*port
)
209 struct sk_buff
*skb
, *skb_tmp
;
212 spin_lock_irqsave(&port
->tx_skbs
.lock
, flags
);
213 skb_queue_walk_safe(&port
->tx_skbs
, skb
, skb_tmp
) {
214 if time_after(SPARX5_SKB_CB(skb
)->jiffies
+ SPARX5_PTP_TIMEOUT
,
218 __skb_unlink(skb
, &port
->tx_skbs
);
219 dev_kfree_skb_any(skb
);
221 spin_unlock_irqrestore(&port
->tx_skbs
.lock
, flags
);
224 int sparx5_ptp_txtstamp_request(struct sparx5_port
*port
,
227 struct sparx5
*sparx5
= port
->sparx5
;
228 u8 rew_op
, pdu_type
, pdu_w16_offset
;
231 sparx5_ptp_classify(port
, skb
, &rew_op
, &pdu_type
, &pdu_w16_offset
);
232 SPARX5_SKB_CB(skb
)->rew_op
= rew_op
;
233 SPARX5_SKB_CB(skb
)->pdu_type
= pdu_type
;
234 SPARX5_SKB_CB(skb
)->pdu_w16_offset
= pdu_w16_offset
;
236 if (rew_op
!= IFH_REW_OP_TWO_STEP_PTP
)
239 sparx5_ptp_txtstamp_old_release(port
);
241 spin_lock_irqsave(&sparx5
->ptp_ts_id_lock
, flags
);
242 if (sparx5
->ptp_skbs
== SPARX5_MAX_PTP_ID
) {
243 spin_unlock_irqrestore(&sparx5
->ptp_ts_id_lock
, flags
);
247 skb_shinfo(skb
)->tx_flags
|= SKBTX_IN_PROGRESS
;
249 skb_queue_tail(&port
->tx_skbs
, skb
);
250 SPARX5_SKB_CB(skb
)->ts_id
= port
->ts_id
;
251 SPARX5_SKB_CB(skb
)->jiffies
= jiffies
;
255 if (port
->ts_id
== SPARX5_MAX_PTP_ID
)
258 spin_unlock_irqrestore(&sparx5
->ptp_ts_id_lock
, flags
);
263 void sparx5_ptp_txtstamp_release(struct sparx5_port
*port
,
266 struct sparx5
*sparx5
= port
->sparx5
;
269 spin_lock_irqsave(&sparx5
->ptp_ts_id_lock
, flags
);
272 skb_unlink(skb
, &port
->tx_skbs
);
273 spin_unlock_irqrestore(&sparx5
->ptp_ts_id_lock
, flags
);
276 void sparx5_get_hwtimestamp(struct sparx5
*sparx5
,
277 struct timespec64
*ts
,
280 /* Read current PTP time to get seconds */
281 const struct sparx5_consts
*consts
= sparx5
->data
->consts
;
285 spin_lock_irqsave(&sparx5
->ptp_clock_lock
, flags
);
287 spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_SAVE
) |
288 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(SPARX5_PHC_PORT
) |
289 PTP_PTP_PIN_CFG_PTP_PIN_SYNC_SET(0),
290 PTP_PTP_PIN_CFG_PTP_PIN_ACTION
|
291 PTP_PTP_PIN_CFG_PTP_PIN_DOM
|
292 PTP_PTP_PIN_CFG_PTP_PIN_SYNC
,
293 sparx5
, PTP_PTP_PIN_CFG(consts
->tod_pin
));
295 ts
->tv_sec
= spx5_rd(sparx5
, PTP_PTP_TOD_SEC_LSB(consts
->tod_pin
));
296 curr_nsec
= spx5_rd(sparx5
, PTP_PTP_TOD_NSEC(consts
->tod_pin
));
300 /* Sec has incremented since the ts was registered */
301 if (curr_nsec
< nsec
)
304 spin_unlock_irqrestore(&sparx5
->ptp_clock_lock
, flags
);
306 EXPORT_SYMBOL_GPL(sparx5_get_hwtimestamp
);
308 irqreturn_t
sparx5_ptp_irq_handler(int irq
, void *args
)
310 int budget
= SPARX5_MAX_PTP_ID
;
311 struct sparx5
*sparx5
= args
;
314 struct sk_buff
*skb
, *skb_tmp
, *skb_match
= NULL
;
315 struct skb_shared_hwtstamps shhwtstamps
;
316 struct sparx5_port
*port
;
317 struct timespec64 ts
;
322 val
= spx5_rd(sparx5
, REW_PTP_TWOSTEP_CTRL
);
324 /* Check if a timestamp can be retrieved */
325 if (!(val
& REW_PTP_TWOSTEP_CTRL_PTP_VLD
))
328 WARN_ON(val
& REW_PTP_TWOSTEP_CTRL_PTP_OVFL
);
330 if (!(val
& REW_PTP_TWOSTEP_CTRL_STAMP_TX
))
333 /* Retrieve the ts Tx port */
334 txport
= REW_PTP_TWOSTEP_CTRL_STAMP_PORT_GET(val
);
336 /* Retrieve its associated skb */
337 port
= sparx5
->ports
[txport
];
339 /* Retrieve the delay */
340 delay
= spx5_rd(sparx5
, REW_PTP_TWOSTEP_STAMP
);
341 delay
= REW_PTP_TWOSTEP_STAMP_STAMP_NSEC_GET(delay
);
343 /* Get next timestamp from fifo, which needs to be the
344 * rx timestamp which represents the id of the frame
346 spx5_rmw(REW_PTP_TWOSTEP_CTRL_PTP_NXT_SET(1),
347 REW_PTP_TWOSTEP_CTRL_PTP_NXT
,
348 sparx5
, REW_PTP_TWOSTEP_CTRL
);
350 val
= spx5_rd(sparx5
, REW_PTP_TWOSTEP_CTRL
);
352 /* Check if a timestamp can be retried */
353 if (!(val
& REW_PTP_TWOSTEP_CTRL_PTP_VLD
))
356 /* Read RX timestamping to get the ID */
357 id
= spx5_rd(sparx5
, REW_PTP_TWOSTEP_STAMP
);
359 id
|= spx5_rd(sparx5
, REW_PTP_TWOSTEP_STAMP_SUBNS
);
361 spin_lock_irqsave(&port
->tx_skbs
.lock
, flags
);
362 skb_queue_walk_safe(&port
->tx_skbs
, skb
, skb_tmp
) {
363 if (SPARX5_SKB_CB(skb
)->ts_id
!= id
)
366 __skb_unlink(skb
, &port
->tx_skbs
);
370 spin_unlock_irqrestore(&port
->tx_skbs
.lock
, flags
);
373 spx5_rmw(REW_PTP_TWOSTEP_CTRL_PTP_NXT_SET(1),
374 REW_PTP_TWOSTEP_CTRL_PTP_NXT
,
375 sparx5
, REW_PTP_TWOSTEP_CTRL
);
377 if (WARN_ON(!skb_match
))
380 spin_lock(&sparx5
->ptp_ts_id_lock
);
382 spin_unlock(&sparx5
->ptp_ts_id_lock
);
384 /* Get the h/w timestamp */
385 sparx5_get_hwtimestamp(sparx5
, &ts
, delay
);
387 /* Set the timestamp into the skb */
388 shhwtstamps
.hwtstamp
= ktime_set(ts
.tv_sec
, ts
.tv_nsec
);
389 skb_tstamp_tx(skb_match
, &shhwtstamps
);
391 dev_kfree_skb_any(skb_match
);
397 static int sparx5_ptp_adjfine(struct ptp_clock_info
*ptp
, long scaled_ppm
)
399 struct sparx5_phc
*phc
= container_of(ptp
, struct sparx5_phc
, info
);
400 struct sparx5
*sparx5
= phc
->sparx5
;
409 if (scaled_ppm
< 0) {
411 scaled_ppm
= -scaled_ppm
;
414 tod_inc
= sparx5_ptp_get_nominal_value(sparx5
);
416 /* The multiplication is split in 2 separate additions because of
417 * overflow issues. If scaled_ppm with 16bit fractional part was bigger
418 * than 20ppm then we got overflow.
420 ref
= sparx5_ptp_get_1ppm(sparx5
) * (scaled_ppm
>> 16);
421 ref
+= (sparx5_ptp_get_1ppm(sparx5
) * (0xffff & scaled_ppm
)) >> 16;
422 tod_inc
= neg_adj
? tod_inc
- ref
: tod_inc
+ ref
;
424 spin_lock_irqsave(&sparx5
->ptp_clock_lock
, flags
);
426 spx5_rmw(PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS_SET(1 << BIT(phc
->index
)),
427 PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS
,
428 sparx5
, PTP_PTP_DOM_CFG
);
430 spx5_wr((u32
)tod_inc
& 0xFFFFFFFF, sparx5
,
431 PTP_CLK_PER_CFG(phc
->index
, 0));
432 spx5_wr((u32
)(tod_inc
>> 32), sparx5
,
433 PTP_CLK_PER_CFG(phc
->index
, 1));
435 spx5_rmw(PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS_SET(0),
436 PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS
, sparx5
,
439 spin_unlock_irqrestore(&sparx5
->ptp_clock_lock
, flags
);
444 static int sparx5_ptp_settime64(struct ptp_clock_info
*ptp
,
445 const struct timespec64
*ts
)
447 struct sparx5_phc
*phc
= container_of(ptp
, struct sparx5_phc
, info
);
448 struct sparx5
*sparx5
= phc
->sparx5
;
449 const struct sparx5_consts
*consts
;
452 consts
= sparx5
->data
->consts
;
454 spin_lock_irqsave(&sparx5
->ptp_clock_lock
, flags
);
456 /* Must be in IDLE mode before the time can be loaded */
457 spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_IDLE
) |
458 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc
->index
) |
459 PTP_PTP_PIN_CFG_PTP_PIN_SYNC_SET(0),
460 PTP_PTP_PIN_CFG_PTP_PIN_ACTION
|
461 PTP_PTP_PIN_CFG_PTP_PIN_DOM
|
462 PTP_PTP_PIN_CFG_PTP_PIN_SYNC
,
463 sparx5
, PTP_PTP_PIN_CFG(consts
->tod_pin
));
466 spx5_wr(PTP_PTP_TOD_SEC_MSB_PTP_TOD_SEC_MSB_SET(upper_32_bits(ts
->tv_sec
)),
467 sparx5
, PTP_PTP_TOD_SEC_MSB(consts
->tod_pin
));
468 spx5_wr(lower_32_bits(ts
->tv_sec
),
469 sparx5
, PTP_PTP_TOD_SEC_LSB(consts
->tod_pin
));
470 spx5_wr(ts
->tv_nsec
, sparx5
, PTP_PTP_TOD_NSEC(consts
->tod_pin
));
472 /* Apply new values */
473 spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_LOAD
) |
474 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc
->index
) |
475 PTP_PTP_PIN_CFG_PTP_PIN_SYNC_SET(0),
476 PTP_PTP_PIN_CFG_PTP_PIN_ACTION
|
477 PTP_PTP_PIN_CFG_PTP_PIN_DOM
|
478 PTP_PTP_PIN_CFG_PTP_PIN_SYNC
,
479 sparx5
, PTP_PTP_PIN_CFG(consts
->tod_pin
));
481 spin_unlock_irqrestore(&sparx5
->ptp_clock_lock
, flags
);
486 int sparx5_ptp_gettime64(struct ptp_clock_info
*ptp
, struct timespec64
*ts
)
488 struct sparx5_phc
*phc
= container_of(ptp
, struct sparx5_phc
, info
);
489 struct sparx5
*sparx5
= phc
->sparx5
;
490 const struct sparx5_consts
*consts
;
495 consts
= sparx5
->data
->consts
;
497 spin_lock_irqsave(&sparx5
->ptp_clock_lock
, flags
);
499 spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_SAVE
) |
500 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc
->index
) |
501 PTP_PTP_PIN_CFG_PTP_PIN_SYNC_SET(0),
502 PTP_PTP_PIN_CFG_PTP_PIN_ACTION
|
503 PTP_PTP_PIN_CFG_PTP_PIN_DOM
|
504 PTP_PTP_PIN_CFG_PTP_PIN_SYNC
,
505 sparx5
, PTP_PTP_PIN_CFG(consts
->tod_pin
));
507 s
= spx5_rd(sparx5
, PTP_PTP_TOD_SEC_MSB(consts
->tod_pin
));
509 s
|= spx5_rd(sparx5
, PTP_PTP_TOD_SEC_LSB(consts
->tod_pin
));
510 ns
= spx5_rd(sparx5
, PTP_PTP_TOD_NSEC(consts
->tod_pin
));
511 ns
&= PTP_PTP_TOD_NSEC_PTP_TOD_NSEC
;
513 spin_unlock_irqrestore(&sparx5
->ptp_clock_lock
, flags
);
515 /* Deal with negative values */
516 if ((ns
& 0xFFFFFFF0) == 0x3FFFFFF0) {
522 set_normalized_timespec64(ts
, s
, ns
);
526 static int sparx5_ptp_adjtime(struct ptp_clock_info
*ptp
, s64 delta
)
528 struct sparx5_phc
*phc
= container_of(ptp
, struct sparx5_phc
, info
);
529 struct sparx5
*sparx5
= phc
->sparx5
;
530 const struct sparx5_consts
*consts
;
532 consts
= sparx5
->data
->consts
;
534 if (delta
> -(NSEC_PER_SEC
/ 2) && delta
< (NSEC_PER_SEC
/ 2)) {
537 spin_lock_irqsave(&sparx5
->ptp_clock_lock
, flags
);
539 /* Must be in IDLE mode before the time can be loaded */
540 spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_IDLE
) |
541 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc
->index
) |
542 PTP_PTP_PIN_CFG_PTP_PIN_SYNC_SET(0),
543 PTP_PTP_PIN_CFG_PTP_PIN_ACTION
|
544 PTP_PTP_PIN_CFG_PTP_PIN_DOM
|
545 PTP_PTP_PIN_CFG_PTP_PIN_SYNC
,
546 sparx5
, PTP_PTP_PIN_CFG(consts
->tod_pin
));
548 spx5_wr(PTP_PTP_TOD_NSEC_PTP_TOD_NSEC_SET(delta
),
549 sparx5
, PTP_PTP_TOD_NSEC(consts
->tod_pin
));
551 /* Adjust time with the value of PTP_TOD_NSEC */
552 spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_DELTA
) |
553 PTP_PTP_PIN_CFG_PTP_PIN_DOM_SET(phc
->index
) |
554 PTP_PTP_PIN_CFG_PTP_PIN_SYNC_SET(0),
555 PTP_PTP_PIN_CFG_PTP_PIN_ACTION
|
556 PTP_PTP_PIN_CFG_PTP_PIN_DOM
|
557 PTP_PTP_PIN_CFG_PTP_PIN_SYNC
,
558 sparx5
, PTP_PTP_PIN_CFG(consts
->tod_pin
));
560 spin_unlock_irqrestore(&sparx5
->ptp_clock_lock
, flags
);
562 /* Fall back using sparx5_ptp_settime64 which is not exact */
563 struct timespec64 ts
;
566 sparx5_ptp_gettime64(ptp
, &ts
);
568 now
= ktime_to_ns(timespec64_to_ktime(ts
));
569 ts
= ns_to_timespec64(now
+ delta
);
571 sparx5_ptp_settime64(ptp
, &ts
);
577 static struct ptp_clock_info sparx5_ptp_clock_info
= {
578 .owner
= THIS_MODULE
,
579 .name
= "sparx5 ptp",
581 .gettime64
= sparx5_ptp_gettime64
,
582 .settime64
= sparx5_ptp_settime64
,
583 .adjtime
= sparx5_ptp_adjtime
,
584 .adjfine
= sparx5_ptp_adjfine
,
587 static int sparx5_ptp_phc_init(struct sparx5
*sparx5
,
589 struct ptp_clock_info
*clock_info
)
591 struct sparx5_phc
*phc
= &sparx5
->phc
[index
];
593 phc
->info
= *clock_info
;
594 phc
->clock
= ptp_clock_register(&phc
->info
, sparx5
->dev
);
595 if (IS_ERR(phc
->clock
))
596 return PTR_ERR(phc
->clock
);
599 phc
->sparx5
= sparx5
;
601 /* PTP Rx stamping is always enabled. */
602 phc
->hwtstamp_config
.rx_filter
= HWTSTAMP_FILTER_PTP_V2_EVENT
;
607 int sparx5_ptp_init(struct sparx5
*sparx5
)
609 u64 tod_adj
= sparx5_ptp_get_nominal_value(sparx5
);
610 struct sparx5_port
*port
;
616 for (i
= 0; i
< SPARX5_PHC_COUNT
; ++i
) {
617 err
= sparx5_ptp_phc_init(sparx5
, i
, &sparx5_ptp_clock_info
);
622 spin_lock_init(&sparx5
->ptp_clock_lock
);
623 spin_lock_init(&sparx5
->ptp_ts_id_lock
);
624 mutex_init(&sparx5
->ptp_lock
);
626 /* Disable master counters */
627 spx5_wr(PTP_PTP_DOM_CFG_PTP_ENA_SET(0), sparx5
, PTP_PTP_DOM_CFG
);
629 /* Configure the nominal TOD increment per clock cycle */
630 spx5_rmw(PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS_SET(0x7),
631 PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS
,
632 sparx5
, PTP_PTP_DOM_CFG
);
634 for (i
= 0; i
< SPARX5_PHC_COUNT
; ++i
) {
635 spx5_wr((u32
)tod_adj
& 0xFFFFFFFF, sparx5
,
636 PTP_CLK_PER_CFG(i
, 0));
637 spx5_wr((u32
)(tod_adj
>> 32), sparx5
,
638 PTP_CLK_PER_CFG(i
, 1));
641 spx5_rmw(PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS_SET(0),
642 PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS
,
643 sparx5
, PTP_PTP_DOM_CFG
);
645 /* Enable master counters */
646 spx5_wr(PTP_PTP_DOM_CFG_PTP_ENA_SET(0x7), sparx5
, PTP_PTP_DOM_CFG
);
648 for (i
= 0; i
< sparx5
->data
->consts
->n_ports
; i
++) {
649 port
= sparx5
->ports
[i
];
653 skb_queue_head_init(&port
->tx_skbs
);
659 void sparx5_ptp_deinit(struct sparx5
*sparx5
)
661 struct sparx5_port
*port
;
664 for (i
= 0; i
< sparx5
->data
->consts
->n_ports
; i
++) {
665 port
= sparx5
->ports
[i
];
669 skb_queue_purge(&port
->tx_skbs
);
672 for (i
= 0; i
< SPARX5_PHC_COUNT
; ++i
)
673 ptp_clock_unregister(sparx5
->phc
[i
].clock
);
676 void sparx5_ptp_rxtstamp(struct sparx5
*sparx5
, struct sk_buff
*skb
,
679 struct skb_shared_hwtstamps
*shhwtstamps
;
680 struct sparx5_phc
*phc
;
681 struct timespec64 ts
;
687 phc
= &sparx5
->phc
[SPARX5_PHC_PORT
];
688 sparx5_ptp_gettime64(&phc
->info
, &ts
);
690 if (ts
.tv_nsec
< timestamp
)
692 ts
.tv_nsec
= timestamp
;
693 full_ts_in_ns
= ktime_set(ts
.tv_sec
, ts
.tv_nsec
);
695 shhwtstamps
= skb_hwtstamps(skb
);
696 shhwtstamps
->hwtstamp
= full_ts_in_ns
;