drivers/net/ethernet/intel/igc/igc_ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/igc/igc_ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/igc/igc_ptp.c
Extension
.c
Size
36752 bytes
Lines
1389
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

if (on) {
			pin = ptp_find_pin(igc->ptp_clock, PTP_PF_EXTTS,
					   rq->extts.index);
			if (pin < 0)
				return -EBUSY;
		}
		if (rq->extts.index == 1) {
			tsauxc_mask = IGC_TSAUXC_EN_TS1;
			tsim_mask = IGC_TSICR_AUTT1;
		} else {
			tsauxc_mask = IGC_TSAUXC_EN_TS0;
			tsim_mask = IGC_TSICR_AUTT0;
		}
		spin_lock_irqsave(&igc->tmreg_lock, flags);
		tsauxc = rd32(IGC_TSAUXC);
		tsim = rd32(IGC_TSIM);
		if (on) {
			igc_pin_extts(igc, rq->extts.index, pin);
			tsauxc |= tsauxc_mask;
			tsim |= tsim_mask;
		} else {
			tsauxc &= ~tsauxc_mask;
			tsim &= ~tsim_mask;
		}
		wr32(IGC_TSAUXC, tsauxc);
		wr32(IGC_TSIM, tsim);
		spin_unlock_irqrestore(&igc->tmreg_lock, flags);
		return 0;

	case PTP_CLK_REQ_PEROUT:
		if (on) {
			pin = ptp_find_pin(igc->ptp_clock, PTP_PF_PEROUT,
					   rq->perout.index);
			if (pin < 0)
				return -EBUSY;
		}
		ts.tv_sec = rq->perout.period.sec;
		ts.tv_nsec = rq->perout.period.nsec;
		ns = timespec64_to_ns(&ts);
		ns = ns >> 1;
		if (on && (ns <= 70000000LL || ns == 125000000LL ||
			   ns == 250000000LL || ns == 500000000LL)) {
			if (ns < 8LL)
				return -EINVAL;
			use_freq = 1;
		}
		ts = ns_to_timespec64(ns);
		if (rq->perout.index == 1) {
			if (use_freq) {
				tsauxc_mask = IGC_TSAUXC_EN_CLK1 | IGC_TSAUXC_ST1;
				tsim_mask = 0;
			} else {
				tsauxc_mask = IGC_TSAUXC_EN_TT1;
				tsim_mask = IGC_TSICR_TT1;
			}
			trgttiml = IGC_TRGTTIML1;
			trgttimh = IGC_TRGTTIMH1;
			freqout = IGC_FREQOUT1;
		} else {
			if (use_freq) {
				tsauxc_mask = IGC_TSAUXC_EN_CLK0 | IGC_TSAUXC_ST0;
				tsim_mask = 0;
			} else {
				tsauxc_mask = IGC_TSAUXC_EN_TT0;
				tsim_mask = IGC_TSICR_TT0;
			}
			trgttiml = IGC_TRGTTIML0;
			trgttimh = IGC_TRGTTIMH0;
			freqout = IGC_FREQOUT0;
		}
		spin_lock_irqsave(&igc->tmreg_lock, flags);
		tsauxc = rd32(IGC_TSAUXC);
		tsim = rd32(IGC_TSIM);
		if (rq->perout.index == 1) {
			tsauxc &= ~(IGC_TSAUXC_EN_TT1 | IGC_TSAUXC_EN_CLK1 |
				    IGC_TSAUXC_ST1);
			tsim &= ~IGC_TSICR_TT1;
		} else {
			tsauxc &= ~(IGC_TSAUXC_EN_TT0 | IGC_TSAUXC_EN_CLK0 |
				    IGC_TSAUXC_ST0);
			tsim &= ~IGC_TSICR_TT0;
		}
		if (on) {
			struct timespec64 safe_start;
			int i = rq->perout.index;

			igc_pin_perout(igc, i, pin, use_freq);
			igc_ptp_read(igc, &safe_start);

			/* PPS output start time is triggered by Target time(TT)

Annotation

Implementation Notes