|
@@ -117,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
|
|
|
rtsr = RTSR;
|
|
|
/* clear interrupt sources */
|
|
|
RTSR = 0;
|
|
|
- RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
|
|
|
+ /* Fix for a nasty initialization problem the in SA11xx RTSR register.
|
|
|
+ * See also the comments in sa1100_rtc_probe(). */
|
|
|
+ if (rtsr & (RTSR_ALE | RTSR_HZE)) {
|
|
|
+ /* This is the original code, before there was the if test
|
|
|
+ * above. This code does not clear interrupts that were not
|
|
|
+ * enabled. */
|
|
|
+ RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
|
|
|
+ } else {
|
|
|
+ /* For some reason, it is possible to enter this routine
|
|
|
+ * without interruptions enabled, it has been tested with
|
|
|
+ * several units (Bug in SA11xx chip?).
|
|
|
+ *
|
|
|
+ * This situation leads to an infinite "loop" of interrupt
|
|
|
+ * routine calling and as a result the processor seems to
|
|
|
+ * lock on its first call to open(). */
|
|
|
+ RTSR = RTSR_AL | RTSR_HZ;
|
|
|
+ }
|
|
|
|
|
|
/* clear alarm interrupt if it has occurred */
|
|
|
if (rtsr & RTSR_AL)
|
|
@@ -382,6 +398,30 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
|
|
|
|
|
|
platform_set_drvdata(pdev, rtc);
|
|
|
|
|
|
+ /* Fix for a nasty initialization problem the in SA11xx RTSR register.
|
|
|
+ * See also the comments in sa1100_rtc_interrupt().
|
|
|
+ *
|
|
|
+ * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
|
|
|
+ * interrupt pending, even though interrupts were never enabled.
|
|
|
+ * In this case, this bit it must be reset before enabling
|
|
|
+ * interruptions to avoid a nonexistent interrupt to occur.
|
|
|
+ *
|
|
|
+ * In principle, the same problem would apply to bit 0, although it has
|
|
|
+ * never been observed to happen.
|
|
|
+ *
|
|
|
+ * This issue is addressed both here and in sa1100_rtc_interrupt().
|
|
|
+ * If the issue is not addressed here, in the times when the processor
|
|
|
+ * wakes up with the bit set there will be one spurious interrupt.
|
|
|
+ *
|
|
|
+ * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
|
|
|
+ * safe side, once the condition that lead to this strange
|
|
|
+ * initialization is unknown and could in principle happen during
|
|
|
+ * normal processing.
|
|
|
+ *
|
|
|
+ * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
|
|
|
+ * the corresponding bits in RTSR. */
|
|
|
+ RTSR = RTSR_AL | RTSR_HZ;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|