| .. | .. |
|---|
| 72 | 72 | #define IXGBE_INCPER_SHIFT_82599 24 |
|---|
| 73 | 73 | |
|---|
| 74 | 74 | #define IXGBE_OVERFLOW_PERIOD (HZ * 30) |
|---|
| 75 | | -#define IXGBE_PTP_TX_TIMEOUT (HZ * 15) |
|---|
| 75 | +#define IXGBE_PTP_TX_TIMEOUT (HZ) |
|---|
| 76 | 76 | |
|---|
| 77 | | -/* half of a one second clock period, for use with PPS signal. We have to use |
|---|
| 78 | | - * this instead of something pre-defined like IXGBE_PTP_PPS_HALF_SECOND, in |
|---|
| 79 | | - * order to force at least 64bits of precision for shifting |
|---|
| 77 | +/* We use our own definitions instead of NSEC_PER_SEC because we want to mark |
|---|
| 78 | + * the value as a ULL to force precision when bit shifting. |
|---|
| 80 | 79 | */ |
|---|
| 81 | | -#define IXGBE_PTP_PPS_HALF_SECOND 500000000ULL |
|---|
| 80 | +#define NS_PER_SEC 1000000000ULL |
|---|
| 81 | +#define NS_PER_HALF_SEC 500000000ULL |
|---|
| 82 | 82 | |
|---|
| 83 | 83 | /* In contrast, the X550 controller has two registers, SYSTIMEH and SYSTIMEL |
|---|
| 84 | 84 | * which contain measurements of seconds and nanoseconds respectively. This |
|---|
| .. | .. |
|---|
| 141 | 141 | #define MAX_TIMADJ 0x7FFFFFFF |
|---|
| 142 | 142 | |
|---|
| 143 | 143 | /** |
|---|
| 144 | | - * ixgbe_ptp_setup_sdp_x540 |
|---|
| 144 | + * ixgbe_ptp_setup_sdp_X540 |
|---|
| 145 | 145 | * @adapter: private adapter structure |
|---|
| 146 | 146 | * |
|---|
| 147 | 147 | * this function enables or disables the clock out feature on SDP0 for |
|---|
| 148 | | - * the X540 device. It will create a 1second periodic output that can |
|---|
| 148 | + * the X540 device. It will create a 1 second periodic output that can |
|---|
| 149 | 149 | * be used as the PPS (via an interrupt). |
|---|
| 150 | 150 | * |
|---|
| 151 | | - * It calculates when the systime will be on an exact second, and then |
|---|
| 152 | | - * aligns the start of the PPS signal to that value. The shift is |
|---|
| 153 | | - * necessary because it can change based on the link speed. |
|---|
| 151 | + * It calculates when the system time will be on an exact second, and then |
|---|
| 152 | + * aligns the start of the PPS signal to that value. |
|---|
| 153 | + * |
|---|
| 154 | + * This works by using the cycle counter shift and mult values in reverse, and |
|---|
| 155 | + * assumes that the values we're shifting will not overflow. |
|---|
| 154 | 156 | */ |
|---|
| 155 | | -static void ixgbe_ptp_setup_sdp_x540(struct ixgbe_adapter *adapter) |
|---|
| 157 | +static void ixgbe_ptp_setup_sdp_X540(struct ixgbe_adapter *adapter) |
|---|
| 156 | 158 | { |
|---|
| 159 | + struct cyclecounter *cc = &adapter->hw_cc; |
|---|
| 157 | 160 | struct ixgbe_hw *hw = &adapter->hw; |
|---|
| 158 | | - int shift = adapter->hw_cc.shift; |
|---|
| 159 | 161 | u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem; |
|---|
| 160 | | - u64 ns = 0, clock_edge = 0; |
|---|
| 162 | + u64 ns = 0, clock_edge = 0, clock_period; |
|---|
| 163 | + unsigned long flags; |
|---|
| 161 | 164 | |
|---|
| 162 | 165 | /* disable the pin first */ |
|---|
| 163 | 166 | IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); |
|---|
| .. | .. |
|---|
| 177 | 180 | /* enable the Clock Out feature on SDP0, and allow |
|---|
| 178 | 181 | * interrupts to occur when the pin changes |
|---|
| 179 | 182 | */ |
|---|
| 180 | | - tsauxc = IXGBE_TSAUXC_EN_CLK | |
|---|
| 181 | | - IXGBE_TSAUXC_SYNCLK | |
|---|
| 182 | | - IXGBE_TSAUXC_SDP0_INT; |
|---|
| 183 | + tsauxc = (IXGBE_TSAUXC_EN_CLK | |
|---|
| 184 | + IXGBE_TSAUXC_SYNCLK | |
|---|
| 185 | + IXGBE_TSAUXC_SDP0_INT); |
|---|
| 183 | 186 | |
|---|
| 184 | | - /* clock period (or pulse length) */ |
|---|
| 185 | | - clktiml = (u32)(IXGBE_PTP_PPS_HALF_SECOND << shift); |
|---|
| 186 | | - clktimh = (u32)((IXGBE_PTP_PPS_HALF_SECOND << shift) >> 32); |
|---|
| 187 | | - |
|---|
| 188 | | - /* Account for the cyclecounter wrap-around value by |
|---|
| 189 | | - * using the converted ns value of the current time to |
|---|
| 190 | | - * check for when the next aligned second would occur. |
|---|
| 187 | + /* Determine the clock time period to use. This assumes that the |
|---|
| 188 | + * cycle counter shift is small enough to avoid overflow. |
|---|
| 191 | 189 | */ |
|---|
| 192 | | - clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML); |
|---|
| 193 | | - clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; |
|---|
| 194 | | - ns = timecounter_cyc2time(&adapter->hw_tc, clock_edge); |
|---|
| 190 | + clock_period = div_u64((NS_PER_HALF_SEC << cc->shift), cc->mult); |
|---|
| 191 | + clktiml = (u32)(clock_period); |
|---|
| 192 | + clktimh = (u32)(clock_period >> 32); |
|---|
| 195 | 193 | |
|---|
| 196 | | - div_u64_rem(ns, IXGBE_PTP_PPS_HALF_SECOND, &rem); |
|---|
| 197 | | - clock_edge += ((IXGBE_PTP_PPS_HALF_SECOND - (u64)rem) << shift); |
|---|
| 194 | + /* Read the current clock time, and save the cycle counter value */ |
|---|
| 195 | + spin_lock_irqsave(&adapter->tmreg_lock, flags); |
|---|
| 196 | + ns = timecounter_read(&adapter->hw_tc); |
|---|
| 197 | + clock_edge = adapter->hw_tc.cycle_last; |
|---|
| 198 | + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
|---|
| 198 | 199 | |
|---|
| 199 | | - /* specify the initial clock start time */ |
|---|
| 200 | + /* Figure out how many seconds to add in order to round up */ |
|---|
| 201 | + div_u64_rem(ns, NS_PER_SEC, &rem); |
|---|
| 202 | + |
|---|
| 203 | + /* Figure out how many nanoseconds to add to round the clock edge up |
|---|
| 204 | + * to the next full second |
|---|
| 205 | + */ |
|---|
| 206 | + rem = (NS_PER_SEC - rem); |
|---|
| 207 | + |
|---|
| 208 | + /* Adjust the clock edge to align with the next full second. */ |
|---|
| 209 | + clock_edge += div_u64(((u64)rem << cc->shift), cc->mult); |
|---|
| 200 | 210 | trgttiml = (u32)clock_edge; |
|---|
| 201 | 211 | trgttimh = (u32)(clock_edge >> 32); |
|---|
| 202 | 212 | |
|---|
| .. | .. |
|---|
| 212 | 222 | } |
|---|
| 213 | 223 | |
|---|
| 214 | 224 | /** |
|---|
| 225 | + * ixgbe_ptp_setup_sdp_X550 |
|---|
| 226 | + * @adapter: private adapter structure |
|---|
| 227 | + * |
|---|
| 228 | + * Enable or disable a clock output signal on SDP 0 for X550 hardware. |
|---|
| 229 | + * |
|---|
| 230 | + * Use the target time feature to align the output signal on the next full |
|---|
| 231 | + * second. |
|---|
| 232 | + * |
|---|
| 233 | + * This works by using the cycle counter shift and mult values in reverse, and |
|---|
| 234 | + * assumes that the values we're shifting will not overflow. |
|---|
| 235 | + */ |
|---|
| 236 | +static void ixgbe_ptp_setup_sdp_X550(struct ixgbe_adapter *adapter) |
|---|
| 237 | +{ |
|---|
| 238 | + u32 esdp, tsauxc, freqout, trgttiml, trgttimh, rem, tssdp; |
|---|
| 239 | + struct cyclecounter *cc = &adapter->hw_cc; |
|---|
| 240 | + struct ixgbe_hw *hw = &adapter->hw; |
|---|
| 241 | + u64 ns = 0, clock_edge = 0; |
|---|
| 242 | + struct timespec64 ts; |
|---|
| 243 | + unsigned long flags; |
|---|
| 244 | + |
|---|
| 245 | + /* disable the pin first */ |
|---|
| 246 | + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); |
|---|
| 247 | + IXGBE_WRITE_FLUSH(hw); |
|---|
| 248 | + |
|---|
| 249 | + if (!(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED)) |
|---|
| 250 | + return; |
|---|
| 251 | + |
|---|
| 252 | + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); |
|---|
| 253 | + |
|---|
| 254 | + /* enable the SDP0 pin as output, and connected to the |
|---|
| 255 | + * native function for Timesync (ClockOut) |
|---|
| 256 | + */ |
|---|
| 257 | + esdp |= IXGBE_ESDP_SDP0_DIR | |
|---|
| 258 | + IXGBE_ESDP_SDP0_NATIVE; |
|---|
| 259 | + |
|---|
| 260 | + /* enable the Clock Out feature on SDP0, and use Target Time 0 to |
|---|
| 261 | + * enable generation of interrupts on the clock change. |
|---|
| 262 | + */ |
|---|
| 263 | +#define IXGBE_TSAUXC_DIS_TS_CLEAR 0x40000000 |
|---|
| 264 | + tsauxc = (IXGBE_TSAUXC_EN_CLK | IXGBE_TSAUXC_ST0 | |
|---|
| 265 | + IXGBE_TSAUXC_EN_TT0 | IXGBE_TSAUXC_SDP0_INT | |
|---|
| 266 | + IXGBE_TSAUXC_DIS_TS_CLEAR); |
|---|
| 267 | + |
|---|
| 268 | + tssdp = (IXGBE_TSSDP_TS_SDP0_EN | |
|---|
| 269 | + IXGBE_TSSDP_TS_SDP0_CLK0); |
|---|
| 270 | + |
|---|
| 271 | + /* Determine the clock time period to use. This assumes that the |
|---|
| 272 | + * cycle counter shift is small enough to avoid overflowing a 32bit |
|---|
| 273 | + * value. |
|---|
| 274 | + */ |
|---|
| 275 | + freqout = div_u64(NS_PER_HALF_SEC << cc->shift, cc->mult); |
|---|
| 276 | + |
|---|
| 277 | + /* Read the current clock time, and save the cycle counter value */ |
|---|
| 278 | + spin_lock_irqsave(&adapter->tmreg_lock, flags); |
|---|
| 279 | + ns = timecounter_read(&adapter->hw_tc); |
|---|
| 280 | + clock_edge = adapter->hw_tc.cycle_last; |
|---|
| 281 | + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
|---|
| 282 | + |
|---|
| 283 | + /* Figure out how far past the next second we are */ |
|---|
| 284 | + div_u64_rem(ns, NS_PER_SEC, &rem); |
|---|
| 285 | + |
|---|
| 286 | + /* Figure out how many nanoseconds to add to round the clock edge up |
|---|
| 287 | + * to the next full second |
|---|
| 288 | + */ |
|---|
| 289 | + rem = (NS_PER_SEC - rem); |
|---|
| 290 | + |
|---|
| 291 | + /* Adjust the clock edge to align with the next full second. */ |
|---|
| 292 | + clock_edge += div_u64(((u64)rem << cc->shift), cc->mult); |
|---|
| 293 | + |
|---|
| 294 | + /* X550 hardware stores the time in 32bits of 'billions of cycles' and |
|---|
| 295 | + * 32bits of 'cycles'. There's no guarantee that cycles represents |
|---|
| 296 | + * nanoseconds. However, we can use the math from a timespec64 to |
|---|
| 297 | + * convert into the hardware representation. |
|---|
| 298 | + * |
|---|
| 299 | + * See ixgbe_ptp_read_X550() for more details. |
|---|
| 300 | + */ |
|---|
| 301 | + ts = ns_to_timespec64(clock_edge); |
|---|
| 302 | + trgttiml = (u32)ts.tv_nsec; |
|---|
| 303 | + trgttimh = (u32)ts.tv_sec; |
|---|
| 304 | + |
|---|
| 305 | + IXGBE_WRITE_REG(hw, IXGBE_FREQOUT0, freqout); |
|---|
| 306 | + IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml); |
|---|
| 307 | + IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh); |
|---|
| 308 | + |
|---|
| 309 | + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); |
|---|
| 310 | + IXGBE_WRITE_REG(hw, IXGBE_TSSDP, tssdp); |
|---|
| 311 | + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); |
|---|
| 312 | + |
|---|
| 313 | + IXGBE_WRITE_FLUSH(hw); |
|---|
| 314 | +} |
|---|
| 315 | + |
|---|
| 316 | +/** |
|---|
| 215 | 317 | * ixgbe_ptp_read_X550 - read cycle counter value |
|---|
| 216 | | - * @hw_cc: cyclecounter structure |
|---|
| 318 | + * @cc: cyclecounter structure |
|---|
| 217 | 319 | * |
|---|
| 218 | 320 | * This function reads SYSTIME registers. It is called by the cyclecounter |
|---|
| 219 | 321 | * structure to convert from internal representation into nanoseconds. We need |
|---|
| .. | .. |
|---|
| 221 | 323 | * result of SYSTIME is 32bits of "billions of cycles" and 32 bits of |
|---|
| 222 | 324 | * "cycles", rather than seconds and nanoseconds. |
|---|
| 223 | 325 | */ |
|---|
| 224 | | -static u64 ixgbe_ptp_read_X550(const struct cyclecounter *hw_cc) |
|---|
| 326 | +static u64 ixgbe_ptp_read_X550(const struct cyclecounter *cc) |
|---|
| 225 | 327 | { |
|---|
| 226 | 328 | struct ixgbe_adapter *adapter = |
|---|
| 227 | | - container_of(hw_cc, struct ixgbe_adapter, hw_cc); |
|---|
| 329 | + container_of(cc, struct ixgbe_adapter, hw_cc); |
|---|
| 228 | 330 | struct ixgbe_hw *hw = &adapter->hw; |
|---|
| 229 | 331 | struct timespec64 ts; |
|---|
| 230 | 332 | |
|---|
| .. | .. |
|---|
| 443 | 545 | } |
|---|
| 444 | 546 | |
|---|
| 445 | 547 | /** |
|---|
| 446 | | - * ixgbe_ptp_gettime |
|---|
| 548 | + * ixgbe_ptp_gettimex |
|---|
| 447 | 549 | * @ptp: the ptp clock structure |
|---|
| 448 | | - * @ts: timespec structure to hold the current time value |
|---|
| 550 | + * @ts: timespec to hold the PHC timestamp |
|---|
| 551 | + * @sts: structure to hold the system time before and after reading the PHC |
|---|
| 449 | 552 | * |
|---|
| 450 | 553 | * read the timecounter and return the correct value on ns, |
|---|
| 451 | 554 | * after converting it into a struct timespec. |
|---|
| 452 | 555 | */ |
|---|
| 453 | | -static int ixgbe_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) |
|---|
| 556 | +static int ixgbe_ptp_gettimex(struct ptp_clock_info *ptp, |
|---|
| 557 | + struct timespec64 *ts, |
|---|
| 558 | + struct ptp_system_timestamp *sts) |
|---|
| 454 | 559 | { |
|---|
| 455 | 560 | struct ixgbe_adapter *adapter = |
|---|
| 456 | 561 | container_of(ptp, struct ixgbe_adapter, ptp_caps); |
|---|
| 562 | + struct ixgbe_hw *hw = &adapter->hw; |
|---|
| 457 | 563 | unsigned long flags; |
|---|
| 458 | | - u64 ns; |
|---|
| 564 | + u64 ns, stamp; |
|---|
| 459 | 565 | |
|---|
| 460 | 566 | spin_lock_irqsave(&adapter->tmreg_lock, flags); |
|---|
| 461 | | - ns = timecounter_read(&adapter->hw_tc); |
|---|
| 567 | + |
|---|
| 568 | + switch (adapter->hw.mac.type) { |
|---|
| 569 | + case ixgbe_mac_X550: |
|---|
| 570 | + case ixgbe_mac_X550EM_x: |
|---|
| 571 | + case ixgbe_mac_x550em_a: |
|---|
| 572 | + /* Upper 32 bits represent billions of cycles, lower 32 bits |
|---|
| 573 | + * represent cycles. However, we use timespec64_to_ns for the |
|---|
| 574 | + * correct math even though the units haven't been corrected |
|---|
| 575 | + * yet. |
|---|
| 576 | + */ |
|---|
| 577 | + ptp_read_system_prets(sts); |
|---|
| 578 | + IXGBE_READ_REG(hw, IXGBE_SYSTIMR); |
|---|
| 579 | + ptp_read_system_postts(sts); |
|---|
| 580 | + ts->tv_nsec = IXGBE_READ_REG(hw, IXGBE_SYSTIML); |
|---|
| 581 | + ts->tv_sec = IXGBE_READ_REG(hw, IXGBE_SYSTIMH); |
|---|
| 582 | + stamp = timespec64_to_ns(ts); |
|---|
| 583 | + break; |
|---|
| 584 | + default: |
|---|
| 585 | + ptp_read_system_prets(sts); |
|---|
| 586 | + stamp = IXGBE_READ_REG(hw, IXGBE_SYSTIML); |
|---|
| 587 | + ptp_read_system_postts(sts); |
|---|
| 588 | + stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; |
|---|
| 589 | + break; |
|---|
| 590 | + } |
|---|
| 591 | + |
|---|
| 592 | + ns = timecounter_cyc2time(&adapter->hw_tc, stamp); |
|---|
| 593 | + |
|---|
| 462 | 594 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
|---|
| 463 | 595 | |
|---|
| 464 | 596 | *ts = ns_to_timespec64(ns); |
|---|
| .. | .. |
|---|
| 567 | 699 | { |
|---|
| 568 | 700 | bool timeout = time_is_before_jiffies(adapter->last_overflow_check + |
|---|
| 569 | 701 | IXGBE_OVERFLOW_PERIOD); |
|---|
| 570 | | - struct timespec64 ts; |
|---|
| 702 | + unsigned long flags; |
|---|
| 571 | 703 | |
|---|
| 572 | 704 | if (timeout) { |
|---|
| 573 | | - ixgbe_ptp_gettime(&adapter->ptp_caps, &ts); |
|---|
| 705 | + /* Update the timecounter */ |
|---|
| 706 | + spin_lock_irqsave(&adapter->tmreg_lock, flags); |
|---|
| 707 | + timecounter_read(&adapter->hw_tc); |
|---|
| 708 | + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
|---|
| 709 | + |
|---|
| 574 | 710 | adapter->last_overflow_check = jiffies; |
|---|
| 575 | 711 | } |
|---|
| 576 | 712 | } |
|---|
| .. | .. |
|---|
| 804 | 940 | ixgbe_ptp_convert_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); |
|---|
| 805 | 941 | } |
|---|
| 806 | 942 | |
|---|
| 943 | +/** |
|---|
| 944 | + * ixgbe_ptp_get_ts_config - get current hardware timestamping configuration |
|---|
| 945 | + * @adapter: pointer to adapter structure |
|---|
| 946 | + * @ifr: ioctl data |
|---|
| 947 | + * |
|---|
| 948 | + * This function returns the current timestamping settings. Rather than |
|---|
| 949 | + * attempt to deconstruct registers to fill in the values, simply keep a copy |
|---|
| 950 | + * of the old settings around, and return a copy when requested. |
|---|
| 951 | + */ |
|---|
| 807 | 952 | int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) |
|---|
| 808 | 953 | { |
|---|
| 809 | 954 | struct hwtstamp_config *config = &adapter->tstamp_config; |
|---|
| .. | .. |
|---|
| 844 | 989 | u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED; |
|---|
| 845 | 990 | u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED; |
|---|
| 846 | 991 | u32 tsync_rx_mtrl = PTP_EV_PORT << 16; |
|---|
| 992 | + u32 aflags = adapter->flags; |
|---|
| 847 | 993 | bool is_l2 = false; |
|---|
| 848 | 994 | u32 regval; |
|---|
| 849 | 995 | |
|---|
| .. | .. |
|---|
| 864 | 1010 | case HWTSTAMP_FILTER_NONE: |
|---|
| 865 | 1011 | tsync_rx_ctl = 0; |
|---|
| 866 | 1012 | tsync_rx_mtrl = 0; |
|---|
| 867 | | - adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 868 | | - IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 1013 | + aflags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 1014 | + IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 869 | 1015 | break; |
|---|
| 870 | 1016 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: |
|---|
| 871 | 1017 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; |
|---|
| 872 | 1018 | tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG; |
|---|
| 873 | | - adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 874 | | - IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 1019 | + aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 1020 | + IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 875 | 1021 | break; |
|---|
| 876 | 1022 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: |
|---|
| 877 | 1023 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; |
|---|
| 878 | 1024 | tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG; |
|---|
| 879 | | - adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 880 | | - IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 1025 | + aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 1026 | + IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 881 | 1027 | break; |
|---|
| 882 | 1028 | case HWTSTAMP_FILTER_PTP_V2_EVENT: |
|---|
| 883 | 1029 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: |
|---|
| .. | .. |
|---|
| 891 | 1037 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2; |
|---|
| 892 | 1038 | is_l2 = true; |
|---|
| 893 | 1039 | config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; |
|---|
| 894 | | - adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 895 | | - IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 1040 | + aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 1041 | + IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 896 | 1042 | break; |
|---|
| 897 | 1043 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: |
|---|
| 898 | 1044 | case HWTSTAMP_FILTER_NTP_ALL: |
|---|
| .. | .. |
|---|
| 903 | 1049 | if (hw->mac.type >= ixgbe_mac_X550) { |
|---|
| 904 | 1050 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_ALL; |
|---|
| 905 | 1051 | config->rx_filter = HWTSTAMP_FILTER_ALL; |
|---|
| 906 | | - adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED; |
|---|
| 1052 | + aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED; |
|---|
| 907 | 1053 | break; |
|---|
| 908 | 1054 | } |
|---|
| 909 | | - /* fall through */ |
|---|
| 1055 | + fallthrough; |
|---|
| 910 | 1056 | default: |
|---|
| 911 | 1057 | /* |
|---|
| 912 | 1058 | * register RXMTRL must be set in order to do V1 packets, |
|---|
| .. | .. |
|---|
| 914 | 1060 | * Delay_Req messages and hardware does not support |
|---|
| 915 | 1061 | * timestamping all packets => return error |
|---|
| 916 | 1062 | */ |
|---|
| 917 | | - adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED | |
|---|
| 918 | | - IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER); |
|---|
| 919 | 1063 | config->rx_filter = HWTSTAMP_FILTER_NONE; |
|---|
| 920 | 1064 | return -ERANGE; |
|---|
| 921 | 1065 | } |
|---|
| .. | .. |
|---|
| 947 | 1091 | IXGBE_TSYNCRXCTL_TYPE_ALL | |
|---|
| 948 | 1092 | IXGBE_TSYNCRXCTL_TSIP_UT_EN; |
|---|
| 949 | 1093 | config->rx_filter = HWTSTAMP_FILTER_ALL; |
|---|
| 950 | | - adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED; |
|---|
| 951 | | - adapter->flags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER; |
|---|
| 1094 | + aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED; |
|---|
| 1095 | + aflags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER; |
|---|
| 952 | 1096 | is_l2 = true; |
|---|
| 953 | 1097 | break; |
|---|
| 954 | 1098 | default: |
|---|
| .. | .. |
|---|
| 980 | 1124 | IXGBE_WRITE_REG(hw, IXGBE_RXMTRL, tsync_rx_mtrl); |
|---|
| 981 | 1125 | |
|---|
| 982 | 1126 | IXGBE_WRITE_FLUSH(hw); |
|---|
| 1127 | + |
|---|
| 1128 | + /* configure adapter flags only when HW is actually configured */ |
|---|
| 1129 | + adapter->flags = aflags; |
|---|
| 983 | 1130 | |
|---|
| 984 | 1131 | /* clear TX/RX time stamp registers, just to be sure */ |
|---|
| 985 | 1132 | ixgbe_ptp_clear_tx_timestamp(adapter); |
|---|
| .. | .. |
|---|
| 1066 | 1213 | struct cyclecounter cc; |
|---|
| 1067 | 1214 | unsigned long flags; |
|---|
| 1068 | 1215 | u32 incval = 0; |
|---|
| 1069 | | - u32 tsauxc = 0; |
|---|
| 1070 | 1216 | u32 fuse0 = 0; |
|---|
| 1071 | 1217 | |
|---|
| 1072 | 1218 | /* For some of the boards below this mask is technically incorrect. |
|---|
| .. | .. |
|---|
| 1097 | 1243 | cc.mult = 3; |
|---|
| 1098 | 1244 | cc.shift = 2; |
|---|
| 1099 | 1245 | } |
|---|
| 1100 | | - /* fallthrough */ |
|---|
| 1246 | + fallthrough; |
|---|
| 1101 | 1247 | case ixgbe_mac_x550em_a: |
|---|
| 1102 | 1248 | case ixgbe_mac_X550: |
|---|
| 1103 | 1249 | cc.read = ixgbe_ptp_read_X550; |
|---|
| 1104 | | - |
|---|
| 1105 | | - /* enable SYSTIME counter */ |
|---|
| 1106 | | - IXGBE_WRITE_REG(hw, IXGBE_SYSTIMR, 0); |
|---|
| 1107 | | - IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0); |
|---|
| 1108 | | - IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0); |
|---|
| 1109 | | - tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC); |
|---|
| 1110 | | - IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, |
|---|
| 1111 | | - tsauxc & ~IXGBE_TSAUXC_DISABLE_SYSTIME); |
|---|
| 1112 | | - IXGBE_WRITE_REG(hw, IXGBE_TSIM, IXGBE_TSIM_TXTS); |
|---|
| 1113 | | - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_TIMESYNC); |
|---|
| 1114 | | - |
|---|
| 1115 | | - IXGBE_WRITE_FLUSH(hw); |
|---|
| 1116 | 1250 | break; |
|---|
| 1117 | 1251 | case ixgbe_mac_X540: |
|---|
| 1118 | 1252 | cc.read = ixgbe_ptp_read_82599; |
|---|
| .. | .. |
|---|
| 1145 | 1279 | } |
|---|
| 1146 | 1280 | |
|---|
| 1147 | 1281 | /** |
|---|
| 1282 | + * ixgbe_ptp_init_systime - Initialize SYSTIME registers |
|---|
| 1283 | + * @adapter: the ixgbe private board structure |
|---|
| 1284 | + * |
|---|
| 1285 | + * Initialize and start the SYSTIME registers. |
|---|
| 1286 | + */ |
|---|
| 1287 | +static void ixgbe_ptp_init_systime(struct ixgbe_adapter *adapter) |
|---|
| 1288 | +{ |
|---|
| 1289 | + struct ixgbe_hw *hw = &adapter->hw; |
|---|
| 1290 | + u32 tsauxc; |
|---|
| 1291 | + |
|---|
| 1292 | + switch (hw->mac.type) { |
|---|
| 1293 | + case ixgbe_mac_X550EM_x: |
|---|
| 1294 | + case ixgbe_mac_x550em_a: |
|---|
| 1295 | + case ixgbe_mac_X550: |
|---|
| 1296 | + tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC); |
|---|
| 1297 | + |
|---|
| 1298 | + /* Reset SYSTIME registers to 0 */ |
|---|
| 1299 | + IXGBE_WRITE_REG(hw, IXGBE_SYSTIMR, 0); |
|---|
| 1300 | + IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0); |
|---|
| 1301 | + IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0); |
|---|
| 1302 | + |
|---|
| 1303 | + /* Reset interrupt settings */ |
|---|
| 1304 | + IXGBE_WRITE_REG(hw, IXGBE_TSIM, IXGBE_TSIM_TXTS); |
|---|
| 1305 | + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_TIMESYNC); |
|---|
| 1306 | + |
|---|
| 1307 | + /* Activate the SYSTIME counter */ |
|---|
| 1308 | + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, |
|---|
| 1309 | + tsauxc & ~IXGBE_TSAUXC_DISABLE_SYSTIME); |
|---|
| 1310 | + break; |
|---|
| 1311 | + case ixgbe_mac_X540: |
|---|
| 1312 | + case ixgbe_mac_82599EB: |
|---|
| 1313 | + /* Reset SYSTIME registers to 0 */ |
|---|
| 1314 | + IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0); |
|---|
| 1315 | + IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0); |
|---|
| 1316 | + break; |
|---|
| 1317 | + default: |
|---|
| 1318 | + /* Other devices aren't supported */ |
|---|
| 1319 | + return; |
|---|
| 1320 | + }; |
|---|
| 1321 | + |
|---|
| 1322 | + IXGBE_WRITE_FLUSH(hw); |
|---|
| 1323 | +} |
|---|
| 1324 | + |
|---|
| 1325 | +/** |
|---|
| 1148 | 1326 | * ixgbe_ptp_reset |
|---|
| 1149 | 1327 | * @adapter: the ixgbe private board structure |
|---|
| 1150 | 1328 | * |
|---|
| .. | .. |
|---|
| 1169 | 1347 | return; |
|---|
| 1170 | 1348 | |
|---|
| 1171 | 1349 | ixgbe_ptp_start_cyclecounter(adapter); |
|---|
| 1350 | + |
|---|
| 1351 | + ixgbe_ptp_init_systime(adapter); |
|---|
| 1172 | 1352 | |
|---|
| 1173 | 1353 | spin_lock_irqsave(&adapter->tmreg_lock, flags); |
|---|
| 1174 | 1354 | timecounter_init(&adapter->hw_tc, &adapter->hw_cc, |
|---|
| .. | .. |
|---|
| 1216 | 1396 | adapter->ptp_caps.pps = 1; |
|---|
| 1217 | 1397 | adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; |
|---|
| 1218 | 1398 | adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; |
|---|
| 1219 | | - adapter->ptp_caps.gettime64 = ixgbe_ptp_gettime; |
|---|
| 1399 | + adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; |
|---|
| 1220 | 1400 | adapter->ptp_caps.settime64 = ixgbe_ptp_settime; |
|---|
| 1221 | 1401 | adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; |
|---|
| 1222 | | - adapter->ptp_setup_sdp = ixgbe_ptp_setup_sdp_x540; |
|---|
| 1402 | + adapter->ptp_setup_sdp = ixgbe_ptp_setup_sdp_X540; |
|---|
| 1223 | 1403 | break; |
|---|
| 1224 | 1404 | case ixgbe_mac_82599EB: |
|---|
| 1225 | 1405 | snprintf(adapter->ptp_caps.name, |
|---|
| .. | .. |
|---|
| 1233 | 1413 | adapter->ptp_caps.pps = 0; |
|---|
| 1234 | 1414 | adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; |
|---|
| 1235 | 1415 | adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; |
|---|
| 1236 | | - adapter->ptp_caps.gettime64 = ixgbe_ptp_gettime; |
|---|
| 1416 | + adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; |
|---|
| 1237 | 1417 | adapter->ptp_caps.settime64 = ixgbe_ptp_settime; |
|---|
| 1238 | 1418 | adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; |
|---|
| 1239 | 1419 | break; |
|---|
| .. | .. |
|---|
| 1246 | 1426 | adapter->ptp_caps.n_alarm = 0; |
|---|
| 1247 | 1427 | adapter->ptp_caps.n_ext_ts = 0; |
|---|
| 1248 | 1428 | adapter->ptp_caps.n_per_out = 0; |
|---|
| 1249 | | - adapter->ptp_caps.pps = 0; |
|---|
| 1429 | + adapter->ptp_caps.pps = 1; |
|---|
| 1250 | 1430 | adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_X550; |
|---|
| 1251 | 1431 | adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; |
|---|
| 1252 | | - adapter->ptp_caps.gettime64 = ixgbe_ptp_gettime; |
|---|
| 1432 | + adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; |
|---|
| 1253 | 1433 | adapter->ptp_caps.settime64 = ixgbe_ptp_settime; |
|---|
| 1254 | 1434 | adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; |
|---|
| 1255 | | - adapter->ptp_setup_sdp = NULL; |
|---|
| 1435 | + adapter->ptp_setup_sdp = ixgbe_ptp_setup_sdp_X550; |
|---|
| 1256 | 1436 | break; |
|---|
| 1257 | 1437 | default: |
|---|
| 1258 | 1438 | adapter->ptp_clock = NULL; |
|---|