@@ -37,6 +37,22 @@ enum {
37
37
MLX5E_CYCLES_SHIFT = 23
38
38
};
39
39
40
+ enum {
41
+ MLX5E_PIN_MODE_IN = 0x0 ,
42
+ MLX5E_PIN_MODE_OUT = 0x1 ,
43
+ };
44
+
45
+ enum {
46
+ MLX5E_OUT_PATTERN_PULSE = 0x0 ,
47
+ MLX5E_OUT_PATTERN_PERIODIC = 0x1 ,
48
+ };
49
+
50
+ enum {
51
+ MLX5E_EVENT_MODE_DISABLE = 0x0 ,
52
+ MLX5E_EVENT_MODE_REPETETIVE = 0x1 ,
53
+ MLX5E_EVENT_MODE_ONCE_TILL_ARM = 0x2 ,
54
+ };
55
+
40
56
void mlx5e_fill_hwstamp (struct mlx5e_tstamp * tstamp , u64 timestamp ,
41
57
struct skb_shared_hwtstamps * hwts )
42
58
{
@@ -189,6 +205,18 @@ static int mlx5e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
189
205
int neg_adj = 0 ;
190
206
struct mlx5e_tstamp * tstamp = container_of (ptp , struct mlx5e_tstamp ,
191
207
ptp_info );
208
+ struct mlx5e_priv * priv =
209
+ container_of (tstamp , struct mlx5e_priv , tstamp );
210
+
211
+ if (MLX5_CAP_GEN (priv -> mdev , pps_modify )) {
212
+ u32 in [MLX5_ST_SZ_DW (mtpps_reg )] = {0 };
213
+
214
+ /* For future use need to add a loop for finding all 1PPS out pins */
215
+ MLX5_SET (mtpps_reg , in , pin_mode , MLX5E_PIN_MODE_OUT );
216
+ MLX5_SET (mtpps_reg , in , out_periodic_adjustment , delta & 0xFFFF );
217
+
218
+ mlx5_set_mtpps (priv -> mdev , in , sizeof (in ));
219
+ }
192
220
193
221
if (delta < 0 ) {
194
222
neg_adj = 1 ;
@@ -208,6 +236,124 @@ static int mlx5e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
208
236
return 0 ;
209
237
}
210
238
239
+ static int mlx5e_extts_configure (struct ptp_clock_info * ptp ,
240
+ struct ptp_clock_request * rq ,
241
+ int on )
242
+ {
243
+ struct mlx5e_tstamp * tstamp =
244
+ container_of (ptp , struct mlx5e_tstamp , ptp_info );
245
+ struct mlx5e_priv * priv =
246
+ container_of (tstamp , struct mlx5e_priv , tstamp );
247
+ u32 in [MLX5_ST_SZ_DW (mtpps_reg )] = {0 };
248
+ u8 pattern = 0 ;
249
+ int pin = -1 ;
250
+ int err = 0 ;
251
+
252
+ if (!MLX5_CAP_GEN (priv -> mdev , pps ) ||
253
+ !MLX5_CAP_GEN (priv -> mdev , pps_modify ))
254
+ return - EOPNOTSUPP ;
255
+
256
+ if (rq -> extts .index >= tstamp -> ptp_info .n_pins )
257
+ return - EINVAL ;
258
+
259
+ if (on ) {
260
+ pin = ptp_find_pin (tstamp -> ptp , PTP_PF_EXTTS , rq -> extts .index );
261
+ if (pin < 0 )
262
+ return - EBUSY ;
263
+ }
264
+
265
+ if (rq -> extts .flags & PTP_FALLING_EDGE )
266
+ pattern = 1 ;
267
+
268
+ MLX5_SET (mtpps_reg , in , pin , pin );
269
+ MLX5_SET (mtpps_reg , in , pin_mode , MLX5E_PIN_MODE_IN );
270
+ MLX5_SET (mtpps_reg , in , pattern , pattern );
271
+ MLX5_SET (mtpps_reg , in , enable , on );
272
+
273
+ err = mlx5_set_mtpps (priv -> mdev , in , sizeof (in ));
274
+ if (err )
275
+ return err ;
276
+
277
+ return mlx5_set_mtppse (priv -> mdev , pin , 0 ,
278
+ MLX5E_EVENT_MODE_REPETETIVE & on );
279
+ }
280
+
281
+ static int mlx5e_perout_configure (struct ptp_clock_info * ptp ,
282
+ struct ptp_clock_request * rq ,
283
+ int on )
284
+ {
285
+ struct mlx5e_tstamp * tstamp =
286
+ container_of (ptp , struct mlx5e_tstamp , ptp_info );
287
+ struct mlx5e_priv * priv =
288
+ container_of (tstamp , struct mlx5e_priv , tstamp );
289
+ u32 in [MLX5_ST_SZ_DW (mtpps_reg )] = {0 };
290
+ u64 nsec_now , nsec_delta , time_stamp ;
291
+ u64 cycles_now , cycles_delta ;
292
+ struct timespec64 ts ;
293
+ unsigned long flags ;
294
+ int pin = -1 ;
295
+ s64 ns ;
296
+
297
+ if (!MLX5_CAP_GEN (priv -> mdev , pps_modify ))
298
+ return - EOPNOTSUPP ;
299
+
300
+ if (rq -> perout .index >= tstamp -> ptp_info .n_pins )
301
+ return - EINVAL ;
302
+
303
+ if (on ) {
304
+ pin = ptp_find_pin (tstamp -> ptp , PTP_PF_PEROUT ,
305
+ rq -> perout .index );
306
+ if (pin < 0 )
307
+ return - EBUSY ;
308
+ }
309
+
310
+ ts .tv_sec = rq -> perout .period .sec ;
311
+ ts .tv_nsec = rq -> perout .period .nsec ;
312
+ ns = timespec64_to_ns (& ts );
313
+ if (on )
314
+ if ((ns >> 1 ) != 500000000LL )
315
+ return - EINVAL ;
316
+ ts .tv_sec = rq -> perout .start .sec ;
317
+ ts .tv_nsec = rq -> perout .start .nsec ;
318
+ ns = timespec64_to_ns (& ts );
319
+ cycles_now = mlx5_read_internal_timer (tstamp -> mdev );
320
+ write_lock_irqsave (& tstamp -> lock , flags );
321
+ nsec_now = timecounter_cyc2time (& tstamp -> clock , cycles_now );
322
+ nsec_delta = ns - nsec_now ;
323
+ cycles_delta = div64_u64 (nsec_delta << tstamp -> cycles .shift ,
324
+ tstamp -> cycles .mult );
325
+ write_unlock_irqrestore (& tstamp -> lock , flags );
326
+ time_stamp = cycles_now + cycles_delta ;
327
+ MLX5_SET (mtpps_reg , in , pin , pin );
328
+ MLX5_SET (mtpps_reg , in , pin_mode , MLX5E_PIN_MODE_OUT );
329
+ MLX5_SET (mtpps_reg , in , pattern , MLX5E_OUT_PATTERN_PERIODIC );
330
+ MLX5_SET (mtpps_reg , in , enable , on );
331
+ MLX5_SET64 (mtpps_reg , in , time_stamp , time_stamp );
332
+
333
+ return mlx5_set_mtpps (priv -> mdev , in , sizeof (in ));
334
+ }
335
+
336
+ static int mlx5e_ptp_enable (struct ptp_clock_info * ptp ,
337
+ struct ptp_clock_request * rq ,
338
+ int on )
339
+ {
340
+ switch (rq -> type ) {
341
+ case PTP_CLK_REQ_EXTTS :
342
+ return mlx5e_extts_configure (ptp , rq , on );
343
+ case PTP_CLK_REQ_PEROUT :
344
+ return mlx5e_perout_configure (ptp , rq , on );
345
+ default :
346
+ return - EOPNOTSUPP ;
347
+ }
348
+ return 0 ;
349
+ }
350
+
351
+ static int mlx5e_ptp_verify (struct ptp_clock_info * ptp , unsigned int pin ,
352
+ enum ptp_pin_function func , unsigned int chan )
353
+ {
354
+ return (func == PTP_PF_PHYSYNC ) ? - EOPNOTSUPP : 0 ;
355
+ }
356
+
211
357
static const struct ptp_clock_info mlx5e_ptp_clock_info = {
212
358
.owner = THIS_MODULE ,
213
359
.max_adj = 100000000 ,
@@ -221,6 +367,7 @@ static const struct ptp_clock_info mlx5e_ptp_clock_info = {
221
367
.gettime64 = mlx5e_ptp_gettime ,
222
368
.settime64 = mlx5e_ptp_settime ,
223
369
.enable = NULL ,
370
+ .verify = NULL ,
224
371
};
225
372
226
373
static void mlx5e_timestamp_init_config (struct mlx5e_tstamp * tstamp )
@@ -229,6 +376,62 @@ static void mlx5e_timestamp_init_config(struct mlx5e_tstamp *tstamp)
229
376
tstamp -> hwtstamp_config .rx_filter = HWTSTAMP_FILTER_NONE ;
230
377
}
231
378
379
+ static int mlx5e_init_pin_config (struct mlx5e_tstamp * tstamp )
380
+ {
381
+ int i ;
382
+
383
+ tstamp -> ptp_info .pin_config =
384
+ kzalloc (sizeof (* tstamp -> ptp_info .pin_config ) *
385
+ tstamp -> ptp_info .n_pins , GFP_KERNEL );
386
+ if (!tstamp -> ptp_info .pin_config )
387
+ return - ENOMEM ;
388
+ tstamp -> ptp_info .enable = mlx5e_ptp_enable ;
389
+ tstamp -> ptp_info .verify = mlx5e_ptp_verify ;
390
+
391
+ for (i = 0 ; i < tstamp -> ptp_info .n_pins ; i ++ ) {
392
+ snprintf (tstamp -> ptp_info .pin_config [i ].name ,
393
+ sizeof (tstamp -> ptp_info .pin_config [i ].name ),
394
+ "mlx5_pps%d" , i );
395
+ tstamp -> ptp_info .pin_config [i ].index = i ;
396
+ tstamp -> ptp_info .pin_config [i ].func = PTP_PF_NONE ;
397
+ tstamp -> ptp_info .pin_config [i ].chan = i ;
398
+ }
399
+
400
+ return 0 ;
401
+ }
402
+
403
+ static void mlx5e_get_pps_caps (struct mlx5e_priv * priv ,
404
+ struct mlx5e_tstamp * tstamp )
405
+ {
406
+ u32 out [MLX5_ST_SZ_DW (mtpps_reg )] = {0 };
407
+
408
+ mlx5_query_mtpps (priv -> mdev , out , sizeof (out ));
409
+
410
+ tstamp -> ptp_info .n_pins = MLX5_GET (mtpps_reg , out ,
411
+ cap_number_of_pps_pins );
412
+ tstamp -> ptp_info .n_ext_ts = MLX5_GET (mtpps_reg , out ,
413
+ cap_max_num_of_pps_in_pins );
414
+ tstamp -> ptp_info .n_per_out = MLX5_GET (mtpps_reg , out ,
415
+ cap_max_num_of_pps_out_pins );
416
+
417
+ tstamp -> pps_pin_caps [0 ] = MLX5_GET (mtpps_reg , out , cap_pin_0_mode );
418
+ tstamp -> pps_pin_caps [1 ] = MLX5_GET (mtpps_reg , out , cap_pin_1_mode );
419
+ tstamp -> pps_pin_caps [2 ] = MLX5_GET (mtpps_reg , out , cap_pin_2_mode );
420
+ tstamp -> pps_pin_caps [3 ] = MLX5_GET (mtpps_reg , out , cap_pin_3_mode );
421
+ tstamp -> pps_pin_caps [4 ] = MLX5_GET (mtpps_reg , out , cap_pin_4_mode );
422
+ tstamp -> pps_pin_caps [5 ] = MLX5_GET (mtpps_reg , out , cap_pin_5_mode );
423
+ tstamp -> pps_pin_caps [6 ] = MLX5_GET (mtpps_reg , out , cap_pin_6_mode );
424
+ tstamp -> pps_pin_caps [7 ] = MLX5_GET (mtpps_reg , out , cap_pin_7_mode );
425
+ }
426
+
427
+ void mlx5e_pps_event_handler (struct mlx5e_priv * priv ,
428
+ struct ptp_clock_event * event )
429
+ {
430
+ struct mlx5e_tstamp * tstamp = & priv -> tstamp ;
431
+
432
+ ptp_clock_event (tstamp -> ptp , event );
433
+ }
434
+
232
435
void mlx5e_timestamp_init (struct mlx5e_priv * priv )
233
436
{
234
437
struct mlx5e_tstamp * tstamp = & priv -> tstamp ;
@@ -272,6 +475,18 @@ void mlx5e_timestamp_init(struct mlx5e_priv *priv)
272
475
tstamp -> ptp_info = mlx5e_ptp_clock_info ;
273
476
snprintf (tstamp -> ptp_info .name , 16 , "mlx5 ptp" );
274
477
478
+ /* Initialize 1PPS data structures */
479
+ #define MAX_PIN_NUM 8
480
+ tstamp -> pps_pin_caps = kzalloc (sizeof (u8 ) * MAX_PIN_NUM , GFP_KERNEL );
481
+ if (tstamp -> pps_pin_caps ) {
482
+ if (MLX5_CAP_GEN (priv -> mdev , pps ))
483
+ mlx5e_get_pps_caps (priv , tstamp );
484
+ if (tstamp -> ptp_info .n_pins )
485
+ mlx5e_init_pin_config (tstamp );
486
+ } else {
487
+ mlx5_core_warn (priv -> mdev , "1PPS initialization failed\n" );
488
+ }
489
+
275
490
tstamp -> ptp = ptp_clock_register (& tstamp -> ptp_info ,
276
491
& priv -> mdev -> pdev -> dev );
277
492
if (IS_ERR (tstamp -> ptp )) {
@@ -293,5 +508,8 @@ void mlx5e_timestamp_cleanup(struct mlx5e_priv *priv)
293
508
priv -> tstamp .ptp = NULL ;
294
509
}
295
510
511
+ kfree (tstamp -> pps_pin_caps );
512
+ kfree (tstamp -> ptp_info .pin_config );
513
+
296
514
cancel_delayed_work_sync (& tstamp -> overflow_work );
297
515
}
0 commit comments