drivers/ptp/ptp_qoriq.c

Source file repositories/reference/linux-study-clean/drivers/ptp/ptp_qoriq.c

File Facts

System
Linux kernel
Corpus path
drivers/ptp/ptp_qoriq.c
Extension
.c
Size
17326 bytes
Lines
701
Domain
Driver Families
Bucket
drivers/ptp
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (update_event) {
			event.timestamp = ((u64) hi) << 32;
			event.timestamp |= lo;
			ptp_clock_event(ptp_qoriq->clock, &event);
		}

		if (!ptp_qoriq->extts_fifo_support)
			break;
	} while (ptp_qoriq->read(&regs->ctrl_regs->tmr_stat) & valid);

	return 0;
}
EXPORT_SYMBOL_GPL(extts_clean_up);

/*
 * Interrupt service routine
 */

irqreturn_t ptp_qoriq_isr(int irq, void *priv)
{
	struct ptp_qoriq *ptp_qoriq = priv;
	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
	struct ptp_clock_event event;
	u32 ack = 0, mask, val, irqs;

	spin_lock(&ptp_qoriq->lock);

	val = ptp_qoriq->read(&regs->ctrl_regs->tmr_tevent);
	mask = ptp_qoriq->read(&regs->ctrl_regs->tmr_temask);

	spin_unlock(&ptp_qoriq->lock);

	irqs = val & mask;

	if (irqs & ETS1) {
		ack |= ETS1;
		extts_clean_up(ptp_qoriq, 0, true);
	}

	if (irqs & ETS2) {
		ack |= ETS2;
		extts_clean_up(ptp_qoriq, 1, true);
	}

	if (irqs & PP1) {
		ack |= PP1;
		event.type = PTP_CLOCK_PPS;
		ptp_clock_event(ptp_qoriq->clock, &event);
	}

	if (ack) {
		ptp_qoriq->write(&regs->ctrl_regs->tmr_tevent, ack);
		return IRQ_HANDLED;
	} else
		return IRQ_NONE;
}
EXPORT_SYMBOL_GPL(ptp_qoriq_isr);

/*
 * PTP clock operations
 */

int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
	u64 adj, diff;
	u32 tmr_add;
	int neg_adj = 0;
	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;

	if (scaled_ppm < 0) {
		neg_adj = 1;
		scaled_ppm = -scaled_ppm;
	}
	tmr_add = ptp_qoriq->tmr_add;
	adj = tmr_add;

	/*
	 * Calculate diff and round() to the nearest integer
	 *
	 * diff = adj * (ppb / 1000000000)
	 *      = adj * scaled_ppm / 65536000000
	 */
	diff = mul_u64_u64_div_u64(adj, scaled_ppm, 32768000000);
	diff = DIV64_U64_ROUND_UP(diff, 2);

	tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
	ptp_qoriq->write(&regs->ctrl_regs->tmr_add, tmr_add);

	return 0;

Annotation

Implementation Notes