aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/acpi/device.c52
-rw-r--r--src/include/acpi/acpi_device.h6
2 files changed, 56 insertions, 2 deletions
diff --git a/src/acpi/device.c b/src/acpi/device.c
index 5d4d9be4ce..42fa63985b 100644
--- a/src/acpi/device.c
+++ b/src/acpi/device.c
@@ -598,6 +598,50 @@ void acpi_device_write_uart(const struct acpi_uart *uart)
acpi_device_fill_len(desc_length);
}
+#define ACPI_POWER_RESOURCE_STATUS_ON_OP ONE_OP
+#define ACPI_POWER_RESOURCE_STATUS_OFF_OP ZERO_OP
+
+/**
+ * Writes an ACPI fragment that will check the GPIO and return 0 if the GPIO
+ * state does not match the active parameter.
+ */
+static void acpigen_write_gpio_STA(const struct acpi_gpio *gpio, bool active)
+{
+ if (!gpio || !gpio->pin_count)
+ return;
+
+ /* Read current GPIO status into Local0. */
+ acpigen_get_tx_gpio(gpio);
+
+ /*
+ * If (!Local0)
+ * {
+ * Return (Zero)
+ * }
+ */
+ acpigen_write_if();
+ if (active)
+ acpigen_emit_byte(LNOT_OP);
+ acpigen_emit_byte(LOCAL0_OP);
+ acpigen_write_return_op(ACPI_POWER_RESOURCE_STATUS_OFF_OP);
+ acpigen_write_if_end();
+}
+
+static void acpigen_write_power_res_STA(const struct acpi_power_res_params *params)
+{
+ acpigen_write_method_serialized("_STA", 0);
+
+ /* Verify all the GPIOs are in the ON state, otherwise return 0 */
+ acpigen_write_gpio_STA(params->enable_gpio, true);
+ acpigen_write_gpio_STA(params->reset_gpio, false);
+ acpigen_write_gpio_STA(params->stop_gpio, false);
+
+ /* All GPIOs are in the ON state */
+ acpigen_write_return_op(ACPI_POWER_RESOURCE_STATUS_ON_OP);
+
+ acpigen_pop_len(); /* Method */
+}
+
/* PowerResource() with Enable and/or Reset control */
void acpi_device_add_power_res(const struct acpi_power_res_params *params)
{
@@ -613,8 +657,12 @@ void acpi_device_add_power_res(const struct acpi_power_res_params *params)
acpigen_write_power_res("PRIC", 0, 0, power_res_dev_states,
ARRAY_SIZE(power_res_dev_states));
- /* Method (_STA, 0, NotSerialized) { Return (0x1) } */
- acpigen_write_STA(0x1);
+ if (params->use_gpio_for_status) {
+ acpigen_write_power_res_STA(params);
+ } else {
+ /* Method (_STA, 0, NotSerialized) { Return (0x1) } */
+ acpigen_write_STA(ACPI_POWER_RESOURCE_STATUS_ON_OP);
+ }
/* Method (_ON, 0, Serialized) */
acpigen_write_method_serialized("_ON", 0);
diff --git a/src/include/acpi/acpi_device.h b/src/include/acpi/acpi_device.h
index 301f9b0156..71809eb6d4 100644
--- a/src/include/acpi/acpi_device.h
+++ b/src/include/acpi/acpi_device.h
@@ -456,6 +456,12 @@ struct acpi_power_res_params {
* (_OFF method delay)
*/
unsigned int stop_off_delay_ms;
+
+ /* Write a _STA method that uses the state of the GPIOs to determine if
+ * the PowerResource is ON or OFF. If this is false, the _STA method
+ * will always return ON.
+ */
+ bool use_gpio_for_status;
};
/*