diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/acpi/device.c | 52 | ||||
-rw-r--r-- | src/include/acpi/acpi_device.h | 6 |
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; }; /* |