poweroff.c 1.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * poweroff.c - ACPI handler for powering off the system.
 *
 * AKA S5, but it is independent of whether or not the kernel supports
 * any other sleep support in the system.
A
Alexey Starikovskiy 已提交
6 7 8 9
 *
 * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
 *
 * This file is released under the GPLv2.
L
Linus Torvalds 已提交
10 11 12 13 14
 */

#include <linux/pm.h>
#include <linux/init.h>
#include <acpi/acpi_bus.h>
A
Alexey Starikovskiy 已提交
15 16
#include <linux/sysdev.h>
#include <asm/io.h>
L
Linus Torvalds 已提交
17 18
#include "sleep.h"

A
Alexey Starikovskiy 已提交
19 20
int acpi_sleep_prepare(u32 acpi_state)
{
L
Len Brown 已提交
21
#ifdef CONFIG_ACPI_SLEEP
A
Alexey Starikovskiy 已提交
22
	/* do we have a wakeup address for S2 and S3? */
23
	if (acpi_state == ACPI_STATE_S3) {
A
Alexey Starikovskiy 已提交
24 25 26 27 28 29 30 31 32 33
		if (!acpi_wakeup_address) {
			return -EFAULT;
		}
		acpi_set_firmware_waking_vector((acpi_physical_address)
						virt_to_phys((void *)
							     acpi_wakeup_address));

	}
	ACPI_FLUSH_CPU_CACHE();
	acpi_enable_wakeup_device_prep(acpi_state);
L
Len Brown 已提交
34
#endif
35
	acpi_gpe_sleep_prepare(acpi_state);
A
Alexey Starikovskiy 已提交
36 37 38 39
	acpi_enter_sleep_state_prep(acpi_state);
	return 0;
}

40 41
#ifdef CONFIG_PM

42 43 44 45 46 47 48
static void acpi_power_off_prepare(void)
{
	/* Prepare to power off the system */
	acpi_sleep_prepare(ACPI_STATE_S5);
}

static void acpi_power_off(void)
L
Linus Torvalds 已提交
49
{
50
	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
A
Alexey Starikovskiy 已提交
51 52
	printk("%s called\n", __FUNCTION__);
	local_irq_disable();
L
Linus Torvalds 已提交
53 54 55 56 57 58 59 60 61 62
	/* Some SMP machines only can poweroff in boot CPU */
	acpi_enter_sleep_state(ACPI_STATE_S5);
}

static int acpi_poweroff_init(void)
{
	if (!acpi_disabled) {
		u8 type_a, type_b;
		acpi_status status;

A
Alexey Starikovskiy 已提交
63 64 65
		status =
		    acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
		if (ACPI_SUCCESS(status)) {
66 67
			pm_power_off_prepare = acpi_power_off_prepare;
			pm_power_off = acpi_power_off;
A
Alexey Starikovskiy 已提交
68
		}
L
Linus Torvalds 已提交
69 70 71 72 73
	}
	return 0;
}

late_initcall(acpi_poweroff_init);
74

L
Len Brown 已提交
75
#endif				/* CONFIG_PM */