diff options
| author | Aaron Durbin <adurbin@google.com> | 2008-07-16 23:27:08 +0200 | 
|---|---|---|
| committer | Andi Kleen <andi@basil.nowhere.org> | 2008-07-16 23:27:08 +0200 | 
| commit | 4d3870431d17346c4fdd80e087b7d76f1b5941d5 (patch) | |
| tree | a8d3dcc5ab984ed7cbf67965372d58145bc90e9a /drivers/acpi/reboot.c | |
| parent | c83642d5123225a22cccd75adea6e97c245714cb (diff) | |
| download | olio-linux-3.10-4d3870431d17346c4fdd80e087b7d76f1b5941d5.tar.xz olio-linux-3.10-4d3870431d17346c4fdd80e087b7d76f1b5941d5.zip  | |
Add the ability to reset the machine using the RESET_REG in ACPI's FADT table.
Signed-off-by: Aaron Durbin <adurbin@google.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Cc: Len Brown <lenb@kernel.org>
Cc: Andi Kleen <andi@firstfloor.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'drivers/acpi/reboot.c')
| -rw-r--r-- | drivers/acpi/reboot.c | 50 | 
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c new file mode 100644 index 00000000000..a6b662c00b6 --- /dev/null +++ b/drivers/acpi/reboot.c @@ -0,0 +1,50 @@ + +#include <linux/pci.h> +#include <linux/acpi.h> +#include <acpi/reboot.h> + +void acpi_reboot(void) +{ +	struct acpi_generic_address *rr; +	struct pci_bus *bus0; +	u8 reset_value; +	unsigned int devfn; + +	if (acpi_disabled) +		return; + +	rr = &acpi_gbl_FADT.reset_register; + +	/* Is the reset register supported? */ +	if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || +	    rr->bit_width != 8 || rr->bit_offset != 0) +		return; + +	reset_value = acpi_gbl_FADT.reset_value; + +	/* The reset register can only exist in I/O, Memory or PCI config space +	 * on a device on bus 0. */ +	switch (rr->space_id) { +	case ACPI_ADR_SPACE_PCI_CONFIG: +		/* The reset register can only live on bus 0. */ +		bus0 = pci_find_bus(0, 0); +		if (!bus0) +			return; +		/* Form PCI device/function pair. */ +		devfn = PCI_DEVFN((rr->address >> 32) & 0xffff, +				  (rr->address >> 16) & 0xffff); +		printk(KERN_DEBUG "Resetting with ACPI PCI RESET_REG."); +		/* Write the value that resets us. */ +		pci_bus_write_config_byte(bus0, devfn, +				(rr->address & 0xffff), reset_value); +		break; + +	case ACPI_ADR_SPACE_SYSTEM_MEMORY: +	case ACPI_ADR_SPACE_SYSTEM_IO: +		printk(KERN_DEBUG "ACPI MEMORY or I/O RESET_REG.\n"); +		acpi_hw_low_level_write(8, reset_value, rr); +		break; +	} +	/* Wait ten seconds */ +	acpi_os_stall(10000000); +}  |