From: richardcochran@gmail.com (Richard Cochran)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM.
Date: Wed, 23 Nov 2016 22:03:18 +0100 [thread overview]
Message-ID: <20161123210318.GB2845@localhost.localdomain> (raw)
In-Reply-To: <e592169a-6287-7f3c-b4fd-23c4c79198b0@microchip.com>
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;
}
WARNING: multiple messages have this Message-ID (diff)
From: Richard Cochran <richardcochran@gmail.com>
To: Andrei Pistirica <andrei.pistirica@microchip.com>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, davem@davemloft.net,
nicolas.ferre@atmel.com, harinikatakamlinux@gmail.com,
harini.katakam@xilinx.com, punnaia@xilinx.com,
michals@xilinx.com, anirudh@xilinx.com,
boris.brezillon@free-electrons.com,
alexandre.belloni@free-electrons.com, tbultel@pixelsurmer.com
Subject: Re: [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM.
Date: Wed, 23 Nov 2016 22:03:18 +0100 [thread overview]
Message-ID: <20161123210318.GB2845@localhost.localdomain> (raw)
In-Reply-To: <e592169a-6287-7f3c-b4fd-23c4c79198b0@microchip.com>
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;
}
WARNING: multiple messages have this Message-ID (diff)
From: Richard Cochran <richardcochran@gmail.com>
To: Andrei Pistirica <andrei.pistirica@microchip.com>
Cc: tbultel@pixelsurmer.com, boris.brezillon@free-electrons.com,
netdev@vger.kernel.org, alexandre.belloni@free-electrons.com,
nicolas.ferre@atmel.com, linux-kernel@vger.kernel.org,
harinikatakamlinux@gmail.com, michals@xilinx.com,
anirudh@xilinx.com, punnaia@xilinx.com,
harini.katakam@xilinx.com, davem@davemloft.net,
linux-arm-kernel@lists.infradead.org
Subject: Re: [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM.
Date: Wed, 23 Nov 2016 22:03:18 +0100 [thread overview]
Message-ID: <20161123210318.GB2845@localhost.localdomain> (raw)
In-Reply-To: <e592169a-6287-7f3c-b4fd-23c4c79198b0@microchip.com>
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;
}
next prev parent reply other threads:[~2016-11-23 21:03 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-18 14:21 [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM Andrei Pistirica
2016-11-18 14:21 ` Andrei Pistirica
2016-11-18 14:21 ` [RFC PATCH v2 2/2] macb: Enable 1588 support in SAMA5D2 platform Andrei Pistirica
2016-11-18 14:21 ` Andrei Pistirica
2016-11-20 19:54 ` Richard Cochran
2016-11-20 19:54 ` Richard Cochran
2016-11-23 13:35 ` Andrei Pistirica
2016-11-23 13:35 ` Andrei Pistirica
2016-11-20 19:18 ` [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM Richard Cochran
2016-11-20 19:18 ` Richard Cochran
2016-11-20 19:18 ` Richard Cochran
2016-11-23 13:34 ` Andrei Pistirica
2016-11-23 13:34 ` Andrei Pistirica
2016-11-23 21:03 ` Richard Cochran [this message]
2016-11-23 21:03 ` Richard Cochran
2016-11-23 21:03 ` Richard Cochran
2016-11-24 9:36 ` Andrei.Pistirica at microchip.com
2016-11-24 9:36 ` Andrei.Pistirica
2016-11-24 9:36 ` Andrei.Pistirica
2016-11-20 19:37 ` Richard Cochran
2016-11-20 19:37 ` Richard Cochran
2016-11-23 13:36 ` Andrei Pistirica
2016-11-23 13:36 ` Andrei Pistirica
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=20161123210318.GB2845@localhost.localdomain \
--to=richardcochran@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.