aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMark Langsdorf <mark.langsdorf@amd.com>2011-11-18 10:33:06 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-12-21 15:57:39 -0500
commitf4347eb6d2aae437d9552a26704bcb07f4626d6c (patch)
treee78b2d81528b5e143d8e17fd0fbf9cf83c56bb7e /arch
parent53824693961bf513fe152d35c887e83eb016eaea (diff)
x86, hpet: Immediately disable HPET timer 1 if rtc irq is masked
commit 2ded6e6a94c98ea453a156748cb7fabaf39a76b9 upstream. When HPET is operating in RTC mode, the TN_ENABLE bit on timer1 controls whether the HPET or the RTC delivers interrupts to irq8. When the system goes into suspend, the RTC driver sends a signal to the HPET driver so that the HPET releases control of irq8, allowing the RTC to wake the system from suspend. The switchover is accomplished by a write to the HPET configuration registers which currently only occurs while servicing the HPET interrupt. On some systems, I have seen the system suspend before an HPET interrupt occurs, preventing the write to the HPET configuration register and leaving the HPET in control of the irq8. As the HPET is not active during suspend, it does not generate a wake signal and RTC alarms do not work. This patch forces the HPET driver to immediately transfer control of the irq8 channel to the RTC instead of waiting until the next interrupt event. Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com> Link: http://lkml.kernel.org/r/20111118153306.GB16319@alberich.amd.com Tested-by: Andreas Herrmann <andreas.herrmann3@amd.com> Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/hpet.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 6781765b3a0..aa083d35074 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -1054,6 +1054,14 @@ int hpet_rtc_timer_init(void)
1054} 1054}
1055EXPORT_SYMBOL_GPL(hpet_rtc_timer_init); 1055EXPORT_SYMBOL_GPL(hpet_rtc_timer_init);
1056 1056
1057static void hpet_disable_rtc_channel(void)
1058{
1059 unsigned long cfg;
1060 cfg = hpet_readl(HPET_T1_CFG);
1061 cfg &= ~HPET_TN_ENABLE;
1062 hpet_writel(cfg, HPET_T1_CFG);
1063}
1064
1057/* 1065/*
1058 * The functions below are called from rtc driver. 1066 * The functions below are called from rtc driver.
1059 * Return 0 if HPET is not being used. 1067 * Return 0 if HPET is not being used.
@@ -1065,6 +1073,9 @@ int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
1065 return 0; 1073 return 0;
1066 1074
1067 hpet_rtc_flags &= ~bit_mask; 1075 hpet_rtc_flags &= ~bit_mask;
1076 if (unlikely(!hpet_rtc_flags))
1077 hpet_disable_rtc_channel();
1078
1068 return 1; 1079 return 1;
1069} 1080}
1070EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit); 1081EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit);
@@ -1130,15 +1141,11 @@ EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq);
1130 1141
1131static void hpet_rtc_timer_reinit(void) 1142static void hpet_rtc_timer_reinit(void)
1132{ 1143{
1133 unsigned int cfg, delta; 1144 unsigned int delta;
1134 int lost_ints = -1; 1145 int lost_ints = -1;
1135 1146
1136 if (unlikely(!hpet_rtc_flags)) { 1147 if (unlikely(!hpet_rtc_flags))
1137 cfg = hpet_readl(HPET_T1_CFG); 1148 hpet_disable_rtc_channel();
1138 cfg &= ~HPET_TN_ENABLE;
1139 hpet_writel(cfg, HPET_T1_CFG);
1140 return;
1141 }
1142 1149
1143 if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit) 1150 if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
1144 delta = hpet_default_delta; 1151 delta = hpet_default_delta;