void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { struct mlx4_dev *dev = mdev->dev; u64 temp_mult; memset(&mdev->cycles, 0, sizeof(mdev->cycles)); mdev->cycles.read = mlx4_en_read_clock; mdev->cycles.mask = CLOCKSOURCE_MASK(48); /* * we have hca_core_clock in MHz, so to translate cycles to nsecs * we need to divide cycles by freq and multiply by 1000; * in order to get precise result we shift left the value, * since we don't have floating point there; * at the end shift result back */ temp_mult = div_u64(((1ull * 1000) << 29), dev->caps.hca_core_clock); mdev->cycles.mult = (u32)temp_mult; mdev->cycles.shift = 29; timecounter_init(&mdev->clock, &mdev->cycles, ktime_to_ns(ktime_get_real())); memset(&mdev->compare, 0, sizeof(mdev->compare)); mdev->compare.source = &mdev->clock; mdev->compare.target = ktime_get_real; mdev->compare.num_samples = 10; timecompare_update(&mdev->compare, 0); }
void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { struct mlx4_dev *dev = mdev->dev; u64 ns; memset(&mdev->cycles, 0, sizeof(mdev->cycles)); mdev->cycles.read = mlx4_en_read_clock; mdev->cycles.mask = CLOCKSOURCE_MASK(48); /* Using shift to make calculation more accurate. Since current HW * clock frequency is 427 MHz, and cycles are given using a 48 bits * register, the biggest shift when calculating using u64, is 14 * (max_cycles * multiplier < 2^64) */ mdev->cycles.shift = 14; mdev->cycles.mult = clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift); timecounter_init(&mdev->clock, &mdev->cycles, ktime_to_ns(ktime_get_real())); /* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least once every wrap around. */ ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask); do_div(ns, NSEC_PER_SEC / 2 / HZ); mdev->overflow_period = ns; }
static inline void setup_clksrc(u32 freq) { struct clocksource *cs = &gpt_clocksource; struct gpt_device *dev = id_to_dev(GPT_CLKSRC_ID); struct timecounter *mt_timecounter; u64 start_count; pr_alert("setup_clksrc1: dev->base_addr=0x%lx GPT2_CON=0x%x\n", (unsigned long)dev->base_addr, __raw_readl(dev->base_addr)); cs->mult = clocksource_hz2mult(freq, cs->shift); sched_clock_register(mt_read_sched_clock, 32, freq); setup_gpt_dev_locked(dev, GPT_FREE_RUN, GPT_CLK_SRC_SYS, GPT_CLK_DIV_1, 0, NULL, 0); clocksource_register(cs); start_count = mt_read_sched_clock(); mt_cyclecounter.mult = cs->mult; mt_cyclecounter.shift = cs->shift; mt_timecounter = arch_timer_get_timecounter(); timecounter_init(mt_timecounter, &mt_cyclecounter, start_count); pr_alert("setup_clksrc1: mt_cyclecounter.mult=0x%x mt_cyclecounter.shift=0x%x\n", mt_cyclecounter.mult, mt_cyclecounter.shift); pr_alert("setup_clksrc2: dev->base_addr=0x%lx GPT2_CON=0x%x\n", (unsigned long)dev->base_addr, __raw_readl(dev->base_addr)); }
/** * ixgbe_ptp_reset * @adapter: the ixgbe private board structure * * When the MAC resets, all of the hardware configuration for timesync is * reset. This function should be called to re-enable the device for PTP, * using the last known settings. However, we do lose the current clock time, * so we fallback to resetting it based on the kernel's realtime clock. * * This function will maintain the hwtstamp_config settings, and it retriggers * the SDP output if it's enabled. */ void ixgbe_ptp_reset(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; unsigned long flags; /* reset the hardware timestamping mode */ ixgbe_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); switch (hw->mac.type) { case ixgbe_mac_X540: case ixgbe_mac_82599EB: ixgbe_ptp_start_cyclecounter(adapter); spin_lock_irqsave(&adapter->tmreg_lock, flags); timecounter_init(&adapter->hw_tc, &adapter->hw_cc, ktime_to_ns(ktime_get_real())); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); adapter->last_overflow_check = jiffies; break; default: return; } /* * Now that the shift has been calculated and the systime * registers reset, (re-)enable the Clock out feature */ if (adapter->ptp_setup_sdp) adapter->ptp_setup_sdp(adapter); }
/** * fec_ptp_settime * @ptp: the ptp clock structure * @ts: the timespec containing the new time for the cycle counter * * reset the timecounter to use a new base value instead of the kernel * wall timer value. */ static int fec_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct fec_enet_private *fep = container_of(ptp, struct fec_enet_private, ptp_caps); u64 ns; unsigned long flags; u32 counter; mutex_lock(&fep->ptp_clk_mutex); /* Check the ptp clock */ if (!fep->ptp_clk_on) { mutex_unlock(&fep->ptp_clk_mutex); return -EINVAL; } ns = timespec64_to_ns(ts); /* Get the timer value based on timestamp. * Update the counter with the masked value. */ counter = ns & fep->cc.mask; spin_lock_irqsave(&fep->tmreg_lock, flags); writel(counter, fep->hwp + FEC_ATIME); timecounter_init(&fep->tc, &fep->cc, ns); spin_unlock_irqrestore(&fep->tmreg_lock, flags); mutex_unlock(&fep->ptp_clk_mutex); return 0; }
static void __init arch_counter_register(unsigned type) { u64 start_count; /* Register the CP15 based counter if we have one */ if (type & ARCH_CP15_TIMER) { if (IS_ENABLED(CONFIG_ARM64) || arch_timer_use_virtual) arch_timer_read_counter = arch_counter_get_cntvct; else arch_timer_read_counter = arch_counter_get_cntpct; } else { arch_timer_read_counter = arch_counter_get_cntvct_mem; /* If the clocksource name is "arch_sys_counter" the * VDSO will attempt to read the CP15-based counter. * Ensure this does not happen when CP15-based * counter is not available. */ clocksource_counter.name = "arch_mem_counter"; } start_count = arch_timer_read_counter(); clocksource_register_hz(&clocksource_counter, arch_timer_rate); cyclecounter.mult = clocksource_counter.mult; cyclecounter.shift = clocksource_counter.shift; timecounter_init(&timecounter, &cyclecounter, start_count); /* 56 bits minimum, so we assume worst case rollover */ sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate); }
/** * fec_ptp_start_cyclecounter - create the cycle counter from hw * @ndev: network device * * this function initializes the timecounter and cyclecounter * structures for use in generated a ns counter from the arbitrary * fixed point cycles registers in the hardware. */ void fec_ptp_start_cyclecounter(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); unsigned long flags; int inc; inc = 1000000000 / fep->cycle_speed; /* grab the ptp lock */ spin_lock_irqsave(&fep->tmreg_lock, flags); /* 1ns counter */ writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC); /* use free running count */ writel(0, fep->hwp + FEC_ATIME_EVT_PERIOD); writel(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL); memset(&fep->cc, 0, sizeof(fep->cc)); fep->cc.read = fec_ptp_read; fep->cc.mask = CLOCKSOURCE_MASK(32); fep->cc.shift = 31; fep->cc.mult = FEC_CC_MULT; /* reset the ns time counter */ timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real())); spin_unlock_irqrestore(&fep->tmreg_lock, flags); }
static int __init init_microblaze_timecounter(void) { microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, microblaze_cc.shift); timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); return 0; }
static int __init init_xilinx_timecounter(void) { xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, xilinx_cc.shift); timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock()); return 0; }
void mlx5e_timestamp_init(struct mlx5e_priv *priv) { struct mlx5e_tstamp *tstamp = &priv->tstamp; u64 ns; u64 frac = 0; u32 dev_freq; mlx5e_timestamp_init_config(tstamp); dev_freq = MLX5_CAP_GEN(priv->mdev, device_frequency_khz); if (!dev_freq) { mlx5_core_warn(priv->mdev, "invalid device_frequency_khz, aborting HW clock init\n"); return; } rwlock_init(&tstamp->lock); tstamp->cycles.read = mlx5e_read_internal_timer; tstamp->cycles.shift = MLX5E_CYCLES_SHIFT; tstamp->cycles.mult = clocksource_khz2mult(dev_freq, tstamp->cycles.shift); tstamp->nominal_c_mult = tstamp->cycles.mult; tstamp->cycles.mask = CLOCKSOURCE_MASK(41); tstamp->mdev = priv->mdev; timecounter_init(&tstamp->clock, &tstamp->cycles, ktime_to_ns(ktime_get_real())); /* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least once every wrap around. */ ns = cyclecounter_cyc2ns(&tstamp->cycles, tstamp->cycles.mask, frac, &frac); do_div(ns, NSEC_PER_SEC / 2 / HZ); tstamp->overflow_period = ns; INIT_DELAYED_WORK(&tstamp->overflow_work, mlx5e_timestamp_overflow); if (tstamp->overflow_period) schedule_delayed_work(&tstamp->overflow_work, 0); else mlx5_core_warn(priv->mdev, "invalid overflow period, overflow_work is not scheduled\n"); /* Configure the PHC */ tstamp->ptp_info = mlx5e_ptp_clock_info; snprintf(tstamp->ptp_info.name, 16, "mlx5 ptp"); tstamp->ptp = ptp_clock_register(&tstamp->ptp_info, &priv->mdev->pdev->dev); if (IS_ERR(tstamp->ptp)) { mlx5_core_warn(priv->mdev, "ptp_clock_register failed %ld\n", PTR_ERR(tstamp->ptp)); tstamp->ptp = NULL; } }
static int mlx5e_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct mlx5e_tstamp *tstamp = container_of(ptp, struct mlx5e_tstamp, ptp_info); u64 ns = timespec64_to_ns(ts); unsigned long flags; write_lock_irqsave(&tstamp->lock, flags); timecounter_init(&tstamp->clock, &tstamp->cycles, ns); write_unlock_irqrestore(&tstamp->lock, flags); return 0; }
/** * igb_ptp_reset - Re-enable the adapter for PTP following a reset. * @adapter: Board private structure. * * This function handles the reset work required to re-enable the PTP device. **/ void igb_ptp_reset(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; unsigned long flags; /* reset the tstamp_config */ igb_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); spin_lock_irqsave(&adapter->tmreg_lock, flags); switch (adapter->hw.mac.type) { case e1000_82576: /* Dial the nominal frequency. */ wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); break; case e1000_82580: case e1000_i354: case e1000_i350: case e1000_i210: case e1000_i211: wr32(E1000_TSAUXC, 0x0); wr32(E1000_TSSDP, 0x0); wr32(E1000_TSIM, TSYNC_INTERRUPTS | (adapter->pps_sys_wrap_on ? TSINTR_SYS_WRAP : 0)); wr32(E1000_IMS, E1000_IMS_TS); break; default: /* No work to do. */ goto out; } /* Re-initialize the timer. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec64 ts = ktime_to_timespec64(ktime_get_real()); igb_ptp_write_i210(adapter, &ts); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); } out: spin_unlock_irqrestore(&adapter->tmreg_lock, flags); wrfl(); if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK) schedule_delayed_work(&adapter->ptp_overflow_work, IGB_SYSTIM_OVERFLOW_PERIOD); }
void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { panic("Disabled"); #if 0 // AKAROS_PORT struct mlx4_dev *dev = mdev->dev; unsigned long flags; uint64_t ns, zero = 0; rwlock_init(&mdev->clock_lock); memset(&mdev->cycles, 0, sizeof(mdev->cycles)); mdev->cycles.read = mlx4_en_read_clock; mdev->cycles.mask = CLOCKSOURCE_MASK(48); /* Using shift to make calculation more accurate. Since current HW * clock frequency is 427 MHz, and cycles are given using a 48 bits * register, the biggest shift when calculating using u64, is 14 * (max_cycles * multiplier < 2^64) */ mdev->cycles.shift = 14; mdev->cycles.mult = clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift); mdev->nominal_c_mult = mdev->cycles.mult; write_lock_irqsave(&mdev->clock_lock, flags); timecounter_init(&mdev->clock, &mdev->cycles, epoch_nsec()); write_unlock_irqrestore(&mdev->clock_lock, flags); /* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least once every wrap around. */ ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask, zero, &zero); do_div(ns, NSEC_PER_SEC / 2 / HZ); mdev->overflow_period = ns; /* Configure the PHC */ mdev->ptp_clock_info = mlx4_en_ptp_clock_info; snprintf(mdev->ptp_clock_info.name, 16, "mlx4 ptp"); mdev->ptp_clock = ptp_clock_register(&mdev->ptp_clock_info, &mdev->pdev->dev); if (IS_ERR(mdev->ptp_clock)) { mdev->ptp_clock = NULL; mlx4_err(mdev, "ptp_clock_register failed\n"); } else { mlx4_info(mdev, "registered PHC clock\n"); } #endif }
void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { struct mlx4_dev *dev = mdev->dev; unsigned long flags; u64 ns; /* mlx4_en_init_timestamp is called for each netdev. * mdev->ptp_clock is common for all ports, skip initialization if * was done for other port. */ if (mdev->ptp_clock) return; rwlock_init(&mdev->clock_lock); memset(&mdev->cycles, 0, sizeof(mdev->cycles)); mdev->cycles.read = mlx4_en_read_clock; mdev->cycles.mask = CLOCKSOURCE_MASK(48); mdev->cycles.shift = freq_to_shift(dev->caps.hca_core_clock); mdev->cycles.mult = clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift); mdev->nominal_c_mult = mdev->cycles.mult; write_lock_irqsave(&mdev->clock_lock, flags); timecounter_init(&mdev->clock, &mdev->cycles, ktime_to_ns(ktime_get_real())); write_unlock_irqrestore(&mdev->clock_lock, flags); /* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least once every wrap around. */ ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask); do_div(ns, NSEC_PER_SEC / 2 / HZ); mdev->overflow_period = ns; /* Configure the PHC */ mdev->ptp_clock_info = mlx4_en_ptp_clock_info; snprintf(mdev->ptp_clock_info.name, 16, "mlx4 ptp"); mdev->ptp_clock = ptp_clock_register(&mdev->ptp_clock_info, &mdev->pdev->dev); if (IS_ERR(mdev->ptp_clock)) { mdev->ptp_clock = NULL; mlx4_err(mdev, "ptp_clock_register failed\n"); } else { mlx4_info(mdev, "registered PHC clock\n"); } }
/** * mlx4_en_phc_adjtime - Shift the time of the hardware clock * @ptp: ptp clock structure * @delta: Desired change in nanoseconds * * Adjust the timer by resetting the timecounter structure. **/ static int mlx4_en_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev, ptp_clock_info); unsigned long flags; s64 now; write_lock_irqsave(&mdev->clock_lock, flags); now = timecounter_read(&mdev->clock); now += delta; timecounter_init(&mdev->clock, &mdev->cycles, now); write_unlock_irqrestore(&mdev->clock_lock, flags); return 0; }
/** * e1000e_phc_adjtime - Shift the time of the hardware clock * @ptp: ptp clock structure * @delta: Desired change in nanoseconds * * Adjust the timer by resetting the timecounter structure. **/ static int e1000e_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, ptp_clock_info); unsigned long flags; s64 now; spin_lock_irqsave(&adapter->systim_lock, flags); now = timecounter_read(&adapter->tc); now += delta; timecounter_init(&adapter->tc, &adapter->cc, now); spin_unlock_irqrestore(&adapter->systim_lock, flags); return 0; }
/** * mlx4_en_phc_settime - Set the current time on the hardware clock * @ptp: ptp clock structure * @ts: timespec containing the new time for the cycle counter * * Reset the timecounter to use a new base value instead of the kernel * wall timer value. **/ static int mlx4_en_phc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct mlx4_en_dev *mdev = container_of(ptp, struct mlx4_en_dev, ptp_clock_info); u64 ns = timespec64_to_ns(ts); unsigned long flags; /* reset the timecounter */ write_lock_irqsave(&mdev->clock_lock, flags); timecounter_init(&mdev->clock, &mdev->cycles, ns); write_unlock_irqrestore(&mdev->clock_lock, flags); return 0; }
static void __init arch_counter_register(unsigned type) { u64 start_count; /* Register the CP15 based counter if we have one */ if (type & ARCH_CP15_TIMER) arch_timer_read_counter = arch_counter_get_cntvct_cp15; else arch_timer_read_counter = arch_counter_get_cntvct_mem; start_count = arch_timer_read_counter(); clocksource_register_hz(&clocksource_counter, arch_timer_rate); cyclecounter.mult = clocksource_counter.mult; cyclecounter.shift = clocksource_counter.shift; timecounter_init(&timecounter, &cyclecounter, start_count); }
void xgbe_ptp_register(struct xgbe_prv_data *pdata) { struct ptp_clock_info *info = &pdata->ptp_clock_info; struct ptp_clock *clock; struct cyclecounter *cc = &pdata->tstamp_cc; u64 dividend; snprintf(info->name, sizeof(info->name), "%s", netdev_name(pdata->netdev)); info->owner = THIS_MODULE; info->max_adj = clk_get_rate(pdata->ptpclk); info->adjfreq = xgbe_adjfreq; info->adjtime = xgbe_adjtime; info->gettime = xgbe_gettime; info->settime = xgbe_settime; info->enable = xgbe_enable; clock = ptp_clock_register(info, pdata->dev); if (IS_ERR(clock)) { dev_err(pdata->dev, "ptp_clock_register failed\n"); return; } pdata->ptp_clock = clock; /* Calculate the addend: * addend = 2^32 / (PTP ref clock / 50Mhz) * = (2^32 * 50Mhz) / PTP ref clock */ dividend = 50000000; dividend <<= 32; pdata->tstamp_addend = div_u64(dividend, clk_get_rate(pdata->ptpclk)); /* Setup the timecounter */ cc->read = xgbe_cc_read; cc->mask = CLOCKSOURCE_MASK(64); cc->mult = 1; cc->shift = 0; timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, ktime_to_ns(ktime_get_real())); /* Disable all timestamping to start */ XGMAC_IOWRITE(pdata, MAC_TCR, 0); pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF; pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; }
/** * e1000e_phc_settime - Set the current time on the hardware clock * @ptp: ptp clock structure * @ts: timespec containing the new time for the cycle counter * * Reset the timecounter to use a new base value instead of the kernel * wall timer value. **/ static int e1000e_phc_settime(struct ptp_clock_info *ptp, const struct timespec *ts) { struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, ptp_clock_info); unsigned long flags; u64 ns; ns = timespec_to_ns(ts); /* reset the timecounter */ spin_lock_irqsave(&adapter->systim_lock, flags); timecounter_init(&adapter->tc, &adapter->cc, ns); spin_unlock_irqrestore(&adapter->systim_lock, flags); return 0; }
/** * igb_ptp_reset - Re-enable the adapter for PTP following a reset. * @adapter: Board private structure. * * This function handles the reset work required to re-enable the PTP device. **/ void igb_ptp_reset(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; unsigned long flags; if (!(adapter->flags & IGB_FLAG_PTP)) return; /* reset the tstamp_config */ igb_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); spin_lock_irqsave(&adapter->tmreg_lock, flags); switch (adapter->hw.mac.type) { case e1000_82576: /* Dial the nominal frequency. */ E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); E1000_WRITE_REG(hw, E1000_TSSDP, 0x0); E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); break; default: /* No work to do. */ goto out; } /* Re-initialize the timer. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec64 ts64 = ktime_to_timespec64(ktime_get_real()); igb_ptp_write_i210(adapter, &ts64); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); } out: spin_unlock_irqrestore(&adapter->tmreg_lock, flags); }
static int igb_ptp_adjtime_82576(struct ptp_clock_info *ptp, s64 delta) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; s64 now; spin_lock_irqsave(&igb->tmreg_lock, flags); now = timecounter_read(&igb->tc); now += delta; timecounter_init(&igb->tc, &igb->cc, now); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; }
/** * fec_ptp_settime * @ptp: the ptp clock structure * @ts: the timespec containing the new time for the cycle counter * * reset the timecounter to use a new base value instead of the kernel * wall timer value. */ static int fec_ptp_settime(struct ptp_clock_info *ptp, const struct timespec *ts) { struct fec_enet_private *fep = container_of(ptp, struct fec_enet_private, ptp_caps); u64 ns; unsigned long flags; ns = ts->tv_sec * 1000000000ULL; ns += ts->tv_nsec; spin_lock_irqsave(&fep->tmreg_lock, flags); timecounter_init(&fep->tc, &fep->cc, ns); spin_unlock_irqrestore(&fep->tmreg_lock, flags); return 0; }
/** * ixgbe_ptp_settime * @ptp - the ptp clock structure * @ts - the timespec containing the new time for the cycle counter * * reset the timecounter to use a new base value instead of the kernel * wall timer value. */ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp, const struct timespec *ts) { struct ixgbe_adapter *adapter = container_of(ptp, struct ixgbe_adapter, ptp_caps); u64 ns; unsigned long flags; ns = ts->tv_sec * 1000000000ULL; ns += ts->tv_nsec; /* reset the timecounter */ spin_lock_irqsave(&adapter->tmreg_lock, flags); timecounter_init(&adapter->tc, &adapter->cc, ns); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); return 0; }
static int xgbe_settime(struct ptp_clock_info *info, const struct timespec *ts) { struct xgbe_prv_data *pdata = container_of(info, struct xgbe_prv_data, ptp_clock_info); unsigned long flags; u64 nsec; nsec = timespec_to_ns(ts); spin_lock_irqsave(&pdata->tstamp_lock, flags); timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec); spin_unlock_irqrestore(&pdata->tstamp_lock, flags); return 0; }
static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; u64 ns; ns = timespec64_to_ns(ts); spin_lock_irqsave(&igb->tmreg_lock, flags); timecounter_init(&igb->tc, &igb->cc, ns); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; }
static void __init arch_counter_register(unsigned type) { u64 start_count; /* Register the CP15 based counter if we have one */ if (type & ARCH_CP15_TIMER) arch_timer_read_counter = arch_counter_get_cntvct_cp15; else arch_timer_read_counter = arch_counter_get_cntvct_mem; start_count = arch_timer_read_counter(); clocksource_register_hz(&clocksource_counter, arch_timer_rate); cyclecounter.mult = clocksource_counter.mult; cyclecounter.shift = clocksource_counter.shift; timecounter_init(&timecounter, &cyclecounter, start_count); /* 56 bits minimum, so we assume worst case rollover */ sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate); }
/** * fec_ptp_adjtime * @ptp: the ptp clock structure * @delta: offset to adjust the cycle counter by * * adjust the timer by resetting the timecounter structure. */ static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct fec_enet_private *fep = container_of(ptp, struct fec_enet_private, ptp_caps); unsigned long flags; u64 now; spin_lock_irqsave(&fep->tmreg_lock, flags); now = timecounter_read(&fep->tc); now += delta; /* reset the timecounter */ timecounter_init(&fep->tc, &fep->cc, now); spin_unlock_irqrestore(&fep->tmreg_lock, flags); return 0; }
static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta) { struct xgbe_prv_data *pdata = container_of(info, struct xgbe_prv_data, ptp_clock_info); unsigned long flags; u64 nsec; spin_lock_irqsave(&pdata->tstamp_lock, flags); nsec = timecounter_read(&pdata->tstamp_tc); nsec += delta; timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec); spin_unlock_irqrestore(&pdata->tstamp_lock, flags); return 0; }
/** * ixgbe_ptp_adjtime * @ptp - the ptp clock structure * @delta - offset to adjust the cycle counter by * * adjust the timer by resetting the timecounter structure. */ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct ixgbe_adapter *adapter = container_of(ptp, struct ixgbe_adapter, ptp_caps); unsigned long flags; u64 now; spin_lock_irqsave(&adapter->tmreg_lock, flags); now = timecounter_read(&adapter->tc); now += delta; /* reset the timecounter */ timecounter_init(&adapter->tc, &adapter->cc, now); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); return 0; }