diff options
author | Matthew Vick <matthew.vick@intel.com> | 2012-08-16 21:30:37 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-09-17 05:04:27 -0400 |
commit | e57b8bdb4833366fd23d03a066c7eb8acc5736c7 (patch) | |
tree | a4dd980249535f34b15bbfdb83d8fd728447fc68 | |
parent | 1f6e8178d6851951876ad8524f4de7a0e6b111be (diff) |
igb: Add 1588 support to I210/I211.
Previously I210/I211 followed the same code flow as 82580/I350 for 1588.
However, since the register sets have changed, we must update the
implementation to accommodate the register changes.
Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: Matthew Vick <matthew.vick@intel.com>
Acked-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_defines.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ptp.c | 216 |
2 files changed, 174 insertions, 45 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 0b27e8fe06bf..cae3070da922 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h | |||
@@ -322,6 +322,9 @@ | |||
322 | #define E1000_FCRTC_RTH_COAL_SHIFT 4 | 322 | #define E1000_FCRTC_RTH_COAL_SHIFT 4 |
323 | #define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision */ | 323 | #define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision */ |
324 | 324 | ||
325 | /* Timestamp in Rx buffer */ | ||
326 | #define E1000_RXPBS_CFG_TS_EN 0x80000000 | ||
327 | |||
325 | /* SerDes Control */ | 328 | /* SerDes Control */ |
326 | #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 | 329 | #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 |
327 | 330 | ||
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index d57060c0813d..e13ba1d5369f 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c | |||
@@ -121,6 +121,41 @@ static cycle_t igb_ptp_read_82580(const struct cyclecounter *cc) | |||
121 | return val; | 121 | return val; |
122 | } | 122 | } |
123 | 123 | ||
124 | /* | ||
125 | * SYSTIM read access for I210/I211 | ||
126 | */ | ||
127 | |||
128 | static void igb_ptp_read_i210(struct igb_adapter *adapter, struct timespec *ts) | ||
129 | { | ||
130 | struct e1000_hw *hw = &adapter->hw; | ||
131 | u32 sec, nsec, jk; | ||
132 | |||
133 | /* | ||
134 | * The timestamp latches on lowest register read. For I210/I211, the | ||
135 | * lowest register is SYSTIMR. Since we only need to provide nanosecond | ||
136 | * resolution, we can ignore it. | ||
137 | */ | ||
138 | jk = rd32(E1000_SYSTIMR); | ||
139 | nsec = rd32(E1000_SYSTIML); | ||
140 | sec = rd32(E1000_SYSTIMH); | ||
141 | |||
142 | ts->tv_sec = sec; | ||
143 | ts->tv_nsec = nsec; | ||
144 | } | ||
145 | |||
146 | static void igb_ptp_write_i210(struct igb_adapter *adapter, | ||
147 | const struct timespec *ts) | ||
148 | { | ||
149 | struct e1000_hw *hw = &adapter->hw; | ||
150 | |||
151 | /* | ||
152 | * Writing the SYSTIMR register is not necessary as it only provides | ||
153 | * sub-nanosecond resolution. | ||
154 | */ | ||
155 | wr32(E1000_SYSTIML, ts->tv_nsec); | ||
156 | wr32(E1000_SYSTIMH, ts->tv_sec); | ||
157 | } | ||
158 | |||
124 | /** | 159 | /** |
125 | * igb_ptp_systim_to_hwtstamp - convert system time value to hw timestamp | 160 | * igb_ptp_systim_to_hwtstamp - convert system time value to hw timestamp |
126 | * @adapter: board private structure | 161 | * @adapter: board private structure |
@@ -146,24 +181,28 @@ static void igb_ptp_systim_to_hwtstamp(struct igb_adapter *adapter, | |||
146 | u64 ns; | 181 | u64 ns; |
147 | 182 | ||
148 | switch (adapter->hw.mac.type) { | 183 | switch (adapter->hw.mac.type) { |
184 | case e1000_82576: | ||
185 | case e1000_82580: | ||
186 | case e1000_i350: | ||
187 | spin_lock_irqsave(&adapter->tmreg_lock, flags); | ||
188 | |||
189 | ns = timecounter_cyc2time(&adapter->tc, systim); | ||
190 | |||
191 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); | ||
192 | |||
193 | memset(hwtstamps, 0, sizeof(*hwtstamps)); | ||
194 | hwtstamps->hwtstamp = ns_to_ktime(ns); | ||
195 | break; | ||
149 | case e1000_i210: | 196 | case e1000_i210: |
150 | case e1000_i211: | 197 | case e1000_i211: |
151 | case e1000_i350: | 198 | memset(hwtstamps, 0, sizeof(*hwtstamps)); |
152 | case e1000_82580: | 199 | /* Upper 32 bits contain s, lower 32 bits contain ns. */ |
153 | case e1000_82576: | 200 | hwtstamps->hwtstamp = ktime_set(systim >> 32, |
201 | systim & 0xFFFFFFFF); | ||
154 | break; | 202 | break; |
155 | default: | 203 | default: |
156 | return; | 204 | break; |
157 | } | 205 | } |
158 | |||
159 | spin_lock_irqsave(&adapter->tmreg_lock, flags); | ||
160 | |||
161 | ns = timecounter_cyc2time(&adapter->tc, systim); | ||
162 | |||
163 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); | ||
164 | |||
165 | memset(hwtstamps, 0, sizeof(*hwtstamps)); | ||
166 | hwtstamps->hwtstamp = ns_to_ktime(ns); | ||
167 | } | 206 | } |
168 | 207 | ||
169 | /* | 208 | /* |
@@ -225,7 +264,7 @@ static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb) | |||
225 | return 0; | 264 | return 0; |
226 | } | 265 | } |
227 | 266 | ||
228 | static int igb_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) | 267 | static int igb_ptp_adjtime_82576(struct ptp_clock_info *ptp, s64 delta) |
229 | { | 268 | { |
230 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, | 269 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, |
231 | ptp_caps); | 270 | ptp_caps); |
@@ -243,7 +282,26 @@ static int igb_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) | |||
243 | return 0; | 282 | return 0; |
244 | } | 283 | } |
245 | 284 | ||
246 | static int igb_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) | 285 | static int igb_ptp_adjtime_i210(struct ptp_clock_info *ptp, s64 delta) |
286 | { | ||
287 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, | ||
288 | ptp_caps); | ||
289 | unsigned long flags; | ||
290 | struct timespec now, then = ns_to_timespec(delta); | ||
291 | |||
292 | spin_lock_irqsave(&igb->tmreg_lock, flags); | ||
293 | |||
294 | igb_ptp_read_i210(igb, &now); | ||
295 | now = timespec_add(now, then); | ||
296 | igb_ptp_write_i210(igb, (const struct timespec *)&now); | ||
297 | |||
298 | spin_unlock_irqrestore(&igb->tmreg_lock, flags); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int igb_ptp_gettime_82576(struct ptp_clock_info *ptp, | ||
304 | struct timespec *ts) | ||
247 | { | 305 | { |
248 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, | 306 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, |
249 | ptp_caps); | 307 | ptp_caps); |
@@ -263,8 +321,24 @@ static int igb_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) | |||
263 | return 0; | 321 | return 0; |
264 | } | 322 | } |
265 | 323 | ||
266 | static int igb_ptp_settime(struct ptp_clock_info *ptp, | 324 | static int igb_ptp_gettime_i210(struct ptp_clock_info *ptp, |
267 | const struct timespec *ts) | 325 | struct timespec *ts) |
326 | { | ||
327 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, | ||
328 | ptp_caps); | ||
329 | unsigned long flags; | ||
330 | |||
331 | spin_lock_irqsave(&igb->tmreg_lock, flags); | ||
332 | |||
333 | igb_ptp_read_i210(igb, ts); | ||
334 | |||
335 | spin_unlock_irqrestore(&igb->tmreg_lock, flags); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, | ||
341 | const struct timespec *ts) | ||
268 | { | 342 | { |
269 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, | 343 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, |
270 | ptp_caps); | 344 | ptp_caps); |
@@ -283,6 +357,22 @@ static int igb_ptp_settime(struct ptp_clock_info *ptp, | |||
283 | return 0; | 357 | return 0; |
284 | } | 358 | } |
285 | 359 | ||
360 | static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, | ||
361 | const struct timespec *ts) | ||
362 | { | ||
363 | struct igb_adapter *igb = container_of(ptp, struct igb_adapter, | ||
364 | ptp_caps); | ||
365 | unsigned long flags; | ||
366 | |||
367 | spin_lock_irqsave(&igb->tmreg_lock, flags); | ||
368 | |||
369 | igb_ptp_write_i210(igb, ts); | ||
370 | |||
371 | spin_unlock_irqrestore(&igb->tmreg_lock, flags); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
286 | static int igb_ptp_enable(struct ptp_clock_info *ptp, | 376 | static int igb_ptp_enable(struct ptp_clock_info *ptp, |
287 | struct ptp_clock_request *rq, int on) | 377 | struct ptp_clock_request *rq, int on) |
288 | { | 378 | { |
@@ -320,7 +410,7 @@ static void igb_ptp_overflow_check(struct work_struct *work) | |||
320 | container_of(work, struct igb_adapter, ptp_overflow_work.work); | 410 | container_of(work, struct igb_adapter, ptp_overflow_work.work); |
321 | struct timespec ts; | 411 | struct timespec ts; |
322 | 412 | ||
323 | igb_ptp_gettime(&igb->ptp_caps, &ts); | 413 | igb->ptp_caps.gettime(&igb->ptp_caps, &ts); |
324 | 414 | ||
325 | pr_debug("igb overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec); | 415 | pr_debug("igb overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec); |
326 | 416 | ||
@@ -506,6 +596,13 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, | |||
506 | if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { | 596 | if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { |
507 | tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; | 597 | tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; |
508 | tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; | 598 | tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; |
599 | |||
600 | if ((hw->mac.type == e1000_i210) || | ||
601 | (hw->mac.type == e1000_i211)) { | ||
602 | regval = rd32(E1000_RXPBS); | ||
603 | regval |= E1000_RXPBS_CFG_TS_EN; | ||
604 | wr32(E1000_RXPBS, regval); | ||
605 | } | ||
509 | } | 606 | } |
510 | 607 | ||
511 | /* enable/disable TX */ | 608 | /* enable/disable TX */ |
@@ -556,7 +653,9 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, | |||
556 | wrfl(); | 653 | wrfl(); |
557 | 654 | ||
558 | /* clear TX/RX time stamp registers, just to be sure */ | 655 | /* clear TX/RX time stamp registers, just to be sure */ |
656 | regval = rd32(E1000_TXSTMPL); | ||
559 | regval = rd32(E1000_TXSTMPH); | 657 | regval = rd32(E1000_TXSTMPH); |
658 | regval = rd32(E1000_RXSTMPL); | ||
560 | regval = rd32(E1000_RXSTMPH); | 659 | regval = rd32(E1000_RXSTMPH); |
561 | 660 | ||
562 | return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? | 661 | return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? |
@@ -569,19 +668,35 @@ void igb_ptp_init(struct igb_adapter *adapter) | |||
569 | struct net_device *netdev = adapter->netdev; | 668 | struct net_device *netdev = adapter->netdev; |
570 | 669 | ||
571 | switch (hw->mac.type) { | 670 | switch (hw->mac.type) { |
572 | case e1000_i210: | 671 | case e1000_82576: |
573 | case e1000_i211: | 672 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); |
574 | case e1000_i350: | 673 | adapter->ptp_caps.owner = THIS_MODULE; |
674 | adapter->ptp_caps.max_adj = 1000000000; | ||
675 | adapter->ptp_caps.n_ext_ts = 0; | ||
676 | adapter->ptp_caps.pps = 0; | ||
677 | adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; | ||
678 | adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; | ||
679 | adapter->ptp_caps.gettime = igb_ptp_gettime_82576; | ||
680 | adapter->ptp_caps.settime = igb_ptp_settime_82576; | ||
681 | adapter->ptp_caps.enable = igb_ptp_enable; | ||
682 | adapter->cc.read = igb_ptp_read_82576; | ||
683 | adapter->cc.mask = CLOCKSOURCE_MASK(64); | ||
684 | adapter->cc.mult = 1; | ||
685 | adapter->cc.shift = IGB_82576_TSYNC_SHIFT; | ||
686 | /* Dial the nominal frequency. */ | ||
687 | wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); | ||
688 | break; | ||
575 | case e1000_82580: | 689 | case e1000_82580: |
690 | case e1000_i350: | ||
576 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); | 691 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); |
577 | adapter->ptp_caps.owner = THIS_MODULE; | 692 | adapter->ptp_caps.owner = THIS_MODULE; |
578 | adapter->ptp_caps.max_adj = 62499999; | 693 | adapter->ptp_caps.max_adj = 62499999; |
579 | adapter->ptp_caps.n_ext_ts = 0; | 694 | adapter->ptp_caps.n_ext_ts = 0; |
580 | adapter->ptp_caps.pps = 0; | 695 | adapter->ptp_caps.pps = 0; |
581 | adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; | 696 | adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; |
582 | adapter->ptp_caps.adjtime = igb_ptp_adjtime; | 697 | adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; |
583 | adapter->ptp_caps.gettime = igb_ptp_gettime; | 698 | adapter->ptp_caps.gettime = igb_ptp_gettime_82576; |
584 | adapter->ptp_caps.settime = igb_ptp_settime; | 699 | adapter->ptp_caps.settime = igb_ptp_settime_82576; |
585 | adapter->ptp_caps.enable = igb_ptp_enable; | 700 | adapter->ptp_caps.enable = igb_ptp_enable; |
586 | adapter->cc.read = igb_ptp_read_82580; | 701 | adapter->cc.read = igb_ptp_read_82580; |
587 | adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580); | 702 | adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580); |
@@ -590,23 +705,20 @@ void igb_ptp_init(struct igb_adapter *adapter) | |||
590 | /* Enable the timer functions by clearing bit 31. */ | 705 | /* Enable the timer functions by clearing bit 31. */ |
591 | wr32(E1000_TSAUXC, 0x0); | 706 | wr32(E1000_TSAUXC, 0x0); |
592 | break; | 707 | break; |
593 | case e1000_82576: | 708 | case e1000_i210: |
709 | case e1000_i211: | ||
594 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); | 710 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); |
595 | adapter->ptp_caps.owner = THIS_MODULE; | 711 | adapter->ptp_caps.owner = THIS_MODULE; |
596 | adapter->ptp_caps.max_adj = 1000000000; | 712 | adapter->ptp_caps.max_adj = 62499999; |
597 | adapter->ptp_caps.n_ext_ts = 0; | 713 | adapter->ptp_caps.n_ext_ts = 0; |
598 | adapter->ptp_caps.pps = 0; | 714 | adapter->ptp_caps.pps = 0; |
599 | adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; | 715 | adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; |
600 | adapter->ptp_caps.adjtime = igb_ptp_adjtime; | 716 | adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; |
601 | adapter->ptp_caps.gettime = igb_ptp_gettime; | 717 | adapter->ptp_caps.gettime = igb_ptp_gettime_i210; |
602 | adapter->ptp_caps.settime = igb_ptp_settime; | 718 | adapter->ptp_caps.settime = igb_ptp_settime_i210; |
603 | adapter->ptp_caps.enable = igb_ptp_enable; | 719 | adapter->ptp_caps.enable = igb_ptp_enable; |
604 | adapter->cc.read = igb_ptp_read_82576; | 720 | /* Enable the timer functions by clearing bit 31. */ |
605 | adapter->cc.mask = CLOCKSOURCE_MASK(64); | 721 | wr32(E1000_TSAUXC, 0x0); |
606 | adapter->cc.mult = 1; | ||
607 | adapter->cc.shift = IGB_82576_TSYNC_SHIFT; | ||
608 | /* Dial the nominal frequency. */ | ||
609 | wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); | ||
610 | break; | 722 | break; |
611 | default: | 723 | default: |
612 | adapter->ptp_clock = NULL; | 724 | adapter->ptp_clock = NULL; |
@@ -615,17 +727,24 @@ void igb_ptp_init(struct igb_adapter *adapter) | |||
615 | 727 | ||
616 | wrfl(); | 728 | wrfl(); |
617 | 729 | ||
618 | timecounter_init(&adapter->tc, &adapter->cc, | 730 | spin_lock_init(&adapter->tmreg_lock); |
619 | ktime_to_ns(ktime_get_real())); | 731 | INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); |
620 | 732 | ||
621 | INIT_DELAYED_WORK(&adapter->ptp_overflow_work, igb_ptp_overflow_check); | 733 | /* Initialize the clock and overflow work for devices that need it. */ |
734 | if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { | ||
735 | struct timespec ts = ktime_to_timespec(ktime_get_real()); | ||
622 | 736 | ||
623 | spin_lock_init(&adapter->tmreg_lock); | 737 | igb_ptp_settime_i210(&adapter->ptp_caps, &ts); |
738 | } else { | ||
739 | timecounter_init(&adapter->tc, &adapter->cc, | ||
740 | ktime_to_ns(ktime_get_real())); | ||
624 | 741 | ||
625 | INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); | 742 | INIT_DELAYED_WORK(&adapter->ptp_overflow_work, |
743 | igb_ptp_overflow_check); | ||
626 | 744 | ||
627 | schedule_delayed_work(&adapter->ptp_overflow_work, | 745 | schedule_delayed_work(&adapter->ptp_overflow_work, |
628 | IGB_SYSTIM_OVERFLOW_PERIOD); | 746 | IGB_SYSTIM_OVERFLOW_PERIOD); |
747 | } | ||
629 | 748 | ||
630 | /* Initialize the time sync interrupts for devices that support it. */ | 749 | /* Initialize the time sync interrupts for devices that support it. */ |
631 | if (hw->mac.type >= e1000_82580) { | 750 | if (hw->mac.type >= e1000_82580) { |
@@ -708,6 +827,13 @@ void igb_ptp_reset(struct igb_adapter *adapter) | |||
708 | return; | 827 | return; |
709 | } | 828 | } |
710 | 829 | ||
711 | timecounter_init(&adapter->tc, &adapter->cc, | 830 | /* Re-initialize the timer. */ |
712 | ktime_to_ns(ktime_get_real())); | 831 | if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { |
832 | struct timespec ts = ktime_to_timespec(ktime_get_real()); | ||
833 | |||
834 | igb_ptp_settime_i210(&adapter->ptp_caps, &ts); | ||
835 | } else { | ||
836 | timecounter_init(&adapter->tc, &adapter->cc, | ||
837 | ktime_to_ns(ktime_get_real())); | ||
838 | } | ||
713 | } | 839 | } |