All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH v2 09/35] acpi: Support generation of GPIO descriptor
Date: Sun, 10 May 2020 14:33:43 -0600	[thread overview]
Message-ID: <20200510203409.203520-7-sjg@chromium.org> (raw)
In-Reply-To: <20200510203409.203520-1-sjg@chromium.org>

Add a function to write a GPIO descriptor to the generated ACPI code.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v2: None
Changes in v1: None

 include/acpi/acpi_device.h |  22 ++++++
 lib/acpi/acpi_device.c     | 151 +++++++++++++++++++++++++++++++++++++
 test/dm/acpigen.c          |  89 ++++++++++++++++++++++
 3 files changed, 262 insertions(+)

diff --git a/include/acpi/acpi_device.h b/include/acpi/acpi_device.h
index cb9166aeae..5f229d79cf 100644
--- a/include/acpi/acpi_device.h
+++ b/include/acpi/acpi_device.h
@@ -12,6 +12,7 @@
 #include <linux/bitops.h>
 
 struct acpi_ctx;
+struct gpio_desc;
 struct irq;
 struct udevice;
 
@@ -233,4 +234,25 @@ enum acpi_dev_status acpi_device_status(const struct udevice *dev);
 int acpi_device_write_interrupt_irq(struct acpi_ctx *ctx,
 				    const struct irq *req_irq);
 
+/**
+ * acpi_device_write_gpio() - Write GpioIo() or GpioInt() descriptor
+ *
+ * @gpio: GPIO information to write
+ * @return 0 if OK, -ve on error
+ */
+int acpi_device_write_gpio(struct acpi_ctx *ctx, const struct acpi_gpio *gpio);
+
+/**
+ * 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.
+ *
+ * @ctx: ACPI context pointer
+ * @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);
+
 #endif
diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c
index 6b2fb7e47e..4c5bfdb9a2 100644
--- a/lib/acpi/acpi_device.c
+++ b/lib/acpi/acpi_device.c
@@ -12,6 +12,7 @@
 #include <log.h>
 #include <acpi/acpi_device.h>
 #include <acpi/acpigen.h>
+#include <asm-generic/gpio.h>
 #include <dm/acpi.h>
 
 /**
@@ -204,3 +205,153 @@ int acpi_device_write_interrupt_irq(struct acpi_ctx *ctx,
 
 	return 0;
 }
+
+/* ACPI 6.3 section 6.4.3.8.1 - GPIO Interrupt or I/O */
+int acpi_device_write_gpio(struct acpi_ctx *ctx, const struct acpi_gpio *gpio)
+{
+	void *start, *desc_length;
+	void *pin_table_offset, *vendor_data_offset, *resource_offset;
+	u16 flags = 0;
+	int pin;
+
+	if (gpio->type > ACPI_GPIO_TYPE_IO)
+		return -EINVAL;
+
+	start = acpigen_get_current(ctx);
+
+	/* Byte 0: Descriptor Type */
+	acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_GPIO);
+
+	/* Byte 1-2: Length (fill in later) */
+	desc_length = acpi_device_write_zero_len(ctx);
+
+	/* Byte 3: Revision ID */
+	acpigen_emit_byte(ctx, ACPI_GPIO_REVISION_ID);
+
+	/* Byte 4: GpioIo or GpioInt */
+	acpigen_emit_byte(ctx, gpio->type);
+
+	/*
+	 * Byte 5-6: General Flags
+	 *   [15:1]: 0 => Reserved
+	 *      [0]: 1 => ResourceConsumer
+	 */
+	acpigen_emit_word(ctx, 1 << 0);
+
+	switch (gpio->type) {
+	case ACPI_GPIO_TYPE_INTERRUPT:
+		/*
+		 * Byte 7-8: GPIO Interrupt Flags
+		 *   [15:5]: 0 => Reserved
+		 *      [4]: Wake     (0=NO_WAKE   1=WAKE)
+		 *      [3]: Sharing  (0=EXCLUSIVE 1=SHARED)
+		 *    [2:1]: Polarity (0=HIGH      1=LOW     2=BOTH)
+		 *      [0]: Mode     (0=LEVEL     1=EDGE)
+		 */
+		if (gpio->irq.mode == ACPI_IRQ_EDGE_TRIGGERED)
+			flags |= 1 << 0;
+		if (gpio->irq.shared == ACPI_IRQ_SHARED)
+			flags |= 1 << 3;
+		if (gpio->irq.wake == ACPI_IRQ_WAKE)
+			flags |= 1 << 4;
+
+		switch (gpio->irq.polarity) {
+		case ACPI_IRQ_ACTIVE_HIGH:
+			flags |= 0 << 1;
+			break;
+		case ACPI_IRQ_ACTIVE_LOW:
+			flags |= 1 << 1;
+			break;
+		case ACPI_IRQ_ACTIVE_BOTH:
+			flags |= 2 << 1;
+			break;
+		}
+		break;
+
+	case ACPI_GPIO_TYPE_IO:
+		/*
+		 * Byte 7-8: GPIO IO Flags
+		 *   [15:4]: 0 => Reserved
+		 *      [3]: Sharing  (0=EXCLUSIVE 1=SHARED)
+		 *      [2]: 0 => Reserved
+		 *    [1:0]: IO Restriction
+		 *           0 => IoRestrictionNone
+		 *           1 => IoRestrictionInputOnly
+		 *           2 => IoRestrictionOutputOnly
+		 *           3 => IoRestrictionNoneAndPreserve
+		 */
+		flags |= gpio->io_restrict & 3;
+		if (gpio->io_shared)
+			flags |= 1 << 3;
+		break;
+	}
+	acpigen_emit_word(ctx, flags);
+
+	/*
+	 * Byte 9: Pin Configuration
+	 *  0x01 => Default (no configuration applied)
+	 *  0x02 => Pull-up
+	 *  0x03 => Pull-down
+	 *  0x04-0x7F => Reserved
+	 *  0x80-0xff => Vendor defined
+	 */
+	acpigen_emit_byte(ctx, gpio->pull);
+
+	/* Byte 10-11: Output Drive Strength in 1/100 mA */
+	acpigen_emit_word(ctx, gpio->output_drive_strength);
+
+	/* Byte 12-13: Debounce Timeout in 1/100 ms */
+	acpigen_emit_word(ctx, gpio->interrupt_debounce_timeout);
+
+	/* Byte 14-15: Pin Table Offset, relative to start */
+	pin_table_offset = acpi_device_write_zero_len(ctx);
+
+	/* Byte 16: Reserved */
+	acpigen_emit_byte(ctx, 0);
+
+	/* Byte 17-18: Resource Source Name Offset, relative to start */
+	resource_offset = acpi_device_write_zero_len(ctx);
+
+	/* Byte 19-20: Vendor Data Offset, relative to start */
+	vendor_data_offset = acpi_device_write_zero_len(ctx);
+
+	/* Byte 21-22: Vendor Data Length */
+	acpigen_emit_word(ctx, 0);
+
+	/* Fill in Pin Table Offset */
+	acpi_device_fill_from_len(ctx, pin_table_offset, start);
+
+	/* Pin Table, one word for each pin */
+	for (pin = 0; pin < gpio->pin_count; pin++)
+		acpigen_emit_word(ctx, gpio->pins[pin]);
+
+	/* Fill in Resource Source Name Offset */
+	acpi_device_fill_from_len(ctx, resource_offset, start);
+
+	/* Resource Source Name String */
+	acpigen_emit_string(ctx, gpio->resource);
+
+	/* Fill in Vendor Data Offset */
+	acpi_device_fill_from_len(ctx, vendor_data_offset, start);
+
+	/* Fill in GPIO Descriptor Length (account for len word) */
+	acpi_device_fill_len(ctx, desc_length);
+
+	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;
+}
diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c
index 77d1a3bba6..73fe6c9f4d 100644
--- a/test/dm/acpigen.c
+++ b/test/dm/acpigen.c
@@ -12,6 +12,7 @@
 #include <malloc.h>
 #include <acpi/acpigen.h>
 #include <acpi/acpi_device.h>
+#include <asm/gpio.h>
 #include <asm/unaligned.h>
 #include <dm/acpi.h>
 #include <dm/test.h>
@@ -136,3 +137,91 @@ static int dm_test_acpi_interrupt(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_acpi_interrupt, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test emitting a GPIO descriptor */
+static int dm_test_acpi_gpio(struct unit_test_state *uts)
+{
+	struct gpio_desc desc;
+	struct acpi_ctx *ctx;
+	struct udevice *dev;
+	u8 *ptr;
+
+	ut_assertok(alloc_context(&ctx));
+
+	ptr = acpigen_get_current(ctx);
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+	ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
+
+	ut_assertok(acpi_device_write_gpio_desc(ctx, &desc));
+	ut_asserteq(35, acpigen_get_current(ctx) - ptr);
+	ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
+	ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
+	ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
+	ut_asserteq(ACPI_GPIO_TYPE_IO, ptr[4]);
+	ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
+	ut_asserteq(9, get_unaligned((u16 *)(ptr + 7)));
+	ut_asserteq(ACPI_GPIO_PULL_UP, ptr[9]);
+	ut_asserteq(1234, get_unaligned((u16 *)(ptr + 10)));
+	ut_asserteq(0, get_unaligned((u16 *)(ptr + 12)));
+	ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
+	ut_asserteq(0, ptr[16]);
+	ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
+	ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
+	ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
+
+	/* pin0 */
+	ut_asserteq(4, get_unaligned((u16 *)(ptr + 23)));
+
+	ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
+
+	free_context(&ctx);
+
+	return 0;
+}
+DM_TEST(dm_test_acpi_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test emitting a GPIO descriptor with an interrupt */
+static int dm_test_acpi_gpio_irq(struct unit_test_state *uts)
+{
+	struct gpio_desc desc;
+	struct acpi_ctx *ctx;
+	struct udevice *dev;
+	u8 *ptr;
+
+	ut_assertok(alloc_context(&ctx));
+
+	ptr = acpigen_get_current(ctx);
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+	ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0));
+
+	ut_assertok(acpi_device_write_gpio_desc(ctx, &desc));
+	ut_asserteq(35, acpigen_get_current(ctx) - ptr);
+	ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
+	ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
+	ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
+	ut_asserteq(ACPI_GPIO_TYPE_INTERRUPT, ptr[4]);
+	ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
+	ut_asserteq(29, get_unaligned((u16 *)(ptr + 7)));
+	ut_asserteq(ACPI_GPIO_PULL_DOWN, ptr[9]);
+	ut_asserteq(0, get_unaligned((u16 *)(ptr + 10)));
+	ut_asserteq(4321, get_unaligned((u16 *)(ptr + 12)));
+	ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
+	ut_asserteq(0, ptr[16]);
+	ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
+	ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
+	ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
+
+	/* pin0 */
+	ut_asserteq(6, get_unaligned((u16 *)(ptr + 23)));
+
+	ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
+
+	free_context(&ctx);
+
+	return 0;
+}
+DM_TEST(dm_test_acpi_gpio_irq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.26.2.645.ge9eca65c58-goog

  parent reply	other threads:[~2020-05-10 20:33 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-10 20:33 [PATCH v2 00/35] dm: Add programmatic generation of ACPI tables (part B) Simon Glass
2020-05-10 20:33 ` [PATCH v2 01/35] dm: core: Add an ACPI name for the root node Simon Glass
2020-05-17 14:40   ` Bin Meng
2020-05-10 20:33 ` [PATCH v2 02/35] acpi: Add a function to get a device path and scope Simon Glass
2020-05-17 14:54   ` Bin Meng
2020-05-10 20:33 ` [PATCH v2 03/35] acpi: Add a way to check device status Simon Glass
2020-05-10 20:33 ` [PATCH v2 04/35] irq: Add a method to convert an interrupt to ACPI Simon Glass
2020-05-10 20:33 ` [PATCH v2 05/35] acpi: Support generation of ACPI code Simon Glass
2020-05-10 20:33 ` [PATCH v2 06/35] acpi: Support generation of interrupt descriptor Simon Glass
2020-05-10 20:33 ` [PATCH v2 07/35] gpio: Add a method to convert a GPIO to ACPI Simon Glass
2020-05-10 20:33 ` [PATCH v2 08/35] acpi: Support string output Simon Glass
2020-05-10 20:33 ` Simon Glass [this message]
2020-05-10 20:33 ` [PATCH v2 10/35] acpi: Support generation of a GPIO/irq for a device Simon Glass
2020-05-10 20:33 ` [PATCH v2 11/35] acpi: Support generation of I2C descriptor Simon Glass
2020-05-10 20:33 ` [PATCH v2 12/35] acpi: Support generation of SPI descriptor Simon Glass
2020-05-10 20:33 ` [PATCH v2 13/35] acpigen: Support writing a length Simon Glass
2020-05-10 20:33 ` [PATCH v2 14/35] acpigen: Support writing a package Simon Glass
2020-05-10 20:33 ` [PATCH v2 15/35] acpi: Support writing an integer Simon Glass
2020-05-10 20:33 ` [PATCH v2 16/35] acpi: Support writing a string Simon Glass
2020-05-10 20:33 ` [PATCH v2 17/35] acpi: Support writing a name Simon Glass
2020-05-10 20:33 ` [PATCH v2 18/35] acpi: Support writing a UUID Simon Glass
2020-05-10 20:33 ` [PATCH v2 19/35] acpi: Support writing Device Properties objects via _DSD Simon Glass
2020-05-10 20:33 ` [PATCH v2 20/35] acpi: Support writing a GPIO Simon Glass
2020-05-10 20:33 ` [PATCH v2 21/35] acpi: Support copying properties from device tree to ACPI Simon Glass
2020-05-10 20:33 ` [PATCH v2 22/35] acpi: Add support for various misc ACPI opcodes Simon Glass
2020-05-10 20:33 ` [PATCH v2 23/35] acpi: Add support for writing a Power Resource Simon Glass
2020-05-10 20:33 ` [PATCH v2 24/35] acpi: Add support for writing a GPIO power sequence Simon Glass
2020-05-10 20:33 ` [PATCH v2 25/35] acpi: Add support for a generic " Simon Glass
2020-05-10 20:34 ` [PATCH v2 26/35] acpi: Add support for SSDT generation Simon Glass
2020-05-10 20:34 ` [PATCH v2 27/35] x86: acpi: Move MADT down a bit Simon Glass
2020-05-10 20:34 ` [PATCH v2 28/35] acpi: Record the items added to SSDT Simon Glass
2020-05-10 20:34 ` [PATCH v2 29/35] acpi: Support ordering SSDT data by device Simon Glass
2020-05-10 20:34 ` [PATCH v2 30/35] x86: Allow devices to write an SSDT Simon Glass
2020-05-10 20:34 ` [PATCH v2 31/35] acpi: Add support for DSDT generation Simon Glass
2020-05-10 20:34 ` [PATCH v2 32/35] x86: Allow devices to write to DSDT Simon Glass
2020-05-10 20:34 ` [PATCH v2 33/35] pci: Avoid a crash in device_is_on_pci_bus() Simon Glass
2020-05-10 20:34 ` [PATCH v2 34/35] dm: acpi: Enhance acpi_get_name() Simon Glass
2020-05-10 20:34 ` [PATCH v2 35/35] acpi: Add an acpi split command Simon Glass
2020-05-12  2:13 ` [PATCH v2 00/35] dm: Add programmatic generation of ACPI tables (part B) Bin Meng
2020-05-12 11:55 ` Antwort: " Wolfgang Wallner
2020-05-12 12:32   ` Andy Shevchenko
2020-05-12 23:22     ` Simon Glass
2020-05-13  9:55       ` Andy Shevchenko
2020-05-14 16:02         ` Simon Glass
2020-05-14 16:38           ` Andy Shevchenko
2020-05-13 12:18 ` Antwort: [PATCH v2 03/35] acpi: Add a way to check device status Wolfgang Wallner
2020-05-13 13:01 ` Antwort: [PATCH v2 04/35] irq: Add a method to convert an interrupt to ACPI Wolfgang Wallner
2020-05-14 16:02   ` Simon Glass
2020-05-18  7:47   ` Antwort: " Wolfgang Wallner
2020-05-14  8:32 ` Antwort: [PATCH v2 05/35] acpi: Support generation of ACPI code Wolfgang Wallner
2020-06-09 21:14   ` Simon Glass
2020-06-10  7:33   ` Wolfgang Wallner
2020-06-10  7:39   ` Wolfgang Wallner
2020-05-19  8:14 ` Antwort: [PATCH v2 08/35] acpi: Support string output Wolfgang Wallner
2020-05-19  8:56 ` [PATCH v2 09/35] acpi: Support generation of GPIO descriptor Wolfgang Wallner
2020-05-19  9:32 ` Antwort: [PATCH v2 10/35] acpi: Support generation of a GPIO/irq for a device Wolfgang Wallner
2020-05-19 11:58 ` Antwort: [PATCH v2 11/35] acpi: Support generation of I2C descriptor Wolfgang Wallner
2020-06-09 21:14   ` Simon Glass
2020-05-19 13:14 ` Antwort: [PATCH v2 13/35] acpigen: Support writing a length Wolfgang Wallner
2020-05-27 13:04 ` [PATCH v2 14/35] acpigen: Support writing a package Wolfgang Wallner
2020-05-28  9:45 ` [PATCH v2 15/35] acpi: Support writing an integer Wolfgang Wallner
2020-05-28  9:45 ` Antwort: [PATCH v2 16/35] acpi: Support writing a string Wolfgang Wallner
2020-05-28  9:46 ` [PATCH v2 17/35] acpi: Support writing a name Wolfgang Wallner
2020-05-28  9:57 ` [PATCH v2 18/35] acpi: Support writing a UUID Wolfgang Wallner
2020-05-28 13:36 ` [PATCH v2 19/35] acpi: Support writing Device Properties objects via _DSD Wolfgang Wallner
2020-06-03 11:49 ` Antwort: [PATCH v2 20/35] acpi: Support writing a GPIO Wolfgang Wallner
2020-06-03 12:00 ` [PATCH v2 21/35] acpi: Support copying properties from device tree to ACPI Wolfgang Wallner
2020-06-03 13:04 ` [PATCH v2 22/35] acpi: Add support for various misc ACPI opcodes Wolfgang Wallner
2020-06-04  7:39 ` Antwort: [PATCH v2 23/35] acpi: Add support for writing a Power Resource Wolfgang Wallner
2020-06-04  8:50 ` [PATCH v2 24/35] acpi: Add support for writing a GPIO power sequence Wolfgang Wallner
2020-06-04  9:12 ` [PATCH v2 25/35] acpi: Add support for a generic " Wolfgang Wallner
2020-06-04  9:20 ` [PATCH v2 27/35] x86: acpi: Move MADT down a bit Wolfgang Wallner
2020-06-04 11:52 ` [PATCH v2 29/35] acpi: Support ordering SSDT data by device Wolfgang Wallner
2020-06-04 11:54 ` [PATCH v2 28/35] acpi: Record the items added to SSDT Wolfgang Wallner
2020-06-04 12:20 ` [PATCH v2 30/35] x86: Allow devices to write an SSDT Wolfgang Wallner
2020-06-04 12:22 ` [PATCH v2 33/35] pci: Avoid a crash in device_is_on_pci_bus() Wolfgang Wallner
2020-06-04 12:26 ` [PATCH v2 31/35] acpi: Add support for DSDT generation Wolfgang Wallner
2020-06-04 12:55 ` [PATCH v2 32/35] x86: Allow devices to write to DSDT Wolfgang Wallner
2020-06-04 13:04 ` [PATCH v2 35/35] acpi: Add an acpi split command Wolfgang Wallner
2020-06-04 13:17 ` [PATCH v2 34/35] dm: acpi: Enhance acpi_get_name() Wolfgang Wallner
2020-06-04 13:27 ` [PATCH v2 00/35] dm: Add programmatic generation of ACPI tables (part B) Wolfgang Wallner
2020-06-04 15:59   ` Simon Glass
2020-06-10  8:06 ` [PATCH v2 06/35] acpi: Support generation of interrupt descriptor Wolfgang Wallner
2020-06-10  8:40 ` [PATCH v2 12/35] acpi: Support generation of SPI descriptor Wolfgang Wallner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200510203409.203520-7-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.