162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "ixgbe.h" 562306a36Sopenharmony_ci#include <linux/ptp_classify.h> 662306a36Sopenharmony_ci#include <linux/clocksource.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * The 82599 and the X540 do not have true 64bit nanosecond scale 1062306a36Sopenharmony_ci * counter registers. Instead, SYSTIME is defined by a fixed point 1162306a36Sopenharmony_ci * system which allows the user to define the scale counter increment 1262306a36Sopenharmony_ci * value at every level change of the oscillator driving the SYSTIME 1362306a36Sopenharmony_ci * value. For both devices the TIMINCA:IV field defines this 1462306a36Sopenharmony_ci * increment. On the X540 device, 31 bits are provided. However on the 1562306a36Sopenharmony_ci * 82599 only provides 24 bits. The time unit is determined by the 1662306a36Sopenharmony_ci * clock frequency of the oscillator in combination with the TIMINCA 1762306a36Sopenharmony_ci * register. When these devices link at 10Gb the oscillator has a 1862306a36Sopenharmony_ci * period of 6.4ns. In order to convert the scale counter into 1962306a36Sopenharmony_ci * nanoseconds the cyclecounter and timecounter structures are 2062306a36Sopenharmony_ci * used. The SYSTIME registers need to be converted to ns values by use 2162306a36Sopenharmony_ci * of only a right shift (division by power of 2). The following math 2262306a36Sopenharmony_ci * determines the largest incvalue that will fit into the available 2362306a36Sopenharmony_ci * bits in the TIMINCA register. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * PeriodWidth: Number of bits to store the clock period 2662306a36Sopenharmony_ci * MaxWidth: The maximum width value of the TIMINCA register 2762306a36Sopenharmony_ci * Period: The clock period for the oscillator 2862306a36Sopenharmony_ci * round(): discard the fractional portion of the calculation 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * Period * [ 2 ^ ( MaxWidth - PeriodWidth ) ] 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * For the X540, MaxWidth is 31 bits, and the base period is 6.4 ns 3362306a36Sopenharmony_ci * For the 82599, MaxWidth is 24 bits, and the base period is 6.4 ns 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * The period also changes based on the link speed: 3662306a36Sopenharmony_ci * At 10Gb link or no link, the period remains the same. 3762306a36Sopenharmony_ci * At 1Gb link, the period is multiplied by 10. (64ns) 3862306a36Sopenharmony_ci * At 100Mb link, the period is multiplied by 100. (640ns) 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * The calculated value allows us to right shift the SYSTIME register 4162306a36Sopenharmony_ci * value in order to quickly convert it into a nanosecond clock, 4262306a36Sopenharmony_ci * while allowing for the maximum possible adjustment value. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * These diagrams are only for the 10Gb link period 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * SYSTIMEH SYSTIMEL 4762306a36Sopenharmony_ci * +--------------+ +--------------+ 4862306a36Sopenharmony_ci * X540 | 32 | | 1 | 3 | 28 | 4962306a36Sopenharmony_ci * *--------------+ +--------------+ 5062306a36Sopenharmony_ci * \________ 36 bits ______/ fract 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * +--------------+ +--------------+ 5362306a36Sopenharmony_ci * 82599 | 32 | | 8 | 3 | 21 | 5462306a36Sopenharmony_ci * *--------------+ +--------------+ 5562306a36Sopenharmony_ci * \________ 43 bits ______/ fract 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * The 36 bit X540 SYSTIME overflows every 5862306a36Sopenharmony_ci * 2^36 * 10^-9 / 60 = 1.14 minutes or 69 seconds 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * The 43 bit 82599 SYSTIME overflows every 6162306a36Sopenharmony_ci * 2^43 * 10^-9 / 3600 = 2.4 hours 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_ci#define IXGBE_INCVAL_10GB 0x66666666 6462306a36Sopenharmony_ci#define IXGBE_INCVAL_1GB 0x40000000 6562306a36Sopenharmony_ci#define IXGBE_INCVAL_100 0x50000000 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define IXGBE_INCVAL_SHIFT_10GB 28 6862306a36Sopenharmony_ci#define IXGBE_INCVAL_SHIFT_1GB 24 6962306a36Sopenharmony_ci#define IXGBE_INCVAL_SHIFT_100 21 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define IXGBE_INCVAL_SHIFT_82599 7 7262306a36Sopenharmony_ci#define IXGBE_INCPER_SHIFT_82599 24 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define IXGBE_OVERFLOW_PERIOD (HZ * 30) 7562306a36Sopenharmony_ci#define IXGBE_PTP_TX_TIMEOUT (HZ) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* We use our own definitions instead of NSEC_PER_SEC because we want to mark 7862306a36Sopenharmony_ci * the value as a ULL to force precision when bit shifting. 7962306a36Sopenharmony_ci */ 8062306a36Sopenharmony_ci#define NS_PER_SEC 1000000000ULL 8162306a36Sopenharmony_ci#define NS_PER_HALF_SEC 500000000ULL 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* In contrast, the X550 controller has two registers, SYSTIMEH and SYSTIMEL 8462306a36Sopenharmony_ci * which contain measurements of seconds and nanoseconds respectively. This 8562306a36Sopenharmony_ci * matches the standard linux representation of time in the kernel. In addition, 8662306a36Sopenharmony_ci * the X550 also has a SYSTIMER register which represents residue, or 8762306a36Sopenharmony_ci * subnanosecond overflow adjustments. To control clock adjustment, the TIMINCA 8862306a36Sopenharmony_ci * register is used, but it is unlike the X540 and 82599 devices. TIMINCA 8962306a36Sopenharmony_ci * represents units of 2^-32 nanoseconds, and uses 31 bits for this, with the 9062306a36Sopenharmony_ci * high bit representing whether the adjustent is positive or negative. Every 9162306a36Sopenharmony_ci * clock cycle, the X550 will add 12.5 ns + TIMINCA which can result in a range 9262306a36Sopenharmony_ci * of 12 to 13 nanoseconds adjustment. Unlike the 82599 and X540 devices, the 9362306a36Sopenharmony_ci * X550's clock for purposes of SYSTIME generation is constant and not dependent 9462306a36Sopenharmony_ci * on the link speed. 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * SYSTIMEH SYSTIMEL SYSTIMER 9762306a36Sopenharmony_ci * +--------------+ +--------------+ +-------------+ 9862306a36Sopenharmony_ci * X550 | 32 | | 32 | | 32 | 9962306a36Sopenharmony_ci * *--------------+ +--------------+ +-------------+ 10062306a36Sopenharmony_ci * \____seconds___/ \_nanoseconds_/ \__2^-32 ns__/ 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * This results in a full 96 bits to represent the clock, with 32 bits for 10362306a36Sopenharmony_ci * seconds, 32 bits for nanoseconds (largest value is 0d999999999 or just under 10462306a36Sopenharmony_ci * 1 second) and an additional 32 bits to measure sub nanosecond adjustments for 10562306a36Sopenharmony_ci * underflow of adjustments. 10662306a36Sopenharmony_ci * 10762306a36Sopenharmony_ci * The 32 bits of seconds for the X550 overflows every 10862306a36Sopenharmony_ci * 2^32 / ( 365.25 * 24 * 60 * 60 ) = ~136 years. 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * In order to adjust the clock frequency for the X550, the TIMINCA register is 11162306a36Sopenharmony_ci * provided. This register represents a + or minus nearly 0.5 ns adjustment to 11262306a36Sopenharmony_ci * the base frequency. It is measured in 2^-32 ns units, with the high bit being 11362306a36Sopenharmony_ci * the sign bit. This register enables software to calculate frequency 11462306a36Sopenharmony_ci * adjustments and apply them directly to the clock rate. 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * The math for converting scaled_ppm into TIMINCA values is fairly 11762306a36Sopenharmony_ci * straightforward. 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci * TIMINCA value = ( Base_Frequency * scaled_ppm ) / 1000000ULL << 16 12062306a36Sopenharmony_ci * 12162306a36Sopenharmony_ci * To avoid overflow, we simply use mul_u64_u64_div_u64. 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * This assumes that scaled_ppm is never high enough to create a value bigger 12462306a36Sopenharmony_ci * than TIMINCA's 31 bits can store. This is ensured by the stack, and is 12562306a36Sopenharmony_ci * measured in parts per billion. Calculating this value is also simple. 12662306a36Sopenharmony_ci * Max ppb = ( Max Adjustment / Base Frequency ) / 1000000000ULL 12762306a36Sopenharmony_ci * 12862306a36Sopenharmony_ci * For the X550, the Max adjustment is +/- 0.5 ns, and the base frequency is 12962306a36Sopenharmony_ci * 12.5 nanoseconds. This means that the Max ppb is 39999999 13062306a36Sopenharmony_ci * Note: We subtract one in order to ensure no overflow, because the TIMINCA 13162306a36Sopenharmony_ci * register can only hold slightly under 0.5 nanoseconds. 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci * Because TIMINCA is measured in 2^-32 ns units, we have to convert 12.5 ns 13462306a36Sopenharmony_ci * into 2^-32 units, which is 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * 12.5 * 2^32 = C80000000 13762306a36Sopenharmony_ci * 13862306a36Sopenharmony_ci * Some revisions of hardware have a faster base frequency than the registers 13962306a36Sopenharmony_ci * were defined for. To fix this, we use a timecounter structure with the 14062306a36Sopenharmony_ci * proper mult and shift to convert the cycles into nanoseconds of time. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci#define IXGBE_X550_BASE_PERIOD 0xC80000000ULL 14362306a36Sopenharmony_ci#define INCVALUE_MASK 0x7FFFFFFF 14462306a36Sopenharmony_ci#define ISGN 0x80000000 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/** 14762306a36Sopenharmony_ci * ixgbe_ptp_setup_sdp_X540 14862306a36Sopenharmony_ci * @adapter: private adapter structure 14962306a36Sopenharmony_ci * 15062306a36Sopenharmony_ci * this function enables or disables the clock out feature on SDP0 for 15162306a36Sopenharmony_ci * the X540 device. It will create a 1 second periodic output that can 15262306a36Sopenharmony_ci * be used as the PPS (via an interrupt). 15362306a36Sopenharmony_ci * 15462306a36Sopenharmony_ci * It calculates when the system time will be on an exact second, and then 15562306a36Sopenharmony_ci * aligns the start of the PPS signal to that value. 15662306a36Sopenharmony_ci * 15762306a36Sopenharmony_ci * This works by using the cycle counter shift and mult values in reverse, and 15862306a36Sopenharmony_ci * assumes that the values we're shifting will not overflow. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_cistatic void ixgbe_ptp_setup_sdp_X540(struct ixgbe_adapter *adapter) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci struct cyclecounter *cc = &adapter->hw_cc; 16362306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 16462306a36Sopenharmony_ci u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem; 16562306a36Sopenharmony_ci u64 ns = 0, clock_edge = 0, clock_period; 16662306a36Sopenharmony_ci unsigned long flags; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* disable the pin first */ 16962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); 17062306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci if (!(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED)) 17362306a36Sopenharmony_ci return; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* enable the SDP0 pin as output, and connected to the 17862306a36Sopenharmony_ci * native function for Timesync (ClockOut) 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci esdp |= IXGBE_ESDP_SDP0_DIR | 18162306a36Sopenharmony_ci IXGBE_ESDP_SDP0_NATIVE; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* enable the Clock Out feature on SDP0, and allow 18462306a36Sopenharmony_ci * interrupts to occur when the pin changes 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci tsauxc = (IXGBE_TSAUXC_EN_CLK | 18762306a36Sopenharmony_ci IXGBE_TSAUXC_SYNCLK | 18862306a36Sopenharmony_ci IXGBE_TSAUXC_SDP0_INT); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* Determine the clock time period to use. This assumes that the 19162306a36Sopenharmony_ci * cycle counter shift is small enough to avoid overflow. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ci clock_period = div_u64((NS_PER_HALF_SEC << cc->shift), cc->mult); 19462306a36Sopenharmony_ci clktiml = (u32)(clock_period); 19562306a36Sopenharmony_ci clktimh = (u32)(clock_period >> 32); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* Read the current clock time, and save the cycle counter value */ 19862306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 19962306a36Sopenharmony_ci ns = timecounter_read(&adapter->hw_tc); 20062306a36Sopenharmony_ci clock_edge = adapter->hw_tc.cycle_last; 20162306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Figure out how many seconds to add in order to round up */ 20462306a36Sopenharmony_ci div_u64_rem(ns, NS_PER_SEC, &rem); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* Figure out how many nanoseconds to add to round the clock edge up 20762306a36Sopenharmony_ci * to the next full second 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_ci rem = (NS_PER_SEC - rem); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* Adjust the clock edge to align with the next full second. */ 21262306a36Sopenharmony_ci clock_edge += div_u64(((u64)rem << cc->shift), cc->mult); 21362306a36Sopenharmony_ci trgttiml = (u32)clock_edge; 21462306a36Sopenharmony_ci trgttimh = (u32)(clock_edge >> 32); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CLKTIML, clktiml); 21762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_CLKTIMH, clktimh); 21862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml); 21962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 22262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/** 22862306a36Sopenharmony_ci * ixgbe_ptp_setup_sdp_X550 22962306a36Sopenharmony_ci * @adapter: private adapter structure 23062306a36Sopenharmony_ci * 23162306a36Sopenharmony_ci * Enable or disable a clock output signal on SDP 0 for X550 hardware. 23262306a36Sopenharmony_ci * 23362306a36Sopenharmony_ci * Use the target time feature to align the output signal on the next full 23462306a36Sopenharmony_ci * second. 23562306a36Sopenharmony_ci * 23662306a36Sopenharmony_ci * This works by using the cycle counter shift and mult values in reverse, and 23762306a36Sopenharmony_ci * assumes that the values we're shifting will not overflow. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_cistatic void ixgbe_ptp_setup_sdp_X550(struct ixgbe_adapter *adapter) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci u32 esdp, tsauxc, freqout, trgttiml, trgttimh, rem, tssdp; 24262306a36Sopenharmony_ci struct cyclecounter *cc = &adapter->hw_cc; 24362306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 24462306a36Sopenharmony_ci u64 ns = 0, clock_edge = 0; 24562306a36Sopenharmony_ci struct timespec64 ts; 24662306a36Sopenharmony_ci unsigned long flags; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* disable the pin first */ 24962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); 25062306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (!(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED)) 25362306a36Sopenharmony_ci return; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* enable the SDP0 pin as output, and connected to the 25862306a36Sopenharmony_ci * native function for Timesync (ClockOut) 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci esdp |= IXGBE_ESDP_SDP0_DIR | 26162306a36Sopenharmony_ci IXGBE_ESDP_SDP0_NATIVE; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* enable the Clock Out feature on SDP0, and use Target Time 0 to 26462306a36Sopenharmony_ci * enable generation of interrupts on the clock change. 26562306a36Sopenharmony_ci */ 26662306a36Sopenharmony_ci#define IXGBE_TSAUXC_DIS_TS_CLEAR 0x40000000 26762306a36Sopenharmony_ci tsauxc = (IXGBE_TSAUXC_EN_CLK | IXGBE_TSAUXC_ST0 | 26862306a36Sopenharmony_ci IXGBE_TSAUXC_EN_TT0 | IXGBE_TSAUXC_SDP0_INT | 26962306a36Sopenharmony_ci IXGBE_TSAUXC_DIS_TS_CLEAR); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci tssdp = (IXGBE_TSSDP_TS_SDP0_EN | 27262306a36Sopenharmony_ci IXGBE_TSSDP_TS_SDP0_CLK0); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* Determine the clock time period to use. This assumes that the 27562306a36Sopenharmony_ci * cycle counter shift is small enough to avoid overflowing a 32bit 27662306a36Sopenharmony_ci * value. 27762306a36Sopenharmony_ci */ 27862306a36Sopenharmony_ci freqout = div_u64(NS_PER_HALF_SEC << cc->shift, cc->mult); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* Read the current clock time, and save the cycle counter value */ 28162306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 28262306a36Sopenharmony_ci ns = timecounter_read(&adapter->hw_tc); 28362306a36Sopenharmony_ci clock_edge = adapter->hw_tc.cycle_last; 28462306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* Figure out how far past the next second we are */ 28762306a36Sopenharmony_ci div_u64_rem(ns, NS_PER_SEC, &rem); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* Figure out how many nanoseconds to add to round the clock edge up 29062306a36Sopenharmony_ci * to the next full second 29162306a36Sopenharmony_ci */ 29262306a36Sopenharmony_ci rem = (NS_PER_SEC - rem); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* Adjust the clock edge to align with the next full second. */ 29562306a36Sopenharmony_ci clock_edge += div_u64(((u64)rem << cc->shift), cc->mult); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* X550 hardware stores the time in 32bits of 'billions of cycles' and 29862306a36Sopenharmony_ci * 32bits of 'cycles'. There's no guarantee that cycles represents 29962306a36Sopenharmony_ci * nanoseconds. However, we can use the math from a timespec64 to 30062306a36Sopenharmony_ci * convert into the hardware representation. 30162306a36Sopenharmony_ci * 30262306a36Sopenharmony_ci * See ixgbe_ptp_read_X550() for more details. 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci ts = ns_to_timespec64(clock_edge); 30562306a36Sopenharmony_ci trgttiml = (u32)ts.tv_nsec; 30662306a36Sopenharmony_ci trgttimh = (u32)ts.tv_sec; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FREQOUT0, freqout); 30962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml); 31062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 31362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSSDP, tssdp); 31462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/** 32062306a36Sopenharmony_ci * ixgbe_ptp_read_X550 - read cycle counter value 32162306a36Sopenharmony_ci * @cc: cyclecounter structure 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * This function reads SYSTIME registers. It is called by the cyclecounter 32462306a36Sopenharmony_ci * structure to convert from internal representation into nanoseconds. We need 32562306a36Sopenharmony_ci * this for X550 since some skews do not have expected clock frequency and 32662306a36Sopenharmony_ci * result of SYSTIME is 32bits of "billions of cycles" and 32 bits of 32762306a36Sopenharmony_ci * "cycles", rather than seconds and nanoseconds. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_cistatic u64 ixgbe_ptp_read_X550(const struct cyclecounter *cc) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 33262306a36Sopenharmony_ci container_of(cc, struct ixgbe_adapter, hw_cc); 33362306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 33462306a36Sopenharmony_ci struct timespec64 ts; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* storage is 32 bits of 'billions of cycles' and 32 bits of 'cycles'. 33762306a36Sopenharmony_ci * Some revisions of hardware run at a higher frequency and so the 33862306a36Sopenharmony_ci * cycles are not guaranteed to be nanoseconds. The timespec64 created 33962306a36Sopenharmony_ci * here is used for its math/conversions but does not necessarily 34062306a36Sopenharmony_ci * represent nominal time. 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci * It should be noted that this cyclecounter will overflow at a 34362306a36Sopenharmony_ci * non-bitmask field since we have to convert our billions of cycles 34462306a36Sopenharmony_ci * into an actual cycles count. This results in some possible weird 34562306a36Sopenharmony_ci * situations at high cycle counter stamps. However given that 32 bits 34662306a36Sopenharmony_ci * of "seconds" is ~138 years this isn't a problem. Even at the 34762306a36Sopenharmony_ci * increased frequency of some revisions, this is still ~103 years. 34862306a36Sopenharmony_ci * Since the SYSTIME values start at 0 and we never write them, it is 34962306a36Sopenharmony_ci * highly unlikely for the cyclecounter to overflow in practice. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_SYSTIMR); 35262306a36Sopenharmony_ci ts.tv_nsec = IXGBE_READ_REG(hw, IXGBE_SYSTIML); 35362306a36Sopenharmony_ci ts.tv_sec = IXGBE_READ_REG(hw, IXGBE_SYSTIMH); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci return (u64)timespec64_to_ns(&ts); 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci/** 35962306a36Sopenharmony_ci * ixgbe_ptp_read_82599 - read raw cycle counter (to be used by time counter) 36062306a36Sopenharmony_ci * @cc: the cyclecounter structure 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * this function reads the cyclecounter registers and is called by the 36362306a36Sopenharmony_ci * cyclecounter structure used to construct a ns counter from the 36462306a36Sopenharmony_ci * arbitrary fixed point registers 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_cistatic u64 ixgbe_ptp_read_82599(const struct cyclecounter *cc) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 36962306a36Sopenharmony_ci container_of(cc, struct ixgbe_adapter, hw_cc); 37062306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 37162306a36Sopenharmony_ci u64 stamp = 0; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML); 37462306a36Sopenharmony_ci stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci return stamp; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci/** 38062306a36Sopenharmony_ci * ixgbe_ptp_convert_to_hwtstamp - convert register value to hw timestamp 38162306a36Sopenharmony_ci * @adapter: private adapter structure 38262306a36Sopenharmony_ci * @hwtstamp: stack timestamp structure 38362306a36Sopenharmony_ci * @timestamp: unsigned 64bit system time value 38462306a36Sopenharmony_ci * 38562306a36Sopenharmony_ci * We need to convert the adapter's RX/TXSTMP registers into a hwtstamp value 38662306a36Sopenharmony_ci * which can be used by the stack's ptp functions. 38762306a36Sopenharmony_ci * 38862306a36Sopenharmony_ci * The lock is used to protect consistency of the cyclecounter and the SYSTIME 38962306a36Sopenharmony_ci * registers. However, it does not need to protect against the Rx or Tx 39062306a36Sopenharmony_ci * timestamp registers, as there can't be a new timestamp until the old one is 39162306a36Sopenharmony_ci * unlatched by reading. 39262306a36Sopenharmony_ci * 39362306a36Sopenharmony_ci * In addition to the timestamp in hardware, some controllers need a software 39462306a36Sopenharmony_ci * overflow cyclecounter, and this function takes this into account as well. 39562306a36Sopenharmony_ci **/ 39662306a36Sopenharmony_cistatic void ixgbe_ptp_convert_to_hwtstamp(struct ixgbe_adapter *adapter, 39762306a36Sopenharmony_ci struct skb_shared_hwtstamps *hwtstamp, 39862306a36Sopenharmony_ci u64 timestamp) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci unsigned long flags; 40162306a36Sopenharmony_ci struct timespec64 systime; 40262306a36Sopenharmony_ci u64 ns; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci memset(hwtstamp, 0, sizeof(*hwtstamp)); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci switch (adapter->hw.mac.type) { 40762306a36Sopenharmony_ci /* X550 and later hardware supposedly represent time using a seconds 40862306a36Sopenharmony_ci * and nanoseconds counter, instead of raw 64bits nanoseconds. We need 40962306a36Sopenharmony_ci * to convert the timestamp into cycles before it can be fed to the 41062306a36Sopenharmony_ci * cyclecounter. We need an actual cyclecounter because some revisions 41162306a36Sopenharmony_ci * of hardware run at a higher frequency and thus the counter does 41262306a36Sopenharmony_ci * not represent seconds/nanoseconds. Instead it can be thought of as 41362306a36Sopenharmony_ci * cycles and billions of cycles. 41462306a36Sopenharmony_ci */ 41562306a36Sopenharmony_ci case ixgbe_mac_X550: 41662306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 41762306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 41862306a36Sopenharmony_ci /* Upper 32 bits represent billions of cycles, lower 32 bits 41962306a36Sopenharmony_ci * represent cycles. However, we use timespec64_to_ns for the 42062306a36Sopenharmony_ci * correct math even though the units haven't been corrected 42162306a36Sopenharmony_ci * yet. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_ci systime.tv_sec = timestamp >> 32; 42462306a36Sopenharmony_ci systime.tv_nsec = timestamp & 0xFFFFFFFF; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci timestamp = timespec64_to_ns(&systime); 42762306a36Sopenharmony_ci break; 42862306a36Sopenharmony_ci default: 42962306a36Sopenharmony_ci break; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 43362306a36Sopenharmony_ci ns = timecounter_cyc2time(&adapter->hw_tc, timestamp); 43462306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci hwtstamp->hwtstamp = ns_to_ktime(ns); 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/** 44062306a36Sopenharmony_ci * ixgbe_ptp_adjfine_82599 44162306a36Sopenharmony_ci * @ptp: the ptp clock structure 44262306a36Sopenharmony_ci * @scaled_ppm: scaled parts per million adjustment from base 44362306a36Sopenharmony_ci * 44462306a36Sopenharmony_ci * Adjust the frequency of the ptp cycle counter by the 44562306a36Sopenharmony_ci * indicated scaled_ppm from the base frequency. 44662306a36Sopenharmony_ci * 44762306a36Sopenharmony_ci * Scaled parts per million is ppm with a 16-bit binary fractional field. 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_cistatic int ixgbe_ptp_adjfine_82599(struct ptp_clock_info *ptp, long scaled_ppm) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 45262306a36Sopenharmony_ci container_of(ptp, struct ixgbe_adapter, ptp_caps); 45362306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 45462306a36Sopenharmony_ci u64 incval; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci smp_mb(); 45762306a36Sopenharmony_ci incval = READ_ONCE(adapter->base_incval); 45862306a36Sopenharmony_ci incval = adjust_by_scaled_ppm(incval, scaled_ppm); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci switch (hw->mac.type) { 46162306a36Sopenharmony_ci case ixgbe_mac_X540: 46262306a36Sopenharmony_ci if (incval > 0xFFFFFFFFULL) 46362306a36Sopenharmony_ci e_dev_warn("PTP scaled_ppm adjusted SYSTIME rate overflowed!\n"); 46462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, (u32)incval); 46562306a36Sopenharmony_ci break; 46662306a36Sopenharmony_ci case ixgbe_mac_82599EB: 46762306a36Sopenharmony_ci if (incval > 0x00FFFFFFULL) 46862306a36Sopenharmony_ci e_dev_warn("PTP scaled_ppm adjusted SYSTIME rate overflowed!\n"); 46962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, 47062306a36Sopenharmony_ci BIT(IXGBE_INCPER_SHIFT_82599) | 47162306a36Sopenharmony_ci ((u32)incval & 0x00FFFFFFUL)); 47262306a36Sopenharmony_ci break; 47362306a36Sopenharmony_ci default: 47462306a36Sopenharmony_ci break; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci return 0; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci/** 48162306a36Sopenharmony_ci * ixgbe_ptp_adjfine_X550 48262306a36Sopenharmony_ci * @ptp: the ptp clock structure 48362306a36Sopenharmony_ci * @scaled_ppm: scaled parts per million adjustment from base 48462306a36Sopenharmony_ci * 48562306a36Sopenharmony_ci * Adjust the frequency of the SYSTIME registers by the indicated scaled_ppm 48662306a36Sopenharmony_ci * from base frequency. 48762306a36Sopenharmony_ci * 48862306a36Sopenharmony_ci * Scaled parts per million is ppm with a 16-bit binary fractional field. 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_cistatic int ixgbe_ptp_adjfine_X550(struct ptp_clock_info *ptp, long scaled_ppm) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 49362306a36Sopenharmony_ci container_of(ptp, struct ixgbe_adapter, ptp_caps); 49462306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 49562306a36Sopenharmony_ci bool neg_adj; 49662306a36Sopenharmony_ci u64 rate; 49762306a36Sopenharmony_ci u32 inca; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci neg_adj = diff_by_scaled_ppm(IXGBE_X550_BASE_PERIOD, scaled_ppm, &rate); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* warn if rate is too large */ 50262306a36Sopenharmony_ci if (rate >= INCVALUE_MASK) 50362306a36Sopenharmony_ci e_dev_warn("PTP scaled_ppm adjusted SYSTIME rate overflowed!\n"); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci inca = rate & INCVALUE_MASK; 50662306a36Sopenharmony_ci if (neg_adj) 50762306a36Sopenharmony_ci inca |= ISGN; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, inca); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci return 0; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci/** 51562306a36Sopenharmony_ci * ixgbe_ptp_adjtime 51662306a36Sopenharmony_ci * @ptp: the ptp clock structure 51762306a36Sopenharmony_ci * @delta: offset to adjust the cycle counter by 51862306a36Sopenharmony_ci * 51962306a36Sopenharmony_ci * adjust the timer by resetting the timecounter structure. 52062306a36Sopenharmony_ci */ 52162306a36Sopenharmony_cistatic int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 52462306a36Sopenharmony_ci container_of(ptp, struct ixgbe_adapter, ptp_caps); 52562306a36Sopenharmony_ci unsigned long flags; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 52862306a36Sopenharmony_ci timecounter_adjtime(&adapter->hw_tc, delta); 52962306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci if (adapter->ptp_setup_sdp) 53262306a36Sopenharmony_ci adapter->ptp_setup_sdp(adapter); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci return 0; 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/** 53862306a36Sopenharmony_ci * ixgbe_ptp_gettimex 53962306a36Sopenharmony_ci * @ptp: the ptp clock structure 54062306a36Sopenharmony_ci * @ts: timespec to hold the PHC timestamp 54162306a36Sopenharmony_ci * @sts: structure to hold the system time before and after reading the PHC 54262306a36Sopenharmony_ci * 54362306a36Sopenharmony_ci * read the timecounter and return the correct value on ns, 54462306a36Sopenharmony_ci * after converting it into a struct timespec. 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_cistatic int ixgbe_ptp_gettimex(struct ptp_clock_info *ptp, 54762306a36Sopenharmony_ci struct timespec64 *ts, 54862306a36Sopenharmony_ci struct ptp_system_timestamp *sts) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 55162306a36Sopenharmony_ci container_of(ptp, struct ixgbe_adapter, ptp_caps); 55262306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 55362306a36Sopenharmony_ci unsigned long flags; 55462306a36Sopenharmony_ci u64 ns, stamp; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci switch (adapter->hw.mac.type) { 55962306a36Sopenharmony_ci case ixgbe_mac_X550: 56062306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 56162306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 56262306a36Sopenharmony_ci /* Upper 32 bits represent billions of cycles, lower 32 bits 56362306a36Sopenharmony_ci * represent cycles. However, we use timespec64_to_ns for the 56462306a36Sopenharmony_ci * correct math even though the units haven't been corrected 56562306a36Sopenharmony_ci * yet. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci ptp_read_system_prets(sts); 56862306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_SYSTIMR); 56962306a36Sopenharmony_ci ptp_read_system_postts(sts); 57062306a36Sopenharmony_ci ts->tv_nsec = IXGBE_READ_REG(hw, IXGBE_SYSTIML); 57162306a36Sopenharmony_ci ts->tv_sec = IXGBE_READ_REG(hw, IXGBE_SYSTIMH); 57262306a36Sopenharmony_ci stamp = timespec64_to_ns(ts); 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci default: 57562306a36Sopenharmony_ci ptp_read_system_prets(sts); 57662306a36Sopenharmony_ci stamp = IXGBE_READ_REG(hw, IXGBE_SYSTIML); 57762306a36Sopenharmony_ci ptp_read_system_postts(sts); 57862306a36Sopenharmony_ci stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; 57962306a36Sopenharmony_ci break; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci ns = timecounter_cyc2time(&adapter->hw_tc, stamp); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci *ts = ns_to_timespec64(ns); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci return 0; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci/** 59262306a36Sopenharmony_ci * ixgbe_ptp_settime 59362306a36Sopenharmony_ci * @ptp: the ptp clock structure 59462306a36Sopenharmony_ci * @ts: the timespec containing the new time for the cycle counter 59562306a36Sopenharmony_ci * 59662306a36Sopenharmony_ci * reset the timecounter to use a new base value instead of the kernel 59762306a36Sopenharmony_ci * wall timer value. 59862306a36Sopenharmony_ci */ 59962306a36Sopenharmony_cistatic int ixgbe_ptp_settime(struct ptp_clock_info *ptp, 60062306a36Sopenharmony_ci const struct timespec64 *ts) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 60362306a36Sopenharmony_ci container_of(ptp, struct ixgbe_adapter, ptp_caps); 60462306a36Sopenharmony_ci unsigned long flags; 60562306a36Sopenharmony_ci u64 ns = timespec64_to_ns(ts); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* reset the timecounter */ 60862306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 60962306a36Sopenharmony_ci timecounter_init(&adapter->hw_tc, &adapter->hw_cc, ns); 61062306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci if (adapter->ptp_setup_sdp) 61362306a36Sopenharmony_ci adapter->ptp_setup_sdp(adapter); 61462306a36Sopenharmony_ci return 0; 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci/** 61862306a36Sopenharmony_ci * ixgbe_ptp_feature_enable 61962306a36Sopenharmony_ci * @ptp: the ptp clock structure 62062306a36Sopenharmony_ci * @rq: the requested feature to change 62162306a36Sopenharmony_ci * @on: whether to enable or disable the feature 62262306a36Sopenharmony_ci * 62362306a36Sopenharmony_ci * enable (or disable) ancillary features of the phc subsystem. 62462306a36Sopenharmony_ci * our driver only supports the PPS feature on the X540 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_cistatic int ixgbe_ptp_feature_enable(struct ptp_clock_info *ptp, 62762306a36Sopenharmony_ci struct ptp_clock_request *rq, int on) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci struct ixgbe_adapter *adapter = 63062306a36Sopenharmony_ci container_of(ptp, struct ixgbe_adapter, ptp_caps); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci /** 63362306a36Sopenharmony_ci * When PPS is enabled, unmask the interrupt for the ClockOut 63462306a36Sopenharmony_ci * feature, so that the interrupt handler can send the PPS 63562306a36Sopenharmony_ci * event when the clock SDP triggers. Clear mask when PPS is 63662306a36Sopenharmony_ci * disabled 63762306a36Sopenharmony_ci */ 63862306a36Sopenharmony_ci if (rq->type != PTP_CLK_REQ_PPS || !adapter->ptp_setup_sdp) 63962306a36Sopenharmony_ci return -ENOTSUPP; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci if (on) 64262306a36Sopenharmony_ci adapter->flags2 |= IXGBE_FLAG2_PTP_PPS_ENABLED; 64362306a36Sopenharmony_ci else 64462306a36Sopenharmony_ci adapter->flags2 &= ~IXGBE_FLAG2_PTP_PPS_ENABLED; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci adapter->ptp_setup_sdp(adapter); 64762306a36Sopenharmony_ci return 0; 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci/** 65162306a36Sopenharmony_ci * ixgbe_ptp_check_pps_event 65262306a36Sopenharmony_ci * @adapter: the private adapter structure 65362306a36Sopenharmony_ci * 65462306a36Sopenharmony_ci * This function is called by the interrupt routine when checking for 65562306a36Sopenharmony_ci * interrupts. It will check and handle a pps event. 65662306a36Sopenharmony_ci */ 65762306a36Sopenharmony_civoid ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 66062306a36Sopenharmony_ci struct ptp_clock_event event; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci event.type = PTP_CLOCK_PPS; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /* this check is necessary in case the interrupt was enabled via some 66562306a36Sopenharmony_ci * alternative means (ex. debug_fs). Better to check here than 66662306a36Sopenharmony_ci * everywhere that calls this function. 66762306a36Sopenharmony_ci */ 66862306a36Sopenharmony_ci if (!adapter->ptp_clock) 66962306a36Sopenharmony_ci return; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci switch (hw->mac.type) { 67262306a36Sopenharmony_ci case ixgbe_mac_X540: 67362306a36Sopenharmony_ci ptp_clock_event(adapter->ptp_clock, &event); 67462306a36Sopenharmony_ci break; 67562306a36Sopenharmony_ci default: 67662306a36Sopenharmony_ci break; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci/** 68162306a36Sopenharmony_ci * ixgbe_ptp_overflow_check - watchdog task to detect SYSTIME overflow 68262306a36Sopenharmony_ci * @adapter: private adapter struct 68362306a36Sopenharmony_ci * 68462306a36Sopenharmony_ci * this watchdog task periodically reads the timecounter 68562306a36Sopenharmony_ci * in order to prevent missing when the system time registers wrap 68662306a36Sopenharmony_ci * around. This needs to be run approximately twice a minute. 68762306a36Sopenharmony_ci */ 68862306a36Sopenharmony_civoid ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci bool timeout = time_is_before_jiffies(adapter->last_overflow_check + 69162306a36Sopenharmony_ci IXGBE_OVERFLOW_PERIOD); 69262306a36Sopenharmony_ci unsigned long flags; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (timeout) { 69562306a36Sopenharmony_ci /* Update the timecounter */ 69662306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 69762306a36Sopenharmony_ci timecounter_read(&adapter->hw_tc); 69862306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci adapter->last_overflow_check = jiffies; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci} 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci/** 70562306a36Sopenharmony_ci * ixgbe_ptp_rx_hang - detect error case when Rx timestamp registers latched 70662306a36Sopenharmony_ci * @adapter: private network adapter structure 70762306a36Sopenharmony_ci * 70862306a36Sopenharmony_ci * this watchdog task is scheduled to detect error case where hardware has 70962306a36Sopenharmony_ci * dropped an Rx packet that was timestamped when the ring is full. The 71062306a36Sopenharmony_ci * particular error is rare but leaves the device in a state unable to timestamp 71162306a36Sopenharmony_ci * any future packets. 71262306a36Sopenharmony_ci */ 71362306a36Sopenharmony_civoid ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 71662306a36Sopenharmony_ci u32 tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); 71762306a36Sopenharmony_ci struct ixgbe_ring *rx_ring; 71862306a36Sopenharmony_ci unsigned long rx_event; 71962306a36Sopenharmony_ci int n; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci /* if we don't have a valid timestamp in the registers, just update the 72262306a36Sopenharmony_ci * timeout counter and exit 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ci if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) { 72562306a36Sopenharmony_ci adapter->last_rx_ptp_check = jiffies; 72662306a36Sopenharmony_ci return; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* determine the most recent watchdog or rx_timestamp event */ 73062306a36Sopenharmony_ci rx_event = adapter->last_rx_ptp_check; 73162306a36Sopenharmony_ci for (n = 0; n < adapter->num_rx_queues; n++) { 73262306a36Sopenharmony_ci rx_ring = adapter->rx_ring[n]; 73362306a36Sopenharmony_ci if (time_after(rx_ring->last_rx_timestamp, rx_event)) 73462306a36Sopenharmony_ci rx_event = rx_ring->last_rx_timestamp; 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci /* only need to read the high RXSTMP register to clear the lock */ 73862306a36Sopenharmony_ci if (time_is_before_jiffies(rx_event + 5 * HZ)) { 73962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RXSTMPH); 74062306a36Sopenharmony_ci adapter->last_rx_ptp_check = jiffies; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci adapter->rx_hwtstamp_cleared++; 74362306a36Sopenharmony_ci e_warn(drv, "clearing RX Timestamp hang\n"); 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci/** 74862306a36Sopenharmony_ci * ixgbe_ptp_clear_tx_timestamp - utility function to clear Tx timestamp state 74962306a36Sopenharmony_ci * @adapter: the private adapter structure 75062306a36Sopenharmony_ci * 75162306a36Sopenharmony_ci * This function should be called whenever the state related to a Tx timestamp 75262306a36Sopenharmony_ci * needs to be cleared. This helps ensure that all related bits are reset for 75362306a36Sopenharmony_ci * the next Tx timestamp event. 75462306a36Sopenharmony_ci */ 75562306a36Sopenharmony_cistatic void ixgbe_ptp_clear_tx_timestamp(struct ixgbe_adapter *adapter) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TXSTMPH); 76062306a36Sopenharmony_ci if (adapter->ptp_tx_skb) { 76162306a36Sopenharmony_ci dev_kfree_skb_any(adapter->ptp_tx_skb); 76262306a36Sopenharmony_ci adapter->ptp_tx_skb = NULL; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci clear_bit_unlock(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state); 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci/** 76862306a36Sopenharmony_ci * ixgbe_ptp_tx_hang - detect error case where Tx timestamp never finishes 76962306a36Sopenharmony_ci * @adapter: private network adapter structure 77062306a36Sopenharmony_ci */ 77162306a36Sopenharmony_civoid ixgbe_ptp_tx_hang(struct ixgbe_adapter *adapter) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci bool timeout = time_is_before_jiffies(adapter->ptp_tx_start + 77462306a36Sopenharmony_ci IXGBE_PTP_TX_TIMEOUT); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci if (!adapter->ptp_tx_skb) 77762306a36Sopenharmony_ci return; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci if (!test_bit(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state)) 78062306a36Sopenharmony_ci return; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci /* If we haven't received a timestamp within the timeout, it is 78362306a36Sopenharmony_ci * reasonable to assume that it will never occur, so we can unlock the 78462306a36Sopenharmony_ci * timestamp bit when this occurs. 78562306a36Sopenharmony_ci */ 78662306a36Sopenharmony_ci if (timeout) { 78762306a36Sopenharmony_ci cancel_work_sync(&adapter->ptp_tx_work); 78862306a36Sopenharmony_ci ixgbe_ptp_clear_tx_timestamp(adapter); 78962306a36Sopenharmony_ci adapter->tx_hwtstamp_timeouts++; 79062306a36Sopenharmony_ci e_warn(drv, "clearing Tx timestamp hang\n"); 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci/** 79562306a36Sopenharmony_ci * ixgbe_ptp_tx_hwtstamp - utility function which checks for TX time stamp 79662306a36Sopenharmony_ci * @adapter: the private adapter struct 79762306a36Sopenharmony_ci * 79862306a36Sopenharmony_ci * if the timestamp is valid, we convert it into the timecounter ns 79962306a36Sopenharmony_ci * value, then store that result into the shhwtstamps structure which 80062306a36Sopenharmony_ci * is passed up the network stack 80162306a36Sopenharmony_ci */ 80262306a36Sopenharmony_cistatic void ixgbe_ptp_tx_hwtstamp(struct ixgbe_adapter *adapter) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci struct sk_buff *skb = adapter->ptp_tx_skb; 80562306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 80662306a36Sopenharmony_ci struct skb_shared_hwtstamps shhwtstamps; 80762306a36Sopenharmony_ci u64 regval = 0; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPL); 81062306a36Sopenharmony_ci regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPH) << 32; 81162306a36Sopenharmony_ci ixgbe_ptp_convert_to_hwtstamp(adapter, &shhwtstamps, regval); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* Handle cleanup of the ptp_tx_skb ourselves, and unlock the state 81462306a36Sopenharmony_ci * bit prior to notifying the stack via skb_tstamp_tx(). This prevents 81562306a36Sopenharmony_ci * well behaved applications from attempting to timestamp again prior 81662306a36Sopenharmony_ci * to the lock bit being clear. 81762306a36Sopenharmony_ci */ 81862306a36Sopenharmony_ci adapter->ptp_tx_skb = NULL; 81962306a36Sopenharmony_ci clear_bit_unlock(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci /* Notify the stack and then free the skb after we've unlocked */ 82262306a36Sopenharmony_ci skb_tstamp_tx(skb, &shhwtstamps); 82362306a36Sopenharmony_ci dev_kfree_skb_any(skb); 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci/** 82762306a36Sopenharmony_ci * ixgbe_ptp_tx_hwtstamp_work 82862306a36Sopenharmony_ci * @work: pointer to the work struct 82962306a36Sopenharmony_ci * 83062306a36Sopenharmony_ci * This work item polls TSYNCTXCTL valid bit to determine when a Tx hardware 83162306a36Sopenharmony_ci * timestamp has been taken for the current skb. It is necessary, because the 83262306a36Sopenharmony_ci * descriptor's "done" bit does not correlate with the timestamp event. 83362306a36Sopenharmony_ci */ 83462306a36Sopenharmony_cistatic void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work) 83562306a36Sopenharmony_ci{ 83662306a36Sopenharmony_ci struct ixgbe_adapter *adapter = container_of(work, struct ixgbe_adapter, 83762306a36Sopenharmony_ci ptp_tx_work); 83862306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 83962306a36Sopenharmony_ci bool timeout = time_is_before_jiffies(adapter->ptp_tx_start + 84062306a36Sopenharmony_ci IXGBE_PTP_TX_TIMEOUT); 84162306a36Sopenharmony_ci u32 tsynctxctl; 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci /* we have to have a valid skb to poll for a timestamp */ 84462306a36Sopenharmony_ci if (!adapter->ptp_tx_skb) { 84562306a36Sopenharmony_ci ixgbe_ptp_clear_tx_timestamp(adapter); 84662306a36Sopenharmony_ci return; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci /* stop polling once we have a valid timestamp */ 85062306a36Sopenharmony_ci tsynctxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); 85162306a36Sopenharmony_ci if (tsynctxctl & IXGBE_TSYNCTXCTL_VALID) { 85262306a36Sopenharmony_ci ixgbe_ptp_tx_hwtstamp(adapter); 85362306a36Sopenharmony_ci return; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci if (timeout) { 85762306a36Sopenharmony_ci ixgbe_ptp_clear_tx_timestamp(adapter); 85862306a36Sopenharmony_ci adapter->tx_hwtstamp_timeouts++; 85962306a36Sopenharmony_ci e_warn(drv, "clearing Tx Timestamp hang\n"); 86062306a36Sopenharmony_ci } else { 86162306a36Sopenharmony_ci /* reschedule to keep checking if it's not available yet */ 86262306a36Sopenharmony_ci schedule_work(&adapter->ptp_tx_work); 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci} 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci/** 86762306a36Sopenharmony_ci * ixgbe_ptp_rx_pktstamp - utility function to get RX time stamp from buffer 86862306a36Sopenharmony_ci * @q_vector: structure containing interrupt and ring information 86962306a36Sopenharmony_ci * @skb: the packet 87062306a36Sopenharmony_ci * 87162306a36Sopenharmony_ci * This function will be called by the Rx routine of the timestamp for this 87262306a36Sopenharmony_ci * packet is stored in the buffer. The value is stored in little endian format 87362306a36Sopenharmony_ci * starting at the end of the packet data. 87462306a36Sopenharmony_ci */ 87562306a36Sopenharmony_civoid ixgbe_ptp_rx_pktstamp(struct ixgbe_q_vector *q_vector, 87662306a36Sopenharmony_ci struct sk_buff *skb) 87762306a36Sopenharmony_ci{ 87862306a36Sopenharmony_ci __le64 regval; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci /* copy the bits out of the skb, and then trim the skb length */ 88162306a36Sopenharmony_ci skb_copy_bits(skb, skb->len - IXGBE_TS_HDR_LEN, ®val, 88262306a36Sopenharmony_ci IXGBE_TS_HDR_LEN); 88362306a36Sopenharmony_ci __pskb_trim(skb, skb->len - IXGBE_TS_HDR_LEN); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci /* The timestamp is recorded in little endian format, and is stored at 88662306a36Sopenharmony_ci * the end of the packet. 88762306a36Sopenharmony_ci * 88862306a36Sopenharmony_ci * DWORD: N N + 1 N + 2 88962306a36Sopenharmony_ci * Field: End of Packet SYSTIMH SYSTIML 89062306a36Sopenharmony_ci */ 89162306a36Sopenharmony_ci ixgbe_ptp_convert_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb), 89262306a36Sopenharmony_ci le64_to_cpu(regval)); 89362306a36Sopenharmony_ci} 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci/** 89662306a36Sopenharmony_ci * ixgbe_ptp_rx_rgtstamp - utility function which checks for RX time stamp 89762306a36Sopenharmony_ci * @q_vector: structure containing interrupt and ring information 89862306a36Sopenharmony_ci * @skb: particular skb to send timestamp with 89962306a36Sopenharmony_ci * 90062306a36Sopenharmony_ci * if the timestamp is valid, we convert it into the timecounter ns 90162306a36Sopenharmony_ci * value, then store that result into the shhwtstamps structure which 90262306a36Sopenharmony_ci * is passed up the network stack 90362306a36Sopenharmony_ci */ 90462306a36Sopenharmony_civoid ixgbe_ptp_rx_rgtstamp(struct ixgbe_q_vector *q_vector, 90562306a36Sopenharmony_ci struct sk_buff *skb) 90662306a36Sopenharmony_ci{ 90762306a36Sopenharmony_ci struct ixgbe_adapter *adapter; 90862306a36Sopenharmony_ci struct ixgbe_hw *hw; 90962306a36Sopenharmony_ci u64 regval = 0; 91062306a36Sopenharmony_ci u32 tsyncrxctl; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci /* we cannot process timestamps on a ring without a q_vector */ 91362306a36Sopenharmony_ci if (!q_vector || !q_vector->adapter) 91462306a36Sopenharmony_ci return; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci adapter = q_vector->adapter; 91762306a36Sopenharmony_ci hw = &adapter->hw; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci /* Read the tsyncrxctl register afterwards in order to prevent taking an 92062306a36Sopenharmony_ci * I/O hit on every packet. 92162306a36Sopenharmony_ci */ 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); 92462306a36Sopenharmony_ci if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) 92562306a36Sopenharmony_ci return; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL); 92862306a36Sopenharmony_ci regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci ixgbe_ptp_convert_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci/** 93462306a36Sopenharmony_ci * ixgbe_ptp_get_ts_config - get current hardware timestamping configuration 93562306a36Sopenharmony_ci * @adapter: pointer to adapter structure 93662306a36Sopenharmony_ci * @ifr: ioctl data 93762306a36Sopenharmony_ci * 93862306a36Sopenharmony_ci * This function returns the current timestamping settings. Rather than 93962306a36Sopenharmony_ci * attempt to deconstruct registers to fill in the values, simply keep a copy 94062306a36Sopenharmony_ci * of the old settings around, and return a copy when requested. 94162306a36Sopenharmony_ci */ 94262306a36Sopenharmony_ciint ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) 94362306a36Sopenharmony_ci{ 94462306a36Sopenharmony_ci struct hwtstamp_config *config = &adapter->tstamp_config; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci return copy_to_user(ifr->ifr_data, config, 94762306a36Sopenharmony_ci sizeof(*config)) ? -EFAULT : 0; 94862306a36Sopenharmony_ci} 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci/** 95162306a36Sopenharmony_ci * ixgbe_ptp_set_timestamp_mode - setup the hardware for the requested mode 95262306a36Sopenharmony_ci * @adapter: the private ixgbe adapter structure 95362306a36Sopenharmony_ci * @config: the hwtstamp configuration requested 95462306a36Sopenharmony_ci * 95562306a36Sopenharmony_ci * Outgoing time stamping can be enabled and disabled. Play nice and 95662306a36Sopenharmony_ci * disable it when requested, although it shouldn't cause any overhead 95762306a36Sopenharmony_ci * when no packet needs it. At most one packet in the queue may be 95862306a36Sopenharmony_ci * marked for time stamping, otherwise it would be impossible to tell 95962306a36Sopenharmony_ci * for sure to which packet the hardware time stamp belongs. 96062306a36Sopenharmony_ci * 96162306a36Sopenharmony_ci * Incoming time stamping has to be configured via the hardware 96262306a36Sopenharmony_ci * filters. Not all combinations are supported, in particular event 96362306a36Sopenharmony_ci * type has to be specified. Matching the kind of event packet is 96462306a36Sopenharmony_ci * not supported, with the exception of "all V2 events regardless of 96562306a36Sopenharmony_ci * level 2 or 4". 96662306a36Sopenharmony_ci * 96762306a36Sopenharmony_ci * Since hardware always timestamps Path delay packets when timestamping V2 96862306a36Sopenharmony_ci * packets, regardless of the type specified in the register, only use V2 96962306a36Sopenharmony_ci * Event mode. This more accurately tells the user what the hardware is going 97062306a36Sopenharmony_ci * to do anyways. 97162306a36Sopenharmony_ci * 97262306a36Sopenharmony_ci * Note: this may modify the hwtstamp configuration towards a more general 97362306a36Sopenharmony_ci * mode, if required to support the specifically requested mode. 97462306a36Sopenharmony_ci */ 97562306a36Sopenharmony_cistatic int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter, 97662306a36Sopenharmony_ci struct hwtstamp_config *config) 97762306a36Sopenharmony_ci{ 97862306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 97962306a36Sopenharmony_ci u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED; 98062306a36Sopenharmony_ci u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED; 98162306a36Sopenharmony_ci u32 tsync_rx_mtrl = PTP_EV_PORT << 16; 98262306a36Sopenharmony_ci u32 aflags = adapter->flags; 98362306a36Sopenharmony_ci bool is_l2 = false; 98462306a36Sopenharmony_ci u32 regval; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci switch (config->tx_type) { 98762306a36Sopenharmony_ci case HWTSTAMP_TX_OFF: 98862306a36Sopenharmony_ci tsync_tx_ctl = 0; 98962306a36Sopenharmony_ci break; 99062306a36Sopenharmony_ci case HWTSTAMP_TX_ON: 99162306a36Sopenharmony_ci break; 99262306a36Sopenharmony_ci default: 99362306a36Sopenharmony_ci return -ERANGE; 99462306a36Sopenharmony_ci } 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci switch (config->rx_filter) { 99762306a36Sopenharmony_ci case HWTSTAMP_FILTER_NONE: 99862306a36Sopenharmony_ci tsync_rx_ctl = 0; 99962306a36Sopenharmony_ci tsync_rx_mtrl = 0; 100062306a36Sopenharmony_ci aflags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED | 100162306a36Sopenharmony_ci IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); 100262306a36Sopenharmony_ci break; 100362306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 100462306a36Sopenharmony_ci tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; 100562306a36Sopenharmony_ci tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG; 100662306a36Sopenharmony_ci aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | 100762306a36Sopenharmony_ci IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); 100862306a36Sopenharmony_ci break; 100962306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 101062306a36Sopenharmony_ci tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; 101162306a36Sopenharmony_ci tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG; 101262306a36Sopenharmony_ci aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | 101362306a36Sopenharmony_ci IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); 101462306a36Sopenharmony_ci break; 101562306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_EVENT: 101662306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 101762306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 101862306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_SYNC: 101962306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 102062306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 102162306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 102262306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 102362306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 102462306a36Sopenharmony_ci tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2; 102562306a36Sopenharmony_ci is_l2 = true; 102662306a36Sopenharmony_ci config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 102762306a36Sopenharmony_ci aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | 102862306a36Sopenharmony_ci IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); 102962306a36Sopenharmony_ci break; 103062306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 103162306a36Sopenharmony_ci case HWTSTAMP_FILTER_NTP_ALL: 103262306a36Sopenharmony_ci case HWTSTAMP_FILTER_ALL: 103362306a36Sopenharmony_ci /* The X550 controller is capable of timestamping all packets, 103462306a36Sopenharmony_ci * which allows it to accept any filter. 103562306a36Sopenharmony_ci */ 103662306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_X550) { 103762306a36Sopenharmony_ci tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_ALL; 103862306a36Sopenharmony_ci config->rx_filter = HWTSTAMP_FILTER_ALL; 103962306a36Sopenharmony_ci aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED; 104062306a36Sopenharmony_ci break; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci fallthrough; 104362306a36Sopenharmony_ci default: 104462306a36Sopenharmony_ci /* 104562306a36Sopenharmony_ci * register RXMTRL must be set in order to do V1 packets, 104662306a36Sopenharmony_ci * therefore it is not possible to time stamp both V1 Sync and 104762306a36Sopenharmony_ci * Delay_Req messages and hardware does not support 104862306a36Sopenharmony_ci * timestamping all packets => return error 104962306a36Sopenharmony_ci */ 105062306a36Sopenharmony_ci config->rx_filter = HWTSTAMP_FILTER_NONE; 105162306a36Sopenharmony_ci return -ERANGE; 105262306a36Sopenharmony_ci } 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_82598EB) { 105562306a36Sopenharmony_ci adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED | 105662306a36Sopenharmony_ci IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); 105762306a36Sopenharmony_ci if (tsync_rx_ctl | tsync_tx_ctl) 105862306a36Sopenharmony_ci return -ERANGE; 105962306a36Sopenharmony_ci return 0; 106062306a36Sopenharmony_ci } 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci /* Per-packet timestamping only works if the filter is set to all 106362306a36Sopenharmony_ci * packets. Since this is desired, always timestamp all packets as long 106462306a36Sopenharmony_ci * as any Rx filter was configured. 106562306a36Sopenharmony_ci */ 106662306a36Sopenharmony_ci switch (hw->mac.type) { 106762306a36Sopenharmony_ci case ixgbe_mac_X550: 106862306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 106962306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 107062306a36Sopenharmony_ci /* enable timestamping all packets only if at least some 107162306a36Sopenharmony_ci * packets were requested. Otherwise, play nice and disable 107262306a36Sopenharmony_ci * timestamping 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_ci if (config->rx_filter == HWTSTAMP_FILTER_NONE) 107562306a36Sopenharmony_ci break; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED | 107862306a36Sopenharmony_ci IXGBE_TSYNCRXCTL_TYPE_ALL | 107962306a36Sopenharmony_ci IXGBE_TSYNCRXCTL_TSIP_UT_EN; 108062306a36Sopenharmony_ci config->rx_filter = HWTSTAMP_FILTER_ALL; 108162306a36Sopenharmony_ci aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED; 108262306a36Sopenharmony_ci aflags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER; 108362306a36Sopenharmony_ci is_l2 = true; 108462306a36Sopenharmony_ci break; 108562306a36Sopenharmony_ci default: 108662306a36Sopenharmony_ci break; 108762306a36Sopenharmony_ci } 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci /* define ethertype filter for timestamping L2 packets */ 109062306a36Sopenharmony_ci if (is_l2) 109162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 109262306a36Sopenharmony_ci (IXGBE_ETQF_FILTER_EN | /* enable filter */ 109362306a36Sopenharmony_ci IXGBE_ETQF_1588 | /* enable timestamping */ 109462306a36Sopenharmony_ci ETH_P_1588)); /* 1588 eth protocol type */ 109562306a36Sopenharmony_ci else 109662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 0); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci /* enable/disable TX */ 109962306a36Sopenharmony_ci regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); 110062306a36Sopenharmony_ci regval &= ~IXGBE_TSYNCTXCTL_ENABLED; 110162306a36Sopenharmony_ci regval |= tsync_tx_ctl; 110262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, regval); 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci /* enable/disable RX */ 110562306a36Sopenharmony_ci regval = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); 110662306a36Sopenharmony_ci regval &= ~(IXGBE_TSYNCRXCTL_ENABLED | IXGBE_TSYNCRXCTL_TYPE_MASK); 110762306a36Sopenharmony_ci regval |= tsync_rx_ctl; 110862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, regval); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci /* define which PTP packets are time stamped */ 111162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RXMTRL, tsync_rx_mtrl); 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci /* configure adapter flags only when HW is actually configured */ 111662306a36Sopenharmony_ci adapter->flags = aflags; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci /* clear TX/RX time stamp registers, just to be sure */ 111962306a36Sopenharmony_ci ixgbe_ptp_clear_tx_timestamp(adapter); 112062306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RXSTMPH); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci return 0; 112362306a36Sopenharmony_ci} 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci/** 112662306a36Sopenharmony_ci * ixgbe_ptp_set_ts_config - user entry point for timestamp mode 112762306a36Sopenharmony_ci * @adapter: pointer to adapter struct 112862306a36Sopenharmony_ci * @ifr: ioctl data 112962306a36Sopenharmony_ci * 113062306a36Sopenharmony_ci * Set hardware to requested mode. If unsupported, return an error with no 113162306a36Sopenharmony_ci * changes. Otherwise, store the mode for future reference. 113262306a36Sopenharmony_ci */ 113362306a36Sopenharmony_ciint ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) 113462306a36Sopenharmony_ci{ 113562306a36Sopenharmony_ci struct hwtstamp_config config; 113662306a36Sopenharmony_ci int err; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) 113962306a36Sopenharmony_ci return -EFAULT; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci err = ixgbe_ptp_set_timestamp_mode(adapter, &config); 114262306a36Sopenharmony_ci if (err) 114362306a36Sopenharmony_ci return err; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* save these settings for future reference */ 114662306a36Sopenharmony_ci memcpy(&adapter->tstamp_config, &config, 114762306a36Sopenharmony_ci sizeof(adapter->tstamp_config)); 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? 115062306a36Sopenharmony_ci -EFAULT : 0; 115162306a36Sopenharmony_ci} 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_cistatic void ixgbe_ptp_link_speed_adjust(struct ixgbe_adapter *adapter, 115462306a36Sopenharmony_ci u32 *shift, u32 *incval) 115562306a36Sopenharmony_ci{ 115662306a36Sopenharmony_ci /** 115762306a36Sopenharmony_ci * Scale the NIC cycle counter by a large factor so that 115862306a36Sopenharmony_ci * relatively small corrections to the frequency can be added 115962306a36Sopenharmony_ci * or subtracted. The drawbacks of a large factor include 116062306a36Sopenharmony_ci * (a) the clock register overflows more quickly, (b) the cycle 116162306a36Sopenharmony_ci * counter structure must be able to convert the systime value 116262306a36Sopenharmony_ci * to nanoseconds using only a multiplier and a right-shift, 116362306a36Sopenharmony_ci * and (c) the value must fit within the timinca register space 116462306a36Sopenharmony_ci * => math based on internal DMA clock rate and available bits 116562306a36Sopenharmony_ci * 116662306a36Sopenharmony_ci * Note that when there is no link, internal DMA clock is same as when 116762306a36Sopenharmony_ci * link speed is 10Gb. Set the registers correctly even when link is 116862306a36Sopenharmony_ci * down to preserve the clock setting 116962306a36Sopenharmony_ci */ 117062306a36Sopenharmony_ci switch (adapter->link_speed) { 117162306a36Sopenharmony_ci case IXGBE_LINK_SPEED_100_FULL: 117262306a36Sopenharmony_ci *shift = IXGBE_INCVAL_SHIFT_100; 117362306a36Sopenharmony_ci *incval = IXGBE_INCVAL_100; 117462306a36Sopenharmony_ci break; 117562306a36Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 117662306a36Sopenharmony_ci *shift = IXGBE_INCVAL_SHIFT_1GB; 117762306a36Sopenharmony_ci *incval = IXGBE_INCVAL_1GB; 117862306a36Sopenharmony_ci break; 117962306a36Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 118062306a36Sopenharmony_ci default: 118162306a36Sopenharmony_ci *shift = IXGBE_INCVAL_SHIFT_10GB; 118262306a36Sopenharmony_ci *incval = IXGBE_INCVAL_10GB; 118362306a36Sopenharmony_ci break; 118462306a36Sopenharmony_ci } 118562306a36Sopenharmony_ci} 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci/** 118862306a36Sopenharmony_ci * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw 118962306a36Sopenharmony_ci * @adapter: pointer to the adapter structure 119062306a36Sopenharmony_ci * 119162306a36Sopenharmony_ci * This function should be called to set the proper values for the TIMINCA 119262306a36Sopenharmony_ci * register and tell the cyclecounter structure what the tick rate of SYSTIME 119362306a36Sopenharmony_ci * is. It does not directly modify SYSTIME registers or the timecounter 119462306a36Sopenharmony_ci * structure. It should be called whenever a new TIMINCA value is necessary, 119562306a36Sopenharmony_ci * such as during initialization or when the link speed changes. 119662306a36Sopenharmony_ci */ 119762306a36Sopenharmony_civoid ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) 119862306a36Sopenharmony_ci{ 119962306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 120062306a36Sopenharmony_ci struct cyclecounter cc; 120162306a36Sopenharmony_ci unsigned long flags; 120262306a36Sopenharmony_ci u32 incval = 0; 120362306a36Sopenharmony_ci u32 fuse0 = 0; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci /* For some of the boards below this mask is technically incorrect. 120662306a36Sopenharmony_ci * The timestamp mask overflows at approximately 61bits. However the 120762306a36Sopenharmony_ci * particular hardware does not overflow on an even bitmask value. 120862306a36Sopenharmony_ci * Instead, it overflows due to conversion of upper 32bits billions of 120962306a36Sopenharmony_ci * cycles. Timecounters are not really intended for this purpose so 121062306a36Sopenharmony_ci * they do not properly function if the overflow point isn't 2^N-1. 121162306a36Sopenharmony_ci * However, the actual SYSTIME values in question take ~138 years to 121262306a36Sopenharmony_ci * overflow. In practice this means they won't actually overflow. A 121362306a36Sopenharmony_ci * proper fix to this problem would require modification of the 121462306a36Sopenharmony_ci * timecounter delta calculations. 121562306a36Sopenharmony_ci */ 121662306a36Sopenharmony_ci cc.mask = CLOCKSOURCE_MASK(64); 121762306a36Sopenharmony_ci cc.mult = 1; 121862306a36Sopenharmony_ci cc.shift = 0; 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci switch (hw->mac.type) { 122162306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 122262306a36Sopenharmony_ci /* SYSTIME assumes X550EM_x board frequency is 300Mhz, and is 122362306a36Sopenharmony_ci * designed to represent seconds and nanoseconds when this is 122462306a36Sopenharmony_ci * the case. However, some revisions of hardware have a 400Mhz 122562306a36Sopenharmony_ci * clock and we have to compensate for this frequency 122662306a36Sopenharmony_ci * variation using corrected mult and shift values. 122762306a36Sopenharmony_ci */ 122862306a36Sopenharmony_ci fuse0 = IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)); 122962306a36Sopenharmony_ci if (!(fuse0 & IXGBE_FUSES0_300MHZ)) { 123062306a36Sopenharmony_ci cc.mult = 3; 123162306a36Sopenharmony_ci cc.shift = 2; 123262306a36Sopenharmony_ci } 123362306a36Sopenharmony_ci fallthrough; 123462306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 123562306a36Sopenharmony_ci case ixgbe_mac_X550: 123662306a36Sopenharmony_ci cc.read = ixgbe_ptp_read_X550; 123762306a36Sopenharmony_ci break; 123862306a36Sopenharmony_ci case ixgbe_mac_X540: 123962306a36Sopenharmony_ci cc.read = ixgbe_ptp_read_82599; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci ixgbe_ptp_link_speed_adjust(adapter, &cc.shift, &incval); 124262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, incval); 124362306a36Sopenharmony_ci break; 124462306a36Sopenharmony_ci case ixgbe_mac_82599EB: 124562306a36Sopenharmony_ci cc.read = ixgbe_ptp_read_82599; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci ixgbe_ptp_link_speed_adjust(adapter, &cc.shift, &incval); 124862306a36Sopenharmony_ci incval >>= IXGBE_INCVAL_SHIFT_82599; 124962306a36Sopenharmony_ci cc.shift -= IXGBE_INCVAL_SHIFT_82599; 125062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, 125162306a36Sopenharmony_ci BIT(IXGBE_INCPER_SHIFT_82599) | incval); 125262306a36Sopenharmony_ci break; 125362306a36Sopenharmony_ci default: 125462306a36Sopenharmony_ci /* other devices aren't supported */ 125562306a36Sopenharmony_ci return; 125662306a36Sopenharmony_ci } 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci /* update the base incval used to calculate frequency adjustment */ 125962306a36Sopenharmony_ci WRITE_ONCE(adapter->base_incval, incval); 126062306a36Sopenharmony_ci smp_mb(); 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci /* need lock to prevent incorrect read while modifying cyclecounter */ 126362306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 126462306a36Sopenharmony_ci memcpy(&adapter->hw_cc, &cc, sizeof(adapter->hw_cc)); 126562306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 126662306a36Sopenharmony_ci} 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci/** 126962306a36Sopenharmony_ci * ixgbe_ptp_init_systime - Initialize SYSTIME registers 127062306a36Sopenharmony_ci * @adapter: the ixgbe private board structure 127162306a36Sopenharmony_ci * 127262306a36Sopenharmony_ci * Initialize and start the SYSTIME registers. 127362306a36Sopenharmony_ci */ 127462306a36Sopenharmony_cistatic void ixgbe_ptp_init_systime(struct ixgbe_adapter *adapter) 127562306a36Sopenharmony_ci{ 127662306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 127762306a36Sopenharmony_ci u32 tsauxc; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci switch (hw->mac.type) { 128062306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 128162306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 128262306a36Sopenharmony_ci case ixgbe_mac_X550: 128362306a36Sopenharmony_ci tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC); 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci /* Reset SYSTIME registers to 0 */ 128662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SYSTIMR, 0); 128762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0); 128862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci /* Reset interrupt settings */ 129162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSIM, IXGBE_TSIM_TXTS); 129262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_TIMESYNC); 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci /* Activate the SYSTIME counter */ 129562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 129662306a36Sopenharmony_ci tsauxc & ~IXGBE_TSAUXC_DISABLE_SYSTIME); 129762306a36Sopenharmony_ci break; 129862306a36Sopenharmony_ci case ixgbe_mac_X540: 129962306a36Sopenharmony_ci case ixgbe_mac_82599EB: 130062306a36Sopenharmony_ci /* Reset SYSTIME registers to 0 */ 130162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0); 130262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0); 130362306a36Sopenharmony_ci break; 130462306a36Sopenharmony_ci default: 130562306a36Sopenharmony_ci /* Other devices aren't supported */ 130662306a36Sopenharmony_ci return; 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 131062306a36Sopenharmony_ci} 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci/** 131362306a36Sopenharmony_ci * ixgbe_ptp_reset 131462306a36Sopenharmony_ci * @adapter: the ixgbe private board structure 131562306a36Sopenharmony_ci * 131662306a36Sopenharmony_ci * When the MAC resets, all the hardware bits for timesync are reset. This 131762306a36Sopenharmony_ci * function is used to re-enable the device for PTP based on current settings. 131862306a36Sopenharmony_ci * We do lose the current clock time, so just reset the cyclecounter to the 131962306a36Sopenharmony_ci * system real clock time. 132062306a36Sopenharmony_ci * 132162306a36Sopenharmony_ci * This function will maintain hwtstamp_config settings, and resets the SDP 132262306a36Sopenharmony_ci * output if it was enabled. 132362306a36Sopenharmony_ci */ 132462306a36Sopenharmony_civoid ixgbe_ptp_reset(struct ixgbe_adapter *adapter) 132562306a36Sopenharmony_ci{ 132662306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 132762306a36Sopenharmony_ci unsigned long flags; 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci /* reset the hardware timestamping mode */ 133062306a36Sopenharmony_ci ixgbe_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci /* 82598 does not support PTP */ 133362306a36Sopenharmony_ci if (hw->mac.type == ixgbe_mac_82598EB) 133462306a36Sopenharmony_ci return; 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci ixgbe_ptp_start_cyclecounter(adapter); 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci ixgbe_ptp_init_systime(adapter); 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 134162306a36Sopenharmony_ci timecounter_init(&adapter->hw_tc, &adapter->hw_cc, 134262306a36Sopenharmony_ci ktime_to_ns(ktime_get_real())); 134362306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci adapter->last_overflow_check = jiffies; 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci /* Now that the shift has been calculated and the systime 134862306a36Sopenharmony_ci * registers reset, (re-)enable the Clock out feature 134962306a36Sopenharmony_ci */ 135062306a36Sopenharmony_ci if (adapter->ptp_setup_sdp) 135162306a36Sopenharmony_ci adapter->ptp_setup_sdp(adapter); 135262306a36Sopenharmony_ci} 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci/** 135562306a36Sopenharmony_ci * ixgbe_ptp_create_clock 135662306a36Sopenharmony_ci * @adapter: the ixgbe private adapter structure 135762306a36Sopenharmony_ci * 135862306a36Sopenharmony_ci * This function performs setup of the user entry point function table and 135962306a36Sopenharmony_ci * initializes the PTP clock device, which is used to access the clock-like 136062306a36Sopenharmony_ci * features of the PTP core. It will be called by ixgbe_ptp_init, and may 136162306a36Sopenharmony_ci * reuse a previously initialized clock (such as during a suspend/resume 136262306a36Sopenharmony_ci * cycle). 136362306a36Sopenharmony_ci */ 136462306a36Sopenharmony_cistatic long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) 136562306a36Sopenharmony_ci{ 136662306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 136762306a36Sopenharmony_ci long err; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci /* do nothing if we already have a clock device */ 137062306a36Sopenharmony_ci if (!IS_ERR_OR_NULL(adapter->ptp_clock)) 137162306a36Sopenharmony_ci return 0; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci switch (adapter->hw.mac.type) { 137462306a36Sopenharmony_ci case ixgbe_mac_X540: 137562306a36Sopenharmony_ci snprintf(adapter->ptp_caps.name, 137662306a36Sopenharmony_ci sizeof(adapter->ptp_caps.name), 137762306a36Sopenharmony_ci "%s", netdev->name); 137862306a36Sopenharmony_ci adapter->ptp_caps.owner = THIS_MODULE; 137962306a36Sopenharmony_ci adapter->ptp_caps.max_adj = 250000000; 138062306a36Sopenharmony_ci adapter->ptp_caps.n_alarm = 0; 138162306a36Sopenharmony_ci adapter->ptp_caps.n_ext_ts = 0; 138262306a36Sopenharmony_ci adapter->ptp_caps.n_per_out = 0; 138362306a36Sopenharmony_ci adapter->ptp_caps.pps = 1; 138462306a36Sopenharmony_ci adapter->ptp_caps.adjfine = ixgbe_ptp_adjfine_82599; 138562306a36Sopenharmony_ci adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; 138662306a36Sopenharmony_ci adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; 138762306a36Sopenharmony_ci adapter->ptp_caps.settime64 = ixgbe_ptp_settime; 138862306a36Sopenharmony_ci adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; 138962306a36Sopenharmony_ci adapter->ptp_setup_sdp = ixgbe_ptp_setup_sdp_X540; 139062306a36Sopenharmony_ci break; 139162306a36Sopenharmony_ci case ixgbe_mac_82599EB: 139262306a36Sopenharmony_ci snprintf(adapter->ptp_caps.name, 139362306a36Sopenharmony_ci sizeof(adapter->ptp_caps.name), 139462306a36Sopenharmony_ci "%s", netdev->name); 139562306a36Sopenharmony_ci adapter->ptp_caps.owner = THIS_MODULE; 139662306a36Sopenharmony_ci adapter->ptp_caps.max_adj = 250000000; 139762306a36Sopenharmony_ci adapter->ptp_caps.n_alarm = 0; 139862306a36Sopenharmony_ci adapter->ptp_caps.n_ext_ts = 0; 139962306a36Sopenharmony_ci adapter->ptp_caps.n_per_out = 0; 140062306a36Sopenharmony_ci adapter->ptp_caps.pps = 0; 140162306a36Sopenharmony_ci adapter->ptp_caps.adjfine = ixgbe_ptp_adjfine_82599; 140262306a36Sopenharmony_ci adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; 140362306a36Sopenharmony_ci adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; 140462306a36Sopenharmony_ci adapter->ptp_caps.settime64 = ixgbe_ptp_settime; 140562306a36Sopenharmony_ci adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; 140662306a36Sopenharmony_ci break; 140762306a36Sopenharmony_ci case ixgbe_mac_X550: 140862306a36Sopenharmony_ci case ixgbe_mac_X550EM_x: 140962306a36Sopenharmony_ci case ixgbe_mac_x550em_a: 141062306a36Sopenharmony_ci snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name); 141162306a36Sopenharmony_ci adapter->ptp_caps.owner = THIS_MODULE; 141262306a36Sopenharmony_ci adapter->ptp_caps.max_adj = 30000000; 141362306a36Sopenharmony_ci adapter->ptp_caps.n_alarm = 0; 141462306a36Sopenharmony_ci adapter->ptp_caps.n_ext_ts = 0; 141562306a36Sopenharmony_ci adapter->ptp_caps.n_per_out = 0; 141662306a36Sopenharmony_ci adapter->ptp_caps.pps = 1; 141762306a36Sopenharmony_ci adapter->ptp_caps.adjfine = ixgbe_ptp_adjfine_X550; 141862306a36Sopenharmony_ci adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; 141962306a36Sopenharmony_ci adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; 142062306a36Sopenharmony_ci adapter->ptp_caps.settime64 = ixgbe_ptp_settime; 142162306a36Sopenharmony_ci adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; 142262306a36Sopenharmony_ci adapter->ptp_setup_sdp = ixgbe_ptp_setup_sdp_X550; 142362306a36Sopenharmony_ci break; 142462306a36Sopenharmony_ci default: 142562306a36Sopenharmony_ci adapter->ptp_clock = NULL; 142662306a36Sopenharmony_ci adapter->ptp_setup_sdp = NULL; 142762306a36Sopenharmony_ci return -EOPNOTSUPP; 142862306a36Sopenharmony_ci } 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, 143162306a36Sopenharmony_ci &adapter->pdev->dev); 143262306a36Sopenharmony_ci if (IS_ERR(adapter->ptp_clock)) { 143362306a36Sopenharmony_ci err = PTR_ERR(adapter->ptp_clock); 143462306a36Sopenharmony_ci adapter->ptp_clock = NULL; 143562306a36Sopenharmony_ci e_dev_err("ptp_clock_register failed\n"); 143662306a36Sopenharmony_ci return err; 143762306a36Sopenharmony_ci } else if (adapter->ptp_clock) 143862306a36Sopenharmony_ci e_dev_info("registered PHC device on %s\n", netdev->name); 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci /* set default timestamp mode to disabled here. We do this in 144162306a36Sopenharmony_ci * create_clock instead of init, because we don't want to override the 144262306a36Sopenharmony_ci * previous settings during a resume cycle. 144362306a36Sopenharmony_ci */ 144462306a36Sopenharmony_ci adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; 144562306a36Sopenharmony_ci adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci return 0; 144862306a36Sopenharmony_ci} 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci/** 145162306a36Sopenharmony_ci * ixgbe_ptp_init 145262306a36Sopenharmony_ci * @adapter: the ixgbe private adapter structure 145362306a36Sopenharmony_ci * 145462306a36Sopenharmony_ci * This function performs the required steps for enabling PTP 145562306a36Sopenharmony_ci * support. If PTP support has already been loaded it simply calls the 145662306a36Sopenharmony_ci * cyclecounter init routine and exits. 145762306a36Sopenharmony_ci */ 145862306a36Sopenharmony_civoid ixgbe_ptp_init(struct ixgbe_adapter *adapter) 145962306a36Sopenharmony_ci{ 146062306a36Sopenharmony_ci /* initialize the spin lock first since we can't control when a user 146162306a36Sopenharmony_ci * will call the entry functions once we have initialized the clock 146262306a36Sopenharmony_ci * device 146362306a36Sopenharmony_ci */ 146462306a36Sopenharmony_ci spin_lock_init(&adapter->tmreg_lock); 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci /* obtain a PTP device, or re-use an existing device */ 146762306a36Sopenharmony_ci if (ixgbe_ptp_create_clock(adapter)) 146862306a36Sopenharmony_ci return; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci /* we have a clock so we can initialize work now */ 147162306a36Sopenharmony_ci INIT_WORK(&adapter->ptp_tx_work, ixgbe_ptp_tx_hwtstamp_work); 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci /* reset the PTP related hardware bits */ 147462306a36Sopenharmony_ci ixgbe_ptp_reset(adapter); 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci /* enter the IXGBE_PTP_RUNNING state */ 147762306a36Sopenharmony_ci set_bit(__IXGBE_PTP_RUNNING, &adapter->state); 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci return; 148062306a36Sopenharmony_ci} 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci/** 148362306a36Sopenharmony_ci * ixgbe_ptp_suspend - stop PTP work items 148462306a36Sopenharmony_ci * @adapter: pointer to adapter struct 148562306a36Sopenharmony_ci * 148662306a36Sopenharmony_ci * this function suspends PTP activity, and prevents more PTP work from being 148762306a36Sopenharmony_ci * generated, but does not destroy the PTP clock device. 148862306a36Sopenharmony_ci */ 148962306a36Sopenharmony_civoid ixgbe_ptp_suspend(struct ixgbe_adapter *adapter) 149062306a36Sopenharmony_ci{ 149162306a36Sopenharmony_ci /* Leave the IXGBE_PTP_RUNNING state. */ 149262306a36Sopenharmony_ci if (!test_and_clear_bit(__IXGBE_PTP_RUNNING, &adapter->state)) 149362306a36Sopenharmony_ci return; 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci adapter->flags2 &= ~IXGBE_FLAG2_PTP_PPS_ENABLED; 149662306a36Sopenharmony_ci if (adapter->ptp_setup_sdp) 149762306a36Sopenharmony_ci adapter->ptp_setup_sdp(adapter); 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci /* ensure that we cancel any pending PTP Tx work item in progress */ 150062306a36Sopenharmony_ci cancel_work_sync(&adapter->ptp_tx_work); 150162306a36Sopenharmony_ci ixgbe_ptp_clear_tx_timestamp(adapter); 150262306a36Sopenharmony_ci} 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ci/** 150562306a36Sopenharmony_ci * ixgbe_ptp_stop - close the PTP device 150662306a36Sopenharmony_ci * @adapter: pointer to adapter struct 150762306a36Sopenharmony_ci * 150862306a36Sopenharmony_ci * completely destroy the PTP device, should only be called when the device is 150962306a36Sopenharmony_ci * being fully closed. 151062306a36Sopenharmony_ci */ 151162306a36Sopenharmony_civoid ixgbe_ptp_stop(struct ixgbe_adapter *adapter) 151262306a36Sopenharmony_ci{ 151362306a36Sopenharmony_ci /* first, suspend PTP activity */ 151462306a36Sopenharmony_ci ixgbe_ptp_suspend(adapter); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci /* disable the PTP clock device */ 151762306a36Sopenharmony_ci if (adapter->ptp_clock) { 151862306a36Sopenharmony_ci ptp_clock_unregister(adapter->ptp_clock); 151962306a36Sopenharmony_ci adapter->ptp_clock = NULL; 152062306a36Sopenharmony_ci e_dev_info("removed PHC on %s\n", 152162306a36Sopenharmony_ci adapter->netdev->name); 152262306a36Sopenharmony_ci } 152362306a36Sopenharmony_ci} 1524