Skip to content

Commit 4ece1ae

Browse files
microchip1kuba-moo
authored andcommitted
net: microchip: lan743x: add support for PTP pulse width (duty cycle)
If the PTP_PEROUT_DUTY_CYCLE flag is set, then check if the request_on value in ptp_perout_request matches the pre-defined values or a toggle option. Return a failure if the value is not supported. Preserve the old behaviors if the PTP_PEROUT_DUTY_CYCLE flag is not set. Tested with an oscilloscope on EVB-LAN7430: e.g., to output PPS 1sec period 500mS on (high) to GPIO 2. ./testptp -L 2,2 ./testptp -p 1000000000 -w 500000000 Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com> Link: https://lore.kernel.org/r/1634046593-64312-1-git-send-email-yuiko.oshino@microchip.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 67ca515 commit 4ece1ae

File tree

2 files changed

+81
-11
lines changed

2 files changed

+81
-11
lines changed

drivers/net/ethernet/microchip/lan743x_main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@
279279
#define PTP_GENERAL_CONFIG_CLOCK_EVENT_1MS_ (3)
280280
#define PTP_GENERAL_CONFIG_CLOCK_EVENT_10MS_ (4)
281281
#define PTP_GENERAL_CONFIG_CLOCK_EVENT_200MS_ (5)
282+
#define PTP_GENERAL_CONFIG_CLOCK_EVENT_TOGGLE_ (6)
282283
#define PTP_GENERAL_CONFIG_CLOCK_EVENT_X_SET_(channel, value) \
283284
(((value) & 0x7) << (1 + ((channel) << 2)))
284285
#define PTP_GENERAL_CONFIG_RELOAD_ADD_X_(channel) (BIT((channel) << 2))

drivers/net/ethernet/microchip/lan743x_ptp.c

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -491,9 +491,10 @@ static int lan743x_ptp_perout(struct lan743x_adapter *adapter, int on,
491491
int perout_pin = 0;
492492
unsigned int index = perout_request->index;
493493
struct lan743x_ptp_perout *perout = &ptp->perout[index];
494+
int ret = 0;
494495

495496
/* Reject requests with unsupported flags */
496-
if (perout_request->flags)
497+
if (perout_request->flags & ~PTP_PEROUT_DUTY_CYCLE)
497498
return -EOPNOTSUPP;
498499

499500
if (on) {
@@ -518,6 +519,7 @@ static int lan743x_ptp_perout(struct lan743x_adapter *adapter, int on,
518519
netif_warn(adapter, drv, adapter->netdev,
519520
"Failed to reserve event channel %d for PEROUT\n",
520521
index);
522+
ret = -EBUSY;
521523
goto failed;
522524
}
523525

@@ -529,6 +531,7 @@ static int lan743x_ptp_perout(struct lan743x_adapter *adapter, int on,
529531
netif_warn(adapter, drv, adapter->netdev,
530532
"Failed to reserve gpio %d for PEROUT\n",
531533
perout_pin);
534+
ret = -EBUSY;
532535
goto failed;
533536
}
534537

@@ -540,27 +543,93 @@ static int lan743x_ptp_perout(struct lan743x_adapter *adapter, int on,
540543
period_sec += perout_request->period.nsec / 1000000000;
541544
period_nsec = perout_request->period.nsec % 1000000000;
542545

543-
if (period_sec == 0) {
544-
if (period_nsec >= 400000000) {
546+
if (perout_request->flags & PTP_PEROUT_DUTY_CYCLE) {
547+
struct timespec64 ts_on, ts_period;
548+
s64 wf_high, period64, half;
549+
s32 reminder;
550+
551+
ts_on.tv_sec = perout_request->on.sec;
552+
ts_on.tv_nsec = perout_request->on.nsec;
553+
wf_high = timespec64_to_ns(&ts_on);
554+
ts_period.tv_sec = perout_request->period.sec;
555+
ts_period.tv_nsec = perout_request->period.nsec;
556+
period64 = timespec64_to_ns(&ts_period);
557+
558+
if (period64 < 200) {
559+
netif_warn(adapter, drv, adapter->netdev,
560+
"perout period too small, minimum is 200nS\n");
561+
ret = -EOPNOTSUPP;
562+
goto failed;
563+
}
564+
if (wf_high >= period64) {
565+
netif_warn(adapter, drv, adapter->netdev,
566+
"pulse width must be smaller than period\n");
567+
ret = -EINVAL;
568+
goto failed;
569+
}
570+
571+
/* Check if we can do 50% toggle on an even value of period.
572+
* If the period number is odd, then check if the requested
573+
* pulse width is the same as one of pre-defined width values.
574+
* Otherwise, return failure.
575+
*/
576+
half = div_s64_rem(period64, 2, &reminder);
577+
if (!reminder) {
578+
if (half == wf_high) {
579+
/* It's 50% match. Use the toggle option */
580+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_TOGGLE_;
581+
/* In this case, devide period value by 2 */
582+
ts_period = ns_to_timespec64(div_s64(period64, 2));
583+
period_sec = ts_period.tv_sec;
584+
period_nsec = ts_period.tv_nsec;
585+
586+
goto program;
587+
}
588+
}
589+
/* if we can't do toggle, then the width option needs to be the exact match */
590+
if (wf_high == 200000000) {
545591
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_200MS_;
546-
} else if (period_nsec >= 20000000) {
592+
} else if (wf_high == 10000000) {
547593
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_10MS_;
548-
} else if (period_nsec >= 2000000) {
594+
} else if (wf_high == 1000000) {
549595
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_1MS_;
550-
} else if (period_nsec >= 200000) {
596+
} else if (wf_high == 100000) {
551597
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_100US_;
552-
} else if (period_nsec >= 20000) {
598+
} else if (wf_high == 10000) {
553599
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_10US_;
554-
} else if (period_nsec >= 200) {
600+
} else if (wf_high == 100) {
555601
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_100NS_;
556602
} else {
557603
netif_warn(adapter, drv, adapter->netdev,
558-
"perout period too small, minimum is 200nS\n");
604+
"duty cycle specified is not supported\n");
605+
ret = -EOPNOTSUPP;
559606
goto failed;
560607
}
561608
} else {
562-
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_200MS_;
609+
if (period_sec == 0) {
610+
if (period_nsec >= 400000000) {
611+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_200MS_;
612+
} else if (period_nsec >= 20000000) {
613+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_10MS_;
614+
} else if (period_nsec >= 2000000) {
615+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_1MS_;
616+
} else if (period_nsec >= 200000) {
617+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_100US_;
618+
} else if (period_nsec >= 20000) {
619+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_10US_;
620+
} else if (period_nsec >= 200) {
621+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_100NS_;
622+
} else {
623+
netif_warn(adapter, drv, adapter->netdev,
624+
"perout period too small, minimum is 200nS\n");
625+
ret = -EOPNOTSUPP;
626+
goto failed;
627+
}
628+
} else {
629+
pulse_width = PTP_GENERAL_CONFIG_CLOCK_EVENT_200MS_;
630+
}
563631
}
632+
program:
564633

565634
/* turn off by setting target far in future */
566635
lan743x_csr_write(adapter,
@@ -599,7 +668,7 @@ static int lan743x_ptp_perout(struct lan743x_adapter *adapter, int on,
599668

600669
failed:
601670
lan743x_ptp_perout_off(adapter, index);
602-
return -ENODEV;
671+
return ret;
603672
}
604673

605674
static int lan743x_ptpci_enable(struct ptp_clock_info *ptpci,

0 commit comments

Comments
 (0)