diff mbox

[2/2] ARM: omap5/dra7xx: Fix counter frequency drift for AM572x errata i856.

Message ID 549018EC.8020207@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lokesh Vutla Dec. 16, 2014, 11:35 a.m. UTC
Hi Lennart,

On Sunday 14 December 2014 10:15 AM, Lennart Sorensen wrote:
> On Fri, Dec 12, 2014 at 05:08:56PM -0500, Lennart Sorensen wrote:
>> Errata i856 for the AM572x (DRA7xx) points out that the 32.768KHz external
>> crystal is not enabled at power up.  Instead the CPU falls back to using
>> an emulation for the 32KHz clock which is SYSCLK1/610.  SYSCLK1 is usually
>> 20MHz on boards so far (which gives an emulated frequency of 32.786KHz),
>> but can also be 19.2 or 27MHz which result in much larger drift.
>>
>> Since this is used to drive the master counter at 32.768KHz * 375 /
>> 2 = 6.144MHz, the emulated speed for 20MHz is of by 570ppm, or about 43
>> seconds per day, and more than the 500ppm NTP is able to tolerate.
>>
>> Checking the CTRL_CORE_BOOTSTRAP register can determine if the CPU
>> is using the real 32.768KHz crystal or the emulated SYSCLK1/610, and
>> by known that the real counter frequency can be determined and used.
> s/known/knowing/
> and a comma after that.
>> The real speed is then SYSCLK1 / 610 * 375 / 2 or SYSCLK1 * 75 / 244.
Is this applicable for OMAP5 also?
If not can you drop omap5 from $subject?

In order to make the code more simpler, can you use the following logic:
and add documentation accordingly.

Comments

Lennart Sorensen Dec. 16, 2014, 4:16 p.m. UTC | #1
On Tue, Dec 16, 2014 at 05:05:08PM +0530, Lokesh Vutla wrote:
> Is this applicable for OMAP5 also?
> If not can you drop omap5 from $subject?

DRA7xx = OMAP57xx, which to me is an omap5.  Isn't it?

And I haven't been able to get a manual for the omap54xx to confirm it,
although it seems it does not apply to the omap54xx from what I have
been able to gather indirectly.

arch_timer_freq = (rate / den) * num;

If I do this with the workaround I get:

20000000 / 75 * 244 = 6147525

where as

20000000 * 244 / 75 = 6147540

best value would be 6147541 with proper rounding.

In the normal case the worst case is:

26000000 * 384 = 9984000000

That is too big for 32 bits.

Now what could be done is prescale by 4 to make the worst case still
fit in 32 bits while doing the multiplication before the division,
so like this:

arch_timer_freq = ((rate / 4) * num / den ) * 4;

That gives the same result in all cases including the errata case for
the dra7xx at 20MHz and 27MHz.  It is off by 3 in the 19.2MHz case though
which isn't so nice.

Would that be more acceptable?  I think having the arch_timer_freq
calculated for the errata case seperately from the normal case is
cleaner looking compared to that mess and gives a better result for the
19.2MHz case.
Nishanth Menon Dec. 16, 2014, 7:56 p.m. UTC | #2
On 12/16/2014 10:16 AM, Lennart Sorensen wrote:
> On Tue, Dec 16, 2014 at 05:05:08PM +0530, Lokesh Vutla wrote:
>> Is this applicable for OMAP5 also?
>> If not can you drop omap5 from $subject?
> 
> DRA7xx = OMAP57xx, which to me is an omap5.  Isn't it?
*AM*57xx is not *OMAP*57xx -> there is no OMAP57xx.

AM57xx and DRA7xx are in the same generation of processors and is
derivative technology (not the same) as OMAP5432/OMAP5430.

We have been using DRA7 as a generic terminology to indicate
AM57xx/DRA7 family of processors.
Lennart Sorensen Dec. 16, 2014, 7:58 p.m. UTC | #3
On Tue, Dec 16, 2014 at 01:56:16PM -0600, Nishanth Menon wrote:
> *AM*57xx is not *OMAP*57xx -> there is no OMAP57xx.

Oh OK.  Thanks for clearing that up.

> AM57xx and DRA7xx are in the same generation of processors and is
> derivative technology (not the same) as OMAP5432/OMAP5430.
> 
> We have been using DRA7 as a generic terminology to indicate
> AM57xx/DRA7 family of processors.

I will drop omap5 from the subject for the next version then since it
seems clear that the omap5 does not have this problem.
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index a3c0133..a80ac2d 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -286,6 +286,10 @@ 
 #define OMAP5XXX_CONTROL_STATUS                0x134
 #define OMAP5_DEVICETYPE_MASK          (0x7 << 6)
 
+/* DRA7XX CONTROL CORE BOOTSTRAP */
+#define DRA7_CTRL_CORE_BOOTSTRAP	0x6c4
+#define DRA7_SPEEDSELECT_MASK		(0x3 << 8)
+
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index fb0cb2b..84aadae 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -54,6 +54,7 @@ 
 
 #include "soc.h"
 #include "common.h"
+#include "control.h"
 #include "powerdomain.h"
 #include "omap-secure.h"
 
@@ -545,6 +546,16 @@  static void __init realtime_counter_init(void)
 		break;
 	}
 
+	if (soc_is_dra7xx()) {
+		reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
+		reg = reg & DRA7_SPEEDSELECT_MASK;
+
+		if (reg) {
+			num = 75;
+			den = 244;
+		}
+	}
+
 	/* Program numerator and denumerator registers */
 	reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
 			NUMERATOR_DENUMERATOR_MASK;