From 685dbe14e93104847f2a3b885d58aef4f8e67192 Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Mon, 5 Oct 2020 10:44:50 -0600 Subject: [PATCH] acpi/device: Add GPIO binding property for an array of GPIOs This change is required for use-cases like GPIO based I2C multiplexer where more than one GPIOs are used as select lines. BUG=b:169444894 TEST=Build and boot waddledee to OS. Ensure that the GPIO bindings for an array of GPIOs are added to the ACPI table as follows: Device (MUX0) { ... Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly, "\\_SB.PCI0.GPIO", 0x00, ResourceConsumer, , ) { // Pin list 0x0125 } GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly, "\\_SB.PCI0.GPIO", 0x00, ResourceConsumer, , ) { // Pin list 0x0126 } }) Name (_DSD, Package (0x02) // _DSD: Device-Specific Data { ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") /* Device Properties for _DSD */, Package (0x01) { Package (0x02) { "mux-gpios", Package (0x08) { \_SB.PCI0.I2C3.MUX0, Zero, Zero, Zero, \_SB.PCI0.I2C3.MUX0, One, Zero, Zero } } } }) } Change-Id: I7c6cc36b1bfca2d48c84f169e6b43fd4be8ba330 Signed-off-by: Karthikeyan Ramasubramanian Reviewed-on: https://review.coreboot.org/c/coreboot/+/46056 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/acpi/device.c | 83 +++++++++++++++++++++++++--------- src/include/acpi/acpi_device.h | 16 +++++++ 2 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/acpi/device.c b/src/acpi/device.c index 450427d47c..5de31b7776 100644 --- a/src/acpi/device.c +++ b/src/acpi/device.c @@ -1019,33 +1019,72 @@ struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name, return dp_array; } +struct acpi_dp *acpi_dp_add_gpio_array(struct acpi_dp *dp, const char *name, + const struct acpi_gpio_res_params *params, + size_t param_count) +{ + struct acpi_dp *gpio; + uint32_t i; + + if (!dp || !param_count) + return NULL; + + gpio = acpi_dp_new_table(name); + if (!gpio) + return NULL; + + /* + * Generate ACPI identifiers as follows: + * Package () { + * name, // e.g. cs-gpios + * Package() { + * ref, index, pin, active_low, // GPIO-0 (params[0]) + * ref, index, pin, active_low, // GPIO-1 (params[1]) + * ... + * } + * } + */ + for (i = 0; i < param_count; i++, params++) { + /* + * If refs is NULL, leave a hole in the gpio array. This can be used in + * conditions where some controllers use both GPIOs and native signals. + */ + if (!params->ref) { + acpi_dp_add_integer(gpio, NULL, 0); + continue; + } + + /* The device that has _CRS containing GpioIO()/GpioInt() */ + acpi_dp_add_reference(gpio, NULL, params->ref); + + /* Index of the GPIO resource in _CRS starting from zero */ + acpi_dp_add_integer(gpio, NULL, params->index); + + /* Pin in the GPIO resource, typically zero */ + acpi_dp_add_integer(gpio, NULL, params->pin); + + /* Set if pin is active low */ + acpi_dp_add_integer(gpio, NULL, params->active_low); + } + acpi_dp_add_array(dp, gpio); + + return gpio; + +} + + struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name, const char *ref, int index, int pin, int active_low) { - if (!dp) - return NULL; + struct acpi_gpio_res_params param = { + .ref = ref, + .index = index, + .pin = pin, + .active_low = active_low, + }; - struct acpi_dp *gpio = acpi_dp_new_table(name); - - if (!gpio) - return NULL; - - /* The device that has _CRS containing GpioIO()/GpioInt() */ - acpi_dp_add_reference(gpio, NULL, ref); - - /* Index of the GPIO resource in _CRS starting from zero */ - acpi_dp_add_integer(gpio, NULL, index); - - /* Pin in the GPIO resource, typically zero */ - acpi_dp_add_integer(gpio, NULL, pin); - - /* Set if pin is active low */ - acpi_dp_add_integer(gpio, NULL, active_low); - - acpi_dp_add_array(dp, gpio); - - return gpio; + return acpi_dp_add_gpio_array(dp, name, ¶m, 1); } /* diff --git a/src/include/acpi/acpi_device.h b/src/include/acpi/acpi_device.h index be13bd7ec8..301f9b0156 100644 --- a/src/include/acpi/acpi_device.h +++ b/src/include/acpi/acpi_device.h @@ -545,6 +545,22 @@ struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name, const char *ref, int index, int pin, int active_low); +struct acpi_gpio_res_params { + /* Reference to the parent device. */ + const char *ref; + /* Index to the GpioIo resource within the _CRS. */ + int index; + /* Index to the pin within the GpioIo resource, usually 0. */ + int pin; + /* Flag to indicate if pin is active low. */ + int active_low; +}; + +/* Add a GPIO binding device property for array of GPIOs */ +struct acpi_dp *acpi_dp_add_gpio_array(struct acpi_dp *dp, const char *name, + const struct acpi_gpio_res_params *params, + size_t param_count); + /* Add a child table of Device Properties */ struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name, struct acpi_dp *child);