Message ID | 50C8ED4B.4010307@corelatus.se (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
On 12/13/2012 2:17 AM, Thomas Lange wrote: > The time drift problem I have been chasing for a while, see > http://linux.davincidsp.com/pipermail/davinci-linux-open-source/2012-December/025821.html > , seems to be due to an undocumented silicon bug. > > The attached patch to master ( c22cf7755db6500df037cecdd6b290394d82392e > Origin: git://gitorious.org/linux-davinci/linux-davinci.git ) > exercises the problem. Example console output from my EVM6446 card: > > ---------------- > Before T0:0x5ed55a T1:0x5ed55d Diff:-3 > After T0:0x5ed817 T1:0x5ed824 Diff:-13 > Before T0:0x62a7e5 T1:0x62a7f3 Diff:-14 > After T0:0x62adff T1:0x62ae17 Diff:-24 > Before T0:0x66cbfb T1:0x66cc14 Diff:-25 > After T0:0x66d1f6 T1:0x66d219 Diff:-35 > Before T0:0x6aeab0 T1:0x6aead4 Diff:-36 > After T0:0x6af0ec T1:0x6af11a Diff:-46 > Before T0:0x6f09ef T1:0x6f0a1e Diff:-47 > After T0:0x6f1018 T1:0x6f1051 Diff:-57 > Before T0:0x732821 T1:0x73285b Diff:-58 > After T0:0x732e1a T1:0x732e5e Diff:-68 > --------------- > > This shows that TIM34_0 misses 11 ticks every time a new event is setup > (10 ticks from my test loop + the original code 1). > > If someone from TI can verify that the problem exists in all Davinci > versions, a workaround should be pretty straightforward, assuming this > is the only symptom of the bug. I was not able to spend too much time on this today, but I did try your patch on my DM644x EVM and have observations similar to what you describe above. Further, I see that reading TIM12 instead of writing it does not cause the same drift on TIM34. I still need to try on a different DaVinci device. One thing to try would be to temporarily stop both TIM12_0 and TIM34_0 using ENAMODE bits in TCR before resetting TIM12_0. There is a cryptic note about writes to timer register being disallowed when timer is running in section 2.4.2 of http://www.ti.com/lit/ug/sprue26/sprue26.pdf Thanks, Sekhar
On 2012-12-13 14:28, Sekhar Nori wrote: > On 12/13/2012 2:17 AM, Thomas Lange wrote: >> The time drift problem I have been chasing for a while, see >> http://linux.davincidsp.com/pipermail/davinci-linux-open-source/2012-December/025821.html >> , seems to be due to an undocumented silicon bug. >> >> The attached patch to master ( c22cf7755db6500df037cecdd6b290394d82392e >> Origin: git://gitorious.org/linux-davinci/linux-davinci.git ) >> exercises the problem. Example console output from my EVM6446 card: >> >> ---------------- >> Before T0:0x5ed55a T1:0x5ed55d Diff:-3 >> After T0:0x5ed817 T1:0x5ed824 Diff:-13 >> Before T0:0x62a7e5 T1:0x62a7f3 Diff:-14 >> After T0:0x62adff T1:0x62ae17 Diff:-24 >> Before T0:0x66cbfb T1:0x66cc14 Diff:-25 >> After T0:0x66d1f6 T1:0x66d219 Diff:-35 >> Before T0:0x6aeab0 T1:0x6aead4 Diff:-36 >> After T0:0x6af0ec T1:0x6af11a Diff:-46 >> Before T0:0x6f09ef T1:0x6f0a1e Diff:-47 >> After T0:0x6f1018 T1:0x6f1051 Diff:-57 >> Before T0:0x732821 T1:0x73285b Diff:-58 >> After T0:0x732e1a T1:0x732e5e Diff:-68 >> --------------- >> >> This shows that TIM34_0 misses 11 ticks every time a new event is setup >> (10 ticks from my test loop + the original code 1). >> >> If someone from TI can verify that the problem exists in all Davinci >> versions, a workaround should be pretty straightforward, assuming this >> is the only symptom of the bug. > > I was not able to spend too much time on this today, but I did try your > patch on my DM644x EVM and have observations similar to what you > describe above. Further, I see that reading TIM12 instead of writing it > does not cause the same drift on TIM34. I still need to try on a > different DaVinci device. Like I wrote in patch, my DM6443 based card behaves the same. > One thing to try would be to temporarily stop both TIM12_0 and TIM34_0 > using ENAMODE bits in TCR before resetting TIM12_0. There is a cryptic > note about writes to timer register being disallowed when timer is > running in section 2.4.2 of http://www.ti.com/lit/ug/sprue26/sprue26.pdf It says that timer registers are protected by hardware when the timer is active. I guess writes are ignored if timer is active. Regards, /Thomas
On 12/13/2012 9:22 PM, Thomas Lange wrote: > On 2012-12-13 14:28, Sekhar Nori wrote: >> On 12/13/2012 2:17 AM, Thomas Lange wrote: >>> The time drift problem I have been chasing for a while, see >>> http://linux.davincidsp.com/pipermail/davinci-linux-open-source/2012-December/025821.html >>> , seems to be due to an undocumented silicon bug. >>> >>> The attached patch to master ( c22cf7755db6500df037cecdd6b290394d82392e >>> Origin: git://gitorious.org/linux-davinci/linux-davinci.git ) >>> exercises the problem. Example console output from my EVM6446 card: >>> >>> ---------------- >>> Before T0:0x5ed55a T1:0x5ed55d Diff:-3 >>> After T0:0x5ed817 T1:0x5ed824 Diff:-13 >>> Before T0:0x62a7e5 T1:0x62a7f3 Diff:-14 >>> After T0:0x62adff T1:0x62ae17 Diff:-24 >>> Before T0:0x66cbfb T1:0x66cc14 Diff:-25 >>> After T0:0x66d1f6 T1:0x66d219 Diff:-35 >>> Before T0:0x6aeab0 T1:0x6aead4 Diff:-36 >>> After T0:0x6af0ec T1:0x6af11a Diff:-46 >>> Before T0:0x6f09ef T1:0x6f0a1e Diff:-47 >>> After T0:0x6f1018 T1:0x6f1051 Diff:-57 >>> Before T0:0x732821 T1:0x73285b Diff:-58 >>> After T0:0x732e1a T1:0x732e5e Diff:-68 >>> --------------- >>> >>> This shows that TIM34_0 misses 11 ticks every time a new event is setup >>> (10 ticks from my test loop + the original code 1). >>> >>> If someone from TI can verify that the problem exists in all Davinci >>> versions, a workaround should be pretty straightforward, assuming this >>> is the only symptom of the bug. >> >> I was not able to spend too much time on this today, but I did try your >> patch on my DM644x EVM and have observations similar to what you >> describe above. Further, I see that reading TIM12 instead of writing it >> does not cause the same drift on TIM34. I still need to try on a >> different DaVinci device. > > Like I wrote in patch, my DM6443 based card behaves the same. I verified that similar behavior exists on DaVinci DA850. > >> One thing to try would be to temporarily stop both TIM12_0 and TIM34_0 >> using ENAMODE bits in TCR before resetting TIM12_0. There is a cryptic >> note about writes to timer register being disallowed when timer is >> running in section 2.4.2 of http://www.ti.com/lit/ug/sprue26/sprue26.pdf > > It says that timer registers are protected by hardware when the timer is active. > I guess writes are ignored if timer is active. I will check internally with the hardware team to see if this is a known issue. Thanks, Sekhar
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 9847938..95be656 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -117,6 +117,61 @@ static char *id_to_name[] = { [T1_TOP] = "timer1_1", }; +/******************************************************************* + Test code by thomas@corelatus.se 121212 + Exercises a timer problem with Davinci, likely a silicon bug. + For each write to TIM12, the TIM34 counter misses a tick. + With current kernel, this causes time to drift 37 ns every time + a new event is set. This can accumulate to 1000 ppms + (1 ms per second) if lots of context switches. + + Verified to exist in: + DM6443 rev 2.1 + DM6446 rev 1.3 +*********************************************************************/ + +static inline void show_timer_diff(const char *str){ + u32 tim34_0, tim34_1; + + tim34_1 = __raw_readl(IO_ADDRESS(DAVINCI_TIMER1_BASE + TIM34)); + tim34_0 = __raw_readl(IO_ADDRESS(DAVINCI_TIMER0_BASE + TIM34)); + + printk("%s T0:0x%x T1:0x%x Diff:%d\n", + str, + tim34_0, + tim34_1, + tim34_0 - tim34_1); +} + +/* When setting up Timer 0-34, setup Timer 1-34 with the same settings. + This way, they should always have about the same counter value. */ +static void mirror(struct timer_s *t){ + /* Timer 1 is +0x400 */ + volatile void *base = t->base + 0x400; + u32 tcr; + + tcr = __raw_readl(base + TCR); + + /* disable timer */ + tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift); + __raw_writel(tcr, base + TCR); + + /* reset counter to zero, set new period */ + __raw_writel(0, base + t->tim_off); + __raw_writel(t->period, base + t->prd_off); + + /* Set enable mode */ + if (t->opts & TIMER_OPTS_ONESHOT) + tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift; + else if (t->opts & TIMER_OPTS_PERIODIC) + tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift; + + __raw_writel(tcr, base + TCR); +} + +#define CHECK_LAPS 20 +static u32 chk = ~0; + static int timer32_config(struct timer_s *t) { u32 tcr; @@ -142,6 +197,19 @@ static int timer32_config(struct timer_s *t) tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift); __raw_writel(tcr, t->base + TCR); + if( chk < CHECK_LAPS && t->id == 0 ){ + int i; + show_timer_diff("Before"); + /* TIM34_0 seems to miss 1 tick every time we write + to TIM12_0! + So, this loop makes us miss 10 ticks: */ + for(i=0;i<10;i++){ + __raw_writel(0, t->base + t->tim_off); + } + show_timer_diff("After"); + chk++; + } + /* reset counter to zero, set new period */ __raw_writel(0, t->base + t->tim_off); __raw_writel(t->period, t->base + t->prd_off); @@ -152,6 +220,15 @@ static int timer32_config(struct timer_s *t) else if (t->opts & TIMER_OPTS_PERIODIC) tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift; + if(t->id == 1){ + /* Timer 0-34 setup + Setup 1-34 as a mirror to 0-34 */ + mirror(t); + + /* Start checking TIM counters */ + chk = 0; + } + __raw_writel(tcr, t->base + TCR); } return 0; @@ -381,6 +458,10 @@ static void __init davinci_timer_init(void) BUG_ON(IS_ERR(timer_clk)); clk_prepare_enable(timer_clk); + timer_clk = clk_get(NULL, "timer1"); + BUG_ON(IS_ERR(timer_clk)); + clk_enable(timer_clk); + /* init timer hw */ timer_init();