drivers/net/ethernet/intel/e1000e/ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/e1000e/ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/e1000e/ptp.c
Extension
.c
Size
9897 bytes
Lines
356
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 1999 - 2018 Intel Corporation. */

/* PTP 1588 Hardware Clock (PHC)
 * Derived from PTP Hardware Clock driver for Intel 82576 and 82580 (igb)
 * Copyright (C) 2011 Richard Cochran <richardcochran@gmail.com>
 */

#include "e1000.h"

#ifdef CONFIG_E1000E_HWTS
#include <linux/clocksource.h>
#include <linux/ktime.h>
#include <asm/tsc.h>
#endif

/**
 * e1000e_phc_adjfine - adjust the frequency of the hardware clock
 * @ptp: ptp clock structure
 * @delta: Desired frequency chance in scaled parts per million
 *
 * Adjust the frequency of the PHC cycle counter by the indicated delta from
 * the base frequency.
 *
 * Scaled parts per million is ppm but with a 16 bit binary fractional field.
 **/
static int e1000e_phc_adjfine(struct ptp_clock_info *ptp, long delta)
{
	struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter,
						     ptp_clock_info);
	struct e1000_hw *hw = &adapter->hw;
	unsigned long flags;
	u64 incvalue;
	u32 timinca;
	s32 ret_val;

	/* Get the System Time Register SYSTIM base frequency */
	ret_val = e1000e_get_base_timinca(adapter, &timinca);
	if (ret_val)
		return ret_val;

	spin_lock_irqsave(&adapter->systim_lock, flags);

	incvalue = timinca & E1000_TIMINCA_INCVALUE_MASK;
	incvalue = adjust_by_scaled_ppm(incvalue, delta);

	timinca &= ~E1000_TIMINCA_INCVALUE_MASK;
	timinca |= incvalue;

	ew32(TIMINCA, timinca);

	adapter->ptp_delta = delta;

	spin_unlock_irqrestore(&adapter->systim_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;

	spin_lock_irqsave(&adapter->systim_lock, flags);
	timecounter_adjtime(&adapter->tc, delta);
	spin_unlock_irqrestore(&adapter->systim_lock, flags);

	return 0;
}

#ifdef CONFIG_E1000E_HWTS
#define MAX_HW_WAIT_COUNT (3)

/**
 * e1000e_phc_get_syncdevicetime - Callback given to timekeeping code reads system/device registers
 * @device: current device time
 * @system: system counter value read synchronously with device time
 * @ctx: context provided by timekeeping code
 *
 * Read device and system (ART) clock simultaneously and return the corrected
 * clock values in ns.
 **/

Annotation

Implementation Notes