aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-sa1100.c
diff options
context:
space:
mode:
authorMarcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>2010-10-18 17:35:54 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-11-10 08:34:45 -0500
commit7decaa557a20f48aabef35f817ec16ef563567b0 (patch)
treec5b5bed714af85ff5715d81c6fd3807b3d0b3888 /drivers/rtc/rtc-sa1100.c
parentfd3ee6d3421bc05ce42ee7f48071aee72051af28 (diff)
ARM: 6454/1: sa1100: Fix for a nasty initialization bug in the RTSR.
This patch fixes a nasty initialization condition on the RTSR register. Sometimes, bit 1 will wake up set, sometimes not. This can be seen by checking the value of the RTSR by typing '$ cat /proc/driver/rtc', which has been provided by the previous patch. If this bit is set, the command '$ cat /dev/rtc0' will lock the system in an endless interrupt routine calling loop. This patch fixes the issue both at sa1100_rtc_probe(), where it avoids a spurious interrupt from happening, and at sa1100_rtc_interrupt(), which is the robust solution, though it does not avoid the first spurious interrupt. Signed-off-by: Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/rtc/rtc-sa1100.c')
-rw-r--r--drivers/rtc/rtc-sa1100.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index b04c8374a279..b0985f727078 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -117,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
117 rtsr = RTSR; 117 rtsr = RTSR;
118 /* clear interrupt sources */ 118 /* clear interrupt sources */
119 RTSR = 0; 119 RTSR = 0;
120 RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); 120 /* Fix for a nasty initialization problem the in SA11xx RTSR register.
121 * See also the comments in sa1100_rtc_probe(). */
122 if (rtsr & (RTSR_ALE | RTSR_HZE)) {
123 /* This is the original code, before there was the if test
124 * above. This code does not clear interrupts that were not
125 * enabled. */
126 RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
127 } else {
128 /* For some reason, it is possible to enter this routine
129 * without interruptions enabled, it has been tested with
130 * several units (Bug in SA11xx chip?).
131 *
132 * This situation leads to an infinite "loop" of interrupt
133 * routine calling and as a result the processor seems to
134 * lock on its first call to open(). */
135 RTSR = RTSR_AL | RTSR_HZ;
136 }
121 137
122 /* clear alarm interrupt if it has occurred */ 138 /* clear alarm interrupt if it has occurred */
123 if (rtsr & RTSR_AL) 139 if (rtsr & RTSR_AL)
@@ -382,6 +398,30 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
382 398
383 platform_set_drvdata(pdev, rtc); 399 platform_set_drvdata(pdev, rtc);
384 400
401 /* Fix for a nasty initialization problem the in SA11xx RTSR register.
402 * See also the comments in sa1100_rtc_interrupt().
403 *
404 * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
405 * interrupt pending, even though interrupts were never enabled.
406 * In this case, this bit it must be reset before enabling
407 * interruptions to avoid a nonexistent interrupt to occur.
408 *
409 * In principle, the same problem would apply to bit 0, although it has
410 * never been observed to happen.
411 *
412 * This issue is addressed both here and in sa1100_rtc_interrupt().
413 * If the issue is not addressed here, in the times when the processor
414 * wakes up with the bit set there will be one spurious interrupt.
415 *
416 * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
417 * safe side, once the condition that lead to this strange
418 * initialization is unknown and could in principle happen during
419 * normal processing.
420 *
421 * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
422 * the corresponding bits in RTSR. */
423 RTSR = RTSR_AL | RTSR_HZ;
424
385 return 0; 425 return 0;
386} 426}
387 427