From 399afa4fc9238fbae42116cf25a54671c0e8f56e Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Thu, 29 Mar 2007 15:46:48 +0200 Subject: [PATCH] [PATCH] Add suspend/resume for HPET This adds support of suspend/resume on i386 for HPET, which fixes a number of timer-related failures around STR. Signed-off-by: Maxim Levitsky Acked-by: Michael S. Tsirkin Acked-by: Jeff Chua Signed-off-by: Linus Torvalds --- arch/i386/kernel/hpet.c | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c index 76afea67f691..17d73459fc5f 100644 --- a/arch/i386/kernel/hpet.c +++ b/arch/i386/kernel/hpet.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include @@ -307,6 +309,7 @@ int __init hpet_enable(void) out_nohpet: iounmap(hpet_virt_address); hpet_virt_address = NULL; + boot_hpet_disable = 1; return 0; } @@ -521,3 +524,68 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } #endif + + +/* + * Suspend/resume part + */ + +#ifdef CONFIG_PM + +static int hpet_suspend(struct sys_device *sys_device, pm_message_t state) +{ + unsigned long cfg = hpet_readl(HPET_CFG); + + cfg &= ~(HPET_CFG_ENABLE|HPET_CFG_LEGACY); + hpet_writel(cfg, HPET_CFG); + + return 0; +} + +static int hpet_resume(struct sys_device *sys_device) +{ + unsigned int id; + + hpet_start_counter(); + + id = hpet_readl(HPET_ID); + + if (id & HPET_ID_LEGSUP) + hpet_enable_int(); + + return 0; +} + +static struct sysdev_class hpet_class = { + set_kset_name("hpet"), + .suspend = hpet_suspend, + .resume = hpet_resume, +}; + +static struct sys_device hpet_device = { + .id = 0, + .cls = &hpet_class, +}; + + +static __init int hpet_register_sysfs(void) +{ + int err; + + if (!is_hpet_capable()) + return 0; + + err = sysdev_class_register(&hpet_class); + + if (!err) { + err = sysdev_register(&hpet_device); + if (err) + sysdev_class_unregister(&hpet_class); + } + + return err; +} + +device_initcall(hpet_register_sysfs); + +#endif -- 2.20.1