@@ -128,6 +128,12 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
128128
129129 spin_lock_irqsave (& fep -> tmreg_lock , flags );
130130
131+ if (fep -> perout_enable ) {
132+ spin_unlock_irqrestore (& fep -> tmreg_lock , flags );
133+ dev_err (& fep -> pdev -> dev , "PEROUT is running" );
134+ return - EBUSY ;
135+ }
136+
131137 if (fep -> pps_enable == enable ) {
132138 spin_unlock_irqrestore (& fep -> tmreg_lock , flags );
133139 return 0 ;
@@ -243,6 +249,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep)
243249 * the FEC_TCCR register in time and missed the start time.
244250 */
245251 if (fep -> perout_stime < curr_time + 100 * NSEC_PER_MSEC ) {
252+ fep -> perout_enable = false;
246253 dev_err (& fep -> pdev -> dev , "Current time is too close to the start time!\n" );
247254 spin_unlock_irqrestore (& fep -> tmreg_lock , flags );
248255 return -1 ;
@@ -497,7 +504,10 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel)
497504{
498505 unsigned long flags ;
499506
507+ hrtimer_cancel (& fep -> perout_timer );
508+
500509 spin_lock_irqsave (& fep -> tmreg_lock , flags );
510+ fep -> perout_enable = false;
501511 writel (0 , fep -> hwp + FEC_TCSR (channel ));
502512 spin_unlock_irqrestore (& fep -> tmreg_lock , flags );
503513
@@ -529,6 +539,8 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
529539
530540 return ret ;
531541 } else if (rq -> type == PTP_CLK_REQ_PEROUT ) {
542+ u32 reload_period ;
543+
532544 /* Reject requests with unsupported flags */
533545 if (rq -> perout .flags )
534546 return - EOPNOTSUPP ;
@@ -548,12 +560,14 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
548560 return - EOPNOTSUPP ;
549561 }
550562
551- fep -> reload_period = div_u64 (period_ns , 2 );
552- if (on && fep -> reload_period ) {
563+ reload_period = div_u64 (period_ns , 2 );
564+ if (on && reload_period ) {
565+ u64 perout_stime ;
566+
553567 /* Convert 1588 timestamp to ns*/
554568 start_time .tv_sec = rq -> perout .start .sec ;
555569 start_time .tv_nsec = rq -> perout .start .nsec ;
556- fep -> perout_stime = timespec64_to_ns (& start_time );
570+ perout_stime = timespec64_to_ns (& start_time );
557571
558572 mutex_lock (& fep -> ptp_clk_mutex );
559573 if (!fep -> ptp_clk_on ) {
@@ -562,18 +576,41 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
562576 return - EOPNOTSUPP ;
563577 }
564578 spin_lock_irqsave (& fep -> tmreg_lock , flags );
579+
580+ if (fep -> pps_enable ) {
581+ dev_err (& fep -> pdev -> dev , "PPS is running" );
582+ ret = - EBUSY ;
583+ goto unlock ;
584+ }
585+
586+ if (fep -> perout_enable ) {
587+ dev_err (& fep -> pdev -> dev ,
588+ "PEROUT has been enabled\n" );
589+ ret = - EBUSY ;
590+ goto unlock ;
591+ }
592+
565593 /* Read current timestamp */
566594 curr_time = timecounter_read (& fep -> tc );
567- spin_unlock_irqrestore (& fep -> tmreg_lock , flags );
568- mutex_unlock (& fep -> ptp_clk_mutex );
595+ if (perout_stime <= curr_time ) {
596+ dev_err (& fep -> pdev -> dev ,
597+ "Start time must be greater than current time\n" );
598+ ret = - EINVAL ;
599+ goto unlock ;
600+ }
569601
570602 /* Calculate time difference */
571- delta = fep -> perout_stime - curr_time ;
603+ delta = perout_stime - curr_time ;
604+ fep -> reload_period = reload_period ;
605+ fep -> perout_stime = perout_stime ;
606+ fep -> perout_enable = true;
572607
573- if (fep -> perout_stime <= curr_time ) {
574- dev_err (& fep -> pdev -> dev , "Start time must larger than current time!\n" );
575- return - EINVAL ;
576- }
608+ unlock :
609+ spin_unlock_irqrestore (& fep -> tmreg_lock , flags );
610+ mutex_unlock (& fep -> ptp_clk_mutex );
611+
612+ if (ret )
613+ return ret ;
577614
578615 /* Because the timer counter of FEC only has 31-bits, correspondingly,
579616 * the time comparison register FEC_TCCR also only low 31 bits can be
@@ -681,8 +718,11 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id)
681718 fep -> next_counter = (fep -> next_counter + fep -> reload_period ) &
682719 fep -> cc .mask ;
683720
684- event .type = PTP_CLOCK_PPS ;
685- ptp_clock_event (fep -> ptp_clock , & event );
721+ if (fep -> pps_enable ) {
722+ event .type = PTP_CLOCK_PPS ;
723+ ptp_clock_event (fep -> ptp_clock , & event );
724+ }
725+
686726 return IRQ_HANDLED ;
687727 }
688728
0 commit comments