diff options
7 files changed, 64 insertions, 334 deletions
diff --git a/packages/linux/linux-omap2-git/beagleboard/01-gptimer_clear_isrs_on_init b/packages/linux/linux-omap2-git/beagleboard/01-gptimer_clear_isrs_on_init deleted file mode 100644 index 5123bafe54..0000000000 --- a/packages/linux/linux-omap2-git/beagleboard/01-gptimer_clear_isrs_on_init +++ /dev/null @@ -1,25 +0,0 @@ -clear - -From: Paul Walmsley <paul@pwsan.com> - - ---- - - arch/arm/plat-omap/dmtimer.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c -index f22506a..e38a11e 100644 ---- a/arch/arm/plat-omap/dmtimer.c -+++ b/arch/arm/plat-omap/dmtimer.c -@@ -703,6 +703,10 @@ int __init omap_dm_timer_init(void) - timer->fclk = clk_get(NULL, clk_name); - } - #endif -+ omap_dm_timer_write_status(timer, OMAP_TIMER_INT_OVERFLOW | -+ OMAP_TIMER_INT_MATCH | -+ OMAP_TIMER_INT_CAPTURE); -+ - } - - return 0; diff --git a/packages/linux/linux-omap2-git/beagleboard/01-make_tick_gptimer_configurable b/packages/linux/linux-omap2-git/beagleboard/01-make_tick_gptimer_configurable new file mode 100644 index 0000000000..bcf0fa79f8 --- /dev/null +++ b/packages/linux/linux-omap2-git/beagleboard/01-make_tick_gptimer_configurable @@ -0,0 +1,58 @@ +OMAP2/3 GPTIMER: allow system tick GPTIMER to be configurable at build + +From: Paul Walmsley <paul@pwsan.com> + +Add Kbuild code to allow the builder to select which GPTIMER block to use +for the Linux clockevents timer. Practical choices at this point are +GPTIMER1 or GPTIMER12. Both of these timers are in the WKUP powerdomain, +and so are unaffected by chip power management. GPTIMER1 can use sys_clk +as a source, for applications where a high-resolution timer is more important +than power management. GPTIMER12 has the special property that it has +the secure 32kHz oscillator as its source clock, which may be less prone +to glitches than the off-chip 32kHz oscillator. + +At this point, it appears that most boards are fine with GPTIMER1, +but Beagle should use GPTIMER12. +--- + + arch/arm/mach-omap2/Kconfig | 16 ++++++++++++++++ + arch/arm/mach-omap2/timer-gp.c | 2 +- + 2 files changed, 17 insertions(+), 1 deletions(-) + +diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig +index bb6d695..0002cb6 100644 +--- a/arch/arm/mach-omap2/Kconfig ++++ b/arch/arm/mach-omap2/Kconfig +@@ -122,3 +122,19 @@ config MACH_OMAP3EVM + config MACH_OMAP3_BEAGLE + bool "OMAP3 BEAGLE board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX ++ ++config OMAP_TICK_GPTIMER ++ int "GPTIMER used for system tick timer" ++ depends on ARCH_OMAP2 || ARCH_OMAP3 ++ range 1 12 ++ default 1 ++ help ++ Linux uses one of the twelve on-board OMAP GPTIMER blocks to generate ++ system tick interrupts. The twelve GPTIMERs have slightly ++ different powerdomain, source clock, and security properties ++ (mostly documented in the OMAP3 TRMs) that can affect the selection ++ of which GPTIMER to use. The historical default is GPTIMER1. ++ If CONFIG_OMAP_32K_TIMER is selected, Beagle may require GPTIMER12 ++ due to hardware sensitivity to glitches on the OMAP 32kHz clock ++ input. ++ +diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c +index 557603f..ec80af5 100644 +--- a/arch/arm/mach-omap2/timer-gp.c ++++ b/arch/arm/mach-omap2/timer-gp.c +@@ -99,7 +99,7 @@ static void __init omap2_gp_clockevent_init(void) + { + u32 tick_rate; + +- gptimer = omap_dm_timer_request_specific(1); ++ gptimer = omap_dm_timer_request_specific(CONFIG_OMAP_TICK_GPTIMER); + BUG_ON(gptimer == NULL); + + #if defined(CONFIG_OMAP_32K_TIMER) diff --git a/packages/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick b/packages/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick deleted file mode 100644 index 6eb6c9b477..0000000000 --- a/packages/linux/linux-omap2-git/beagleboard/02-gptimer_use_match_for_tick +++ /dev/null @@ -1,97 +0,0 @@ -OMAP2/3 system tick GPTIMER: use match interrupts rather than overflow interrupts - -From: Paul Walmsley <paul@pwsan.com> - -On some OMAP3 chips, GPTIMER1 will occasionally decline to interrupt -the MPU when a timer overflow event occurs. The timer stops running; -and TOCR is sometimes incremented; but the MPU apparently never receives -the interrupt. This patch was an experiment in using the GPTIMER -match interrupt to determine if it resolves the problem. -Unfortunately, it does not; the same problem occurs with match -interrupts; but this patch is preserved as the base for a -match+overflow interrupt workaround used in a following patch. ---- - - arch/arm/mach-omap2/timer-gp.c | 32 ++++++++++---------------------- - 1 files changed, 10 insertions(+), 22 deletions(-) - -diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c -index 557603f..51996ba 100644 ---- a/arch/arm/mach-omap2/timer-gp.c -+++ b/arch/arm/mach-omap2/timer-gp.c -@@ -36,6 +36,8 @@ - #include <asm/mach/time.h> - #include <asm/arch/dmtimer.h> - -+#define GPTIMER_MATCH_VAL 0xffff0000 -+ - static struct omap_dm_timer *gptimer; - static struct clock_event_device clockevent_gpt; - -@@ -44,7 +46,7 @@ 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_OVERFLOW); -+ omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_MATCH); - - evt->event_handler(evt); - return IRQ_HANDLED; -@@ -59,7 +61,7 @@ static struct irqaction omap2_gp_timer_irq = { - static int omap2_gp_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) - { -- omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles); -+ omap_dm_timer_set_load_start(gptimer, 0, GPTIMER_MATCH_VAL - cycles); - - return 0; - } -@@ -67,29 +69,12 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles, - static void omap2_gp_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) - { -- u32 period; -- - omap_dm_timer_stop(gptimer); -- -- switch (mode) { -- case CLOCK_EVT_MODE_PERIODIC: -- period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ; -- period -= 1; -- -- omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period); -- break; -- case CLOCK_EVT_MODE_ONESHOT: -- break; -- case CLOCK_EVT_MODE_UNUSED: -- case CLOCK_EVT_MODE_SHUTDOWN: -- case CLOCK_EVT_MODE_RESUME: -- break; -- } - } - - static struct clock_event_device clockevent_gpt = { - .name = "gp timer", -- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, -+ .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, - .set_next_event = omap2_gp_timer_set_next_event, - .set_mode = omap2_gp_timer_set_mode, -@@ -111,12 +96,15 @@ static void __init omap2_gp_clockevent_init(void) - - omap2_gp_timer_irq.dev_id = (void *)gptimer; - setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq); -- omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); -+ 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); - - clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC, - clockevent_gpt.shift); - clockevent_gpt.max_delta_ns = -- clockevent_delta2ns(0xffffffff, &clockevent_gpt); -+ clockevent_delta2ns(GPTIMER_MATCH_VAL, &clockevent_gpt); - clockevent_gpt.min_delta_ns = - clockevent_delta2ns(1, &clockevent_gpt); - diff --git a/packages/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf b/packages/linux/linux-omap2-git/beagleboard/03-gptimer_match_plus_ovf deleted file mode 100644 index 3de6e05042..0000000000 --- a/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); diff --git a/packages/linux/linux-omap2-git/beagleboard/04-gptimer_add_debug_to_sysrq_q b/packages/linux/linux-omap2-git/beagleboard/04-gptimer_add_debug_to_sysrq_q deleted file mode 100644 index aa9f09811a..0000000000 --- a/packages/linux/linux-omap2-git/beagleboard/04-gptimer_add_debug_to_sysrq_q +++ /dev/null @@ -1,110 +0,0 @@ -Add extra debug for the q_d_w_o() when work fn is already active. - -From: Paul Walmsley <paul@pwsan.com> - - ---- - - arch/arm/mach-omap2/timer-gp.c | 3 ++- - arch/arm/plat-omap/dmtimer.c | 20 ++++++++++++++++++++ - include/asm-arm/arch-omap/dmtimer.h | 1 + - kernel/time/timer_list.c | 8 ++++++++ - 4 files changed, 31 insertions(+), 1 deletions(-) - -diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c -index ce5c2b4..e3ed368 100644 ---- a/arch/arm/mach-omap2/timer-gp.c -+++ b/arch/arm/mach-omap2/timer-gp.c -@@ -50,6 +50,7 @@ - #define GPTIMER_MATCH_VAL (0xffffffff - (32768/2)) - - static struct omap_dm_timer *gptimer; -+struct omap_dm_timer *gptimer_pub; - static struct clock_event_device clockevent_gpt; - - static u32 last_load; -@@ -111,7 +112,7 @@ static void __init omap2_gp_clockevent_init(void) - { - u32 tick_rate; - -- gptimer = omap_dm_timer_request_specific(1); -+ gptimer = gptimer_pub = omap_dm_timer_request_specific(1); - BUG_ON(gptimer == NULL); - - #if defined(CONFIG_OMAP_32K_TIMER) -diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c -index e38a11e..b10f8ac 100644 ---- a/arch/arm/plat-omap/dmtimer.c -+++ b/arch/arm/plat-omap/dmtimer.c -@@ -614,6 +614,26 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, - omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value); - } - -+void omap_dm_timer_dump_int_enable(struct omap_dm_timer *timer) -+{ -+ u32 l; -+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); -+ pr_err("GPT TCRR: %08x\n", l); -+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG); -+ pr_err("GPT TMAT: %08x\n", l); -+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); -+ pr_err("GPT TISR: %08x\n", l); -+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_INT_EN_REG); -+ pr_err("GPT TIER: %08x\n", l); -+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); -+ pr_err("GPT TCLR: %08x\n", l); -+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_TICK_INT_MASK_SET_REG); -+ pr_err("GPT TOCR: %08x\n", l); -+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_TICK_INT_MASK_COUNT_REG); -+ pr_err("GPT TOWR: %08x\n", l); -+} -+ -+ - unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) - { - unsigned int l; -diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h -index 02b29e8..a8123e9 100644 ---- a/include/asm-arm/arch-omap/dmtimer.h -+++ b/include/asm-arm/arch-omap/dmtimer.h -@@ -73,6 +73,7 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); - - void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); - -+void omap_dm_timer_dump_int_enable(struct omap_dm_timer *timer); - unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); - void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); - unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); -diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c -index a40e20f..452eab7 100644 ---- a/kernel/time/timer_list.c -+++ b/kernel/time/timer_list.c -@@ -18,6 +18,8 @@ - #include <linux/kallsyms.h> - #include <linux/tick.h> - -+#include <asm/arch/dmtimer.h> -+ - #include <asm/uaccess.h> - - typedef void (*print_fn_t)(struct seq_file *m, unsigned int *classes); -@@ -239,6 +241,8 @@ static void timer_list_show_tickdevices(struct seq_file *m) - static void timer_list_show_tickdevices(struct seq_file *m) { } - #endif - -+extern struct omap_dm_timer *gptimer_pub; -+ - static int timer_list_show(struct seq_file *m, void *v) - { - u64 now = ktime_to_ns(ktime_get()); -@@ -254,6 +258,10 @@ static int timer_list_show(struct seq_file *m, void *v) - SEQ_printf(m, "\n"); - timer_list_show_tickdevices(m); - -+ SEQ_printf(m, "\n"); -+ -+ omap_dm_timer_dump_int_enable(gptimer_pub); -+ - return 0; - } - diff --git a/packages/linux/linux-omap2-git/beagleboard/defconfig b/packages/linux/linux-omap2-git/beagleboard/defconfig index d01d473ed5..c07d0ab5e2 100644 --- a/packages/linux/linux-omap2-git/beagleboard/defconfig +++ b/packages/linux/linux-omap2-git/beagleboard/defconfig @@ -187,8 +187,8 @@ CONFIG_OMAP_BOOT_REASON=y CONFIG_OMAP_MCBSP=y # CONFIG_OMAP_MMU_FWK is not set # CONFIG_OMAP_MBOX_FWK is not set -CONFIG_OMAP_MPU_TIMER=y -# CONFIG_OMAP_32K_TIMER is not set +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y CONFIG_OMAP_DM_TIMER=y # CONFIG_OMAP_LL_DEBUG_UART1 is not set # CONFIG_OMAP_LL_DEBUG_UART2 is not set @@ -203,6 +203,7 @@ CONFIG_ARCH_OMAP3430=y # CONFIG_MACH_OMAP_3430SDP is not set # CONFIG_MACH_OMAP3EVM is not set CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_OMAP_TICK_GPTIMER=12 # # Boot options diff --git a/packages/linux/linux-omap2_git.bb b/packages/linux/linux-omap2_git.bb index 4008102f09..5749d4fc0c 100644 --- a/packages/linux/linux-omap2_git.bb +++ b/packages/linux/linux-omap2_git.bb @@ -6,9 +6,9 @@ SRCREV = "d6daf8d8cc5ccf90247def5551ee9c3e8555e848" PV = "2.6.26" #PV = "2.6.26+2.6.27-rc1+${PR}+git${SRCREV}" -PR = "r58" +PR = "r59" -SRC_URI = "git://source.mvista.com/git/linux-omap-2.6.git;protocol=git \ +SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git;protocol=git \ file://defconfig" SRC_URI_append_beagleboard = " file://no-harry-potter.diff;patch=1 \ @@ -35,10 +35,7 @@ SRC_URI_append_beagleboard = " file://no-harry-potter.diff;patch=1 \ file://mru-clocks3.diff;patch=1 \ file://4bitmmc.diff;patch=1 \ file://no-cortex-deadlock.patch;patch=1 \ - file://01-gptimer_clear_isrs_on_init;patch=1 \ - file://02-gptimer_use_match_for_tick;patch=1 \ - file://03-gptimer_match_plus_ovf;patch=1 \ - file://04-gptimer_add_debug_to_sysrq_q;patch=1 \ + file://01-make_tick_gptimer_configurable;patch=1 \ file://read_die_ids.patch;patch=1 \ " |