We need the ability to support initialization of hpet_default_delta and hpet_t1_cmp counters before irq can be enabled.
This patch splits hpet_rtc_timer_init() into two functions: hpet_rtc_timer_counter_init() and hpet_rtc_timer_enable, so that the above functionality can be achieved. Next patch explains it's need in detail. No functional change in this patch. Signed-off-by: Pratyush Anand <pan...@redhat.com> [dzic...@redhat.com: edited the patch's summary] Signed-off-by: Don Zickus <dzic...@redhat.com> --- arch/x86/include/asm/hpet.h | 2 ++ arch/x86/kernel/hpet.c | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index cc285ec4b2c1..8eecb31bebcb 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -96,6 +96,8 @@ extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec); extern int hpet_set_periodic_freq(unsigned long freq); extern int hpet_rtc_dropped_irq(void); +extern int hpet_rtc_timer_counter_init(void); +extern int hpet_rtc_timer_enable(void); extern int hpet_rtc_timer_init(void); extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); extern int hpet_register_irq_handler(rtc_irq_handler handler); diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ed16e58658a4..6f6d21059b1b 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -1074,14 +1074,12 @@ void hpet_unregister_irq_handler(rtc_irq_handler handler) EXPORT_SYMBOL_GPL(hpet_unregister_irq_handler); /* - * Timer 1 for RTC emulation. We use one shot mode, as periodic mode - * is not supported by all HPET implementations for timer 1. - * - * hpet_rtc_timer_init() is called when the rtc is initialized. + * hpet_rtc_timer_counter_init() is called before interrupt can be + * registered */ -int hpet_rtc_timer_init(void) +int hpet_rtc_timer_counter_init(void) { - unsigned int cfg, cnt, delta; + unsigned int cnt, delta; unsigned long flags; if (!is_hpet_enabled()) @@ -1106,6 +1104,22 @@ int hpet_rtc_timer_init(void) hpet_writel(cnt, HPET_T1_CMP); hpet_t1_cmp = cnt; + local_irq_restore(flags); + + return 1; +} +EXPORT_SYMBOL_GPL(hpet_rtc_timer_counter_init); + +/* + * hpet_rtc_timer_enable() is called during RTC initialization + */ +int hpet_rtc_timer_enable(void) +{ + unsigned int cfg; + unsigned long flags; + + local_irq_save(flags); + cfg = hpet_readl(HPET_T1_CFG); cfg &= ~HPET_TN_PERIODIC; cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; @@ -1115,6 +1129,21 @@ int hpet_rtc_timer_init(void) return 1; } +EXPORT_SYMBOL_GPL(hpet_rtc_timer_enable); + +/* + * Timer 1 for RTC emulation. We use one shot mode, as periodic mode + * is not supported by all HPET implementations for timer 1. + * + * hpet_rtc_timer_init() is called when the rtc is initialized. + */ +int hpet_rtc_timer_init(void) +{ + if (!hpet_rtc_timer_counter_init()) + return 0; + + return hpet_rtc_timer_enable(); +} EXPORT_SYMBOL_GPL(hpet_rtc_timer_init); static void hpet_disable_rtc_channel(void) -- 2.5.5