Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 399afa4f authored by Maxim Levitsky's avatar Maxim Levitsky Committed by Linus Torvalds
Browse files

[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: default avatarMaxim Levitsky <maximlevitsky@gmail.com>
Acked-by: default avatarMichael S. Tsirkin <mst@dev.mellanox.co.il>
Acked-by: default avatarJeff Chua <jeff.chua.linux@gmail.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 22c8c65d
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
#include <linux/errno.h>
#include <linux/hpet.h>
#include <linux/init.h>
#include <linux/sysdev.h>
#include <linux/pm.h>

#include <asm/hpet.h>
#include <asm/io.h>
@@ -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