aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/spi/acpi/acpi.c
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2017-02-17 17:14:35 -0800
committerMartin Roth <martinroth@google.com>2017-02-19 21:37:55 +0100
commitc9db384ea47b8b705ddeaf0319fd53b5c513f423 (patch)
tree1105384eaa83c448ed3957682184defbc21ed012 /src/drivers/spi/acpi/acpi.c
parent4f31d5c2ced908a1d18b14670149c8f2e12fe804 (diff)
drivers/spi/acpi: Add additional generic ACPI support
Add support for more ACPI features in the generic SPI ACPI driver so it can be flexible enough to support more devices, or devices in different configurations. - add a wake pin - add support for using IRQ GPIO instead of PIRQ - add power resource support with enable and reset gpios BUG=chrome-os-partner:61233 TEST=ensure existing SSDT generation is unchanged, and test that new features generate expected code Change-Id: Ibe37cc87e488004baa2c08a369f73c86e6cd6dce Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/18393 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh <furquan@google.com>
Diffstat (limited to 'src/drivers/spi/acpi/acpi.c')
-rw-r--r--src/drivers/spi/acpi/acpi.c85
1 files changed, 82 insertions, 3 deletions
diff --git a/src/drivers/spi/acpi/acpi.c b/src/drivers/spi/acpi/acpi.c
index 0d7d2aa429..028a37c20d 100644
--- a/src/drivers/spi/acpi/acpi.c
+++ b/src/drivers/spi/acpi/acpi.c
@@ -42,10 +42,40 @@ static int spi_acpi_get_bus(struct device *dev)
return -1;
}
+static bool spi_acpi_add_gpios_to_crs(struct drivers_spi_acpi_config *config)
+{
+ /*
+ * Return false if:
+ * 1. Request to explicitly disable export of GPIOs in CRS, or
+ * 2. Both reset and enable GPIOs are not provided.
+ */
+ if (config->disable_gpio_export_in_crs ||
+ ((config->reset_gpio.pin_count == 0) &&
+ (config->enable_gpio.pin_count == 0)))
+ return false;
+
+ return true;
+}
+
+static int spi_acpi_write_gpio(struct acpi_gpio *gpio, int *curr_index)
+{
+ int ret = -1;
+
+ if (gpio->pin_count == 0)
+ return ret;
+
+ acpi_device_write_gpio(gpio);
+ ret = *curr_index;
+ (*curr_index)++;
+
+ return ret;
+}
+
static void spi_acpi_fill_ssdt_generator(struct device *dev)
{
struct drivers_spi_acpi_config *config = dev->chip_info;
const char *scope = acpi_device_scope(dev);
+ const char *path = acpi_device_path(dev);
struct spi_cfg spi_cfg;
struct spi_slave slave;
int bus = -1, cs = dev->path.spi.cs;
@@ -54,6 +84,10 @@ static void spi_acpi_fill_ssdt_generator(struct device *dev)
.speed = config->speed ? : 1 * MHz,
.resource = scope,
};
+ int curr_index = 0;
+ int irq_gpio_index = -1;
+ int reset_gpio_index = -1;
+ int enable_gpio_index = -1;
if (!dev->enabled || !scope)
return;
@@ -101,17 +135,62 @@ static void spi_acpi_fill_ssdt_generator(struct device *dev)
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_spi(&spi);
- acpi_device_write_interrupt(&config->irq);
+
+ /* Use either Interrupt() or GpioInt() */
+ if (config->irq_gpio.pin_count)
+ irq_gpio_index = spi_acpi_write_gpio(&config->irq_gpio,
+ &curr_index);
+ else
+ acpi_device_write_interrupt(&config->irq);
+
+ /* Add enable/reset GPIOs if needed */
+ if (spi_acpi_add_gpios_to_crs(config)) {
+ reset_gpio_index = spi_acpi_write_gpio(&config->reset_gpio,
+ &curr_index);
+ enable_gpio_index = spi_acpi_write_gpio(&config->enable_gpio,
+ &curr_index);
+ }
acpigen_write_resourcetemplate_footer();
- if (config->compat_string) {
+ /* Wake capabilities */
+ if (config->wake) {
+ acpigen_write_name_integer("_S0W", 4);
+ acpigen_write_PRW(config->wake, 3);
+ };
+
+ /* Write device properties if needed */
+ if (config->compat_string || irq_gpio_index >= 0 ||
+ reset_gpio_index >= 0 || enable_gpio_index >= 0) {
struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
- acpi_dp_add_string(dsd, "compatible", config->compat_string);
+ if (config->compat_string)
+ acpi_dp_add_string(dsd, "compatible",
+ config->compat_string);
+ if (irq_gpio_index >= 0)
+ acpi_dp_add_gpio(dsd, "irq-gpios", path,
+ irq_gpio_index, 0,
+ config->irq_gpio.polarity);
+ if (reset_gpio_index >= 0)
+ acpi_dp_add_gpio(dsd, "reset-gpios", path,
+ reset_gpio_index, 0,
+ config->reset_gpio.polarity);
+ if (enable_gpio_index >= 0)
+ acpi_dp_add_gpio(dsd, "enable-gpios", path,
+ enable_gpio_index, 0,
+ config->enable_gpio.polarity);
acpi_dp_write(dsd);
}
+ /* Power Resource */
+ if (config->has_power_resource)
+ acpi_device_add_power_res(
+ &config->reset_gpio, config->reset_delay_ms,
+ &config->enable_gpio, config->enable_delay_ms);
+
acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */
+
+ printk(BIOS_INFO, "%s: %s at %s\n", path,
+ config->desc ? : dev->chip_ops->name, dev_path(dev));
}
static const char *spi_acpi_name(struct device *dev)