From: "Niklas Söderlund" <niklas.soderlund+renesas@ragnatech.se>
To: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Cc: Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Geert Uytterhoeven <geert+renesas@glider.be>,
Magnus Damm <magnus.damm@gmail.com>,
Richard Cochran <richardcochran@gmail.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"DavidS. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org
Subject: Re: [PATCH net-next v4 2/3] ptp: Add driver for R-Car Gen4
Date: Thu, 16 Jul 2026 22:35:38 +0200 [thread overview]
Message-ID: <20260716203538.GD1593320@ragnatech.se> (raw)
In-Reply-To: <21d2e632-5307-4b48-be7b-1269b55f70fe@linux.dev>
Hi Vadim,
Thanks for your feedback.
On 2026-07-02 15:39:25 +0100, Vadim Fedorenko wrote:
> 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?
Yes.
The value written to the PTPTIVC0_REG register is the timer increment in
ns per clock pulse. The PTP is clocked by different rates on different
SoC. 200Mhz on V4H and 320Mhz on S4. On each pulse the PTP timer is
incremented by this value. For example,
If clock frequency is 50 MHz, 100Mhz, 200Mhz, 320MHz or 400MHz,
it should be respectively set to a value around 0xA0000000, 0x50000000,
0x28000000, 0x19000000 or 0x14000000.
>
> > +
> > + 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.
Thanks for the reminder, but is this not then correct and prevents any
overflow? From the calculations above.
(a) s64 addend = priv->default_addend;
...
(b) if (neg_adj)
(b) scaled_ppm = -scaled_ppm;
(c) diff = div_s64(addend * scaled_ppm_to_ppb(scaled_ppm), NSEC_PER_SEC);
(d) addend = neg_adj ? addend - diff : addend + diff;
Section (a) copies the default addend value. This value is calculated at
probe time as a function of the PTP module clock (50 MHz, 100Mhz,
200Mhz, 320MHz or 400MHz) to a known value. The max value being
0xA0000000 for a 50Mhz module clock.
Sections (b) and (d) deals with the value we add at each clock tick is
in fact based on the PTP module clock itself.
So the one place we could overflow is in section (c). Lets look at the
worse case scenario.
addend = priv->default_addend = <from PTP clock worse case 50 MHz> = 0xA0000000
scaled_ppm_to_ppb(scaled_ppm) = .max_adj = 50000000
addend * scaled_ppm_to_ppb(scaled_ppm)
= 0xA0000000 * 50000000
= 0x1DCD65000000000
That is OK and fits inside a s64.
div_s64(0x1DCD65000000000, NSEC_PER_SEC)
= div_s64(0x1DCD65000000000, 1000000000L)
= 0x8000000
That is OK and does not overflow.
But I agree it's not very clear and depends on knowing from the
datasheet that the possible PTP clock rates are.
How can I best move forward here? Drop the clamp added and depend on the
.max_adj value to prevent the overflow with the implicit knowledge of
the clock rates? I can extend the comment in the probe function of how
priv->default_addend is computed, but for somebody looking at the
calculation that might not help much.
>
> > + .adjfine = ptp_rcar_gen4_adjfine,
> > + .adjtime = ptp_rcar_gen4_adjtime,
> > + .gettime64 = ptp_rcar_gen4_gettime,
> > + .settime64 = ptp_rcar_gen4_settime,
> > +};
--
Kind Regards,
Niklas Söderlund
next prev parent reply other threads:[~2026-07-16 20:35 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 12:55 [PATCH net-next v4 0/3] ptp: Add driver for R-Car Gen4 gPTP timer Niklas Söderlund
2026-07-02 12:55 ` [PATCH net-next v4 1/3] dt-bindings: ptp: renesas,rcar-gen4-gptp: Add R-Car Gen4 Niklas Söderlund
2026-07-02 12:55 ` [PATCH net-next v4 2/3] ptp: Add driver for " Niklas Söderlund
2026-07-02 14:39 ` Vadim Fedorenko
2026-07-16 20:35 ` Niklas Söderlund [this message]
2026-07-09 13:51 ` Paolo Abeni
2026-07-13 7:09 ` Uwe Kleine-König
2026-07-16 15:47 ` Niklas Söderlund
2026-07-02 12:55 ` [PATCH net-next v4 3/3] arm64: dts: renesas: r8a779g0: Add gPTP node Niklas Söderlund
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260716203538.GD1593320@ragnatech.se \
--to=niklas.soderlund+renesas@ragnatech.se \
--cc=andrew+netdev@lunn.ch \
--cc=conor+dt@kernel.org \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=edumazet@google.com \
--cc=geert+renesas@glider.be \
--cc=krzk+dt@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=magnus.damm@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=richardcochran@gmail.com \
--cc=robh@kernel.org \
--cc=vadim.fedorenko@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox