On Thu, Jan 7, 2021 at 12:51 PM Peter Maydell <peter.mayd...@linaro.org>
wrote:

> On Thu, 17 Dec 2020 at 00:45, Hao Wu <wuhao...@google.com> wrote:
> >
> > This patch makes NPCM7XX Timer to use a the timer clock generated by the
> > CLK module instead of the magic number TIMER_REF_HZ.
> >
> > Reviewed-by: Havard Skinnemoen <hskinnem...@google.com>
> > Reviewed-by: Tyrone Ting <kft...@nuvoton.com>
> > Signed-off-by: Hao Wu <wuhao...@google.com>
> > ---
> >  hw/arm/npcm7xx.c                 |  5 +++++
> >  hw/timer/npcm7xx_timer.c         | 25 ++++++++++++++-----------
> >  include/hw/misc/npcm7xx_clk.h    |  6 ------
> >  include/hw/timer/npcm7xx_timer.h |  1 +
> >  4 files changed, 20 insertions(+), 17 deletions(-)
>
> > @@ -130,7 +130,7 @@ static int64_t
> npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
> >  {
> >      int64_t ns = count;
> >
> > -    ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
> > +    ns *= clock_get_ns(t->ctrl->clock);
> >      ns *= npcm7xx_tcsr_prescaler(t->tcsr);
>
> I'm afraid that since you wrote and sent this we've updated the
> clock API (in commits 554d523785ef868 and de6a65f11d7e5a2a93f),
> so clock_get_ns() doesn't exist any more. Instead there is
> a new function clock_ticks_to_ns().
>
> The idea of the new function is that clocks don't necessarily
> have a period which is a whole number of nanoseconds, so
> doing arithmetic on the return value from clock_get_ns()
> introduces rounding errors, especially in the case of
> "multiply clock_get_ns() by a tick count to get a duration".
> (The worst case for this is "clock frequency >1GHz", at which
> point the rounding means that clock_get_ns() returns 0...)
>
> There is as yet no function for "convert duration to
> tick count", so code like:
>    count = ns / clock_get_ns(t->ctrl->clock);
>
> should probably for the moment call clock_ticks_to_ns()
> passing a tick count of 1. But I plan to write a patchset
> soon which will avoid the need to do that.
>
> Strictly speaking, even "call clock_ticks_to_ns() and
> then multiply by the prescaler value" can introduce
> rounding error; to deal with that I think you'd need to
> either have an internal Clock object whose period you
> adjusted as the prescalar value was updated by the guest,
> or else do arithmetic with the return value of clock_get()
> (which is in units of 2^-32 ns); I'm not sure either is
> worth it.
>
In this particular case, rounding error is less of a concern since the
clock should be ~25MHz (in the old implementation it was a fixed value.)

Since the prescaler is always an integer, a possible alternative might be
ns = clock_ticks_to_ns(t->ctrl->clock, count *
npcm7xx_tcsr_prescaler(t->tcsr))

and for code to convert ns to count can go
count = ns / clock_ticks_to_ns(t->ctrl->clock,
npcm7xx_tcsr_prescaler(t->tcsr))
or use the new API you proposed.

We'll also need to apply similar changes to other places in the patchset
(ADC and/or PWM) that need to compute clock value.

>
> thanks
> -- PMM
>

Reply via email to