1ae06c70bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0+ 251dce24bSJeff Kirsher /* Copyright (C) 2011 Richard Cochran <richardcochran@gmail.com> */ 351dce24bSJeff Kirsher 4d339b133SRichard Cochran #include <linux/module.h> 5d339b133SRichard Cochran #include <linux/device.h> 6d339b133SRichard Cochran #include <linux/pci.h> 7ba59814bSMatthew Vick #include <linux/ptp_classify.h> 8d339b133SRichard Cochran 9d339b133SRichard Cochran #include "igb.h" 10d339b133SRichard Cochran 11d339b133SRichard Cochran #define INCVALUE_MASK 0x7fffffff 12d339b133SRichard Cochran #define ISGN 0x80000000 13d339b133SRichard Cochran 14b980ac18SJeff Kirsher /* The 82580 timesync updates the system timer every 8ns by 8ns, 157ebae817SRichard Cochran * and this update value cannot be reprogrammed. 167ebae817SRichard Cochran * 17d339b133SRichard Cochran * Neither the 82576 nor the 82580 offer registers wide enough to hold 18d339b133SRichard Cochran * nanoseconds time values for very long. For the 82580, SYSTIM always 19dbedd44eSJoe Perches * counts nanoseconds, but the upper 24 bits are not available. The 20d339b133SRichard Cochran * frequency is adjusted by changing the 32 bit fractional nanoseconds 21d339b133SRichard Cochran * register, TIMINCA. 22d339b133SRichard Cochran * 23d339b133SRichard Cochran * For the 82576, the SYSTIM register time unit is affect by the 24d339b133SRichard Cochran * choice of the 24 bit TININCA:IV (incvalue) field. Five bits of this 25d339b133SRichard Cochran * field are needed to provide the nominal 16 nanosecond period, 26d339b133SRichard Cochran * leaving 19 bits for fractional nanoseconds. 27d339b133SRichard Cochran * 287ebae817SRichard Cochran * We scale the NIC clock cycle by a large factor so that relatively 297ebae817SRichard Cochran * small clock corrections can be added or subtracted at each clock 307ebae817SRichard Cochran * tick. The drawbacks of a large factor are a) that the clock 317ebae817SRichard Cochran * register overflows more quickly (not such a big deal) and b) that 327ebae817SRichard Cochran * the increment per tick has to fit into 24 bits. As a result we 337ebae817SRichard Cochran * need to use a shift of 19 so we can fit a value of 16 into the 347ebae817SRichard Cochran * TIMINCA register. 357ebae817SRichard Cochran * 36d339b133SRichard Cochran * 37d339b133SRichard Cochran * SYSTIMH SYSTIML 38d339b133SRichard Cochran * +--------------+ +---+---+------+ 39d339b133SRichard Cochran * 82576 | 32 | | 8 | 5 | 19 | 40d339b133SRichard Cochran * +--------------+ +---+---+------+ 41d339b133SRichard Cochran * \________ 45 bits _______/ fract 42d339b133SRichard Cochran * 43d339b133SRichard Cochran * +----------+---+ +--------------+ 44d339b133SRichard Cochran * 82580 | 24 | 8 | | 32 | 45d339b133SRichard Cochran * +----------+---+ +--------------+ 46d339b133SRichard Cochran * reserved \______ 40 bits _____/ 47d339b133SRichard Cochran * 48d339b133SRichard Cochran * 49d339b133SRichard Cochran * The 45 bit 82576 SYSTIM overflows every 50d339b133SRichard Cochran * 2^45 * 10^-9 / 3600 = 9.77 hours. 51d339b133SRichard Cochran * 52d339b133SRichard Cochran * The 40 bit 82580 SYSTIM overflows every 53d339b133SRichard Cochran * 2^40 * 10^-9 / 60 = 18.3 minutes. 54094bf4d0SMiroslav Lichvar * 55094bf4d0SMiroslav Lichvar * SYSTIM is converted to real time using a timecounter. As 564c9b658eSMiroslav Lichvar * timecounter_cyc2time() allows old timestamps, the timecounter needs 574c9b658eSMiroslav Lichvar * to be updated at least once per half of the SYSTIM interval. 584c9b658eSMiroslav Lichvar * Scheduling of delayed work is not very accurate, and also the NIC 594c9b658eSMiroslav Lichvar * clock can be adjusted to run up to 6% faster and the system clock 604c9b658eSMiroslav Lichvar * up to 10% slower, so we aim for 6 minutes to be sure the actual 614c9b658eSMiroslav Lichvar * interval in the NIC time is shorter than 9.16 minutes. 62d339b133SRichard Cochran */ 63d339b133SRichard Cochran 644c9b658eSMiroslav Lichvar #define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 6) 65428f1f71SMatthew Vick #define IGB_PTP_TX_TIMEOUT (HZ * 15) 66a51d8c21SJacob Keller #define INCPERIOD_82576 BIT(E1000_TIMINCA_16NS_SHIFT) 67a51d8c21SJacob Keller #define INCVALUE_82576_MASK GENMASK(E1000_TIMINCA_16NS_SHIFT - 1, 0) 68a51d8c21SJacob Keller #define INCVALUE_82576 (16u << IGB_82576_TSYNC_SHIFT) 69d339b133SRichard Cochran #define IGB_NBITS_82580 40 70d339b133SRichard Cochran 71167f3f71SJeff Kirsher static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); 72167f3f71SJeff Kirsher 73b980ac18SJeff Kirsher /* SYSTIM read access for the 82576 */ 74a5a1d1c2SThomas Gleixner static u64 igb_ptp_read_82576(const struct cyclecounter *cc) 75d339b133SRichard Cochran { 76d339b133SRichard Cochran struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc); 77d339b133SRichard Cochran struct e1000_hw *hw = &igb->hw; 78a79f4f88SMatthew Vick u64 val; 79a79f4f88SMatthew Vick u32 lo, hi; 80d339b133SRichard Cochran 81d339b133SRichard Cochran lo = rd32(E1000_SYSTIML); 82d339b133SRichard Cochran hi = rd32(E1000_SYSTIMH); 83d339b133SRichard Cochran 84d339b133SRichard Cochran val = ((u64) hi) << 32; 85d339b133SRichard Cochran val |= lo; 86d339b133SRichard Cochran 87d339b133SRichard Cochran return val; 88d339b133SRichard Cochran } 89d339b133SRichard Cochran 90b980ac18SJeff Kirsher /* SYSTIM read access for the 82580 */ 91a5a1d1c2SThomas Gleixner static u64 igb_ptp_read_82580(const struct cyclecounter *cc) 92d339b133SRichard Cochran { 93d339b133SRichard Cochran struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc); 94d339b133SRichard Cochran struct e1000_hw *hw = &igb->hw; 95e5c3370fSAkeem G Abodunrin u32 lo, hi; 96a79f4f88SMatthew Vick u64 val; 97d339b133SRichard Cochran 98b980ac18SJeff Kirsher /* The timestamp latches on lowest register read. For the 82580 997ebae817SRichard Cochran * the lowest register is SYSTIMR instead of SYSTIML. However we only 1007ebae817SRichard Cochran * need to provide nanosecond resolution, so we just ignore it. 1017ebae817SRichard Cochran */ 102e5c3370fSAkeem G Abodunrin rd32(E1000_SYSTIMR); 103d339b133SRichard Cochran lo = rd32(E1000_SYSTIML); 104d339b133SRichard Cochran hi = rd32(E1000_SYSTIMH); 105d339b133SRichard Cochran 106d339b133SRichard Cochran val = ((u64) hi) << 32; 107d339b133SRichard Cochran val |= lo; 108d339b133SRichard Cochran 109d339b133SRichard Cochran return val; 110d339b133SRichard Cochran } 111d339b133SRichard Cochran 112b980ac18SJeff Kirsher /* SYSTIM read access for I210/I211 */ 113d4c496feSRichard Cochran static void igb_ptp_read_i210(struct igb_adapter *adapter, 114d4c496feSRichard Cochran struct timespec64 *ts) 115e57b8bdbSMatthew Vick { 116e57b8bdbSMatthew Vick struct e1000_hw *hw = &adapter->hw; 117e5c3370fSAkeem G Abodunrin u32 sec, nsec; 118e57b8bdbSMatthew Vick 119b980ac18SJeff Kirsher /* The timestamp latches on lowest register read. For I210/I211, the 120e57b8bdbSMatthew Vick * lowest register is SYSTIMR. Since we only need to provide nanosecond 121e57b8bdbSMatthew Vick * resolution, we can ignore it. 122e57b8bdbSMatthew Vick */ 123e5c3370fSAkeem G Abodunrin rd32(E1000_SYSTIMR); 124e57b8bdbSMatthew Vick nsec = rd32(E1000_SYSTIML); 125e57b8bdbSMatthew Vick sec = rd32(E1000_SYSTIMH); 126e57b8bdbSMatthew Vick 127e57b8bdbSMatthew Vick ts->tv_sec = sec; 128e57b8bdbSMatthew Vick ts->tv_nsec = nsec; 129e57b8bdbSMatthew Vick } 130e57b8bdbSMatthew Vick 131e57b8bdbSMatthew Vick static void igb_ptp_write_i210(struct igb_adapter *adapter, 132d4c496feSRichard Cochran const struct timespec64 *ts) 133e57b8bdbSMatthew Vick { 134e57b8bdbSMatthew Vick struct e1000_hw *hw = &adapter->hw; 135e57b8bdbSMatthew Vick 136b980ac18SJeff Kirsher /* Writing the SYSTIMR register is not necessary as it only provides 137e57b8bdbSMatthew Vick * sub-nanosecond resolution. 138e57b8bdbSMatthew Vick */ 139e57b8bdbSMatthew Vick wr32(E1000_SYSTIML, ts->tv_nsec); 14040c9b079SArnd Bergmann wr32(E1000_SYSTIMH, (u32)ts->tv_sec); 141e57b8bdbSMatthew Vick } 142e57b8bdbSMatthew Vick 143a79f4f88SMatthew Vick /** 144a79f4f88SMatthew Vick * igb_ptp_systim_to_hwtstamp - convert system time value to hw timestamp 145a79f4f88SMatthew Vick * @adapter: board private structure 146a79f4f88SMatthew Vick * @hwtstamps: timestamp structure to update 147a79f4f88SMatthew Vick * @systim: unsigned 64bit system time value. 148a79f4f88SMatthew Vick * 149a79f4f88SMatthew Vick * We need to convert the system time value stored in the RX/TXSTMP registers 150a79f4f88SMatthew Vick * into a hwtstamp which can be used by the upper level timestamping functions. 151a79f4f88SMatthew Vick * 152a79f4f88SMatthew Vick * The 'tmreg_lock' spinlock is used to protect the consistency of the 153a79f4f88SMatthew Vick * system time value. This is needed because reading the 64 bit time 154a79f4f88SMatthew Vick * value involves reading two (or three) 32 bit registers. The first 155a79f4f88SMatthew Vick * read latches the value. Ditto for writing. 156a79f4f88SMatthew Vick * 157a79f4f88SMatthew Vick * In addition, here have extended the system time with an overflow 158a79f4f88SMatthew Vick * counter in software. 159a79f4f88SMatthew Vick **/ 160a79f4f88SMatthew Vick static void igb_ptp_systim_to_hwtstamp(struct igb_adapter *adapter, 161a79f4f88SMatthew Vick struct skb_shared_hwtstamps *hwtstamps, 162a79f4f88SMatthew Vick u64 systim) 163a79f4f88SMatthew Vick { 164a79f4f88SMatthew Vick unsigned long flags; 165a79f4f88SMatthew Vick u64 ns; 166a79f4f88SMatthew Vick 167a79f4f88SMatthew Vick switch (adapter->hw.mac.type) { 168a79f4f88SMatthew Vick case e1000_82576: 169e57b8bdbSMatthew Vick case e1000_82580: 170ceb5f13bSCarolyn Wyborny case e1000_i354: 171e57b8bdbSMatthew Vick case e1000_i350: 172a79f4f88SMatthew Vick spin_lock_irqsave(&adapter->tmreg_lock, flags); 173a79f4f88SMatthew Vick 174a79f4f88SMatthew Vick ns = timecounter_cyc2time(&adapter->tc, systim); 175a79f4f88SMatthew Vick 176a79f4f88SMatthew Vick spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 177a79f4f88SMatthew Vick 178a79f4f88SMatthew Vick memset(hwtstamps, 0, sizeof(*hwtstamps)); 179a79f4f88SMatthew Vick hwtstamps->hwtstamp = ns_to_ktime(ns); 180e57b8bdbSMatthew Vick break; 181e57b8bdbSMatthew Vick case e1000_i210: 182e57b8bdbSMatthew Vick case e1000_i211: 183e57b8bdbSMatthew Vick memset(hwtstamps, 0, sizeof(*hwtstamps)); 184e57b8bdbSMatthew Vick /* Upper 32 bits contain s, lower 32 bits contain ns. */ 185e57b8bdbSMatthew Vick hwtstamps->hwtstamp = ktime_set(systim >> 32, 186e57b8bdbSMatthew Vick systim & 0xFFFFFFFF); 187e57b8bdbSMatthew Vick break; 188e57b8bdbSMatthew Vick default: 189e57b8bdbSMatthew Vick break; 190e57b8bdbSMatthew Vick } 191a79f4f88SMatthew Vick } 192a79f4f88SMatthew Vick 193b980ac18SJeff Kirsher /* PTP clock operations */ 194a79f4f88SMatthew Vick static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb) 195d339b133SRichard Cochran { 196a79f4f88SMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 197a79f4f88SMatthew Vick ptp_caps); 198a79f4f88SMatthew Vick struct e1000_hw *hw = &igb->hw; 199a79f4f88SMatthew Vick int neg_adj = 0; 200d339b133SRichard Cochran u64 rate; 201d339b133SRichard Cochran u32 incvalue; 202d339b133SRichard Cochran 203d339b133SRichard Cochran if (ppb < 0) { 204d339b133SRichard Cochran neg_adj = 1; 205d339b133SRichard Cochran ppb = -ppb; 206d339b133SRichard Cochran } 207d339b133SRichard Cochran rate = ppb; 208d339b133SRichard Cochran rate <<= 14; 209d339b133SRichard Cochran rate = div_u64(rate, 1953125); 210d339b133SRichard Cochran 211d339b133SRichard Cochran incvalue = 16 << IGB_82576_TSYNC_SHIFT; 212d339b133SRichard Cochran 213d339b133SRichard Cochran if (neg_adj) 214d339b133SRichard Cochran incvalue -= rate; 215d339b133SRichard Cochran else 216d339b133SRichard Cochran incvalue += rate; 217d339b133SRichard Cochran 218d339b133SRichard Cochran wr32(E1000_TIMINCA, INCPERIOD_82576 | (incvalue & INCVALUE_82576_MASK)); 219d339b133SRichard Cochran 220d339b133SRichard Cochran return 0; 221d339b133SRichard Cochran } 222d339b133SRichard Cochran 223c79e975eSRichard Cochran static int igb_ptp_adjfine_82580(struct ptp_clock_info *ptp, long scaled_ppm) 224d339b133SRichard Cochran { 225a79f4f88SMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 226a79f4f88SMatthew Vick ptp_caps); 227a79f4f88SMatthew Vick struct e1000_hw *hw = &igb->hw; 228a79f4f88SMatthew Vick int neg_adj = 0; 229d339b133SRichard Cochran u64 rate; 230d339b133SRichard Cochran u32 inca; 231d339b133SRichard Cochran 232c79e975eSRichard Cochran if (scaled_ppm < 0) { 233d339b133SRichard Cochran neg_adj = 1; 234c79e975eSRichard Cochran scaled_ppm = -scaled_ppm; 235d339b133SRichard Cochran } 236c79e975eSRichard Cochran rate = scaled_ppm; 237c79e975eSRichard Cochran rate <<= 13; 238c79e975eSRichard Cochran rate = div_u64(rate, 15625); 239d339b133SRichard Cochran 240d339b133SRichard Cochran inca = rate & INCVALUE_MASK; 241d339b133SRichard Cochran if (neg_adj) 242d339b133SRichard Cochran inca |= ISGN; 243d339b133SRichard Cochran 244d339b133SRichard Cochran wr32(E1000_TIMINCA, inca); 245d339b133SRichard Cochran 246d339b133SRichard Cochran return 0; 247d339b133SRichard Cochran } 248d339b133SRichard Cochran 249e57b8bdbSMatthew Vick static int igb_ptp_adjtime_82576(struct ptp_clock_info *ptp, s64 delta) 250d339b133SRichard Cochran { 251a79f4f88SMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 252a79f4f88SMatthew Vick ptp_caps); 253d339b133SRichard Cochran unsigned long flags; 254d339b133SRichard Cochran 255d339b133SRichard Cochran spin_lock_irqsave(&igb->tmreg_lock, flags); 2565ee698e3SRichard Cochran timecounter_adjtime(&igb->tc, delta); 257d339b133SRichard Cochran spin_unlock_irqrestore(&igb->tmreg_lock, flags); 258d339b133SRichard Cochran 259d339b133SRichard Cochran return 0; 260d339b133SRichard Cochran } 261d339b133SRichard Cochran 262e57b8bdbSMatthew Vick static int igb_ptp_adjtime_i210(struct ptp_clock_info *ptp, s64 delta) 263e57b8bdbSMatthew Vick { 264e57b8bdbSMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 265e57b8bdbSMatthew Vick ptp_caps); 266e57b8bdbSMatthew Vick unsigned long flags; 267d4c496feSRichard Cochran struct timespec64 now, then = ns_to_timespec64(delta); 268e57b8bdbSMatthew Vick 269e57b8bdbSMatthew Vick spin_lock_irqsave(&igb->tmreg_lock, flags); 270e57b8bdbSMatthew Vick 271e57b8bdbSMatthew Vick igb_ptp_read_i210(igb, &now); 272d4c496feSRichard Cochran now = timespec64_add(now, then); 273d4c496feSRichard Cochran igb_ptp_write_i210(igb, (const struct timespec64 *)&now); 274e57b8bdbSMatthew Vick 275e57b8bdbSMatthew Vick spin_unlock_irqrestore(&igb->tmreg_lock, flags); 276e57b8bdbSMatthew Vick 277e57b8bdbSMatthew Vick return 0; 278e57b8bdbSMatthew Vick } 279e57b8bdbSMatthew Vick 280cff8ba28SMiroslav Lichvar static int igb_ptp_gettimex_82576(struct ptp_clock_info *ptp, 281cff8ba28SMiroslav Lichvar struct timespec64 *ts, 282cff8ba28SMiroslav Lichvar struct ptp_system_timestamp *sts) 283d339b133SRichard Cochran { 284a79f4f88SMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 285a79f4f88SMatthew Vick ptp_caps); 286cff8ba28SMiroslav Lichvar struct e1000_hw *hw = &igb->hw; 287a79f4f88SMatthew Vick unsigned long flags; 288cff8ba28SMiroslav Lichvar u32 lo, hi; 289d339b133SRichard Cochran u64 ns; 290d339b133SRichard Cochran 291d339b133SRichard Cochran spin_lock_irqsave(&igb->tmreg_lock, flags); 292d339b133SRichard Cochran 293cff8ba28SMiroslav Lichvar ptp_read_system_prets(sts); 294cff8ba28SMiroslav Lichvar lo = rd32(E1000_SYSTIML); 295cff8ba28SMiroslav Lichvar ptp_read_system_postts(sts); 296cff8ba28SMiroslav Lichvar hi = rd32(E1000_SYSTIMH); 297cff8ba28SMiroslav Lichvar 298cff8ba28SMiroslav Lichvar ns = timecounter_cyc2time(&igb->tc, ((u64)hi << 32) | lo); 299d339b133SRichard Cochran 300d339b133SRichard Cochran spin_unlock_irqrestore(&igb->tmreg_lock, flags); 301d339b133SRichard Cochran 302350f66d5SRichard Cochran *ts = ns_to_timespec64(ns); 303d339b133SRichard Cochran 304d339b133SRichard Cochran return 0; 305d339b133SRichard Cochran } 306d339b133SRichard Cochran 307cff8ba28SMiroslav Lichvar static int igb_ptp_gettimex_82580(struct ptp_clock_info *ptp, 308cff8ba28SMiroslav Lichvar struct timespec64 *ts, 309cff8ba28SMiroslav Lichvar struct ptp_system_timestamp *sts) 310e57b8bdbSMatthew Vick { 311e57b8bdbSMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 312e57b8bdbSMatthew Vick ptp_caps); 313cff8ba28SMiroslav Lichvar struct e1000_hw *hw = &igb->hw; 314cff8ba28SMiroslav Lichvar unsigned long flags; 315cff8ba28SMiroslav Lichvar u32 lo, hi; 316cff8ba28SMiroslav Lichvar u64 ns; 317cff8ba28SMiroslav Lichvar 318cff8ba28SMiroslav Lichvar spin_lock_irqsave(&igb->tmreg_lock, flags); 319cff8ba28SMiroslav Lichvar 320cff8ba28SMiroslav Lichvar ptp_read_system_prets(sts); 321cff8ba28SMiroslav Lichvar rd32(E1000_SYSTIMR); 322cff8ba28SMiroslav Lichvar ptp_read_system_postts(sts); 323cff8ba28SMiroslav Lichvar lo = rd32(E1000_SYSTIML); 324cff8ba28SMiroslav Lichvar hi = rd32(E1000_SYSTIMH); 325cff8ba28SMiroslav Lichvar 326cff8ba28SMiroslav Lichvar ns = timecounter_cyc2time(&igb->tc, ((u64)hi << 32) | lo); 327cff8ba28SMiroslav Lichvar 328cff8ba28SMiroslav Lichvar spin_unlock_irqrestore(&igb->tmreg_lock, flags); 329cff8ba28SMiroslav Lichvar 330cff8ba28SMiroslav Lichvar *ts = ns_to_timespec64(ns); 331cff8ba28SMiroslav Lichvar 332cff8ba28SMiroslav Lichvar return 0; 333cff8ba28SMiroslav Lichvar } 334cff8ba28SMiroslav Lichvar 335cff8ba28SMiroslav Lichvar static int igb_ptp_gettimex_i210(struct ptp_clock_info *ptp, 336cff8ba28SMiroslav Lichvar struct timespec64 *ts, 337cff8ba28SMiroslav Lichvar struct ptp_system_timestamp *sts) 338cff8ba28SMiroslav Lichvar { 339cff8ba28SMiroslav Lichvar struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 340cff8ba28SMiroslav Lichvar ptp_caps); 341cff8ba28SMiroslav Lichvar struct e1000_hw *hw = &igb->hw; 342e57b8bdbSMatthew Vick unsigned long flags; 343e57b8bdbSMatthew Vick 344e57b8bdbSMatthew Vick spin_lock_irqsave(&igb->tmreg_lock, flags); 345e57b8bdbSMatthew Vick 346cff8ba28SMiroslav Lichvar ptp_read_system_prets(sts); 347cff8ba28SMiroslav Lichvar rd32(E1000_SYSTIMR); 348cff8ba28SMiroslav Lichvar ptp_read_system_postts(sts); 349cff8ba28SMiroslav Lichvar ts->tv_nsec = rd32(E1000_SYSTIML); 350cff8ba28SMiroslav Lichvar ts->tv_sec = rd32(E1000_SYSTIMH); 351e57b8bdbSMatthew Vick 352e57b8bdbSMatthew Vick spin_unlock_irqrestore(&igb->tmreg_lock, flags); 353e57b8bdbSMatthew Vick 354e57b8bdbSMatthew Vick return 0; 355e57b8bdbSMatthew Vick } 356e57b8bdbSMatthew Vick 357e57b8bdbSMatthew Vick static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, 358d4c496feSRichard Cochran const struct timespec64 *ts) 359d339b133SRichard Cochran { 360a79f4f88SMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 361a79f4f88SMatthew Vick ptp_caps); 362d339b133SRichard Cochran unsigned long flags; 363a79f4f88SMatthew Vick u64 ns; 364d339b133SRichard Cochran 365350f66d5SRichard Cochran ns = timespec64_to_ns(ts); 366d339b133SRichard Cochran 367d339b133SRichard Cochran spin_lock_irqsave(&igb->tmreg_lock, flags); 368d339b133SRichard Cochran 369d339b133SRichard Cochran timecounter_init(&igb->tc, &igb->cc, ns); 370d339b133SRichard Cochran 371d339b133SRichard Cochran spin_unlock_irqrestore(&igb->tmreg_lock, flags); 372d339b133SRichard Cochran 373d339b133SRichard Cochran return 0; 374d339b133SRichard Cochran } 375d339b133SRichard Cochran 376e57b8bdbSMatthew Vick static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, 377d4c496feSRichard Cochran const struct timespec64 *ts) 378e57b8bdbSMatthew Vick { 379e57b8bdbSMatthew Vick struct igb_adapter *igb = container_of(ptp, struct igb_adapter, 380e57b8bdbSMatthew Vick ptp_caps); 381e57b8bdbSMatthew Vick unsigned long flags; 382e57b8bdbSMatthew Vick 383e57b8bdbSMatthew Vick spin_lock_irqsave(&igb->tmreg_lock, flags); 384e57b8bdbSMatthew Vick 385e57b8bdbSMatthew Vick igb_ptp_write_i210(igb, ts); 386e57b8bdbSMatthew Vick 387e57b8bdbSMatthew Vick spin_unlock_irqrestore(&igb->tmreg_lock, flags); 388e57b8bdbSMatthew Vick 389e57b8bdbSMatthew Vick return 0; 390e57b8bdbSMatthew Vick } 391e57b8bdbSMatthew Vick 392720db4ffSRichard Cochran static void igb_pin_direction(int pin, int input, u32 *ctrl, u32 *ctrl_ext) 393720db4ffSRichard Cochran { 394720db4ffSRichard Cochran u32 *ptr = pin < 2 ? ctrl : ctrl_ext; 395b23c0cc5SAlexander Duyck static const u32 mask[IGB_N_SDP] = { 396720db4ffSRichard Cochran E1000_CTRL_SDP0_DIR, 397720db4ffSRichard Cochran E1000_CTRL_SDP1_DIR, 398720db4ffSRichard Cochran E1000_CTRL_EXT_SDP2_DIR, 399720db4ffSRichard Cochran E1000_CTRL_EXT_SDP3_DIR, 400720db4ffSRichard Cochran }; 401720db4ffSRichard Cochran 402720db4ffSRichard Cochran if (input) 403720db4ffSRichard Cochran *ptr &= ~mask[pin]; 404720db4ffSRichard Cochran else 405720db4ffSRichard Cochran *ptr |= mask[pin]; 406720db4ffSRichard Cochran } 407720db4ffSRichard Cochran 408720db4ffSRichard Cochran static void igb_pin_extts(struct igb_adapter *igb, int chan, int pin) 409720db4ffSRichard Cochran { 410b23c0cc5SAlexander Duyck static const u32 aux0_sel_sdp[IGB_N_SDP] = { 411720db4ffSRichard Cochran AUX0_SEL_SDP0, AUX0_SEL_SDP1, AUX0_SEL_SDP2, AUX0_SEL_SDP3, 412720db4ffSRichard Cochran }; 413b23c0cc5SAlexander Duyck static const u32 aux1_sel_sdp[IGB_N_SDP] = { 414720db4ffSRichard Cochran AUX1_SEL_SDP0, AUX1_SEL_SDP1, AUX1_SEL_SDP2, AUX1_SEL_SDP3, 415720db4ffSRichard Cochran }; 416b23c0cc5SAlexander Duyck static const u32 ts_sdp_en[IGB_N_SDP] = { 417720db4ffSRichard Cochran TS_SDP0_EN, TS_SDP1_EN, TS_SDP2_EN, TS_SDP3_EN, 418720db4ffSRichard Cochran }; 419b23c0cc5SAlexander Duyck struct e1000_hw *hw = &igb->hw; 420720db4ffSRichard Cochran u32 ctrl, ctrl_ext, tssdp = 0; 421720db4ffSRichard Cochran 422720db4ffSRichard Cochran ctrl = rd32(E1000_CTRL); 423720db4ffSRichard Cochran ctrl_ext = rd32(E1000_CTRL_EXT); 424720db4ffSRichard Cochran tssdp = rd32(E1000_TSSDP); 425720db4ffSRichard Cochran 426720db4ffSRichard Cochran igb_pin_direction(pin, 1, &ctrl, &ctrl_ext); 427720db4ffSRichard Cochran 428720db4ffSRichard Cochran /* Make sure this pin is not enabled as an output. */ 429720db4ffSRichard Cochran tssdp &= ~ts_sdp_en[pin]; 430720db4ffSRichard Cochran 431720db4ffSRichard Cochran if (chan == 1) { 432720db4ffSRichard Cochran tssdp &= ~AUX1_SEL_SDP3; 433720db4ffSRichard Cochran tssdp |= aux1_sel_sdp[pin] | AUX1_TS_SDP_EN; 434720db4ffSRichard Cochran } else { 435720db4ffSRichard Cochran tssdp &= ~AUX0_SEL_SDP3; 436720db4ffSRichard Cochran tssdp |= aux0_sel_sdp[pin] | AUX0_TS_SDP_EN; 437720db4ffSRichard Cochran } 438720db4ffSRichard Cochran 439720db4ffSRichard Cochran wr32(E1000_TSSDP, tssdp); 440720db4ffSRichard Cochran wr32(E1000_CTRL, ctrl); 441720db4ffSRichard Cochran wr32(E1000_CTRL_EXT, ctrl_ext); 442720db4ffSRichard Cochran } 443720db4ffSRichard Cochran 44430c72916SRichard Cochran static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq) 445720db4ffSRichard Cochran { 446b23c0cc5SAlexander Duyck static const u32 aux0_sel_sdp[IGB_N_SDP] = { 447720db4ffSRichard Cochran AUX0_SEL_SDP0, AUX0_SEL_SDP1, AUX0_SEL_SDP2, AUX0_SEL_SDP3, 448720db4ffSRichard Cochran }; 449b23c0cc5SAlexander Duyck static const u32 aux1_sel_sdp[IGB_N_SDP] = { 450720db4ffSRichard Cochran AUX1_SEL_SDP0, AUX1_SEL_SDP1, AUX1_SEL_SDP2, AUX1_SEL_SDP3, 451720db4ffSRichard Cochran }; 452b23c0cc5SAlexander Duyck static const u32 ts_sdp_en[IGB_N_SDP] = { 453720db4ffSRichard Cochran TS_SDP0_EN, TS_SDP1_EN, TS_SDP2_EN, TS_SDP3_EN, 454720db4ffSRichard Cochran }; 455b23c0cc5SAlexander Duyck static const u32 ts_sdp_sel_tt0[IGB_N_SDP] = { 456720db4ffSRichard Cochran TS_SDP0_SEL_TT0, TS_SDP1_SEL_TT0, 457720db4ffSRichard Cochran TS_SDP2_SEL_TT0, TS_SDP3_SEL_TT0, 458720db4ffSRichard Cochran }; 459b23c0cc5SAlexander Duyck static const u32 ts_sdp_sel_tt1[IGB_N_SDP] = { 460720db4ffSRichard Cochran TS_SDP0_SEL_TT1, TS_SDP1_SEL_TT1, 461720db4ffSRichard Cochran TS_SDP2_SEL_TT1, TS_SDP3_SEL_TT1, 462720db4ffSRichard Cochran }; 46330c72916SRichard Cochran static const u32 ts_sdp_sel_fc0[IGB_N_SDP] = { 46430c72916SRichard Cochran TS_SDP0_SEL_FC0, TS_SDP1_SEL_FC0, 46530c72916SRichard Cochran TS_SDP2_SEL_FC0, TS_SDP3_SEL_FC0, 46630c72916SRichard Cochran }; 46730c72916SRichard Cochran static const u32 ts_sdp_sel_fc1[IGB_N_SDP] = { 46830c72916SRichard Cochran TS_SDP0_SEL_FC1, TS_SDP1_SEL_FC1, 46930c72916SRichard Cochran TS_SDP2_SEL_FC1, TS_SDP3_SEL_FC1, 47030c72916SRichard Cochran }; 471b23c0cc5SAlexander Duyck static const u32 ts_sdp_sel_clr[IGB_N_SDP] = { 472720db4ffSRichard Cochran TS_SDP0_SEL_FC1, TS_SDP1_SEL_FC1, 473720db4ffSRichard Cochran TS_SDP2_SEL_FC1, TS_SDP3_SEL_FC1, 474720db4ffSRichard Cochran }; 475b23c0cc5SAlexander Duyck struct e1000_hw *hw = &igb->hw; 476720db4ffSRichard Cochran u32 ctrl, ctrl_ext, tssdp = 0; 477720db4ffSRichard Cochran 478720db4ffSRichard Cochran ctrl = rd32(E1000_CTRL); 479720db4ffSRichard Cochran ctrl_ext = rd32(E1000_CTRL_EXT); 480720db4ffSRichard Cochran tssdp = rd32(E1000_TSSDP); 481720db4ffSRichard Cochran 482720db4ffSRichard Cochran igb_pin_direction(pin, 0, &ctrl, &ctrl_ext); 483720db4ffSRichard Cochran 484720db4ffSRichard Cochran /* Make sure this pin is not enabled as an input. */ 485720db4ffSRichard Cochran if ((tssdp & AUX0_SEL_SDP3) == aux0_sel_sdp[pin]) 486720db4ffSRichard Cochran tssdp &= ~AUX0_TS_SDP_EN; 487720db4ffSRichard Cochran 488720db4ffSRichard Cochran if ((tssdp & AUX1_SEL_SDP3) == aux1_sel_sdp[pin]) 489720db4ffSRichard Cochran tssdp &= ~AUX1_TS_SDP_EN; 490720db4ffSRichard Cochran 491720db4ffSRichard Cochran tssdp &= ~ts_sdp_sel_clr[pin]; 49230c72916SRichard Cochran if (freq) { 49330c72916SRichard Cochran if (chan == 1) 49430c72916SRichard Cochran tssdp |= ts_sdp_sel_fc1[pin]; 49530c72916SRichard Cochran else 49630c72916SRichard Cochran tssdp |= ts_sdp_sel_fc0[pin]; 49730c72916SRichard Cochran } else { 498720db4ffSRichard Cochran if (chan == 1) 499720db4ffSRichard Cochran tssdp |= ts_sdp_sel_tt1[pin]; 500720db4ffSRichard Cochran else 501720db4ffSRichard Cochran tssdp |= ts_sdp_sel_tt0[pin]; 50230c72916SRichard Cochran } 503720db4ffSRichard Cochran tssdp |= ts_sdp_en[pin]; 504720db4ffSRichard Cochran 505720db4ffSRichard Cochran wr32(E1000_TSSDP, tssdp); 506720db4ffSRichard Cochran wr32(E1000_CTRL, ctrl); 507720db4ffSRichard Cochran wr32(E1000_CTRL_EXT, ctrl_ext); 508720db4ffSRichard Cochran } 509720db4ffSRichard Cochran 51000c65578SRichard Cochran static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, 51100c65578SRichard Cochran struct ptp_clock_request *rq, int on) 51200c65578SRichard Cochran { 51300c65578SRichard Cochran struct igb_adapter *igb = 51400c65578SRichard Cochran container_of(ptp, struct igb_adapter, ptp_caps); 51500c65578SRichard Cochran struct e1000_hw *hw = &igb->hw; 51630c72916SRichard Cochran u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh, freqout; 51700c65578SRichard Cochran unsigned long flags; 51840c9b079SArnd Bergmann struct timespec64 ts; 51930c72916SRichard Cochran int use_freq = 0, pin = -1; 520720db4ffSRichard Cochran s64 ns; 52100c65578SRichard Cochran 52200c65578SRichard Cochran switch (rq->type) { 523720db4ffSRichard Cochran case PTP_CLK_REQ_EXTTS: 524720db4ffSRichard Cochran if (on) { 525720db4ffSRichard Cochran pin = ptp_find_pin(igb->ptp_clock, PTP_PF_EXTTS, 526720db4ffSRichard Cochran rq->extts.index); 527720db4ffSRichard Cochran if (pin < 0) 528720db4ffSRichard Cochran return -EBUSY; 529720db4ffSRichard Cochran } 530720db4ffSRichard Cochran if (rq->extts.index == 1) { 531720db4ffSRichard Cochran tsauxc_mask = TSAUXC_EN_TS1; 532720db4ffSRichard Cochran tsim_mask = TSINTR_AUTT1; 533720db4ffSRichard Cochran } else { 534720db4ffSRichard Cochran tsauxc_mask = TSAUXC_EN_TS0; 535720db4ffSRichard Cochran tsim_mask = TSINTR_AUTT0; 536720db4ffSRichard Cochran } 537720db4ffSRichard Cochran spin_lock_irqsave(&igb->tmreg_lock, flags); 538720db4ffSRichard Cochran tsauxc = rd32(E1000_TSAUXC); 539720db4ffSRichard Cochran tsim = rd32(E1000_TSIM); 540720db4ffSRichard Cochran if (on) { 541720db4ffSRichard Cochran igb_pin_extts(igb, rq->extts.index, pin); 542720db4ffSRichard Cochran tsauxc |= tsauxc_mask; 543720db4ffSRichard Cochran tsim |= tsim_mask; 544720db4ffSRichard Cochran } else { 545720db4ffSRichard Cochran tsauxc &= ~tsauxc_mask; 546720db4ffSRichard Cochran tsim &= ~tsim_mask; 547720db4ffSRichard Cochran } 548720db4ffSRichard Cochran wr32(E1000_TSAUXC, tsauxc); 549720db4ffSRichard Cochran wr32(E1000_TSIM, tsim); 550720db4ffSRichard Cochran spin_unlock_irqrestore(&igb->tmreg_lock, flags); 551720db4ffSRichard Cochran return 0; 552720db4ffSRichard Cochran 553720db4ffSRichard Cochran case PTP_CLK_REQ_PEROUT: 5547f9048f1SJacob Keller /* Reject requests with unsupported flags */ 5557f9048f1SJacob Keller if (rq->perout.flags) 5567f9048f1SJacob Keller return -EOPNOTSUPP; 5577f9048f1SJacob Keller 558720db4ffSRichard Cochran if (on) { 559720db4ffSRichard Cochran pin = ptp_find_pin(igb->ptp_clock, PTP_PF_PEROUT, 560720db4ffSRichard Cochran rq->perout.index); 561720db4ffSRichard Cochran if (pin < 0) 562720db4ffSRichard Cochran return -EBUSY; 563720db4ffSRichard Cochran } 564720db4ffSRichard Cochran ts.tv_sec = rq->perout.period.sec; 565720db4ffSRichard Cochran ts.tv_nsec = rq->perout.period.nsec; 56640c9b079SArnd Bergmann ns = timespec64_to_ns(&ts); 567720db4ffSRichard Cochran ns = ns >> 1; 568569f3b3dSRoland Hii if (on && ((ns <= 70000000LL) || (ns == 125000000LL) || 569569f3b3dSRoland Hii (ns == 250000000LL) || (ns == 500000000LL))) { 57030c72916SRichard Cochran if (ns < 8LL) 571720db4ffSRichard Cochran return -EINVAL; 57230c72916SRichard Cochran use_freq = 1; 573720db4ffSRichard Cochran } 57440c9b079SArnd Bergmann ts = ns_to_timespec64(ns); 575720db4ffSRichard Cochran if (rq->perout.index == 1) { 57630c72916SRichard Cochran if (use_freq) { 57730c72916SRichard Cochran tsauxc_mask = TSAUXC_EN_CLK1 | TSAUXC_ST1; 57830c72916SRichard Cochran tsim_mask = 0; 57930c72916SRichard Cochran } else { 580720db4ffSRichard Cochran tsauxc_mask = TSAUXC_EN_TT1; 581720db4ffSRichard Cochran tsim_mask = TSINTR_TT1; 58230c72916SRichard Cochran } 583720db4ffSRichard Cochran trgttiml = E1000_TRGTTIML1; 584720db4ffSRichard Cochran trgttimh = E1000_TRGTTIMH1; 58530c72916SRichard Cochran freqout = E1000_FREQOUT1; 58630c72916SRichard Cochran } else { 58730c72916SRichard Cochran if (use_freq) { 58830c72916SRichard Cochran tsauxc_mask = TSAUXC_EN_CLK0 | TSAUXC_ST0; 58930c72916SRichard Cochran tsim_mask = 0; 590720db4ffSRichard Cochran } else { 591720db4ffSRichard Cochran tsauxc_mask = TSAUXC_EN_TT0; 592720db4ffSRichard Cochran tsim_mask = TSINTR_TT0; 59330c72916SRichard Cochran } 594720db4ffSRichard Cochran trgttiml = E1000_TRGTTIML0; 595720db4ffSRichard Cochran trgttimh = E1000_TRGTTIMH0; 59630c72916SRichard Cochran freqout = E1000_FREQOUT0; 597720db4ffSRichard Cochran } 598720db4ffSRichard Cochran spin_lock_irqsave(&igb->tmreg_lock, flags); 599720db4ffSRichard Cochran tsauxc = rd32(E1000_TSAUXC); 600720db4ffSRichard Cochran tsim = rd32(E1000_TSIM); 60130c72916SRichard Cochran if (rq->perout.index == 1) { 60230c72916SRichard Cochran tsauxc &= ~(TSAUXC_EN_TT1 | TSAUXC_EN_CLK1 | TSAUXC_ST1); 60330c72916SRichard Cochran tsim &= ~TSINTR_TT1; 60430c72916SRichard Cochran } else { 60530c72916SRichard Cochran tsauxc &= ~(TSAUXC_EN_TT0 | TSAUXC_EN_CLK0 | TSAUXC_ST0); 60630c72916SRichard Cochran tsim &= ~TSINTR_TT0; 60730c72916SRichard Cochran } 608720db4ffSRichard Cochran if (on) { 609720db4ffSRichard Cochran int i = rq->perout.index; 61030c72916SRichard Cochran igb_pin_perout(igb, i, pin, use_freq); 611720db4ffSRichard Cochran igb->perout[i].start.tv_sec = rq->perout.start.sec; 612720db4ffSRichard Cochran igb->perout[i].start.tv_nsec = rq->perout.start.nsec; 613720db4ffSRichard Cochran igb->perout[i].period.tv_sec = ts.tv_sec; 614720db4ffSRichard Cochran igb->perout[i].period.tv_nsec = ts.tv_nsec; 61558c98be1SRichard Cochran wr32(trgttimh, rq->perout.start.sec); 61658c98be1SRichard Cochran wr32(trgttiml, rq->perout.start.nsec); 61730c72916SRichard Cochran if (use_freq) 61830c72916SRichard Cochran wr32(freqout, ns); 619720db4ffSRichard Cochran tsauxc |= tsauxc_mask; 620720db4ffSRichard Cochran tsim |= tsim_mask; 621720db4ffSRichard Cochran } 622720db4ffSRichard Cochran wr32(E1000_TSAUXC, tsauxc); 623720db4ffSRichard Cochran wr32(E1000_TSIM, tsim); 624720db4ffSRichard Cochran spin_unlock_irqrestore(&igb->tmreg_lock, flags); 625720db4ffSRichard Cochran return 0; 626720db4ffSRichard Cochran 62700c65578SRichard Cochran case PTP_CLK_REQ_PPS: 62800c65578SRichard Cochran spin_lock_irqsave(&igb->tmreg_lock, flags); 62900c65578SRichard Cochran tsim = rd32(E1000_TSIM); 63000c65578SRichard Cochran if (on) 63100c65578SRichard Cochran tsim |= TSINTR_SYS_WRAP; 63200c65578SRichard Cochran else 63300c65578SRichard Cochran tsim &= ~TSINTR_SYS_WRAP; 634ac28b41aSJacob Keller igb->pps_sys_wrap_on = !!on; 63500c65578SRichard Cochran wr32(E1000_TSIM, tsim); 63600c65578SRichard Cochran spin_unlock_irqrestore(&igb->tmreg_lock, flags); 63700c65578SRichard Cochran return 0; 63800c65578SRichard Cochran } 63900c65578SRichard Cochran 64000c65578SRichard Cochran return -EOPNOTSUPP; 64100c65578SRichard Cochran } 64200c65578SRichard Cochran 643102be52fSJacob Keller static int igb_ptp_feature_enable(struct ptp_clock_info *ptp, 644d339b133SRichard Cochran struct ptp_clock_request *rq, int on) 645d339b133SRichard Cochran { 646d339b133SRichard Cochran return -EOPNOTSUPP; 647d339b133SRichard Cochran } 648d339b133SRichard Cochran 649720db4ffSRichard Cochran static int igb_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, 650720db4ffSRichard Cochran enum ptp_pin_function func, unsigned int chan) 651720db4ffSRichard Cochran { 652720db4ffSRichard Cochran switch (func) { 653720db4ffSRichard Cochran case PTP_PF_NONE: 654720db4ffSRichard Cochran case PTP_PF_EXTTS: 655720db4ffSRichard Cochran case PTP_PF_PEROUT: 656720db4ffSRichard Cochran break; 657720db4ffSRichard Cochran case PTP_PF_PHYSYNC: 658720db4ffSRichard Cochran return -1; 659720db4ffSRichard Cochran } 660720db4ffSRichard Cochran return 0; 661720db4ffSRichard Cochran } 662720db4ffSRichard Cochran 6631f6e8178SMatthew Vick /** 6641f6e8178SMatthew Vick * igb_ptp_tx_work 6651f6e8178SMatthew Vick * @work: pointer to work struct 6661f6e8178SMatthew Vick * 6671f6e8178SMatthew Vick * This work function polls the TSYNCTXCTL valid bit to determine when a 6681f6e8178SMatthew Vick * timestamp has been taken for the current stored skb. 669b980ac18SJeff Kirsher **/ 670167f3f71SJeff Kirsher static void igb_ptp_tx_work(struct work_struct *work) 6711f6e8178SMatthew Vick { 6721f6e8178SMatthew Vick struct igb_adapter *adapter = container_of(work, struct igb_adapter, 6731f6e8178SMatthew Vick ptp_tx_work); 6741f6e8178SMatthew Vick struct e1000_hw *hw = &adapter->hw; 6751f6e8178SMatthew Vick u32 tsynctxctl; 6761f6e8178SMatthew Vick 6771f6e8178SMatthew Vick if (!adapter->ptp_tx_skb) 6781f6e8178SMatthew Vick return; 6791f6e8178SMatthew Vick 680428f1f71SMatthew Vick if (time_is_before_jiffies(adapter->ptp_tx_start + 681428f1f71SMatthew Vick IGB_PTP_TX_TIMEOUT)) { 682428f1f71SMatthew Vick dev_kfree_skb_any(adapter->ptp_tx_skb); 683428f1f71SMatthew Vick adapter->ptp_tx_skb = NULL; 684ed4420a3SJakub Kicinski clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); 685428f1f71SMatthew Vick adapter->tx_hwtstamp_timeouts++; 6863a532852SDaniel Hua /* Clear the tx valid bit in TSYNCTXCTL register to enable 6873a532852SDaniel Hua * interrupt 6883a532852SDaniel Hua */ 6893a532852SDaniel Hua rd32(E1000_TXSTMPH); 690c5ffe7e1SJakub Kicinski dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang\n"); 691428f1f71SMatthew Vick return; 692428f1f71SMatthew Vick } 693428f1f71SMatthew Vick 6941f6e8178SMatthew Vick tsynctxctl = rd32(E1000_TSYNCTXCTL); 6951f6e8178SMatthew Vick if (tsynctxctl & E1000_TSYNCTXCTL_VALID) 6961f6e8178SMatthew Vick igb_ptp_tx_hwtstamp(adapter); 6971f6e8178SMatthew Vick else 6981f6e8178SMatthew Vick /* reschedule to check later */ 6991f6e8178SMatthew Vick schedule_work(&adapter->ptp_tx_work); 7001f6e8178SMatthew Vick } 7011f6e8178SMatthew Vick 702a79f4f88SMatthew Vick static void igb_ptp_overflow_check(struct work_struct *work) 703d339b133SRichard Cochran { 704d339b133SRichard Cochran struct igb_adapter *igb = 705a79f4f88SMatthew Vick container_of(work, struct igb_adapter, ptp_overflow_work.work); 706d4c496feSRichard Cochran struct timespec64 ts; 707cff8ba28SMiroslav Lichvar u64 ns; 708d339b133SRichard Cochran 709cff8ba28SMiroslav Lichvar /* Update the timecounter */ 710cff8ba28SMiroslav Lichvar ns = timecounter_read(&igb->tc); 711d339b133SRichard Cochran 712cff8ba28SMiroslav Lichvar ts = ns_to_timespec64(ns); 71332eaf120SDavid S. Miller pr_debug("igb overflow check at %lld.%09lu\n", 71432eaf120SDavid S. Miller (long long) ts.tv_sec, ts.tv_nsec); 715d339b133SRichard Cochran 716a79f4f88SMatthew Vick schedule_delayed_work(&igb->ptp_overflow_work, 717a79f4f88SMatthew Vick IGB_SYSTIM_OVERFLOW_PERIOD); 718a79f4f88SMatthew Vick } 719a79f4f88SMatthew Vick 720a79f4f88SMatthew Vick /** 721fc580751SMatthew Vick * igb_ptp_rx_hang - detect error case when Rx timestamp registers latched 722fc580751SMatthew Vick * @adapter: private network adapter structure 723fc580751SMatthew Vick * 724fc580751SMatthew Vick * This watchdog task is scheduled to detect error case where hardware has 725fc580751SMatthew Vick * dropped an Rx packet that was timestamped when the ring is full. The 726fc580751SMatthew Vick * particular error is rare but leaves the device in a state unable to timestamp 727fc580751SMatthew Vick * any future packets. 728b980ac18SJeff Kirsher **/ 729fc580751SMatthew Vick void igb_ptp_rx_hang(struct igb_adapter *adapter) 730fc580751SMatthew Vick { 731fc580751SMatthew Vick struct e1000_hw *hw = &adapter->hw; 732fc580751SMatthew Vick u32 tsyncrxctl = rd32(E1000_TSYNCRXCTL); 733fc580751SMatthew Vick unsigned long rx_event; 734fc580751SMatthew Vick 735462f1188SJacob Keller /* Other hardware uses per-packet timestamps */ 736fc580751SMatthew Vick if (hw->mac.type != e1000_82576) 737fc580751SMatthew Vick return; 738fc580751SMatthew Vick 739fc580751SMatthew Vick /* If we don't have a valid timestamp in the registers, just update the 740fc580751SMatthew Vick * timeout counter and exit 741fc580751SMatthew Vick */ 742fc580751SMatthew Vick if (!(tsyncrxctl & E1000_TSYNCRXCTL_VALID)) { 743fc580751SMatthew Vick adapter->last_rx_ptp_check = jiffies; 744fc580751SMatthew Vick return; 745fc580751SMatthew Vick } 746fc580751SMatthew Vick 747fc580751SMatthew Vick /* Determine the most recent watchdog or rx_timestamp event */ 748fc580751SMatthew Vick rx_event = adapter->last_rx_ptp_check; 7495499a968SJakub Kicinski if (time_after(adapter->last_rx_timestamp, rx_event)) 7505499a968SJakub Kicinski rx_event = adapter->last_rx_timestamp; 751fc580751SMatthew Vick 752fc580751SMatthew Vick /* Only need to read the high RXSTMP register to clear the lock */ 753fc580751SMatthew Vick if (time_is_before_jiffies(rx_event + 5 * HZ)) { 754fc580751SMatthew Vick rd32(E1000_RXSTMPH); 755fc580751SMatthew Vick adapter->last_rx_ptp_check = jiffies; 756fc580751SMatthew Vick adapter->rx_hwtstamp_cleared++; 757c5ffe7e1SJakub Kicinski dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang\n"); 758fc580751SMatthew Vick } 759fc580751SMatthew Vick } 760fc580751SMatthew Vick 761fc580751SMatthew Vick /** 762e5f36ad1SJacob Keller * igb_ptp_tx_hang - detect error case where Tx timestamp never finishes 763e5f36ad1SJacob Keller * @adapter: private network adapter structure 764e5f36ad1SJacob Keller */ 765e5f36ad1SJacob Keller void igb_ptp_tx_hang(struct igb_adapter *adapter) 766e5f36ad1SJacob Keller { 7673a532852SDaniel Hua struct e1000_hw *hw = &adapter->hw; 768e5f36ad1SJacob Keller bool timeout = time_is_before_jiffies(adapter->ptp_tx_start + 769e5f36ad1SJacob Keller IGB_PTP_TX_TIMEOUT); 770e5f36ad1SJacob Keller 771e5f36ad1SJacob Keller if (!adapter->ptp_tx_skb) 772e5f36ad1SJacob Keller return; 773e5f36ad1SJacob Keller 774e5f36ad1SJacob Keller if (!test_bit(__IGB_PTP_TX_IN_PROGRESS, &adapter->state)) 775e5f36ad1SJacob Keller return; 776e5f36ad1SJacob Keller 777e5f36ad1SJacob Keller /* If we haven't received a timestamp within the timeout, it is 778e5f36ad1SJacob Keller * reasonable to assume that it will never occur, so we can unlock the 779e5f36ad1SJacob Keller * timestamp bit when this occurs. 780e5f36ad1SJacob Keller */ 781e5f36ad1SJacob Keller if (timeout) { 782e5f36ad1SJacob Keller cancel_work_sync(&adapter->ptp_tx_work); 783e5f36ad1SJacob Keller dev_kfree_skb_any(adapter->ptp_tx_skb); 784e5f36ad1SJacob Keller adapter->ptp_tx_skb = NULL; 785e5f36ad1SJacob Keller clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); 786e5f36ad1SJacob Keller adapter->tx_hwtstamp_timeouts++; 7873a532852SDaniel Hua /* Clear the tx valid bit in TSYNCTXCTL register to enable 7883a532852SDaniel Hua * interrupt 7893a532852SDaniel Hua */ 7903a532852SDaniel Hua rd32(E1000_TXSTMPH); 791e5f36ad1SJacob Keller dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang\n"); 792e5f36ad1SJacob Keller } 793e5f36ad1SJacob Keller } 794e5f36ad1SJacob Keller 795e5f36ad1SJacob Keller /** 796a79f4f88SMatthew Vick * igb_ptp_tx_hwtstamp - utility function which checks for TX time stamp 7971f6e8178SMatthew Vick * @adapter: Board private structure. 798a79f4f88SMatthew Vick * 799a79f4f88SMatthew Vick * If we were asked to do hardware stamping and such a time stamp is 800a79f4f88SMatthew Vick * available, then it must have been for this skb here because we only 801a79f4f88SMatthew Vick * allow only one such packet into the queue. 802b980ac18SJeff Kirsher **/ 803167f3f71SJeff Kirsher static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) 804a79f4f88SMatthew Vick { 8054ccdc013SJacob Keller struct sk_buff *skb = adapter->ptp_tx_skb; 806a79f4f88SMatthew Vick struct e1000_hw *hw = &adapter->hw; 807a79f4f88SMatthew Vick struct skb_shared_hwtstamps shhwtstamps; 808a79f4f88SMatthew Vick u64 regval; 8093f544d2aSNathan Sullivan int adjust = 0; 810a79f4f88SMatthew Vick 811a79f4f88SMatthew Vick regval = rd32(E1000_TXSTMPL); 812a79f4f88SMatthew Vick regval |= (u64)rd32(E1000_TXSTMPH) << 32; 813a79f4f88SMatthew Vick 814a79f4f88SMatthew Vick igb_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval); 8153f544d2aSNathan Sullivan /* adjust timestamp for the TX latency based on link speed */ 8163f544d2aSNathan Sullivan if (adapter->hw.mac.type == e1000_i210) { 8173f544d2aSNathan Sullivan switch (adapter->link_speed) { 8183f544d2aSNathan Sullivan case SPEED_10: 8193f544d2aSNathan Sullivan adjust = IGB_I210_TX_LATENCY_10; 8203f544d2aSNathan Sullivan break; 8213f544d2aSNathan Sullivan case SPEED_100: 8223f544d2aSNathan Sullivan adjust = IGB_I210_TX_LATENCY_100; 8233f544d2aSNathan Sullivan break; 8243f544d2aSNathan Sullivan case SPEED_1000: 8253f544d2aSNathan Sullivan adjust = IGB_I210_TX_LATENCY_1000; 8263f544d2aSNathan Sullivan break; 8273f544d2aSNathan Sullivan } 8283f544d2aSNathan Sullivan } 8293f544d2aSNathan Sullivan 8300066c8b6SKshitiz Gupta shhwtstamps.hwtstamp = 8310066c8b6SKshitiz Gupta ktime_add_ns(shhwtstamps.hwtstamp, adjust); 8323f544d2aSNathan Sullivan 8334ccdc013SJacob Keller /* Clear the lock early before calling skb_tstamp_tx so that 8344ccdc013SJacob Keller * applications are not woken up before the lock bit is clear. We use 8354ccdc013SJacob Keller * a copy of the skb pointer to ensure other threads can't change it 8364ccdc013SJacob Keller * while we're notifying the stack. 8374ccdc013SJacob Keller */ 8381f6e8178SMatthew Vick adapter->ptp_tx_skb = NULL; 839ed4420a3SJakub Kicinski clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); 8404ccdc013SJacob Keller 8414ccdc013SJacob Keller /* Notify the stack and free the skb after we've unlocked */ 8424ccdc013SJacob Keller skb_tstamp_tx(skb, &shhwtstamps); 8434ccdc013SJacob Keller dev_kfree_skb_any(skb); 844a79f4f88SMatthew Vick } 845a79f4f88SMatthew Vick 846b534550aSAlexander Duyck /** 847b534550aSAlexander Duyck * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp 848b534550aSAlexander Duyck * @q_vector: Pointer to interrupt specific structure 849b534550aSAlexander Duyck * @va: Pointer to address containing Rx buffer 850b534550aSAlexander Duyck * @skb: Buffer containing timestamp and packet 851b534550aSAlexander Duyck * 852b534550aSAlexander Duyck * This function is meant to retrieve a timestamp from the first buffer of an 853b534550aSAlexander Duyck * incoming frame. The value is stored in little endian format starting on 854b534550aSAlexander Duyck * byte 8. 855b980ac18SJeff Kirsher **/ 8563456fd53SAlexander Duyck void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, 857b534550aSAlexander Duyck struct sk_buff *skb) 858b534550aSAlexander Duyck { 859ac61d515SAlexander Duyck __le64 *regval = (__le64 *)va; 8600066c8b6SKshitiz Gupta struct igb_adapter *adapter = q_vector->adapter; 8610066c8b6SKshitiz Gupta int adjust = 0; 862b534550aSAlexander Duyck 863b980ac18SJeff Kirsher /* The timestamp is recorded in little endian format. 864b534550aSAlexander Duyck * DWORD: 0 1 2 3 865b534550aSAlexander Duyck * Field: Reserved Reserved SYSTIML SYSTIMH 866b534550aSAlexander Duyck */ 8670066c8b6SKshitiz Gupta igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), 868b534550aSAlexander Duyck le64_to_cpu(regval[1])); 8690066c8b6SKshitiz Gupta 8700066c8b6SKshitiz Gupta /* adjust timestamp for the RX latency based on link speed */ 8710066c8b6SKshitiz Gupta if (adapter->hw.mac.type == e1000_i210) { 8720066c8b6SKshitiz Gupta switch (adapter->link_speed) { 8730066c8b6SKshitiz Gupta case SPEED_10: 8740066c8b6SKshitiz Gupta adjust = IGB_I210_RX_LATENCY_10; 8750066c8b6SKshitiz Gupta break; 8760066c8b6SKshitiz Gupta case SPEED_100: 8770066c8b6SKshitiz Gupta adjust = IGB_I210_RX_LATENCY_100; 8780066c8b6SKshitiz Gupta break; 8790066c8b6SKshitiz Gupta case SPEED_1000: 8800066c8b6SKshitiz Gupta adjust = IGB_I210_RX_LATENCY_1000; 8810066c8b6SKshitiz Gupta break; 8820066c8b6SKshitiz Gupta } 8830066c8b6SKshitiz Gupta } 8840066c8b6SKshitiz Gupta skb_hwtstamps(skb)->hwtstamp = 8850066c8b6SKshitiz Gupta ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); 886b534550aSAlexander Duyck } 887b534550aSAlexander Duyck 888b534550aSAlexander Duyck /** 889b534550aSAlexander Duyck * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register 890b534550aSAlexander Duyck * @q_vector: Pointer to interrupt specific structure 891b534550aSAlexander Duyck * @skb: Buffer containing timestamp and packet 892b534550aSAlexander Duyck * 893b534550aSAlexander Duyck * This function is meant to retrieve a timestamp from the internal registers 894b534550aSAlexander Duyck * of the adapter and store it in the skb. 895b980ac18SJeff Kirsher **/ 896b534550aSAlexander Duyck void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, 897a79f4f88SMatthew Vick struct sk_buff *skb) 898a79f4f88SMatthew Vick { 899a79f4f88SMatthew Vick struct igb_adapter *adapter = q_vector->adapter; 900a79f4f88SMatthew Vick struct e1000_hw *hw = &adapter->hw; 901a79f4f88SMatthew Vick u64 regval; 9023f544d2aSNathan Sullivan int adjust = 0; 903a79f4f88SMatthew Vick 904b980ac18SJeff Kirsher /* If this bit is set, then the RX registers contain the time stamp. No 905a79f4f88SMatthew Vick * other packet will be time stamped until we read these registers, so 906a79f4f88SMatthew Vick * read the registers to make them available again. Because only one 907a79f4f88SMatthew Vick * packet can be time stamped at a time, we know that the register 908a79f4f88SMatthew Vick * values must belong to this one here and therefore we don't need to 909a79f4f88SMatthew Vick * compare any of the additional attributes stored for it. 910a79f4f88SMatthew Vick * 911a79f4f88SMatthew Vick * If nothing went wrong, then it should have a shared tx_flags that we 912a79f4f88SMatthew Vick * can turn into a skb_shared_hwtstamps. 913a79f4f88SMatthew Vick */ 914a79f4f88SMatthew Vick if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) 915a79f4f88SMatthew Vick return; 916a79f4f88SMatthew Vick 917a79f4f88SMatthew Vick regval = rd32(E1000_RXSTMPL); 918a79f4f88SMatthew Vick regval |= (u64)rd32(E1000_RXSTMPH) << 32; 919a79f4f88SMatthew Vick 920a79f4f88SMatthew Vick igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); 9215499a968SJakub Kicinski 9223f544d2aSNathan Sullivan /* adjust timestamp for the RX latency based on link speed */ 9233f544d2aSNathan Sullivan if (adapter->hw.mac.type == e1000_i210) { 9243f544d2aSNathan Sullivan switch (adapter->link_speed) { 9253f544d2aSNathan Sullivan case SPEED_10: 9263f544d2aSNathan Sullivan adjust = IGB_I210_RX_LATENCY_10; 9273f544d2aSNathan Sullivan break; 9283f544d2aSNathan Sullivan case SPEED_100: 9293f544d2aSNathan Sullivan adjust = IGB_I210_RX_LATENCY_100; 9303f544d2aSNathan Sullivan break; 9313f544d2aSNathan Sullivan case SPEED_1000: 9323f544d2aSNathan Sullivan adjust = IGB_I210_RX_LATENCY_1000; 9333f544d2aSNathan Sullivan break; 9343f544d2aSNathan Sullivan } 9353f544d2aSNathan Sullivan } 9363f544d2aSNathan Sullivan skb_hwtstamps(skb)->hwtstamp = 9370066c8b6SKshitiz Gupta ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); 9383f544d2aSNathan Sullivan 9395499a968SJakub Kicinski /* Update the last_rx_timestamp timer in order to enable watchdog check 9405499a968SJakub Kicinski * for error case of latched timestamp on a dropped packet. 9415499a968SJakub Kicinski */ 9425499a968SJakub Kicinski adapter->last_rx_timestamp = jiffies; 943a79f4f88SMatthew Vick } 944a79f4f88SMatthew Vick 945a79f4f88SMatthew Vick /** 9466ab5f7b2SJacob Keller * igb_ptp_get_ts_config - get hardware time stamping config 947a79f4f88SMatthew Vick * @netdev: 948a79f4f88SMatthew Vick * @ifreq: 9496ab5f7b2SJacob Keller * 9506ab5f7b2SJacob Keller * Get the hwtstamp_config settings to return to the user. Rather than attempt 9516ab5f7b2SJacob Keller * to deconstruct the settings from the registers, just return a shadow copy 9526ab5f7b2SJacob Keller * of the last known settings. 9536ab5f7b2SJacob Keller **/ 9546ab5f7b2SJacob Keller int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) 9556ab5f7b2SJacob Keller { 9566ab5f7b2SJacob Keller struct igb_adapter *adapter = netdev_priv(netdev); 9576ab5f7b2SJacob Keller struct hwtstamp_config *config = &adapter->tstamp_config; 9586ab5f7b2SJacob Keller 9596ab5f7b2SJacob Keller return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? 9606ab5f7b2SJacob Keller -EFAULT : 0; 9616ab5f7b2SJacob Keller } 9629f62ecf4SJacob Keller 9636ab5f7b2SJacob Keller /** 9649f62ecf4SJacob Keller * igb_ptp_set_timestamp_mode - setup hardware for timestamping 9659f62ecf4SJacob Keller * @adapter: networking device structure 9669f62ecf4SJacob Keller * @config: hwtstamp configuration 967a79f4f88SMatthew Vick * 968a79f4f88SMatthew Vick * Outgoing time stamping can be enabled and disabled. Play nice and 969a79f4f88SMatthew Vick * disable it when requested, although it shouldn't case any overhead 970a79f4f88SMatthew Vick * when no packet needs it. At most one packet in the queue may be 971a79f4f88SMatthew Vick * marked for time stamping, otherwise it would be impossible to tell 972a79f4f88SMatthew Vick * for sure to which packet the hardware time stamp belongs. 973a79f4f88SMatthew Vick * 974a79f4f88SMatthew Vick * Incoming time stamping has to be configured via the hardware 975a79f4f88SMatthew Vick * filters. Not all combinations are supported, in particular event 976a79f4f88SMatthew Vick * type has to be specified. Matching the kind of event packet is 977a79f4f88SMatthew Vick * not supported, with the exception of "all V2 events regardless of 978a79f4f88SMatthew Vick * level 2 or 4". 9799f62ecf4SJacob Keller */ 9809f62ecf4SJacob Keller static int igb_ptp_set_timestamp_mode(struct igb_adapter *adapter, 9819f62ecf4SJacob Keller struct hwtstamp_config *config) 982a79f4f88SMatthew Vick { 983a79f4f88SMatthew Vick struct e1000_hw *hw = &adapter->hw; 984a79f4f88SMatthew Vick u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; 985a79f4f88SMatthew Vick u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; 986a79f4f88SMatthew Vick u32 tsync_rx_cfg = 0; 987a79f4f88SMatthew Vick bool is_l4 = false; 988a79f4f88SMatthew Vick bool is_l2 = false; 989a79f4f88SMatthew Vick u32 regval; 990a79f4f88SMatthew Vick 991a79f4f88SMatthew Vick /* reserved for future extensions */ 9926ab5f7b2SJacob Keller if (config->flags) 993a79f4f88SMatthew Vick return -EINVAL; 994a79f4f88SMatthew Vick 9956ab5f7b2SJacob Keller switch (config->tx_type) { 996a79f4f88SMatthew Vick case HWTSTAMP_TX_OFF: 997a79f4f88SMatthew Vick tsync_tx_ctl = 0; 998a79f4f88SMatthew Vick case HWTSTAMP_TX_ON: 999a79f4f88SMatthew Vick break; 1000a79f4f88SMatthew Vick default: 1001a79f4f88SMatthew Vick return -ERANGE; 1002a79f4f88SMatthew Vick } 1003a79f4f88SMatthew Vick 10046ab5f7b2SJacob Keller switch (config->rx_filter) { 1005a79f4f88SMatthew Vick case HWTSTAMP_FILTER_NONE: 1006a79f4f88SMatthew Vick tsync_rx_ctl = 0; 1007a79f4f88SMatthew Vick break; 1008a79f4f88SMatthew Vick case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 1009a79f4f88SMatthew Vick tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; 1010a79f4f88SMatthew Vick tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; 1011a79f4f88SMatthew Vick is_l4 = true; 1012a79f4f88SMatthew Vick break; 1013a79f4f88SMatthew Vick case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 1014a79f4f88SMatthew Vick tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; 1015a79f4f88SMatthew Vick tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; 1016a79f4f88SMatthew Vick is_l4 = true; 1017a79f4f88SMatthew Vick break; 10183e961a06SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_EVENT: 10193e961a06SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 10203e961a06SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 10213e961a06SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_SYNC: 1022a79f4f88SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 1023a79f4f88SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 10243e961a06SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 1025a79f4f88SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 1026a79f4f88SMatthew Vick case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 1027a79f4f88SMatthew Vick tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; 10286ab5f7b2SJacob Keller config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 1029a79f4f88SMatthew Vick is_l2 = true; 1030a79f4f88SMatthew Vick is_l4 = true; 1031a79f4f88SMatthew Vick break; 10323e961a06SMatthew Vick case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 1033e3412575SMiroslav Lichvar case HWTSTAMP_FILTER_NTP_ALL: 10343e961a06SMatthew Vick case HWTSTAMP_FILTER_ALL: 10353e961a06SMatthew Vick /* 82576 cannot timestamp all packets, which it needs to do to 10363e961a06SMatthew Vick * support both V1 Sync and Delay_Req messages 10373e961a06SMatthew Vick */ 10383e961a06SMatthew Vick if (hw->mac.type != e1000_82576) { 10393e961a06SMatthew Vick tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; 10406ab5f7b2SJacob Keller config->rx_filter = HWTSTAMP_FILTER_ALL; 10413e961a06SMatthew Vick break; 10423e961a06SMatthew Vick } 10433e961a06SMatthew Vick /* fall through */ 1044a79f4f88SMatthew Vick default: 10456ab5f7b2SJacob Keller config->rx_filter = HWTSTAMP_FILTER_NONE; 1046a79f4f88SMatthew Vick return -ERANGE; 1047a79f4f88SMatthew Vick } 1048a79f4f88SMatthew Vick 1049a79f4f88SMatthew Vick if (hw->mac.type == e1000_82575) { 1050a79f4f88SMatthew Vick if (tsync_rx_ctl | tsync_tx_ctl) 1051a79f4f88SMatthew Vick return -EINVAL; 1052a79f4f88SMatthew Vick return 0; 1053a79f4f88SMatthew Vick } 1054a79f4f88SMatthew Vick 1055b980ac18SJeff Kirsher /* Per-packet timestamping only works if all packets are 1056a79f4f88SMatthew Vick * timestamped, so enable timestamping in all packets as 1057b980ac18SJeff Kirsher * long as one Rx filter was configured. 1058a79f4f88SMatthew Vick */ 1059a79f4f88SMatthew Vick if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { 1060a79f4f88SMatthew Vick tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; 1061a79f4f88SMatthew Vick tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; 10626ab5f7b2SJacob Keller config->rx_filter = HWTSTAMP_FILTER_ALL; 10633e961a06SMatthew Vick is_l2 = true; 10643e961a06SMatthew Vick is_l4 = true; 1065e57b8bdbSMatthew Vick 1066e57b8bdbSMatthew Vick if ((hw->mac.type == e1000_i210) || 1067e57b8bdbSMatthew Vick (hw->mac.type == e1000_i211)) { 1068e57b8bdbSMatthew Vick regval = rd32(E1000_RXPBS); 1069e57b8bdbSMatthew Vick regval |= E1000_RXPBS_CFG_TS_EN; 1070e57b8bdbSMatthew Vick wr32(E1000_RXPBS, regval); 1071e57b8bdbSMatthew Vick } 1072a79f4f88SMatthew Vick } 1073a79f4f88SMatthew Vick 1074a79f4f88SMatthew Vick /* enable/disable TX */ 1075a79f4f88SMatthew Vick regval = rd32(E1000_TSYNCTXCTL); 1076a79f4f88SMatthew Vick regval &= ~E1000_TSYNCTXCTL_ENABLED; 1077a79f4f88SMatthew Vick regval |= tsync_tx_ctl; 1078a79f4f88SMatthew Vick wr32(E1000_TSYNCTXCTL, regval); 1079a79f4f88SMatthew Vick 1080a79f4f88SMatthew Vick /* enable/disable RX */ 1081a79f4f88SMatthew Vick regval = rd32(E1000_TSYNCRXCTL); 1082a79f4f88SMatthew Vick regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); 1083a79f4f88SMatthew Vick regval |= tsync_rx_ctl; 1084a79f4f88SMatthew Vick wr32(E1000_TSYNCRXCTL, regval); 1085a79f4f88SMatthew Vick 1086a79f4f88SMatthew Vick /* define which PTP packets are time stamped */ 1087a79f4f88SMatthew Vick wr32(E1000_TSYNCRXCFG, tsync_rx_cfg); 1088a79f4f88SMatthew Vick 1089a79f4f88SMatthew Vick /* define ethertype filter for timestamped packets */ 1090a79f4f88SMatthew Vick if (is_l2) 109164c75d41SGangfeng Huang wr32(E1000_ETQF(IGB_ETQF_FILTER_1588), 1092a79f4f88SMatthew Vick (E1000_ETQF_FILTER_ENABLE | /* enable filter */ 1093a79f4f88SMatthew Vick E1000_ETQF_1588 | /* enable timestamping */ 1094a79f4f88SMatthew Vick ETH_P_1588)); /* 1588 eth protocol type */ 1095a79f4f88SMatthew Vick else 109664c75d41SGangfeng Huang wr32(E1000_ETQF(IGB_ETQF_FILTER_1588), 0); 1097a79f4f88SMatthew Vick 1098a79f4f88SMatthew Vick /* L4 Queue Filter[3]: filter by destination port and protocol */ 1099a79f4f88SMatthew Vick if (is_l4) { 1100a79f4f88SMatthew Vick u32 ftqf = (IPPROTO_UDP /* UDP */ 1101a79f4f88SMatthew Vick | E1000_FTQF_VF_BP /* VF not compared */ 1102a79f4f88SMatthew Vick | E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */ 1103a79f4f88SMatthew Vick | E1000_FTQF_MASK); /* mask all inputs */ 1104a79f4f88SMatthew Vick ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */ 1105a79f4f88SMatthew Vick 1106ba59814bSMatthew Vick wr32(E1000_IMIR(3), htons(PTP_EV_PORT)); 1107a79f4f88SMatthew Vick wr32(E1000_IMIREXT(3), 1108a79f4f88SMatthew Vick (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP)); 1109a79f4f88SMatthew Vick if (hw->mac.type == e1000_82576) { 1110a79f4f88SMatthew Vick /* enable source port check */ 1111ba59814bSMatthew Vick wr32(E1000_SPQF(3), htons(PTP_EV_PORT)); 1112a79f4f88SMatthew Vick ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP; 1113a79f4f88SMatthew Vick } 1114a79f4f88SMatthew Vick wr32(E1000_FTQF(3), ftqf); 1115a79f4f88SMatthew Vick } else { 1116a79f4f88SMatthew Vick wr32(E1000_FTQF(3), E1000_FTQF_MASK); 1117a79f4f88SMatthew Vick } 1118a79f4f88SMatthew Vick wrfl(); 1119a79f4f88SMatthew Vick 1120a79f4f88SMatthew Vick /* clear TX/RX time stamp registers, just to be sure */ 1121e57b8bdbSMatthew Vick regval = rd32(E1000_TXSTMPL); 1122a79f4f88SMatthew Vick regval = rd32(E1000_TXSTMPH); 1123e57b8bdbSMatthew Vick regval = rd32(E1000_RXSTMPL); 1124a79f4f88SMatthew Vick regval = rd32(E1000_RXSTMPH); 1125a79f4f88SMatthew Vick 11269f62ecf4SJacob Keller return 0; 11279f62ecf4SJacob Keller } 11289f62ecf4SJacob Keller 11299f62ecf4SJacob Keller /** 11309f62ecf4SJacob Keller * igb_ptp_set_ts_config - set hardware time stamping config 11319f62ecf4SJacob Keller * @netdev: 11329f62ecf4SJacob Keller * @ifreq: 11339f62ecf4SJacob Keller * 11349f62ecf4SJacob Keller **/ 11359f62ecf4SJacob Keller int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr) 11369f62ecf4SJacob Keller { 11379f62ecf4SJacob Keller struct igb_adapter *adapter = netdev_priv(netdev); 11389f62ecf4SJacob Keller struct hwtstamp_config config; 11399f62ecf4SJacob Keller int err; 11409f62ecf4SJacob Keller 11419f62ecf4SJacob Keller if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) 11429f62ecf4SJacob Keller return -EFAULT; 11439f62ecf4SJacob Keller 11449f62ecf4SJacob Keller err = igb_ptp_set_timestamp_mode(adapter, &config); 11459f62ecf4SJacob Keller if (err) 11469f62ecf4SJacob Keller return err; 11479f62ecf4SJacob Keller 11489f62ecf4SJacob Keller /* save these settings for future reference */ 11499f62ecf4SJacob Keller memcpy(&adapter->tstamp_config, &config, 11509f62ecf4SJacob Keller sizeof(adapter->tstamp_config)); 11519f62ecf4SJacob Keller 11529f62ecf4SJacob Keller return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? 1153a79f4f88SMatthew Vick -EFAULT : 0; 1154d339b133SRichard Cochran } 1155d339b133SRichard Cochran 11564f3ce71bSJacob Keller /** 11574f3ce71bSJacob Keller * igb_ptp_init - Initialize PTP functionality 11584f3ce71bSJacob Keller * @adapter: Board private structure 11594f3ce71bSJacob Keller * 11604f3ce71bSJacob Keller * This function is called at device probe to initialize the PTP 11614f3ce71bSJacob Keller * functionality. 11624f3ce71bSJacob Keller */ 1163d339b133SRichard Cochran void igb_ptp_init(struct igb_adapter *adapter) 1164d339b133SRichard Cochran { 1165d339b133SRichard Cochran struct e1000_hw *hw = &adapter->hw; 1166201987e3SMatthew Vick struct net_device *netdev = adapter->netdev; 1167720db4ffSRichard Cochran int i; 1168d339b133SRichard Cochran 1169d339b133SRichard Cochran switch (hw->mac.type) { 1170d339b133SRichard Cochran case e1000_82576: 1171201987e3SMatthew Vick snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); 1172a79f4f88SMatthew Vick adapter->ptp_caps.owner = THIS_MODULE; 117375517d92SJiri Benc adapter->ptp_caps.max_adj = 999999881; 1174a79f4f88SMatthew Vick adapter->ptp_caps.n_ext_ts = 0; 1175a79f4f88SMatthew Vick adapter->ptp_caps.pps = 0; 1176a79f4f88SMatthew Vick adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; 1177e57b8bdbSMatthew Vick adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; 1178cff8ba28SMiroslav Lichvar adapter->ptp_caps.gettimex64 = igb_ptp_gettimex_82576; 1179d4c496feSRichard Cochran adapter->ptp_caps.settime64 = igb_ptp_settime_82576; 1180102be52fSJacob Keller adapter->ptp_caps.enable = igb_ptp_feature_enable; 1181a79f4f88SMatthew Vick adapter->cc.read = igb_ptp_read_82576; 1182b57c8940SRichard Cochran adapter->cc.mask = CYCLECOUNTER_MASK(64); 1183d339b133SRichard Cochran adapter->cc.mult = 1; 1184d339b133SRichard Cochran adapter->cc.shift = IGB_82576_TSYNC_SHIFT; 118563737166SJacob Keller adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK; 1186d339b133SRichard Cochran break; 1187e57b8bdbSMatthew Vick case e1000_82580: 1188ceb5f13bSCarolyn Wyborny case e1000_i354: 1189e57b8bdbSMatthew Vick case e1000_i350: 1190e57b8bdbSMatthew Vick snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); 1191e57b8bdbSMatthew Vick adapter->ptp_caps.owner = THIS_MODULE; 1192e57b8bdbSMatthew Vick adapter->ptp_caps.max_adj = 62499999; 1193e57b8bdbSMatthew Vick adapter->ptp_caps.n_ext_ts = 0; 1194e57b8bdbSMatthew Vick adapter->ptp_caps.pps = 0; 1195c79e975eSRichard Cochran adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580; 1196e57b8bdbSMatthew Vick adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; 1197cff8ba28SMiroslav Lichvar adapter->ptp_caps.gettimex64 = igb_ptp_gettimex_82580; 1198d4c496feSRichard Cochran adapter->ptp_caps.settime64 = igb_ptp_settime_82576; 1199102be52fSJacob Keller adapter->ptp_caps.enable = igb_ptp_feature_enable; 1200e57b8bdbSMatthew Vick adapter->cc.read = igb_ptp_read_82580; 1201b57c8940SRichard Cochran adapter->cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580); 1202e57b8bdbSMatthew Vick adapter->cc.mult = 1; 1203e57b8bdbSMatthew Vick adapter->cc.shift = 0; 120463737166SJacob Keller adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK; 1205e57b8bdbSMatthew Vick break; 1206e57b8bdbSMatthew Vick case e1000_i210: 1207e57b8bdbSMatthew Vick case e1000_i211: 1208720db4ffSRichard Cochran for (i = 0; i < IGB_N_SDP; i++) { 1209720db4ffSRichard Cochran struct ptp_pin_desc *ppd = &adapter->sdp_config[i]; 1210720db4ffSRichard Cochran 1211720db4ffSRichard Cochran snprintf(ppd->name, sizeof(ppd->name), "SDP%d", i); 1212720db4ffSRichard Cochran ppd->index = i; 1213720db4ffSRichard Cochran ppd->func = PTP_PF_NONE; 1214720db4ffSRichard Cochran } 1215e57b8bdbSMatthew Vick snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); 1216e57b8bdbSMatthew Vick adapter->ptp_caps.owner = THIS_MODULE; 1217e57b8bdbSMatthew Vick adapter->ptp_caps.max_adj = 62499999; 1218720db4ffSRichard Cochran adapter->ptp_caps.n_ext_ts = IGB_N_EXTTS; 1219720db4ffSRichard Cochran adapter->ptp_caps.n_per_out = IGB_N_PEROUT; 1220720db4ffSRichard Cochran adapter->ptp_caps.n_pins = IGB_N_SDP; 122100c65578SRichard Cochran adapter->ptp_caps.pps = 1; 1222720db4ffSRichard Cochran adapter->ptp_caps.pin_config = adapter->sdp_config; 1223c79e975eSRichard Cochran adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580; 1224e57b8bdbSMatthew Vick adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; 1225cff8ba28SMiroslav Lichvar adapter->ptp_caps.gettimex64 = igb_ptp_gettimex_i210; 1226d4c496feSRichard Cochran adapter->ptp_caps.settime64 = igb_ptp_settime_i210; 122700c65578SRichard Cochran adapter->ptp_caps.enable = igb_ptp_feature_enable_i210; 1228720db4ffSRichard Cochran adapter->ptp_caps.verify = igb_ptp_verify_pin; 1229e57b8bdbSMatthew Vick break; 1230d339b133SRichard Cochran default: 1231d339b133SRichard Cochran adapter->ptp_clock = NULL; 1232d339b133SRichard Cochran return; 1233d339b133SRichard Cochran } 1234d339b133SRichard Cochran 1235e57b8bdbSMatthew Vick spin_lock_init(&adapter->tmreg_lock); 1236e57b8bdbSMatthew Vick INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); 1237e57b8bdbSMatthew Vick 12384f3ce71bSJacob Keller if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK) 1239e57b8bdbSMatthew Vick INIT_DELAYED_WORK(&adapter->ptp_overflow_work, 1240e57b8bdbSMatthew Vick igb_ptp_overflow_check); 12411f6e8178SMatthew Vick 12429f62ecf4SJacob Keller adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; 12439f62ecf4SJacob Keller adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; 12449f62ecf4SJacob Keller 12454f3ce71bSJacob Keller igb_ptp_reset(adapter); 12464f3ce71bSJacob Keller 12471ef76158SRichard Cochran adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, 12481ef76158SRichard Cochran &adapter->pdev->dev); 1249d339b133SRichard Cochran if (IS_ERR(adapter->ptp_clock)) { 1250d339b133SRichard Cochran adapter->ptp_clock = NULL; 1251d339b133SRichard Cochran dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n"); 1252efee95f4SNicolas Pitre } else if (adapter->ptp_clock) { 1253d339b133SRichard Cochran dev_info(&adapter->pdev->dev, "added PHC on %s\n", 1254d339b133SRichard Cochran adapter->netdev->name); 1255462f1188SJacob Keller adapter->ptp_flags |= IGB_PTP_ENABLED; 12561f6e8178SMatthew Vick } 1257d339b133SRichard Cochran } 1258d339b133SRichard Cochran 1259a79f4f88SMatthew Vick /** 1260e3f2350dSJacob Keller * igb_ptp_suspend - Disable PTP work items and prepare for suspend 1261e3f2350dSJacob Keller * @adapter: Board private structure 1262a79f4f88SMatthew Vick * 1263e3f2350dSJacob Keller * This function stops the overflow check work and PTP Tx timestamp work, and 1264e3f2350dSJacob Keller * will prepare the device for OS suspend. 1265e3f2350dSJacob Keller */ 1266e3f2350dSJacob Keller void igb_ptp_suspend(struct igb_adapter *adapter) 1267d339b133SRichard Cochran { 126863737166SJacob Keller if (!(adapter->ptp_flags & IGB_PTP_ENABLED)) 1269d3eef8c8SCarolyn Wyborny return; 127063737166SJacob Keller 127163737166SJacob Keller if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK) 127263737166SJacob Keller cancel_delayed_work_sync(&adapter->ptp_overflow_work); 1273d339b133SRichard Cochran 12741f6e8178SMatthew Vick cancel_work_sync(&adapter->ptp_tx_work); 1275badc26ddSMatthew Vick if (adapter->ptp_tx_skb) { 1276badc26ddSMatthew Vick dev_kfree_skb_any(adapter->ptp_tx_skb); 1277badc26ddSMatthew Vick adapter->ptp_tx_skb = NULL; 1278ed4420a3SJakub Kicinski clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); 1279badc26ddSMatthew Vick } 1280e3f2350dSJacob Keller } 1281e3f2350dSJacob Keller 1282e3f2350dSJacob Keller /** 1283e3f2350dSJacob Keller * igb_ptp_stop - Disable PTP device and stop the overflow check. 1284e3f2350dSJacob Keller * @adapter: Board private structure. 1285e3f2350dSJacob Keller * 1286e3f2350dSJacob Keller * This function stops the PTP support and cancels the delayed work. 1287e3f2350dSJacob Keller **/ 1288e3f2350dSJacob Keller void igb_ptp_stop(struct igb_adapter *adapter) 1289e3f2350dSJacob Keller { 1290e3f2350dSJacob Keller igb_ptp_suspend(adapter); 12911f6e8178SMatthew Vick 1292d339b133SRichard Cochran if (adapter->ptp_clock) { 1293d339b133SRichard Cochran ptp_clock_unregister(adapter->ptp_clock); 1294d339b133SRichard Cochran dev_info(&adapter->pdev->dev, "removed PHC on %s\n", 1295d339b133SRichard Cochran adapter->netdev->name); 1296462f1188SJacob Keller adapter->ptp_flags &= ~IGB_PTP_ENABLED; 1297d339b133SRichard Cochran } 1298d339b133SRichard Cochran } 12991f6e8178SMatthew Vick 13001f6e8178SMatthew Vick /** 13011f6e8178SMatthew Vick * igb_ptp_reset - Re-enable the adapter for PTP following a reset. 13021f6e8178SMatthew Vick * @adapter: Board private structure. 13031f6e8178SMatthew Vick * 13041f6e8178SMatthew Vick * This function handles the reset work required to re-enable the PTP device. 13051f6e8178SMatthew Vick **/ 13061f6e8178SMatthew Vick void igb_ptp_reset(struct igb_adapter *adapter) 13071f6e8178SMatthew Vick { 13081f6e8178SMatthew Vick struct e1000_hw *hw = &adapter->hw; 13098298c1ecSRichard Cochran unsigned long flags; 13101f6e8178SMatthew Vick 13116ab5f7b2SJacob Keller /* reset the tstamp_config */ 13129f62ecf4SJacob Keller igb_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); 13136ab5f7b2SJacob Keller 13148298c1ecSRichard Cochran spin_lock_irqsave(&adapter->tmreg_lock, flags); 13158298c1ecSRichard Cochran 13161f6e8178SMatthew Vick switch (adapter->hw.mac.type) { 13171f6e8178SMatthew Vick case e1000_82576: 13181f6e8178SMatthew Vick /* Dial the nominal frequency. */ 13191f6e8178SMatthew Vick wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); 13201f6e8178SMatthew Vick break; 13211f6e8178SMatthew Vick case e1000_82580: 1322ceb5f13bSCarolyn Wyborny case e1000_i354: 13231f6e8178SMatthew Vick case e1000_i350: 13241f6e8178SMatthew Vick case e1000_i210: 13251f6e8178SMatthew Vick case e1000_i211: 13261f6e8178SMatthew Vick wr32(E1000_TSAUXC, 0x0); 1327720db4ffSRichard Cochran wr32(E1000_TSSDP, 0x0); 1328ac28b41aSJacob Keller wr32(E1000_TSIM, 1329ac28b41aSJacob Keller TSYNC_INTERRUPTS | 1330ac28b41aSJacob Keller (adapter->pps_sys_wrap_on ? TSINTR_SYS_WRAP : 0)); 13311f6e8178SMatthew Vick wr32(E1000_IMS, E1000_IMS_TS); 13321f6e8178SMatthew Vick break; 13331f6e8178SMatthew Vick default: 13341f6e8178SMatthew Vick /* No work to do. */ 13358298c1ecSRichard Cochran goto out; 13361f6e8178SMatthew Vick } 13371f6e8178SMatthew Vick 1338e57b8bdbSMatthew Vick /* Re-initialize the timer. */ 1339e57b8bdbSMatthew Vick if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { 1340d4c496feSRichard Cochran struct timespec64 ts = ktime_to_timespec64(ktime_get_real()); 1341e57b8bdbSMatthew Vick 13428298c1ecSRichard Cochran igb_ptp_write_i210(adapter, &ts); 1343e57b8bdbSMatthew Vick } else { 13441f6e8178SMatthew Vick timecounter_init(&adapter->tc, &adapter->cc, 13451f6e8178SMatthew Vick ktime_to_ns(ktime_get_real())); 13461f6e8178SMatthew Vick } 13478298c1ecSRichard Cochran out: 13488298c1ecSRichard Cochran spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 13494f3ce71bSJacob Keller 13504f3ce71bSJacob Keller wrfl(); 13514f3ce71bSJacob Keller 13524f3ce71bSJacob Keller if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK) 13534f3ce71bSJacob Keller schedule_delayed_work(&adapter->ptp_overflow_work, 13544f3ce71bSJacob Keller IGB_SYSTIM_OVERFLOW_PERIOD); 1355e57b8bdbSMatthew Vick } 1356