summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2012-09-05 10:52:44 -0700
committerStefan Reinauer <stefan.reinauer@coreboot.org>2012-11-08 19:40:05 +0100
commit4b1610d766aa1ea0c825b39600fe8a3eb6d2a6be (patch)
tree27558918e6f4afd915ae7273d03b99de0cc58ff9 /src/drivers
parent2558c736a06c416e41bb35c2e6439f457e541f61 (diff)
downloadcoreboot-4b1610d766aa1ea0c825b39600fe8a3eb6d2a6be.tar.xz
RTC: Don't clear pending interrupt in resume path
The linux kernel relies on the RTC reporting pending interrupts if the RTC alarm was used to wake the system. If we clear these flags here then the rtc-cmos driver in the kernel will think that no interrupts are pending and will not re-start the timerqueue to handle the alarm timerqueue node. This flag doesn't exist in SMM but the rtc code is compiled there. Since rtc_init() is not called by SMM it is guarded with an ifdef. I performed several thousand suspend/resume cycles without seeing an issue where hwclock was unable to read from /dev/rtc. There still is a potential kernel issue where the timerqueue can stall but this makes that much less likely to happen on resume. Change-Id: I5a343da4ce5c4c8ec4783b4e503869ccfa5077f0 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/1741 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/pc80/mc146818rtc.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c
index 52cfb63275..6e5b92a35c 100644
--- a/src/drivers/pc80/mc146818rtc.c
+++ b/src/drivers/pc80/mc146818rtc.c
@@ -8,6 +8,9 @@
#include "option_table.h"
#include <cbfs.h>
#endif
+#if CONFIG_HAVE_ACPI_RESUME
+#include <arch/acpi.h>
+#endif
/* control registers - Moto names
*/
@@ -127,6 +130,7 @@ static void rtc_set_checksum(int range_start, int range_end, int cks_loc)
#endif
#endif
+#ifndef __SMM__
void rtc_init(int invalid)
{
int cmos_invalid = 0;
@@ -192,9 +196,20 @@ void rtc_init(int invalid)
PC_CKS_RANGE_END,PC_CKS_LOC);
#endif
+#if CONFIG_HAVE_ACPI_RESUME
+ /*
+ * Avoid clearing pending interrupts in the resume path because
+ * the Linux kernel relies on this to know if it should restart
+ * the RTC timerqueue if the wake was due to the RTC alarm.
+ */
+ if (acpi_slp_type == 3)
+ return;
+#endif
+
/* Clear any pending interrupts */
(void) cmos_read(RTC_INTR_FLAGS);
}
+#endif
#if CONFIG_USE_OPTION_TABLE