diff options
author | Simon Glass <sjg@chromium.org> | 2020-07-07 13:11:44 -0600 |
---|---|---|
committer | Bin Meng <bmeng.cn@gmail.com> | 2020-07-17 14:32:24 +0800 |
commit | 2912686c08c33aff5269512de962dffb35fbee7c (patch) | |
tree | 63cb8bf65f09084ce34c62d4c3da14ce69e860b7 /drivers/gpio | |
parent | ff715c6f4f7a3181fcc6a45907bb8bf0c8c6f08f (diff) |
gpio: Add a method to convert a GPIO to ACPI
When generating ACPI tables we need to convert GPIOs in U-Boot to the ACPI
structures required by ACPI. This is a SoC-specific conversion and cannot
be handled by generic code, so add a new GPIO method to do the conversion.
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-uclass.c | 22 | ||||
-rw-r--r-- | drivers/gpio/sandbox.c | 77 |
2 files changed, 99 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index ab17fa8a5d..9c53299b6a 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -13,6 +13,7 @@ #include <errno.h> #include <fdtdec.h> #include <malloc.h> +#include <acpi/acpi_device.h> #include <asm/gpio.h> #include <dm/device_compat.h> #include <linux/bug.h> @@ -855,6 +856,27 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) return 0; } +#if CONFIG_IS_ENABLED(ACPIGEN) +int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio) +{ + struct dm_gpio_ops *ops; + + memset(gpio, '\0', sizeof(*gpio)); + if (!dm_gpio_is_valid(desc)) { + /* Indicate that the GPIO is not valid */ + gpio->pin_count = 0; + gpio->pins[0] = 0; + return -EINVAL; + } + + ops = gpio_get_ops(desc->dev); + if (!ops->get_acpi) + return -ENOSYS; + + return ops->get_acpi(desc, gpio); +} +#endif + int gpio_claim_vector(const int *gpio_num_array, const char *fmt) { int i, ret; diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index b9a1d65acc..c2f80472b8 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -8,7 +8,9 @@ #include <fdtdec.h> #include <log.h> #include <malloc.h> +#include <acpi/acpi_device.h> #include <asm/gpio.h> +#include <dm/acpi.h> #include <dm/device_compat.h> #include <dm/lists.h> #include <dm/of.h> @@ -197,6 +199,63 @@ static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, return 0; } +#if CONFIG_IS_ENABLED(ACPIGEN) +static int sb_gpio_get_acpi(const struct gpio_desc *desc, + struct acpi_gpio *gpio) +{ + int ret; + + /* Note that gpio_get_acpi() zeroes *gpio before calling here */ + gpio->pin_count = 1; + gpio->pins[0] = desc->offset; + ret = acpi_device_scope(desc->dev, gpio->resource, + sizeof(gpio->resource)); + if (ret) + return log_ret(ret); + + /* All of these values are just used for testing */ + if (desc->flags & GPIOD_ACTIVE_LOW) { + gpio->pin0_addr = 0x80012 + desc->offset; + gpio->type = ACPI_GPIO_TYPE_INTERRUPT; + gpio->pull = ACPI_GPIO_PULL_DOWN; + gpio->interrupt_debounce_timeout = 4321; + + /* We use the GpioInt part */ + gpio->irq.pin = desc->offset; + gpio->irq.polarity = ACPI_IRQ_ACTIVE_BOTH; + gpio->irq.shared = ACPI_IRQ_SHARED; + gpio->irq.wake = ACPI_IRQ_WAKE; + + /* The GpioIo part is only used for testing */ + gpio->polarity = ACPI_GPIO_ACTIVE_LOW; + } else { + gpio->pin0_addr = 0xc00dc + desc->offset; + gpio->type = ACPI_GPIO_TYPE_IO; + gpio->pull = ACPI_GPIO_PULL_UP; + gpio->interrupt_debounce_timeout = 0; + + /* The GpioInt part is not used */ + + /* We use the GpioIo part */ + gpio->output_drive_strength = 1234; + gpio->io_shared = true; + gpio->io_restrict = ACPI_GPIO_IO_RESTRICT_INPUT; + gpio->polarity = 0; + } + + return 0; +} + +static int sb_gpio_get_name(const struct udevice *dev, char *out_name) +{ + return acpi_copy_name(out_name, "GPIO"); +} + +struct acpi_ops gpio_sandbox_acpi_ops = { + .get_name = sb_gpio_get_name, +}; +#endif /* ACPIGEN */ + static const struct dm_gpio_ops gpio_sandbox_ops = { .direction_input = sb_gpio_direction_input, .direction_output = sb_gpio_direction_output, @@ -206,6 +265,9 @@ static const struct dm_gpio_ops gpio_sandbox_ops = { .xlate = sb_gpio_xlate, .set_dir_flags = sb_gpio_set_dir_flags, .get_dir_flags = sb_gpio_get_dir_flags, +#if CONFIG_IS_ENABLED(ACPIGEN) + .get_acpi = sb_gpio_get_acpi, +#endif }; static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev) @@ -252,6 +314,7 @@ U_BOOT_DRIVER(sandbox_gpio) = { .probe = gpio_sandbox_probe, .remove = gpio_sandbox_remove, .ops = &gpio_sandbox_ops, + ACPI_OPS_PTR(&gpio_sandbox_acpi_ops) }; U_BOOT_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias) @@ -421,6 +484,13 @@ static int sb_pinctrl_get_pin_muxing(struct udevice *dev, return 0; } +#if CONFIG_IS_ENABLED(ACPIGEN) +static int sb_pinctrl_get_name(const struct udevice *dev, char *out_name) +{ + return acpi_copy_name(out_name, "PINC"); +} +#endif + static int sandbox_pinctrl_probe(struct udevice *dev) { struct sb_pinctrl_priv *priv = dev_get_priv(dev); @@ -436,6 +506,12 @@ static struct pinctrl_ops sandbox_pinctrl_gpio_ops = { .get_pin_muxing = sb_pinctrl_get_pin_muxing, }; +#if CONFIG_IS_ENABLED(ACPIGEN) +struct acpi_ops pinctrl_sandbox_acpi_ops = { + .get_name = sb_pinctrl_get_name, +}; +#endif + static const struct udevice_id sandbox_pinctrl_gpio_match[] = { { .compatible = "sandbox,pinctrl-gpio" }, { /* sentinel */ } @@ -449,4 +525,5 @@ U_BOOT_DRIVER(sandbox_pinctrl_gpio) = { .bind = dm_scan_fdt_dev, .probe = sandbox_pinctrl_probe, .priv_auto_alloc_size = sizeof(struct sb_pinctrl_priv), + ACPI_OPS_PTR(&pinctrl_sandbox_acpi_ops) }; |