Thread (5 messages) 5 messages, 2 authors, 1d ago

Re: [PATCH net-next v4 2/3] ptp: Add driver for R-Car Gen4

From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Date: 2026-07-02 14:39:42
Also in: linux-devicetree, linux-renesas-soc, lkml

On 02/07/2026 13:55, Niklas Söderlund wrote:
Add driver for the gPTP timer found on R-Car Gen4 devices. The timer is
system-wide and shared by different Ethernet devices on each Gen4
platform. The operation of the timer is however not completely in
depended of the systems Ethernet devices.

   - On R-Car S4 is gated by the RSWITCH Ethernet module clock.

   - On R-Car V4H is gated by the RTSN Ethernet module clock.

   - On R-Car V4M is gated by its own module clock, the system have
     neither RTSN or RSWITCH device. But the module clock is the same as
     RTSN on V4H and the documentation referees to it as tsn (EtherTSN).

The gPTP device do have its own register space on all three platforms.
But on S4 and V4H it will share its clock and reset property with
RSWITCH or RTSN, respectively.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
* Changes since v3
- Clamp increment calculated to register limitations.
- Check return value of clk_get_rate().
- Disable PM if ptp_clock_register() fails.
---
[...]
+struct ptp_rcar_gen4_priv {
+	void __iomem *base;
+	struct clk *clk;
+
+	struct ptp_clock *clock;
+	struct ptp_clock_info info;
+
+	spinlock_t lock;	/* Registers access. */
+	s64 default_addend;
+};
+
+#define ptp_to_priv(ptp) container_of(ptp, struct ptp_rcar_gen4_priv, info)
+
+static int ptp_rcar_gen4_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+	struct ptp_rcar_gen4_priv *priv = ptp_to_priv(ptp);
+	s64 addend = priv->default_addend;
+	bool neg_adj = scaled_ppm < 0;
+	unsigned long flags;
+	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;
+
+	/* Clamp value to register limits, defined as in nanoseconds.
+	 * bit[31:27] - integer
+	 * bit[26:0]  - decimal
+	 */
+	addend = clamp_val(addend, 0, UINT_MAX);
is it always positive number?
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iowrite32(addend, priv->base + PTPTIVC0_REG);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
[...]
+static struct ptp_clock_info ptp_rcar_gen4_info = {
+	.owner = THIS_MODULE,
+	.name = "R-Car Gen4 gPTP",
+	.max_adj = 50000000,
even though clamping addend may work, I would suggest adjusting
".max_adj" value to the one which will not make addend overflow.
And as a reminder, .max_adj is the absolute value in ppb that can be set
for a single call of .adjfine - the value is checked against
[-(.max_adj),.max_adj] range.
+	.adjfine = ptp_rcar_gen4_adjfine,
+	.adjtime = ptp_rcar_gen4_adjtime,
+	.gettime64 = ptp_rcar_gen4_gettime,
+	.settime64 = ptp_rcar_gen4_settime,
+};
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help