acpigen: Add stop gpio control to power resource

There is at least one I2C device (being used by Soraka) that has 3
controls -- enable, reset and stop. If the stop gpio is not put into
the right state when turning off the device in suspend mode, then it
causes leakage. Thus, we need control in power resource to be able to
stop the device when entering suspend state.

BUG=b:64987428
TEST=Verified on soraka that touchscreen stop is correctly configured
on suspend.

Change-Id: Iae5ec7eb3972c5c7f80956d60d0d3c321bbefb0f
Signed-off-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: https://review.coreboot.org/21249
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Furquan Shaikh 2017-08-28 17:20:49 -07:00 committed by Furquan Shaikh
parent a62520bc79
commit edf459fe65
6 changed files with 31 additions and 6 deletions

View File

@ -471,13 +471,15 @@ void acpi_device_write_spi(const struct acpi_spi *spi)
/* PowerResource() with Enable and/or Reset control */ /* PowerResource() with Enable and/or Reset control */
void acpi_device_add_power_res( void acpi_device_add_power_res(
struct acpi_gpio *reset, unsigned int reset_delay_ms, struct acpi_gpio *reset, unsigned int reset_delay_ms,
struct acpi_gpio *enable, unsigned int enable_delay_ms) struct acpi_gpio *enable, unsigned int enable_delay_ms,
struct acpi_gpio *stop, unsigned int stop_delay_ms)
{ {
static const char *power_res_dev_states[] = { "_PR0", "_PR3" }; static const char *power_res_dev_states[] = { "_PR0", "_PR3" };
unsigned int reset_gpio = reset->pins[0]; unsigned int reset_gpio = reset->pins[0];
unsigned int enable_gpio = enable->pins[0]; unsigned int enable_gpio = enable->pins[0];
unsigned int stop_gpio = stop->pins[0];
if (!reset_gpio && !enable_gpio) if (!reset_gpio && !enable_gpio && !stop_gpio)
return; return;
/* PowerResource (PRIC, 0, 0) */ /* PowerResource (PRIC, 0, 0) */
@ -501,10 +503,17 @@ void acpi_device_add_power_res(
if (reset_delay_ms) if (reset_delay_ms)
acpigen_write_sleep(reset_delay_ms); acpigen_write_sleep(reset_delay_ms);
} }
if (stop_gpio) {
acpigen_disable_tx_gpio(stop);
if (stop_delay_ms)
acpigen_write_sleep(stop_delay_ms);
}
acpigen_pop_len(); /* _ON method */ acpigen_pop_len(); /* _ON method */
/* Method (_OFF, 0, Serialized) */ /* Method (_OFF, 0, Serialized) */
acpigen_write_method_serialized("_OFF", 0); acpigen_write_method_serialized("_OFF", 0);
if (stop_gpio)
acpigen_enable_tx_gpio(stop);
if (reset_gpio) if (reset_gpio)
acpigen_enable_tx_gpio(reset); acpigen_enable_tx_gpio(reset);
if (enable_gpio) if (enable_gpio)

View File

@ -308,12 +308,17 @@ void acpi_device_write_spi(const struct acpi_spi *spi);
/* /*
* Add a basic PowerResource block for a device that includes * Add a basic PowerResource block for a device that includes
* GPIOs for enable and/or reset control of the device. Each * GPIOs to control enable, reset and stop operation of the device. Each
* GPIO is optional, but at least one must be provided. * GPIO is optional, but at least one must be provided.
*
* Reset - Put the device into / take the device out of reset.
* Enable - Enable / disable power to device.
* Stop - Stop / start operation of device.
*/ */
void acpi_device_add_power_res( void acpi_device_add_power_res(
struct acpi_gpio *reset, unsigned int reset_delay_ms, struct acpi_gpio *reset, unsigned int reset_delay_ms,
struct acpi_gpio *enable, unsigned int enable_delay_ms); struct acpi_gpio *enable, unsigned int enable_delay_ms,
struct acpi_gpio *stop, unsigned int stop_delay_ms);
/* /*
* Writing Device Properties objects via _DSD * Writing Device Properties objects via _DSD

View File

@ -61,6 +61,10 @@ struct drivers_i2c_generic_config {
struct acpi_gpio enable_gpio; struct acpi_gpio enable_gpio;
/* Delay to be inserted after device is enabled. */ /* Delay to be inserted after device is enabled. */
unsigned enable_delay_ms; unsigned enable_delay_ms;
/* GPIO used to stop operation of device. */
struct acpi_gpio stop_gpio;
/* Delay to be inserted after disabling stop. */
unsigned stop_delay_ms;
/* Generic properties for exporting device-specific data to the OS */ /* Generic properties for exporting device-specific data to the OS */
struct acpi_dp property_list[MAX_GENERIC_PROPERTY_LIST]; struct acpi_dp property_list[MAX_GENERIC_PROPERTY_LIST];

View File

@ -145,7 +145,8 @@ void i2c_generic_fill_ssdt(struct device *dev,
if (config->has_power_resource) if (config->has_power_resource)
acpi_device_add_power_res( acpi_device_add_power_res(
&config->reset_gpio, config->reset_delay_ms, &config->reset_gpio, config->reset_delay_ms,
&config->enable_gpio, config->enable_delay_ms); &config->enable_gpio, config->enable_delay_ms,
&config->stop_gpio, config->stop_delay_ms);
/* Callback if any. */ /* Callback if any. */
if (callback) if (callback)

View File

@ -168,7 +168,8 @@ static void spi_acpi_fill_ssdt_generator(struct device *dev)
if (config->has_power_resource) if (config->has_power_resource)
acpi_device_add_power_res( acpi_device_add_power_res(
&config->reset_gpio, config->reset_delay_ms, &config->reset_gpio, config->reset_delay_ms,
&config->enable_gpio, config->enable_delay_ms); &config->enable_gpio, config->enable_delay_ms,
&config->stop_gpio, config->stop_delay_ms);
acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */ acpigen_pop_len(); /* Scope */

View File

@ -47,6 +47,11 @@ struct drivers_spi_acpi_config {
struct acpi_gpio enable_gpio; struct acpi_gpio enable_gpio;
/* Delay to be inserted after device is enabled. */ /* Delay to be inserted after device is enabled. */
unsigned enable_delay_ms; unsigned enable_delay_ms;
/* GPIO used to stop operation of device. */
struct acpi_gpio stop_gpio;
/* Delay to be inserted after disabling stop. */
unsigned stop_delay_ms;
}; };
#endif /* __SPI_ACPI_CHIP_H__ */ #endif /* __SPI_ACPI_CHIP_H__ */