summaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-acpi.c
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2007-10-11 23:53:58 +0200
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-10-11 23:53:58 +0200
commit5e32132befa5d2cefadf3141fee0bbb40cd11f0e (patch)
tree7bf2002e49b169d24b87a8fe71364875e04d1e90 /drivers/ide/ide-acpi.c
parent8cb1f567f4c0a2fde9cbf77c2af888a28cab3423 (diff)
downloadlinux-stable-5e32132befa5d2cefadf3141fee0bbb40cd11f0e.tar.gz
linux-stable-5e32132befa5d2cefadf3141fee0bbb40cd11f0e.tar.bz2
linux-stable-5e32132befa5d2cefadf3141fee0bbb40cd11f0e.zip
ide: hook ACPI _PSx method to IDE power on/off
ACPI spec defines the sequence of IDE power on/off: Powering down: Call _GTM. Power down drive (calls _PS3 method and turns off power planes). Powering up: Power up drive (calls _PS0 method if present and turns on power planes). Call _STM passing info from _GTM (possibly modified), with ID data from each drive. Initialize the channel. May modify the results of _GTF. For each drive: Call _GTF. Execute task file (possibly modified). This patch adds the missed _PS0/_PS3 methods call. Signed-off-by: Shaohua Li <shaohua.li@intel.com> Acked-by: Len Brown <len.brown@intel.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-acpi.c')
-rw-r--r--drivers/ide/ide-acpi.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 17aea65d7dd2..6bff81a58bf3 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -612,6 +612,46 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
/**
+ * ide_acpi_set_state - set the channel power state
+ * @hwif: target IDE interface
+ * @on: state, on/off
+ *
+ * This function executes the _PS0/_PS3 ACPI method to set the power state.
+ * ACPI spec requires _PS0 when IDE power on and _PS3 when power off
+ */
+void ide_acpi_set_state(ide_hwif_t *hwif, int on)
+{
+ int unit;
+
+ if (ide_noacpi)
+ return;
+
+ DEBPRINT("ENTER:\n");
+
+ if (!hwif->acpidata) {
+ DEBPRINT("no ACPI data for %s\n", hwif->name);
+ return;
+ }
+ /* channel first and then drives for power on and verse versa for power off */
+ if (on)
+ acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
+
+ if (!drive->acpidata->obj_handle)
+ drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
+
+ if (drive->acpidata->obj_handle && drive->present) {
+ acpi_bus_set_power(drive->acpidata->obj_handle,
+ on? ACPI_STATE_D0: ACPI_STATE_D3);
+ }
+ }
+ if (!on)
+ acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3);
+}
+EXPORT_SYMBOL_GPL(ide_acpi_set_state);
+
+/**
* ide_acpi_init - initialize the ACPI link for an IDE interface
* @hwif: target IDE interface (channel)
*
@@ -679,6 +719,8 @@ void ide_acpi_init(ide_hwif_t *hwif)
return;
}
+ /* ACPI _PS0 before _STM */
+ ide_acpi_set_state(hwif, 1);
/*
* ACPI requires us to call _STM on startup
*/