drivers/net/ethernet/renesas/rcar_gen4_ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/renesas/rcar_gen4_ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/renesas/rcar_gen4_ptp.c
Extension
.c
Size
5771 bytes
Lines
220
Domain
Driver Families
Bucket
drivers/net
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

struct rcar_gen4_ptp_private {
	void __iomem *addr;
	struct ptp_clock *clock;
	struct ptp_clock_info info;
	spinlock_t lock;	/* For multiple registers access */
	s64 default_addend;
	bool initialized;
};

#define ptp_to_priv(ptp)	container_of(ptp, struct rcar_gen4_ptp_private, info)

static int rcar_gen4_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
	s64 addend = ptp_priv->default_addend;
	bool neg_adj = scaled_ppm < 0;
	s64 diff;

	if (neg_adj)
		scaled_ppm = -scaled_ppm;
	diff = div_s64(addend * scaled_ppm_to_ppb(scaled_ppm), NSEC_PER_SEC);
	addend = neg_adj ? addend - diff : addend + diff;

	iowrite32(addend, ptp_priv->addr + PTPTIVC0_REG);

	return 0;
}

static void _rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
				   struct timespec64 *ts)
{
	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);

	lockdep_assert_held(&ptp_priv->lock);

	ts->tv_nsec = ioread32(ptp_priv->addr + PTPGPTPTM00_REG);
	ts->tv_sec = ioread32(ptp_priv->addr + PTPGPTPTM10_REG) |
		     ((s64)ioread32(ptp_priv->addr + PTPGPTPTM20_REG) << 32);
}

static int rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
				 struct timespec64 *ts)
{
	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
	unsigned long flags;

	spin_lock_irqsave(&ptp_priv->lock, flags);
	_rcar_gen4_ptp_gettime(ptp, ts);
	spin_unlock_irqrestore(&ptp_priv->lock, flags);

	return 0;
}

/* Caller must hold the lock */
static void _rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
				   const struct timespec64 *ts)
{
	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);

	iowrite32(1, ptp_priv->addr + PTPTMDC_REG);
	iowrite32(0, ptp_priv->addr + PTPTOVC20_REG);
	iowrite32(0, ptp_priv->addr + PTPTOVC10_REG);
	iowrite32(0, ptp_priv->addr + PTPTOVC00_REG);
	iowrite32(1, ptp_priv->addr + PTPTMEC_REG);
	iowrite32(ts->tv_sec >> 32, ptp_priv->addr + PTPTOVC20_REG);
	iowrite32(ts->tv_sec, ptp_priv->addr + PTPTOVC10_REG);
	iowrite32(ts->tv_nsec, ptp_priv->addr + PTPTOVC00_REG);
}

static int rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
				 const struct timespec64 *ts)
{
	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
	unsigned long flags;

	spin_lock_irqsave(&ptp_priv->lock, flags);
	_rcar_gen4_ptp_settime(ptp, ts);
	spin_unlock_irqrestore(&ptp_priv->lock, flags);

	return 0;
}

static int rcar_gen4_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
	struct timespec64 ts;
	unsigned long flags;
	s64 now;

	spin_lock_irqsave(&ptp_priv->lock, flags);

Annotation

Implementation Notes