[oe-commits] org.oe.dev linux-omap2: add patches to fix serial hang

koen commit oe at amethyst.openembedded.net
Thu Jul 31 07:41:04 UTC 2008


linux-omap2: add patches to fix serial hang

Author: koen at openembedded.org
Branch: org.openembedded.dev
Revision: 2f0d85eeec79f2264f9ab9dfd612b78206b10d58
ViewMTN: http://monotone.openembedded.org/revision/info/2f0d85eeec79f2264f9ab9dfd612b78206b10d58
Files:
1
packages/linux/linux-omap2-git/beagleboard/serialfix.diff
packages/linux/linux-omap2-git/beagleboard/01-gptimer_maintain_tldr_lt_0xffffffff
packages/linux/linux-omap2-git/beagleboard/02-gptimer_clear_tocr
packages/linux/linux-omap2_git.bb
Diffs:

#
# mt diff -ref493edac527e566a5fcd08e3ba271256aeec217 -r2f0d85eeec79f2264f9ab9dfd612b78206b10d58
#
#
#
# delete "packages/linux/linux-omap2-git/beagleboard/serialfix.diff"
# 
# add_file "packages/linux/linux-omap2-git/beagleboard/01-gptimer_maintain_tldr_lt_0xffffffff"
#  content [7c9bf439882aa8c9a61562b641bd230143c75fb9]
# 
# add_file "packages/linux/linux-omap2-git/beagleboard/02-gptimer_clear_tocr"
#  content [0f618ebc4d656a0020964339216cfd22e2662469]
# 
# patch "packages/linux/linux-omap2_git.bb"
#  from [d1968e8ba7639627d6db87ba953b800c24ef27ea]
#    to [9117272d8b2908df59a233aaf707e94115da1631]
#
============================================================
--- packages/linux/linux-omap2-git/beagleboard/01-gptimer_maintain_tldr_lt_0xffffffff	7c9bf439882aa8c9a61562b641bd230143c75fb9
+++ packages/linux/linux-omap2-git/beagleboard/01-gptimer_maintain_tldr_lt_0xffffffff	7c9bf439882aa8c9a61562b641bd230143c75fb9
@@ -0,0 +1,62 @@
+3430 TRM 16.2.4.2 states:
+
+From: Paul Walmsley <paul at pwsan.com>
+
+Do not put the overflow value (0xFFFFFFFF) in the GPTi.TLDR register
+     because it can lead to undesired results.
+
+3430 TRM 16.2.4.7 states:
+
+     In the non-PWM mode, GTPi.TLDR must be maintained at less than or
+     equal to 0xFFFF FFFE.
+
+This patch contains some debugging code, and so is not yet intended for
+merging into linux-omap.
+---
+
+ arch/arm/mach-omap2/timer-gp.c |   17 ++++++++++++++++-
+ 1 files changed, 16 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
+index 557603f..edc0c9e 100644
+--- a/arch/arm/mach-omap2/timer-gp.c
++++ b/arch/arm/mach-omap2/timer-gp.c
+@@ -59,6 +59,11 @@ static struct irqaction omap2_gp_timer_irq = {
+ static int omap2_gp_timer_set_next_event(unsigned long cycles,
+ 					 struct clock_event_device *evt)
+ {
++	if (cycles == 0) {
++		pr_err("*** cycles = 0! fixing\n");
++		cycles = 1;
++	}
++
+ 	omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles);
+ 
+ 	return 0;
+@@ -76,6 +81,15 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
+ 		period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
+ 		period -= 1;
+ 
++		/* 
++		 * Unlikely that this will ever be hit since periodic
++		 * mode is rarely used 
++		 */
++		if (period == 0) {
++			pr_err("*** period = 0! fixing\n");
++			period = 1;
++		}
++
+ 		omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period);
+ 		break;
+ 	case CLOCK_EVT_MODE_ONESHOT:
+@@ -117,8 +131,9 @@ static void __init omap2_gp_clockevent_init(void)
+ 				     clockevent_gpt.shift);
+ 	clockevent_gpt.max_delta_ns =
+ 		clockevent_delta2ns(0xffffffff, &clockevent_gpt);
++	/* per 3430 TRM table 16-11 */
+ 	clockevent_gpt.min_delta_ns =
+-		clockevent_delta2ns(1, &clockevent_gpt);
++		clockevent_delta2ns(2, &clockevent_gpt);
+ 
+ 	clockevent_gpt.cpumask = cpumask_of_cpu(0);
+ 	clockevents_register_device(&clockevent_gpt);
============================================================
--- packages/linux/linux-omap2-git/beagleboard/02-gptimer_clear_tocr	0f618ebc4d656a0020964339216cfd22e2662469
+++ packages/linux/linux-omap2-git/beagleboard/02-gptimer_clear_tocr	0f618ebc4d656a0020964339216cfd22e2662469
@@ -0,0 +1,97 @@
+OMAP2/3 GPTIMER: clear TOCR register after timer overflow interrupt and during load
+
+From: Paul Walmsley <paul at pwsan.com>
+
+There appears to be a hardware bug in the 1-ms tick generation section
+of the GPTIMER blocks on some OMAP3530 chips.  TOCR is sometimes
+incremented when a a timer overflow event occurs and TPIR = TPNR =
+TOWR = TOCR = 0, in contradiction of 34xx TRM 16.2.4.2.1.  When TOCR
+is incremented under these conditions, the timer will not generate any
+further overflow interrupts.  (The kernel currently relies on overflow
+interrupts to generate ticks and drive the scheduler.)
+
+This patch works around the bug by clearing TOCR in the GPTIMER
+overflow ISR and in the timer load functions.
+
+The precise sequence of hardware events needed to reproduce this bug
+is still unknown.  Without this patch, the bug is consistently
+observable on several BeagleBoards (including mine and Koen's) within
+a few minutes of boot.  It's not clear whether this bug is present on
+all OMAP3 revisions, or whether it is simply specific to certain
+OMAP3530ES2.2 lots.
+
+This patch fixes the "serial hangs" reported by some BeagleBoard
+users.  During these hangs, characters are still received from the
+serial port, so magic SysRq will still work; but characters are never
+delivered on to the underlying line discipline.  This since
+tty_flip_buffer_push() uses schedule_delayed_work() to defer passing
+the input buffer to the line discipline, but the delayed work function
+is never called since no timer tick ever arrives.
+
+The patch should also fix some other sporadic boot hangs reported by
+BeagleBoard users that are due to timer interrupt non-delivery.
+---
+
+ arch/arm/mach-omap2/timer-gp.c      |    1 +
+ arch/arm/plat-omap/dmtimer.c        |    8 ++++++++
+ include/asm-arm/arch-omap/dmtimer.h |    2 ++
+ 3 files changed, 11 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
+index edc0c9e..869fe14 100644
+--- a/arch/arm/mach-omap2/timer-gp.c
++++ b/arch/arm/mach-omap2/timer-gp.c
+@@ -44,6 +44,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_clear_ovf_cnt(gpt);
+ 	omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_OVERFLOW);
+ 
+ 	evt->event_handler(evt);
+diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
+index f22506a..2cbb4cc 100644
+--- a/arch/arm/plat-omap/dmtimer.c
++++ b/arch/arm/plat-omap/dmtimer.c
+@@ -543,6 +543,8 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+ 	while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)))
+ 		cpu_relax();
+ 
++	omap_dm_timer_write_reg(timer, OMAP_TIMER_TICK_INT_MASK_SET_REG, 0);
++
+ 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ }
+ 
+@@ -561,6 +563,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
+ 
+ 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
+ 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
++	omap_dm_timer_write_reg(timer, OMAP_TIMER_TICK_INT_MASK_SET_REG, 0);
+ 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+ }
+ 
+@@ -614,6 +617,11 @@ 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_clear_ovf_cnt(struct omap_dm_timer *timer)
++{
++	omap_dm_timer_write_reg(timer, OMAP_TIMER_TICK_INT_MASK_SET_REG, 0);
++}
++
+ 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..7b1138b 100644
+--- a/include/asm-arm/arch-omap/dmtimer.h
++++ b/include/asm-arm/arch-omap/dmtimer.h
+@@ -73,6 +73,8 @@ 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_clear_ovf_cnt(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);
============================================================
--- packages/linux/linux-omap2_git.bb	d1968e8ba7639627d6db87ba953b800c24ef27ea
+++ packages/linux/linux-omap2_git.bb	9117272d8b2908df59a233aaf707e94115da1631
@@ -6,7 +6,7 @@ PV = "2.6.26"
 
 PV = "2.6.26"
 #PV = "2.6.26+2.6.27-rc1+${PR}+git${SRCREV}"
-PR = "r50"
+PR = "r51"
 
 SRC_URI = "git://source.mvista.com/git/linux-omap-2.6.git;protocol=git \
 	   file://defconfig"
@@ -29,7 +29,6 @@ SRC_URI_append_beagleboard = " file://no
            file://06-ensure-fclk.diff;patch=1 \
            file://07-set-burst-size.diff;patch=1 \
            file://cache-display-fix.patch;patch=1 \
-           file://serialfix.diff;patch=1 \
            file://i2c-omap-race-fix.diff;patch=1 \
            file://TWL4030-01.patch;patch=1 \
            file://TWL4030-02.patch;patch=1 \
@@ -46,6 +45,8 @@ SRC_URI_append_beagleboard = " file://no
            file://4bitmmc.diff;patch=1 \
 	   file://400khz-i2c.diff;patch=1 \
            file://no-cortex-deadlock.patch;patch=1 \
+           file://01-gptimer_maintain_tldr_lt_0xffffffff;patch=1 \
+           file://02-gptimer_clear_tocr;patch=1 \
 "
 
 SRC_URI_append_omap3evm = " file://no-harry-potter.diff;patch=1 \






More information about the Openembedded-commits mailing list