diff mbox series

[031/108] gpio: Add a method to convert a GPIO to ACPI

Message ID 20200126220508.31.I29adaf758a9ea81f51ffbecf89b53983968a0d2a@changeid
State Superseded
Headers show
Series RFC: dm: Add programatic generation of ACPI tables | expand

Commit Message

Simon Glass Jan. 27, 2020, 5:05 a.m. UTC
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 at chromium.org>
---

 drivers/gpio/gpio-uclass.c | 21 +++++++++++++++++++++
 include/acpi_device.h      | 12 ++++++++++++
 include/asm-generic/gpio.h | 27 +++++++++++++++++++++++++++
 lib/acpi/acpi_device.c     | 16 ++++++++++++++++
 4 files changed, 76 insertions(+)
diff mbox series

Patch

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index c3c60a73eb..b49f64d90d 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -4,6 +4,7 @@ 
  */
 
 #include <common.h>
+#include <acpi_device.h>
 #include <dm.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
@@ -697,6 +698,26 @@  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;
+
+	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/include/acpi_device.h b/include/acpi_device.h
index 919e6bcdaa..fd047f3944 100644
--- a/include/acpi_device.h
+++ b/include/acpi_device.h
@@ -533,6 +533,18 @@  size_t acpi_dp_add_property_list(struct acpi_dp *dp,
  */
 int acpi_dp_write(struct acpi_ctx *ctx, struct acpi_dp *table);
 
+/**
+ * acpi_device_write_gpio_desc() - Write a GPIO to ACPI
+ *
+ * This creates a GPIO descriptor for a GPIO, including information ACPI needs
+ * to use it. The type is always ACPI_GPIO_TYPE_IO.
+ *
+ * @desc: GPIO to write
+ * @return 0 if OK, -ve on error
+ */
+int acpi_device_write_gpio_desc(struct acpi_ctx *ctx,
+				const struct gpio_desc *desc);
+
 /**
  * acpi_device_write_i2c_dev() - Write an I2C device to ACPI, including
  * information ACPI needs to use it.
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index d6cf18744f..42e112ee66 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -9,6 +9,7 @@ 
 
 #include <dm/ofnode.h>
 
+struct acpi_gpio;
 struct ofnode_phandle_args;
 
 /*
@@ -290,6 +291,20 @@  struct dm_gpio_ops {
 	 */
 	int (*xlate)(struct udevice *dev, struct gpio_desc *desc,
 		     struct ofnode_phandle_args *args);
+
+#if CONFIG_IS_ENABLED(ACPIGEN)
+	/**
+	 * get_acpi() - Get the ACPI info for a GPIO
+	 *
+	 * This converts a GPIO to an ACPI structure for adding to the ACPI
+	 * tables.
+	 *
+	 * @desc:	GPIO description to convert
+	 * @gpio:	Output ACPI GPIO information
+	 * @return ACPI pin number or -ve on error
+	 */
+	int (*get_acpi)(const struct gpio_desc *desc, struct acpi_gpio *gpio);
+#endif
 };
 
 /**
@@ -657,4 +672,16 @@  int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
  */
 int gpio_get_number(const struct gpio_desc *desc);
 
+/**
+ * gpio_get_acpi() - Get the ACPI pin for a GPIO
+ *
+ * This converts a GPIO to an ACPI pin number for adding to the ACPI
+ * tables. If the GPIO is invalid, the pin_count and pins[0] are set to 0
+ *
+ * @desc:	GPIO description to convert
+ * @gpio:	Output ACPI GPIO information
+ * @return ACPI pin number or -ve on error
+ */
+int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio);
+
 #endif	/* _ASM_GENERIC_GPIO_H_ */
diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c
index 2d03639714..d94a403aa1 100644
--- a/lib/acpi/acpi_device.c
+++ b/lib/acpi/acpi_device.c
@@ -287,6 +287,22 @@  int acpi_device_write_gpio(struct acpi_ctx *ctx, const struct acpi_gpio *gpio)
 	return 0;
 }
 
+int acpi_device_write_gpio_desc(struct acpi_ctx *ctx,
+				const struct gpio_desc *desc)
+{
+	struct acpi_gpio gpio;
+	int ret;
+
+	ret = gpio_get_acpi(desc, &gpio);
+	if (ret)
+		return log_msg_ret("desc", ret);
+	ret = acpi_device_write_gpio(ctx, &gpio);
+	if (ret)
+		return log_msg_ret("gpio", ret);
+
+	return 0;
+}
+
 /* ACPI 6.1 section 6.4.3.8.2.1 - I2cSerialBus() */
 static void acpi_device_write_i2c(struct acpi_ctx *ctx,
 				  const struct acpi_i2c *i2c)