80
80
#define SYNC_OUT_1 0x0879
81
81
#define SYNC_OUT_2 0x087a
82
82
83
+ #define SYNC_IN_DIVIDER 0x087b
84
+
83
85
#define SYNOUT_TS_0 0x087c
84
86
#define SYNOUT_TS_1 0x087d
85
87
#define SYNOUT_TS_2 0x087e
89
91
#define NSE_CAPTURE_EN BIT(13)
90
92
#define NSE_INIT BIT(12)
91
93
#define NSE_CPU_FRAMESYNC BIT(5)
94
+ #define NSE_SYNC1_FRAMESYNC BIT(3)
92
95
#define NSE_FRAMESYNC_MASK GENMASK(5, 2)
93
96
#define NSE_PEROUT_EN BIT(1)
94
97
#define NSE_ONESHOT_EN BIT(0)
@@ -128,11 +131,14 @@ struct bcm_ptp_private {
128
131
struct mii_timestamper mii_ts ;
129
132
struct ptp_clock * ptp_clock ;
130
133
struct ptp_clock_info ptp_info ;
134
+ struct ptp_pin_desc pin ;
131
135
struct mutex mutex ;
132
136
struct sk_buff_head tx_queue ;
133
137
int tx_type ;
134
138
bool hwts_rx ;
135
139
u16 nse_ctrl ;
140
+ bool pin_active ;
141
+ struct delayed_work pin_work ;
136
142
};
137
143
138
144
struct bcm_ptp_skb_cb {
@@ -511,6 +517,215 @@ static long bcm_ptp_do_aux_work(struct ptp_clock_info *info)
511
517
return reschedule ? 1 : -1 ;
512
518
}
513
519
520
+ static int bcm_ptp_cancel_func (struct bcm_ptp_private * priv )
521
+ {
522
+ if (!priv -> pin_active )
523
+ return 0 ;
524
+
525
+ priv -> pin_active = false;
526
+
527
+ priv -> nse_ctrl &= ~(NSE_SYNC_OUT_MASK | NSE_SYNC1_FRAMESYNC |
528
+ NSE_CAPTURE_EN );
529
+ bcm_phy_write_exp (priv -> phydev , NSE_CTRL , priv -> nse_ctrl );
530
+
531
+ cancel_delayed_work_sync (& priv -> pin_work );
532
+
533
+ return 0 ;
534
+ }
535
+
536
+ static void bcm_ptp_perout_work (struct work_struct * pin_work )
537
+ {
538
+ struct bcm_ptp_private * priv =
539
+ container_of (pin_work , struct bcm_ptp_private , pin_work .work );
540
+ struct phy_device * phydev = priv -> phydev ;
541
+ struct timespec64 ts ;
542
+ u64 ns , next ;
543
+ u16 ctrl ;
544
+
545
+ mutex_lock (& priv -> mutex );
546
+
547
+ /* no longer running */
548
+ if (!priv -> pin_active ) {
549
+ mutex_unlock (& priv -> mutex );
550
+ return ;
551
+ }
552
+
553
+ bcm_ptp_framesync_ts (phydev , NULL , & ts , priv -> nse_ctrl );
554
+
555
+ /* this is 1PPS only */
556
+ next = NSEC_PER_SEC - ts .tv_nsec ;
557
+ ts .tv_sec += next < NSEC_PER_MSEC ? 2 : 1 ;
558
+ ts .tv_nsec = 0 ;
559
+
560
+ ns = timespec64_to_ns (& ts );
561
+
562
+ /* force 0->1 transition for ONESHOT */
563
+ ctrl = bcm_ptp_framesync_disable (phydev ,
564
+ priv -> nse_ctrl & ~NSE_ONESHOT_EN );
565
+
566
+ bcm_phy_write_exp (phydev , SYNOUT_TS_0 , ns & 0xfff0 );
567
+ bcm_phy_write_exp (phydev , SYNOUT_TS_1 , ns >> 16 );
568
+ bcm_phy_write_exp (phydev , SYNOUT_TS_2 , ns >> 32 );
569
+
570
+ /* load values on next framesync */
571
+ bcm_phy_write_exp (phydev , SHADOW_LOAD , SYNC_OUT_LOAD );
572
+
573
+ bcm_ptp_framesync (phydev , ctrl | NSE_ONESHOT_EN | NSE_INIT );
574
+
575
+ priv -> nse_ctrl |= NSE_ONESHOT_EN ;
576
+ bcm_ptp_framesync_restore (phydev , priv -> nse_ctrl );
577
+
578
+ mutex_unlock (& priv -> mutex );
579
+
580
+ next = next + NSEC_PER_MSEC ;
581
+ schedule_delayed_work (& priv -> pin_work , nsecs_to_jiffies (next ));
582
+ }
583
+
584
+ static int bcm_ptp_perout_locked (struct bcm_ptp_private * priv ,
585
+ struct ptp_perout_request * req , int on )
586
+ {
587
+ struct phy_device * phydev = priv -> phydev ;
588
+ u64 period , pulse ;
589
+ u16 val ;
590
+
591
+ if (!on )
592
+ return bcm_ptp_cancel_func (priv );
593
+
594
+ /* 1PPS */
595
+ if (req -> period .sec != 1 || req -> period .nsec != 0 )
596
+ return - EINVAL ;
597
+
598
+ period = BCM_MAX_PERIOD_8NS ; /* write nonzero value */
599
+
600
+ if (req -> flags & PTP_PEROUT_PHASE )
601
+ return - EOPNOTSUPP ;
602
+
603
+ if (req -> flags & PTP_PEROUT_DUTY_CYCLE )
604
+ pulse = ktime_to_ns (ktime_set (req -> on .sec , req -> on .nsec ));
605
+ else
606
+ pulse = (u64 )BCM_MAX_PULSE_8NS << 3 ;
607
+
608
+ /* convert to 8ns units */
609
+ pulse >>= 3 ;
610
+
611
+ if (!pulse || pulse > period || pulse > BCM_MAX_PULSE_8NS )
612
+ return - EINVAL ;
613
+
614
+ bcm_phy_write_exp (phydev , SYNC_OUT_0 , period );
615
+
616
+ val = ((pulse & 0x3 ) << 14 ) | ((period >> 16 ) & 0x3fff );
617
+ bcm_phy_write_exp (phydev , SYNC_OUT_1 , val );
618
+
619
+ val = ((pulse >> 2 ) & 0x7f ) | (pulse << 7 );
620
+ bcm_phy_write_exp (phydev , SYNC_OUT_2 , val );
621
+
622
+ if (priv -> pin_active )
623
+ cancel_delayed_work_sync (& priv -> pin_work );
624
+
625
+ priv -> pin_active = true;
626
+ INIT_DELAYED_WORK (& priv -> pin_work , bcm_ptp_perout_work );
627
+ schedule_delayed_work (& priv -> pin_work , 0 );
628
+
629
+ return 0 ;
630
+ }
631
+
632
+ static void bcm_ptp_extts_work (struct work_struct * pin_work )
633
+ {
634
+ struct bcm_ptp_private * priv =
635
+ container_of (pin_work , struct bcm_ptp_private , pin_work .work );
636
+ struct phy_device * phydev = priv -> phydev ;
637
+ struct ptp_clock_event event ;
638
+ struct timespec64 ts ;
639
+ u16 reg ;
640
+
641
+ mutex_lock (& priv -> mutex );
642
+
643
+ /* no longer running */
644
+ if (!priv -> pin_active ) {
645
+ mutex_unlock (& priv -> mutex );
646
+ return ;
647
+ }
648
+
649
+ reg = bcm_phy_read_exp (phydev , INTR_STATUS );
650
+ if ((reg & INTC_FSYNC ) == 0 )
651
+ goto out ;
652
+
653
+ bcm_ptp_get_framesync_ts (phydev , & ts );
654
+
655
+ event .index = 0 ;
656
+ event .type = PTP_CLOCK_EXTTS ;
657
+ event .timestamp = timespec64_to_ns (& ts );
658
+ ptp_clock_event (priv -> ptp_clock , & event );
659
+
660
+ out :
661
+ mutex_unlock (& priv -> mutex );
662
+ schedule_delayed_work (& priv -> pin_work , HZ / 4 );
663
+ }
664
+
665
+ static int bcm_ptp_extts_locked (struct bcm_ptp_private * priv , int on )
666
+ {
667
+ struct phy_device * phydev = priv -> phydev ;
668
+
669
+ if (!on )
670
+ return bcm_ptp_cancel_func (priv );
671
+
672
+ if (priv -> pin_active )
673
+ cancel_delayed_work_sync (& priv -> pin_work );
674
+
675
+ bcm_ptp_framesync_disable (phydev , priv -> nse_ctrl );
676
+
677
+ priv -> nse_ctrl |= NSE_SYNC1_FRAMESYNC | NSE_CAPTURE_EN ;
678
+
679
+ bcm_ptp_framesync_restore (phydev , priv -> nse_ctrl );
680
+
681
+ priv -> pin_active = true;
682
+ INIT_DELAYED_WORK (& priv -> pin_work , bcm_ptp_extts_work );
683
+ schedule_delayed_work (& priv -> pin_work , 0 );
684
+
685
+ return 0 ;
686
+ }
687
+
688
+ static int bcm_ptp_enable (struct ptp_clock_info * info ,
689
+ struct ptp_clock_request * rq , int on )
690
+ {
691
+ struct bcm_ptp_private * priv = ptp2priv (info );
692
+ int err = - EBUSY ;
693
+
694
+ mutex_lock (& priv -> mutex );
695
+
696
+ switch (rq -> type ) {
697
+ case PTP_CLK_REQ_PEROUT :
698
+ if (priv -> pin .func == PTP_PF_PEROUT )
699
+ err = bcm_ptp_perout_locked (priv , & rq -> perout , on );
700
+ break ;
701
+ case PTP_CLK_REQ_EXTTS :
702
+ if (priv -> pin .func == PTP_PF_EXTTS )
703
+ err = bcm_ptp_extts_locked (priv , on );
704
+ break ;
705
+ default :
706
+ err = - EOPNOTSUPP ;
707
+ break ;
708
+ }
709
+
710
+ mutex_unlock (& priv -> mutex );
711
+
712
+ return err ;
713
+ }
714
+
715
+ static int bcm_ptp_verify (struct ptp_clock_info * info , unsigned int pin ,
716
+ enum ptp_pin_function func , unsigned int chan )
717
+ {
718
+ switch (func ) {
719
+ case PTP_PF_NONE :
720
+ case PTP_PF_EXTTS :
721
+ case PTP_PF_PEROUT :
722
+ break ;
723
+ default :
724
+ return - EOPNOTSUPP ;
725
+ }
726
+ return 0 ;
727
+ }
728
+
514
729
static const struct ptp_clock_info bcm_ptp_clock_info = {
515
730
.owner = THIS_MODULE ,
516
731
.name = KBUILD_MODNAME ,
@@ -519,7 +734,12 @@ static const struct ptp_clock_info bcm_ptp_clock_info = {
519
734
.settime64 = bcm_ptp_settime ,
520
735
.adjtime = bcm_ptp_adjtime ,
521
736
.adjfine = bcm_ptp_adjfine ,
737
+ .enable = bcm_ptp_enable ,
738
+ .verify = bcm_ptp_verify ,
522
739
.do_aux_work = bcm_ptp_do_aux_work ,
740
+ .n_pins = 1 ,
741
+ .n_per_out = 1 ,
742
+ .n_ext_ts = 1 ,
523
743
};
524
744
525
745
static void bcm_ptp_txtstamp (struct mii_timestamper * mii_ts ,
@@ -648,6 +868,7 @@ static int bcm_ptp_ts_info(struct mii_timestamper *mii_ts,
648
868
void bcm_ptp_stop (struct bcm_ptp_private * priv )
649
869
{
650
870
ptp_cancel_worker_sync (priv -> ptp_clock );
871
+ bcm_ptp_cancel_func (priv );
651
872
}
652
873
EXPORT_SYMBOL_GPL (bcm_ptp_stop );
653
874
@@ -667,6 +888,8 @@ void bcm_ptp_config_init(struct phy_device *phydev)
667
888
668
889
/* always allow FREQ_LOAD on framesync */
669
890
bcm_phy_write_exp (phydev , SHADOW_CTRL , FREQ_LOAD );
891
+
892
+ bcm_phy_write_exp (phydev , SYNC_IN_DIVIDER , 1 );
670
893
}
671
894
EXPORT_SYMBOL_GPL (bcm_ptp_config_init );
672
895
@@ -703,6 +926,9 @@ struct bcm_ptp_private *bcm_ptp_probe(struct phy_device *phydev)
703
926
704
927
priv -> ptp_info = bcm_ptp_clock_info ;
705
928
929
+ snprintf (priv -> pin .name , sizeof (priv -> pin .name ), "SYNC_OUT" );
930
+ priv -> ptp_info .pin_config = & priv -> pin ;
931
+
706
932
clock = ptp_clock_register (& priv -> ptp_info , & phydev -> mdio .dev );
707
933
if (IS_ERR (clock ))
708
934
return ERR_CAST (clock );
0 commit comments