History

fec: Restart PPS after link state change

On link state change, the controller gets reset, causing PPS to drop out and the PHC to lose its time and calibration. So we restart it if needed, restoring calibration and time registers. Changes since v2: * Add `fec_ptp_save_state()`/`fec_ptp_restore_state()` * Use `ktime_get_real_ns()` * Use `BIT()` macro Changes since v1: * More ECR #define's * Stop PPS in `fec_ptp_stop()`

Csókás Bence committed 4 years ago

Commit f7995921 parent d5485d93 files · +77 −4Browse files

Unified · Split

3 files
  1. drivers/net/ethernet/freescale/fec.h +10 −0
  2. drivers/net/ethernet/freescale/fec_main.c +38 −4
  3. drivers/net/ethernet/freescale/fec_ptp.c +29 −0
drivers/net/ethernet/freescale/fec.h+10−0
@@ -634,6 +634,13 @@ struct fec_enet_private { · 633 unmodified lines
634634 int pps_enable;
635635 unsigned int next_counter;
636636
637+ struct {
638+ struct timespec64 ts_phc;
639+ u64 ns_sys;
640+ u32 at_corr;
641+ u8 at_inc_corr;
642+ } ptp_saved_state;
643+
637644 u64 ethtool_stats[];
638645 };
639646
@@ -644,5 +651,8 @@ void fec_ptp_disable_hwts(struct net_device *ndev); · 4 unmodified lines
644651 int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
645652 int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
646653
654+void fec_ptp_save_state(struct fec_enet_private *fep);
655+int fec_ptp_restore_state(struct fec_enet_private *fep);
656+
647657 /****************************************************************************/
648658 #endif /* FEC_H */
drivers/net/ethernet/freescale/fec_main.c+38−4
@@ -285,8 +285,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); · 284 unmodified lines
285285 #define FEC_MMFR_TA (2 << 16)
286286 #define FEC_MMFR_DATA(v) (v & 0xffff)
287287 /* FEC ECR bits definition */
288−#define FEC_ECR_MAGICEN (1 << 2)
289−#define FEC_ECR_SLEEP (1 << 3)
288+#define FEC_ECR_RESET BIT(0)
289+#define FEC_ECR_ETHEREN BIT(1)
290+#define FEC_ECR_MAGICEN BIT(2)
291+#define FEC_ECR_SLEEP BIT(3)
292+#define FEC_ECR_EN1588 BIT(4)
290293
291294 #define FEC_MII_TIMEOUT 30000 /* us */
292295
@@ -982,6 +985,9 @@ fec_restart(struct net_device *ndev) · 689 unmodified lines
982985 u32 temp_mac[2];
983986 u32 rcntl = OPT_FRAME_SIZE | 0x04;
984987 u32 ecntl = 0x2; /* ETHEREN */
988+ struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
989+
990+ fec_ptp_save_state(fep);
985991
986992 /* Whack a reset. We should wait for this.
987993 * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
@@ -1135,7 +1141,7 @@ fec_restart(struct net_device *ndev) · 147 unmodified lines
11351141 }
11361142
11371143 if (fep->bufdesc_ex)
1138− ecntl |= (1 << 4);
1144+ ecntl |= FEC_ECR_EN1588;
11391145
11401146 if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT &&
11411147 fep->rgmii_txc_dly)
@@ -1156,6 +1162,14 @@ fec_restart(struct net_device *ndev) · 14 unmodified lines
11561162 if (fep->bufdesc_ex)
11571163 fec_ptp_start_cyclecounter(ndev);
11581164
1165+ /* Restart PPS if needed */
1166+ if (fep->pps_enable) {
1167+ /* Clear flag so fec_ptp_enable_pps() doesn't return immediately */
1168+ fep->pps_enable = 0;
1169+ fec_ptp_restore_state(fep);
1170+ fep->ptp_caps.enable(&fep->ptp_caps, &ptp_rq, 1);
1171+ }
1172+
11591173 /* Enable interrupts we wish to service */
11601174 if (fep->link)
11611175 writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
@@ -1206,6 +1220,8 @@ fec_stop(struct net_device *ndev) · 44 unmodified lines
12061220 struct fec_enet_private *fep = netdev_priv(ndev);
12071221 u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
12081222 u32 val;
1223+ struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
1224+ u32 ecntl = 0;
12091225
12101226 /* We cannot expect a graceful transmit stop without link !!! */
12111227 if (fep->link) {
@@ -1215,6 +1231,8 @@ fec_stop(struct net_device *ndev) · 3 unmodified lines
12151231 netdev_err(ndev, "Graceful transmit stop did not complete!\n");
12161232 }
12171233
1234+ fec_ptp_save_state(fep);
1235+
12181236 /* Whack a reset. We should wait for this.
12191237 * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
12201238 * instead of reset MAC itself.
@@ -1234,12 +1252,28 @@ fec_stop(struct net_device *ndev) · 13 unmodified lines
12341252 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
12351253 writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
12361254
1255+ if (fep->bufdesc_ex)
1256+ ecntl |= FEC_ECR_EN1588;
1257+
12371258 /* We have to keep ENET enabled to have MII interrupt stay working */
12381259 if (fep->quirks & FEC_QUIRK_ENET_MAC &&
12391260 !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
1240− writel(2, fep->hwp + FEC_ECNTRL);
1261+ ecntl |= FEC_ECR_ETHEREN;
12411262 writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
12421263 }
1264+
1265+ writel(ecntl, fep->hwp + FEC_ECNTRL);
1266+
1267+ if (fep->bufdesc_ex)
1268+ fec_ptp_start_cyclecounter(ndev);
1269+
1270+ /* Restart PPS if needed */
1271+ if (fep->pps_enable) {
1272+ /* Clear flag so fec_ptp_enable_pps() doesn't return immediately */
1273+ fep->pps_enable = 0;
1274+ fec_ptp_restore_state(fep);
1275+ fep->ptp_caps.enable(&fep->ptp_caps, &ptp_rq, 1);
1276+ }
12431277 }
12441278
12451279
drivers/net/ethernet/freescale/fec_ptp.c+29−0
@@ -633,7 +633,36 @@ void fec_ptp_stop(struct platform_device *pdev) · 632 unmodified lines
633633 struct net_device *ndev = platform_get_drvdata(pdev);
634634 struct fec_enet_private *fep = netdev_priv(ndev);
635635
636+ if (fep->pps_enable)
637+ fec_ptp_enable_pps(fep, 0);
638+
636639 cancel_delayed_work_sync(&fep->time_keep);
637640 if (fep->ptp_clock)
638641 ptp_clock_unregister(fep->ptp_clock);
639642 }
643+
644+void fec_ptp_save_state(struct fec_enet_private *fep)
645+{
646+ u32 atime_inc_corr;
647+
648+ fec_ptp_gettime(&fep->ptp_caps, &fep->ptp_saved_state.ts_phc);
649+ fep->ptp_saved_state.ns_sys = ktime_get_ns();
650+
651+ fep->ptp_saved_state.at_corr = readl(fep->hwp + FEC_ATIME_CORR);
652+ atime_inc_corr = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_CORR_MASK;
653+ fep->ptp_saved_state.at_inc_corr = (u8)(atime_inc_corr >> FEC_T_INC_CORR_OFFSET);
654+}
655+
656+int fec_ptp_restore_state(struct fec_enet_private *fep)
657+{
658+ u32 atime_inc = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
659+ u64 ns_sys;
660+
661+ writel(fep->ptp_saved_state.at_corr, fep->hwp + FEC_ATIME_CORR);
662+ atime_inc |= ((u32)fep->ptp_saved_state.at_inc_corr) << FEC_T_INC_CORR_OFFSET;
663+ writel(atime_inc, fep->hwp + FEC_ATIME_INC);
664+
665+ ns_sys = ktime_get_ns() - fep->ptp_saved_state.ns_sys;
666+ timespec64_add_ns(&fep->ptp_saved_state.ts_phc, ns_sys);
667+ return fec_ptp_settime(&fep->ptp_caps, &fep->ptp_saved_state.ts_phc);
668+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t