aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadopenembedded-core-contrib-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf')
-rw-r--r--meta/recipes-kernel/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf94
1 files changed, 94 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf
new file mode 100644
index 0000000000..3de6e05042
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf
@@ -0,0 +1,94 @@
+OMAP2/3 system tick GPTIMER: use overflow interrupts to detect missing match interrupts
+
+From: Paul Walmsley <paul@pwsan.com>
+
+GPTIMER1 on some OMAP3 chips occasionally misses match conditions
+between the timer counter and the target register value, and does not
+interrupt to the MPU. This patch adds another line of defense by
+setting the timer to generate an overflow interrupt 0.5 seconds after the
+timer passes the original comparison value.
+
+If interrupts are masked for a long period of time, one would expect
+both a match and an overflow interrupt to be logged. This is considered
+a normal condition. However, if only an overflow interrupt is logged,
+this is considered evidence of a hardware bug and the kernel will issue
+a warning.
+
+This workaround is unlikely to be 100% effective, since GPTIMER1 has
+also been observed to lose overflow interrupts occasionally. It is
+hoped that the probability of losing both will be significantly lower
+than the probability of losing either one.
+---
+
+ arch/arm/mach-omap2/timer-gp.c | 36 ++++++++++++++++++++++++++++++++----
+ 1 files changed, 32 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
+index 51996ba..ce5c2b4 100644
+--- a/arch/arm/mach-omap2/timer-gp.c
++++ b/arch/arm/mach-omap2/timer-gp.c
+@@ -36,17 +36,43 @@
+ #include <asm/mach/time.h>
+ #include <asm/arch/dmtimer.h>
+
+-#define GPTIMER_MATCH_VAL 0xffff0000
++/*
++ * The number of timer ticks to delay will be subtracted from
++ * GPTIMER_MATCH_VAL before loading into the timer. So GPTIMER_MATCH_VAL
++ * constrains the longest delay that can be generated with the timer.
++ * Since the current code uses overflow interrupts as protection against
++ * missed comparison interrupts, this value should also be sufficiently
++ * large such that there is not an excessively long delay between ticks
++ * if the comparison interrupt fails to arrive. The 0xfffff800 value
++ * below results in a half-second delay in such a case when using
++ * the 32kHz timer as source.
++ */
++#define GPTIMER_MATCH_VAL (0xffffffff - (32768/2))
+
+ static struct omap_dm_timer *gptimer;
+ static struct clock_event_device clockevent_gpt;
+
++static u32 last_load;
++
+ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
+ {
+ struct omap_dm_timer *gpt = (struct omap_dm_timer *)dev_id;
+ struct clock_event_device *evt = &clockevent_gpt;
+-
+- omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_MATCH);
++ u32 v;
++
++ v = omap_dm_timer_read_status(gpt);
++ if ((v & OMAP_TIMER_INT_OVERFLOW) && !(v & OMAP_TIMER_INT_MATCH)) {
++ /*
++ * Should never happen. Current belief is that this is
++ * due to a hardware bug in the GPTIMER block on some
++ * OMAP3 revisions.
++ */
++ pr_err("*** GPTIMER missed match interrupt! last load: %08x\n",
++ last_load);
++ WARN_ON(1);
++ }
++
++ omap_dm_timer_write_status(gpt, v);
+
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+@@ -61,6 +87,7 @@ static struct irqaction omap2_gp_timer_irq = {
+ static int omap2_gp_timer_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+ {
++ last_load = GPTIMER_MATCH_VAL - cycles;
+ omap_dm_timer_set_load_start(gptimer, 0, GPTIMER_MATCH_VAL - cycles);
+
+ return 0;
+@@ -99,7 +126,8 @@ static void __init omap2_gp_clockevent_init(void)
+ omap_dm_timer_stop(gptimer);
+ /* omap_dm_timer_set_load(gptimer, 0, 0);*/
+ omap_dm_timer_set_match(gptimer, 1, GPTIMER_MATCH_VAL);
+- omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_MATCH);
++ omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_MATCH |
++ OMAP_TIMER_INT_OVERFLOW);
+
+ clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC,
+ clockevent_gpt.shift);