patch-2.4.25 linux-2.4.25/drivers/acpi/hardware/hwsleep.c
Next file: linux-2.4.25/drivers/acpi/hardware/hwtimer.c
Previous file: linux-2.4.25/drivers/acpi/hardware/hwregs.c
Back to the patch index
Back to the overall index
- Lines: 228
- Date:
2004-02-18 05:36:31.000000000 -0800
- Orig file:
linux-2.4.24/drivers/acpi/hardware/hwsleep.c
- Orig date:
2003-08-25 04:44:41.000000000 -0700
diff -urN linux-2.4.24/drivers/acpi/hardware/hwsleep.c linux-2.4.25/drivers/acpi/hardware/hwsleep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2003, R. Byron Moore
+ * Copyright (C) 2000 - 2004, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -181,6 +181,13 @@
return_ACPI_STATUS (status);
}
+ /* Set the system indicators to show the desired sleep state. */
+
+ status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+ if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
+ }
+
return_ACPI_STATUS (AE_OK);
}
@@ -220,30 +227,31 @@
return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
}
-
sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
- /* Clear wake status */
+ if (sleep_state != ACPI_STATE_S5) {
+ /* Clear wake status */
- status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
- status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
- /* Disable BM arbitration */
+ /* Disable BM arbitration */
- status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
- status = acpi_hw_disable_non_wakeup_gpes();
+ status = acpi_hw_disable_non_wakeup_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
@@ -266,6 +274,11 @@
PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
+ /*
+ * We split the writes of SLP_TYP and SLP_EN to workaround
+ * poorly implemented hardware.
+ */
+
/* Write #1: fill in SLP_TYP data */
status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
@@ -297,13 +310,15 @@
return_ACPI_STATUS (status);
}
- /*
- * Wait a second, then try again. This is to get S4/5 to work on all machines.
- */
if (sleep_state > ACPI_STATE_S3) {
/*
+ * We wanted to sleep > S3, but it didn't happen (by virtue of the fact that
+ * we are still executing!)
+ *
+ * Wait ten seconds, then try again. This is to get S4/S5 to work on all machines.
+ *
* We wait so long to allow chipsets that poll this reg very slowly to
- * still read the right value. Ideally, this entire block would go
+ * still read the right value. Ideally, this block would go
* away entirely.
*/
acpi_os_stall (10000000);
@@ -354,12 +369,23 @@
ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_s4bios");
- acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
- acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
- acpi_hw_disable_non_wakeup_gpes();
+ status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ status = acpi_hw_disable_non_wakeup_gpes ();
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
- ACPI_FLUSH_CPU_CACHE();
+ ACPI_FLUSH_CPU_CACHE ();
status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, (u32) acpi_gbl_FADT->S4bios_req, 8);
@@ -389,16 +415,56 @@
acpi_status
acpi_leave_sleep_state (
- u8 sleep_state)
+ u8 sleep_state)
{
- struct acpi_object_list arg_list;
- union acpi_object arg;
- acpi_status status;
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ acpi_status status;
+ struct acpi_bit_register_info *sleep_type_reg_info;
+ struct acpi_bit_register_info *sleep_enable_reg_info;
+ u32 PM1Acontrol;
+ u32 PM1Bcontrol;
ACPI_FUNCTION_TRACE ("acpi_leave_sleep_state");
+ /*
+ * Set SLP_TYPE and SLP_EN to state S0.
+ * This is unclear from the ACPI Spec, but it is required
+ * by some machines.
+ */
+ status = acpi_get_sleep_type_data (ACPI_STATE_S0,
+ &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
+ if (ACPI_SUCCESS (status)) {
+ sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
+ sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
+
+ /* Get current value of PM1A control */
+
+ status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
+ if (ACPI_SUCCESS (status)) {
+ /* Clear SLP_EN and SLP_TYP fields */
+
+ PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
+ sleep_enable_reg_info->access_bit_mask);
+ PM1Bcontrol = PM1Acontrol;
+
+ /* Insert SLP_TYP bits */
+
+ PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
+ PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
+
+ /* Just ignore any errors */
+
+ (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
+ (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
+ }
+ }
+
/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
@@ -407,12 +473,17 @@
arg_list.count = 1;
arg_list.pointer = &arg;
-
arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = sleep_state;
/* Ignore any errors from these methods */
+ arg.integer.value = 0;
+ status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+ if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
+ }
+
+ arg.integer.value = sleep_state;
status = acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL);
if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status)));
@@ -425,13 +496,13 @@
/* _WAK returns stuff - do we want to look at it? */
- status = acpi_hw_enable_non_wakeup_gpes();
+ status = acpi_hw_enable_non_wakeup_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
- /* Disable BM arbitration */
- status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
+ /* Enable BM arbitration */
+ status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
return_ACPI_STATUS (status);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)