Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7decaa55 authored by Marcelo Roberto Jimenez's avatar Marcelo Roberto Jimenez Committed by Russell King
Browse files

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: default avatarMarcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent fd3ee6d3
Loading
Loading
Loading
Loading
+41 −1
Original line number Diff line number Diff line
@@ -117,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
	rtsr = RTSR;
	/* clear interrupt sources */
	RTSR = 0;
	/* 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;
}