patch-2.4.14 linux/drivers/acpi/hardware/hwgpe.c

Next file: linux/drivers/acpi/hardware/hwregs.c
Previous file: linux/drivers/acpi/hardware/hwacpi.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.13/linux/drivers/acpi/hardware/hwgpe.c linux/drivers/acpi/hardware/hwgpe.c
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
- *              $Revision: 32 $
+ *              $Revision: 35 $
  *
  *****************************************************************************/
 
@@ -77,6 +77,45 @@
 			   (in_byte | bit_mask), 8);
 }
 
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_hw_enable_gpe_for_wakeup
+ *
+ * PARAMETERS:  Gpe_number      - The GPE
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Keep track of which GPEs the OS has requested not be
+ *              disabled when going to sleep.
+ *
+ ******************************************************************************/
+
+void
+acpi_hw_enable_gpe_for_wakeup (
+	u32                     gpe_number)
+{
+	u32                     register_index;
+	u32                     bit_mask;
+
+
+	FUNCTION_ENTRY ();
+
+
+	/*
+	 * Translate GPE number to index into global registers array.
+	 */
+	register_index = acpi_gbl_gpe_valid[gpe_number];
+
+	/*
+	 * Figure out the bit offset for this GPE within the target register.
+	 */
+	bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)];
+
+	/*
+	 * Set the bit so we will not disable this when sleeping
+	 */
+	acpi_gbl_gpe_registers[register_index].wake_enable |= bit_mask;
+}
 
 /******************************************************************************
  *
@@ -120,8 +159,49 @@
 	acpi_os_read_port (acpi_gbl_gpe_registers[register_index].enable_addr, &in_byte, 8);
 	acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr,
 			 (in_byte & ~bit_mask), 8);
+
+	acpi_hw_disable_gpe_for_wakeup(gpe_number);
 }
 
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_hw_disable_gpe_for_wakeup
+ *
+ * PARAMETERS:  Gpe_number      - The GPE
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Keep track of which GPEs the OS has requested not be
+ *              disabled when going to sleep.
+ *
+ ******************************************************************************/
+
+void
+acpi_hw_disable_gpe_for_wakeup (
+	u32                     gpe_number)
+{
+	u32                     register_index;
+	u32                     bit_mask;
+
+
+	FUNCTION_ENTRY ();
+
+
+	/*
+	 * Translate GPE number to index into global registers array.
+	 */
+	register_index = acpi_gbl_gpe_valid[gpe_number];
+
+	/*
+	 * Figure out the bit offset for this GPE within the target register.
+	 */
+	bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)];
+
+	/*
+	 * Clear the bit so we will disable this when sleeping
+	 */
+	acpi_gbl_gpe_registers[register_index].wake_enable &= ~bit_mask;
+}
 
 /******************************************************************************
  *
@@ -215,11 +295,88 @@
 	}
 
 	/*
+	 * Enabled for wake?:
+	 */
+	if (bit_mask & acpi_gbl_gpe_registers[register_index].wake_enable) {
+		(*event_status) |= ACPI_EVENT_FLAG_WAKE_ENABLED;
+	}
+
+	/*
 	 * Set?
 	 */
 	in_byte = 0;
 	acpi_os_read_port (acpi_gbl_gpe_registers[register_index].status_addr, &in_byte, 8);
 	if (bit_mask & in_byte) {
 		(*event_status) |= ACPI_EVENT_FLAG_SET;
+	}
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_hw_disable_non_wakeup_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Disable all non-wakeup GPEs
+ *              Call with interrupts disabled. The interrupt handler also
+ *              modifies Acpi_gbl_Gpe_registers[i].Enable, so it should not be
+ *              given the chance to run until after non-wake GPEs are
+ *              re-enabled.
+ *
+ ******************************************************************************/
+
+void
+acpi_hw_disable_non_wakeup_gpes (
+	void)
+{
+	u32                     i;
+
+	FUNCTION_ENTRY ();
+
+	for (i = 0; i < acpi_gbl_gpe_register_count; i++) {
+		/*
+		 * Read the enabled status of all GPEs. We
+		 * will be using it to restore all the GPEs later.
+		 */
+		acpi_os_read_port (acpi_gbl_gpe_registers[i].enable_addr,
+				&acpi_gbl_gpe_registers[i].enable, 8);
+
+		/*
+		 * Disable all GPEs but wakeup GPEs.
+		 */
+		acpi_os_write_port(acpi_gbl_gpe_registers[i].enable_addr,
+				acpi_gbl_gpe_registers[i].wake_enable, 8);
+	}
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_hw_enable_non_wakeup_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Enable all non-wakeup GPEs we previously enabled.
+ *
+ ******************************************************************************/
+
+void
+acpi_hw_enable_non_wakeup_gpes (
+	void)
+{
+	u32                     i;
+
+	FUNCTION_ENTRY ();
+
+	for (i = 0; i < acpi_gbl_gpe_register_count; i++) {
+		/*
+		 * We previously stored the enabled status of all GPEs.
+		 * Blast them back in.
+		 */
+		acpi_os_write_port(acpi_gbl_gpe_registers[i].enable_addr,
+				acpi_gbl_gpe_registers[i].enable, 8);
 	}
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)