diff options
Diffstat (limited to 'meta/packages/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf')
-rw-r--r-- | meta/packages/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf | 94 |
1 files changed, 0 insertions, 94 deletions
diff --git a/meta/packages/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf b/meta/packages/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf deleted file mode 100644 index 3de6e0504..000000000 --- a/meta/packages/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf +++ /dev/null @@ -1,94 +0,0 @@ -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); |