summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick')
-rw-r--r--meta/recipes-kernel/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick97
1 files changed, 97 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick
new file mode 100644
index 0000000000..6eb6c9b477
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick
@@ -0,0 +1,97 @@
1OMAP2/3 system tick GPTIMER: use match interrupts rather than overflow interrupts
2
3From: Paul Walmsley <paul@pwsan.com>
4
5On some OMAP3 chips, GPTIMER1 will occasionally decline to interrupt
6the MPU when a timer overflow event occurs. The timer stops running;
7and TOCR is sometimes incremented; but the MPU apparently never receives
8the interrupt. This patch was an experiment in using the GPTIMER
9match interrupt to determine if it resolves the problem.
10Unfortunately, it does not; the same problem occurs with match
11interrupts; but this patch is preserved as the base for a
12match+overflow interrupt workaround used in a following patch.
13---
14
15 arch/arm/mach-omap2/timer-gp.c | 32 ++++++++++----------------------
16 1 files changed, 10 insertions(+), 22 deletions(-)
17
18diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
19index 557603f..51996ba 100644
20--- a/arch/arm/mach-omap2/timer-gp.c
21+++ b/arch/arm/mach-omap2/timer-gp.c
22@@ -36,6 +36,8 @@
23 #include <asm/mach/time.h>
24 #include <asm/arch/dmtimer.h>
25
26+#define GPTIMER_MATCH_VAL 0xffff0000
27+
28 static struct omap_dm_timer *gptimer;
29 static struct clock_event_device clockevent_gpt;
30
31@@ -44,7 +46,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
32 struct omap_dm_timer *gpt = (struct omap_dm_timer *)dev_id;
33 struct clock_event_device *evt = &clockevent_gpt;
34
35- omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_OVERFLOW);
36+ omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_MATCH);
37
38 evt->event_handler(evt);
39 return IRQ_HANDLED;
40@@ -59,7 +61,7 @@ static struct irqaction omap2_gp_timer_irq = {
41 static int omap2_gp_timer_set_next_event(unsigned long cycles,
42 struct clock_event_device *evt)
43 {
44- omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles);
45+ omap_dm_timer_set_load_start(gptimer, 0, GPTIMER_MATCH_VAL - cycles);
46
47 return 0;
48 }
49@@ -67,29 +69,12 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles,
50 static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
51 struct clock_event_device *evt)
52 {
53- u32 period;
54-
55 omap_dm_timer_stop(gptimer);
56-
57- switch (mode) {
58- case CLOCK_EVT_MODE_PERIODIC:
59- period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
60- period -= 1;
61-
62- omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period);
63- break;
64- case CLOCK_EVT_MODE_ONESHOT:
65- break;
66- case CLOCK_EVT_MODE_UNUSED:
67- case CLOCK_EVT_MODE_SHUTDOWN:
68- case CLOCK_EVT_MODE_RESUME:
69- break;
70- }
71 }
72
73 static struct clock_event_device clockevent_gpt = {
74 .name = "gp timer",
75- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
76+ .features = CLOCK_EVT_FEAT_ONESHOT,
77 .shift = 32,
78 .set_next_event = omap2_gp_timer_set_next_event,
79 .set_mode = omap2_gp_timer_set_mode,
80@@ -111,12 +96,15 @@ static void __init omap2_gp_clockevent_init(void)
81
82 omap2_gp_timer_irq.dev_id = (void *)gptimer;
83 setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
84- omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
85+ omap_dm_timer_stop(gptimer);
86+ /* omap_dm_timer_set_load(gptimer, 0, 0);*/
87+ omap_dm_timer_set_match(gptimer, 1, GPTIMER_MATCH_VAL);
88+ omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_MATCH);
89
90 clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC,
91 clockevent_gpt.shift);
92 clockevent_gpt.max_delta_ns =
93- clockevent_delta2ns(0xffffffff, &clockevent_gpt);
94+ clockevent_delta2ns(GPTIMER_MATCH_VAL, &clockevent_gpt);
95 clockevent_gpt.min_delta_ns =
96 clockevent_delta2ns(1, &clockevent_gpt);
97