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);
}
Beispiel #2
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);
}
Beispiel #5
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 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;
}
Beispiel #6
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);
}
Beispiel #8
0
static int __init init_microblaze_timecounter(void)
{
	microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
				microblaze_cc.shift);

	timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());

	return 0;
}
Beispiel #9
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;
}
Beispiel #10
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;
	}
}
Beispiel #11
0
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;
}
Beispiel #12
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);
}
Beispiel #13
0
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
}
Beispiel #14
0
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;
}
Beispiel #17
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);
}
Beispiel #19
0
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;
}
Beispiel #21
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);
}
Beispiel #22
0
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;
}
Beispiel #24
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;
}
Beispiel #25
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;
}
Beispiel #26
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;
}
Beispiel #27
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;
}
Beispiel #29
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;
}
Beispiel #30
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;
}