@@ -204,6 +204,123 @@ void lan966x_ptp_txtstamp_release(struct lan966x_port *port,
204
204
spin_unlock_irqrestore (& lan966x -> ptp_ts_id_lock , flags );
205
205
}
206
206
207
+ static void lan966x_get_hwtimestamp (struct lan966x * lan966x ,
208
+ struct timespec64 * ts ,
209
+ u32 nsec )
210
+ {
211
+ /* Read current PTP time to get seconds */
212
+ unsigned long flags ;
213
+ u32 curr_nsec ;
214
+
215
+ spin_lock_irqsave (& lan966x -> ptp_clock_lock , flags );
216
+
217
+ lan_rmw (PTP_PIN_CFG_PIN_ACTION_SET (PTP_PIN_ACTION_SAVE ) |
218
+ PTP_PIN_CFG_PIN_DOM_SET (LAN966X_PHC_PORT ) |
219
+ PTP_PIN_CFG_PIN_SYNC_SET (0 ),
220
+ PTP_PIN_CFG_PIN_ACTION |
221
+ PTP_PIN_CFG_PIN_DOM |
222
+ PTP_PIN_CFG_PIN_SYNC ,
223
+ lan966x , PTP_PIN_CFG (TOD_ACC_PIN ));
224
+
225
+ ts -> tv_sec = lan_rd (lan966x , PTP_TOD_SEC_LSB (TOD_ACC_PIN ));
226
+ curr_nsec = lan_rd (lan966x , PTP_TOD_NSEC (TOD_ACC_PIN ));
227
+
228
+ ts -> tv_nsec = nsec ;
229
+
230
+ /* Sec has incremented since the ts was registered */
231
+ if (curr_nsec < nsec )
232
+ ts -> tv_sec -- ;
233
+
234
+ spin_unlock_irqrestore (& lan966x -> ptp_clock_lock , flags );
235
+ }
236
+
237
+ irqreturn_t lan966x_ptp_irq_handler (int irq , void * args )
238
+ {
239
+ int budget = LAN966X_MAX_PTP_ID ;
240
+ struct lan966x * lan966x = args ;
241
+
242
+ while (budget -- ) {
243
+ struct sk_buff * skb , * skb_tmp , * skb_match = NULL ;
244
+ struct skb_shared_hwtstamps shhwtstamps ;
245
+ struct lan966x_port * port ;
246
+ struct timespec64 ts ;
247
+ unsigned long flags ;
248
+ u32 val , id , txport ;
249
+ u32 delay ;
250
+
251
+ val = lan_rd (lan966x , PTP_TWOSTEP_CTRL );
252
+
253
+ /* Check if a timestamp can be retrieved */
254
+ if (!(val & PTP_TWOSTEP_CTRL_VLD ))
255
+ break ;
256
+
257
+ WARN_ON (val & PTP_TWOSTEP_CTRL_OVFL );
258
+
259
+ if (!(val & PTP_TWOSTEP_CTRL_STAMP_TX ))
260
+ continue ;
261
+
262
+ /* Retrieve the ts Tx port */
263
+ txport = PTP_TWOSTEP_CTRL_STAMP_PORT_GET (val );
264
+
265
+ /* Retrieve its associated skb */
266
+ port = lan966x -> ports [txport ];
267
+
268
+ /* Retrieve the delay */
269
+ delay = lan_rd (lan966x , PTP_TWOSTEP_STAMP );
270
+ delay = PTP_TWOSTEP_STAMP_STAMP_NSEC_GET (delay );
271
+
272
+ /* Get next timestamp from fifo, which needs to be the
273
+ * rx timestamp which represents the id of the frame
274
+ */
275
+ lan_rmw (PTP_TWOSTEP_CTRL_NXT_SET (1 ),
276
+ PTP_TWOSTEP_CTRL_NXT ,
277
+ lan966x , PTP_TWOSTEP_CTRL );
278
+
279
+ val = lan_rd (lan966x , PTP_TWOSTEP_CTRL );
280
+
281
+ /* Check if a timestamp can be retried */
282
+ if (!(val & PTP_TWOSTEP_CTRL_VLD ))
283
+ break ;
284
+
285
+ /* Read RX timestamping to get the ID */
286
+ id = lan_rd (lan966x , PTP_TWOSTEP_STAMP );
287
+
288
+ spin_lock_irqsave (& port -> tx_skbs .lock , flags );
289
+ skb_queue_walk_safe (& port -> tx_skbs , skb , skb_tmp ) {
290
+ if (LAN966X_SKB_CB (skb )-> ts_id != id )
291
+ continue ;
292
+
293
+ __skb_unlink (skb , & port -> tx_skbs );
294
+ skb_match = skb ;
295
+ break ;
296
+ }
297
+ spin_unlock_irqrestore (& port -> tx_skbs .lock , flags );
298
+
299
+ /* Next ts */
300
+ lan_rmw (PTP_TWOSTEP_CTRL_NXT_SET (1 ),
301
+ PTP_TWOSTEP_CTRL_NXT ,
302
+ lan966x , PTP_TWOSTEP_CTRL );
303
+
304
+ if (WARN_ON (!skb_match ))
305
+ continue ;
306
+
307
+ spin_lock (& lan966x -> ptp_ts_id_lock );
308
+ lan966x -> ptp_skbs -- ;
309
+ spin_unlock (& lan966x -> ptp_ts_id_lock );
310
+
311
+ /* Get the h/w timestamp */
312
+ lan966x_get_hwtimestamp (lan966x , & ts , delay );
313
+
314
+ /* Set the timestamp into the skb */
315
+ shhwtstamps .hwtstamp = ktime_set (ts .tv_sec , ts .tv_nsec );
316
+ skb_tstamp_tx (skb_match , & shhwtstamps );
317
+
318
+ dev_kfree_skb_any (skb_match );
319
+ }
320
+
321
+ return IRQ_HANDLED ;
322
+ }
323
+
207
324
static int lan966x_ptp_adjfine (struct ptp_clock_info * ptp , long scaled_ppm )
208
325
{
209
326
struct lan966x_phc * phc = container_of (ptp , struct lan966x_phc , info );
0 commit comments