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
634 int pps_enable;634 int pps_enable;
635 unsigned int next_counter;635 unsigned int next_counter;
636 636
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
637 u64 ethtool_stats[];644 u64 ethtool_stats[];
638};645};
639 646
@@ -644,5 +651,8 @@ void fec_ptp_disable_hwts(struct net_device *ndev); · 4 unmodified lines
644int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);651int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
645int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);652int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
646 653
654void fec_ptp_save_state(struct fec_enet_private *fep);
655int fec_ptp_restore_state(struct fec_enet_private *fep);
656
647/****************************************************************************/657/****************************************************************************/
648#endif /* FEC_H */658#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
285#define FEC_MMFR_TA (2 << 16)285#define FEC_MMFR_TA (2 << 16)
286#define FEC_MMFR_DATA(v) (v & 0xffff)286#define FEC_MMFR_DATA(v) (v & 0xffff)
287/* FEC ECR bits definition */287/* FEC ECR bits definition */
288#define FEC_ECR_MAGICEN (1 << 2)288#define FEC_ECR_RESET BIT(0)
289#define FEC_ECR_SLEEP (1 << 3)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)
290 293
291#define FEC_MII_TIMEOUT 30000 /* us */294#define FEC_MII_TIMEOUT 30000 /* us */
292 295
@@ -982,6 +985,9 @@ fec_restart(struct net_device *ndev) · 689 unmodified lines
982 u32 temp_mac[2];985 u32 temp_mac[2];
983 u32 rcntl = OPT_FRAME_SIZE | 0x04;986 u32 rcntl = OPT_FRAME_SIZE | 0x04;
984 u32 ecntl = 0x2; /* ETHEREN */987 u32 ecntl = 0x2; /* ETHEREN */
988 struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
989
990 fec_ptp_save_state(fep);
985 991
986 /* Whack a reset. We should wait for this.992 /* Whack a reset. We should wait for this.
987 * For i.MX6SX SOC, enet use AXI bus, we use disable MAC993 * 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
1135 }1141 }
1136 1142
1137 if (fep->bufdesc_ex)1143 if (fep->bufdesc_ex)
1138 ecntl |= (1 << 4);1144 ecntl |= FEC_ECR_EN1588;
1139 1145
1140 if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT &&1146 if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT &&
1141 fep->rgmii_txc_dly)1147 fep->rgmii_txc_dly)
@@ -1156,6 +1162,14 @@ fec_restart(struct net_device *ndev) · 14 unmodified lines
1156 if (fep->bufdesc_ex)1162 if (fep->bufdesc_ex)
1157 fec_ptp_start_cyclecounter(ndev);1163 fec_ptp_start_cyclecounter(ndev);
1158 1164
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
1159 /* Enable interrupts we wish to service */1173 /* Enable interrupts we wish to service */
1160 if (fep->link)1174 if (fep->link)
1161 writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);1175 writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
@@ -1206,6 +1220,8 @@ fec_stop(struct net_device *ndev) · 44 unmodified lines
1206 struct fec_enet_private *fep = netdev_priv(ndev);1220 struct fec_enet_private *fep = netdev_priv(ndev);
1207 u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);1221 u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
1208 u32 val;1222 u32 val;
1223 struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
1224 u32 ecntl = 0;
1209 1225
1210 /* We cannot expect a graceful transmit stop without link !!! */1226 /* We cannot expect a graceful transmit stop without link !!! */
1211 if (fep->link) {1227 if (fep->link) {
@@ -1215,6 +1231,8 @@ fec_stop(struct net_device *ndev) · 3 unmodified lines
1215 netdev_err(ndev, "Graceful transmit stop did not complete!\n");1231 netdev_err(ndev, "Graceful transmit stop did not complete!\n");
1216 }1232 }
1217 1233
1234 fec_ptp_save_state(fep);
1235
1218 /* Whack a reset. We should wait for this.1236 /* Whack a reset. We should wait for this.
1219 * For i.MX6SX SOC, enet use AXI bus, we use disable MAC1237 * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
1220 * instead of reset MAC itself.1238 * instead of reset MAC itself.
@@ -1234,12 +1252,28 @@ fec_stop(struct net_device *ndev) · 13 unmodified lines
1234 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);1252 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
1235 writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);1253 writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
1236 1254
1255 if (fep->bufdesc_ex)
1256 ecntl |= FEC_ECR_EN1588;
1257
1237 /* We have to keep ENET enabled to have MII interrupt stay working */1258 /* We have to keep ENET enabled to have MII interrupt stay working */
1238 if (fep->quirks & FEC_QUIRK_ENET_MAC &&1259 if (fep->quirks & FEC_QUIRK_ENET_MAC &&
1239 !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {1260 !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
1240 writel(2, fep->hwp + FEC_ECNTRL);1261 ecntl |= FEC_ECR_ETHEREN;
1241 writel(rmii_mode, fep->hwp + FEC_R_CNTRL);1262 writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
1242 }1263 }
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 }
1243}1277}
1244 1278
1245 1279
drivers/net/ethernet/freescale/fec_ptp.c+29−0
@@ -633,7 +633,36 @@ void fec_ptp_stop(struct platform_device *pdev) · 632 unmodified lines
633 struct net_device *ndev = platform_get_drvdata(pdev);633 struct net_device *ndev = platform_get_drvdata(pdev);
634 struct fec_enet_private *fep = netdev_priv(ndev);634 struct fec_enet_private *fep = netdev_priv(ndev);
635 635
636 if (fep->pps_enable)
637 fec_ptp_enable_pps(fep, 0);
638
636 cancel_delayed_work_sync(&fep->time_keep);639 cancel_delayed_work_sync(&fep->time_keep);
637 if (fep->ptp_clock)640 if (fep->ptp_clock)
638 ptp_clock_unregister(fep->ptp_clock);641 ptp_clock_unregister(fep->ptp_clock);
639}642}
643
644void 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
656int 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