From 6d2bc001ea8ee07be94fd25b91423d76918f001c Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Thu, 27 May 2021 15:04:21 -0600 Subject: acpi/device: Add ability to generate proper _STA for PowerResource acpi_device_add_power_res currently generates a `_STA` method hardcoded to ON. This change enables the ability to generate a `_STA` method that queries the status of the GPIOs to determine if the power resource is ON or OFF. BUG=b:184617186 TEST=Dump SSDT table for guybrush Signed-off-by: Raul E Rangel Change-Id: I91410556db002c620fd9aaa99981457808da93a5 Reviewed-on: https://review.coreboot.org/c/coreboot/+/55027 Tested-by: build bot (Jenkins) Reviewed-by: Lance Zhao Reviewed-by: Tim Wawrzynczak --- src/acpi/device.c | 52 ++++++++++++++++++++++++++++++++++++++++-- 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; }; /* -- cgit v1.2.3