RE: [PATCH v6 2/2] pwm: Add support for RZ/G2L GPT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> -----Original Message-----
> From: Biju Das
> Sent: 20 September 2022 18:01
> To: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
> Cc: Thierry Reding <thierry.reding@xxxxxxxxx>; Lee Jones
> <lee.jones@xxxxxxxxxx>; Philipp Zabel <p.zabel@xxxxxxxxxxxxxx>; linux-
> pwm@xxxxxxxxxxxxxxx; Geert Uytterhoeven <geert+renesas@xxxxxxxxx>;
> Chris Paterson <Chris.Paterson2@xxxxxxxxxxx>; Biju Das
> <biju.das@xxxxxxxxxxxxxx>; Prabhakar Mahadev Lad <prabhakar.mahadev-
> lad.rj@xxxxxxxxxxxxxx>; linux-renesas-soc@xxxxxxxxxxxxxxx
> Subject: RE: [PATCH v6 2/2] pwm: Add support for RZ/G2L GPT
> 
> Hi Uwe,
> 
> > Subject: Re: [PATCH v6 2/2] pwm: Add support for RZ/G2L GPT
> >
> > Hello,
> >
> > On Tue, Sep 20, 2022 at 03:31:16PM +0000, Biju Das wrote:
> > > > On Mon, Sep 05, 2022 at 06:13:28PM +0100, Biju Das wrote:
> > > > > +	if (period_cycles >= (1024ULL << 32))
> > > > > +		pv = U32_MAX;
> > > > > +	else
> > > > > +		pv = period_cycles >> (2 * prescale);
> > > >
> > > > You're assuming that pv <= U32_MAX after this block, right? Then
> > > > maybe
> > > Yes, That is correct.
> > >
> > > >
> > > > 	if (period_cycles >> (2 * prescale) <= U32_MAX)
> > > >
> > > > is the more intuitive check?
> > >
> > > Ok will add like below, so we support up to (U32_MAX * 1024); Is
> it
> > ok
> > > for you?
> > >
> > >   if (!(period_cycles >> (2 * prescale) <= U32_MAX))
> > > +               return -EINVAL;
> > > +
> > > +       pv = period_cycles >> (2 * prescale);
> >
> > Not -EINVAL, using pv = U32_MAX is correct.
> 
> OK.
> 
> >
> > > Same case for duty cycle.
> > > >
> > > > > +	duty_cycles = mul_u64_u32_div(state->duty_cycle,
> > > > > +rzg2l_gpt->rate, NSEC_PER_SEC);
> > > > > +
> > > > > +	if (duty_cycles >= (1024ULL << 32))
> > > > > +		dc = U32_MAX;
> > > > > +	else
> > > > > +		dc = duty_cycles >> (2 * prescale);
> > > > > +
> > > > > +	/* Counter must be stopped before modifying Mode and
> > Prescaler */
> > > > > +	if (rzg2l_gpt_read(rzg2l_gpt, RZG2L_GTCR) & RZG2L_GTCR_CST)
> > > > > +		rzg2l_gpt_disable(rzg2l_gpt);
> > > >
> > > > For v5 I asked if this affects other channels, you said yes and
> in
> > > > the follow up I failed to reply how to improve this.
> > > >
> > > > I wonder how this affects other channels. Does it restart a
> period
> > > > afterwards, or is the effect only that the currently running
> > period
> > > > is a bit stretched?
> > >
> > > If we stops the counter, it resets to starting count position.
> >
> > So if I update pwm#1, pwm#0 doesn't only freeze for a moment, but
> > starts a new period. Hui.
> >
> > > >At least point that this stops the global counter and  so affects
> > the
> > > >other PWMs provided by this chip.
> > >
> > > We should not allow Counter to stop if it is running.
> > > We should allow changing mode and prescalar only for the first
> > enabled
> > > channel in Linux.
> > >
> > > Also as per the HW manual, we should not change RZG2L_GTCNT,
> > > RZG2L_GTBER while Counter is running.
> > >
> > > Will add bool is_counter_running to take care of this conditions.
> > >
> > > Is it ok with you?
> >
> > I'm torn here. Resetting the period for the other counter is quite
> > disturbing. If you cannot prevent that, please document that in the
> > Limitations section above.
> 

OK, I will document this in limitation section. 

 * - While using dual channels, both the channels should be enabled and
 *   disabled at the same time as it uses shared register for controlling
 *   counter start/stop.

Cheers,
Biju

> >
> > > > > +	pm_runtime_get_sync(chip->dev);
> > > > > +	val = rzg2l_gpt_read(rzg2l_gpt, RZG2L_GTCR);
> > > > > +	state->enabled = val & RZG2L_GTCR_CST;
> > > > > +	if (state->enabled) {
> > > > > +		prescale = FIELD_GET(RZG2L_GTCR_TPCS, val);
> > > > > +
> > > > > +		val = rzg2l_gpt_read(rzg2l_gpt, RZG2L_GTPR);
> > > > > +		tmp = NSEC_PER_SEC * val << (2 * prescale);
> > > >
> > > > This can overflow.
> > >
> > > OK will use inverse calculation to avoid overflow.
> > > mul_u64_u32_div(val << (2 * prescale), NSEC_PER_SEC, rzg2l_gpt-
> > >rate);
> > >
> > > Is it ok?
> >
> > It uses the wrong rounding direction :-\ Using
> >
> > 	tmp = NSEC_PER_SEC * (u64)val << (2 * prescale);
> >
> > should be enough to fix the problem I pointed out.
> 
> OK, Thanks for the pointer.
> 
> Cheers,
> Biju
> 
> >
> > > > > +		state->period = DIV_ROUND_UP_ULL(tmp, rzg2l_gpt-
> > >rate);
> > > > > +
> > > > > +		val = rzg2l_gpt_read(rzg2l_gpt, RZG2L_GTCCR(pwm-
> > >hwpwm));
> > > > > +		tmp = NSEC_PER_SEC * val << (2 * prescale);
> >
> > Best regards
> > Uwe
> >
> > --
> > Pengutronix e.K.                           | Uwe Kleine-König
> > |
> > Industrial Linux Solutions                 |
> > https://www.pengutronix.de/ |




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux