提交 2ded6e6a 编写于 作者: M Mark Langsdorf 提交者: Thomas Gleixner

x86, hpet: Immediately disable HPET timer 1 if rtc irq is masked

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: NMark Langsdorf <mark.langsdorf@amd.com>
Link: http://lkml.kernel.org/r/20111118153306.GB16319@alberich.amd.comTested-by: NAndreas Herrmann <andreas.herrmann3@amd.com>
Signed-off-by: NAndreas Herrmann <andreas.herrmann3@amd.com>
Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
上级 4e2b1c4f
...@@ -1049,6 +1049,14 @@ int hpet_rtc_timer_init(void) ...@@ -1049,6 +1049,14 @@ int hpet_rtc_timer_init(void)
} }
EXPORT_SYMBOL_GPL(hpet_rtc_timer_init); EXPORT_SYMBOL_GPL(hpet_rtc_timer_init);
static void hpet_disable_rtc_channel(void)
{
unsigned long cfg;
cfg = hpet_readl(HPET_T1_CFG);
cfg &= ~HPET_TN_ENABLE;
hpet_writel(cfg, HPET_T1_CFG);
}
/* /*
* The functions below are called from rtc driver. * The functions below are called from rtc driver.
* Return 0 if HPET is not being used. * Return 0 if HPET is not being used.
...@@ -1060,6 +1068,9 @@ int hpet_mask_rtc_irq_bit(unsigned long bit_mask) ...@@ -1060,6 +1068,9 @@ int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
return 0; return 0;
hpet_rtc_flags &= ~bit_mask; hpet_rtc_flags &= ~bit_mask;
if (unlikely(!hpet_rtc_flags))
hpet_disable_rtc_channel();
return 1; return 1;
} }
EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit); EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit);
...@@ -1125,15 +1136,11 @@ EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq); ...@@ -1125,15 +1136,11 @@ EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq);
static void hpet_rtc_timer_reinit(void) static void hpet_rtc_timer_reinit(void)
{ {
unsigned int cfg, delta; unsigned int delta;
int lost_ints = -1; int lost_ints = -1;
if (unlikely(!hpet_rtc_flags)) { if (unlikely(!hpet_rtc_flags))
cfg = hpet_readl(HPET_T1_CFG); hpet_disable_rtc_channel();
cfg &= ~HPET_TN_ENABLE;
hpet_writel(cfg, HPET_T1_CFG);
return;
}
if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit) if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
delta = hpet_default_delta; delta = hpet_default_delta;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册