RE: [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM.

From: Andrei.Pistirica
Date: Thu Nov 24 2016 - 04:44:45 EST




> -----Original Message-----
> From: Richard Cochran [mailto:richardcochran@xxxxxxxxx]
> Sent: Wednesday, November 23, 2016 11:03 PM
> To: Andrei Pistirica - M16132
> Cc: netdev@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; linux-arm-
> kernel@xxxxxxxxxxxxxxxxxxx; davem@xxxxxxxxxxxxx;
> nicolas.ferre@xxxxxxxxx; harinikatakamlinux@xxxxxxxxx;
> harini.katakam@xxxxxxxxxx; punnaia@xxxxxxxxxx; michals@xxxxxxxxxx;
> anirudh@xxxxxxxxxx; boris.brezillon@xxxxxxxxxxxxxxxxxx;
> alexandre.belloni@xxxxxxxxxxxxxxxxxx; tbultel@xxxxxxxxxxxxxxx
> Subject: Re: [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM.
>
> On Wed, Nov 23, 2016 at 02:34:03PM +0100, Andrei Pistirica wrote:
> > From what I understand, your suggestion is:
> > (ns | frac) * ppb = (total_ns | total_frac) (total_ns | total_frac) /
> > 10^9 = (adj_ns | adj_frac) This is correct iff total_ns/10^9 >= 1, but
> > the problem is that there are missed fractions due to the following
> > approximation:
> > frac*ppb =~
> > (ns*ppb+frac*ppb*2^16)*2^16-10^9*2^16*flor(ns*ppb+frac*ppb*2^16,
> > 10^9).
>
> -ENOPARSE;
>
> > An example which uses values from a real test:
> > let ppb=4891, ns=12 and frac=3158
>
> That is a very strange example for nominal frequency. The clock period is
> 12.048187255859375 nanoseconds, and so the frequency is
> 83000037.99 Hz.
>
> But hey, let's go with it...
>
> > - using suggested algorithm, yields: adj_ns = 0 and adj_frac = 0
> > - using in-place algorithm, yields: adj_ns = 0, adj_frac = 4 You can
> > check the calculus.
>
> The test program, below, shows you what I meant. (Of course, you should
> adjust this to fit the adjfine() method.)
>
> Unfortunately, this device has a very coarse frequency resolution.
> Using a nominal period of ns=12 as an example, the resolution is
> 2^-16 / 12 or 1.27 ppm. The 24 bit device is much better in this repect.
>
> The output using your example numbers is:
>
> $ ./a.out 12 3158 4891
> ns=12 frac=3158
> ns=12 frac=3162
>
> $ ./a.out 12 3158 -4891
> ns=12 frac=3158
> ns=12 frac=3154
>
> See how you get a result of +/- 4 with just one division?
>
> Thanks,
> Richard
>
> ---
> #include <stdint.h>
> #include <stdio.h>
> #include <stdlib.h>
>
> static void adjfreq(uint32_t ns, uint32_t frac, int32_t ppb) {
> uint64_t adj;
> uint32_t diff, word;
> int neg_adj = 0;
>
> printf("ns=%u frac=%u\n", ns, frac);
>
> if (ppb < 0) {
> neg_adj = 1;
> ppb = -ppb;
> }
> word = (ns << 16) + frac;
> adj = word;
> adj *= ppb;
> adj += 500000000UL;
> diff = adj / 1000000000UL;
>
> word = neg_adj ? word - diff : word + diff;
> printf("ns=%u frac=%u\n", word >> 16, word & 0xffff); }
>
> int main(int argc, char *argv[])
> {
> uint32_t ns, frac;
> int32_t ppb;
>
> if (argc != 4) {
> puts("need ns, frac, and ppb");
> return -1;
> }
> ns = atoi(argv[1]);
> frac = atoi(argv[2]);
> ppb = atoi(argv[3]);
> adjfreq(ns, frac, ppb);
> return 0;
> }

Ok, thanks.
I will use this one then.

Regards,
Andrei