All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH v4 06/35] acpi: Support generation of interrupt descriptor
Date: Tue,  7 Jul 2020 13:11:43 -0600	[thread overview]
Message-ID: <20200707191212.2542638-3-sjg@chromium.org> (raw)
In-Reply-To: <20200707191212.2542638-1-sjg@chromium.org>

Add a function to write an interrupt descriptor to the generated ACPI
code.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com>
---

Changes in v4:
- Rename the length-writing functions to indicate they are for large resources

 include/acpi/acpi_device.h |  15 +++++
 lib/acpi/acpi_device.c     | 119 +++++++++++++++++++++++++++++++++++++
 test/dm/acpigen.c          |  32 ++++++++++
 3 files changed, 166 insertions(+)

diff --git a/include/acpi/acpi_device.h b/include/acpi/acpi_device.h
index 24895de0da..e72fede54c 100644
--- a/include/acpi/acpi_device.h
+++ b/include/acpi/acpi_device.h
@@ -11,6 +11,8 @@
 
 #include <linux/bitops.h>
 
+struct acpi_ctx;
+struct irq;
 struct udevice;
 
 /* ACPI descriptor values for common descriptors: SERIAL_BUS means I2C */
@@ -128,4 +130,17 @@ int acpi_device_scope(const struct udevice *dev, char *scope, int maxlen);
  */
 enum acpi_dev_status acpi_device_status(const struct udevice *dev);
 
+/**
+ * acpi_device_write_interrupt_irq() - Write an interrupt descriptor
+ *
+ * This writes an ACPI interrupt descriptor for the given interrupt, converting
+ * fields as needed.
+ *
+ * @ctx: ACPI context pointer
+ * @req_irq: Interrupt to output
+ * @return IRQ pin number if OK, -ve on error
+ */
+int acpi_device_write_interrupt_irq(struct acpi_ctx *ctx,
+				    const struct irq *req_irq);
+
 #endif
diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c
index 60f4fd8cd5..d854a45cbc 100644
--- a/lib/acpi/acpi_device.c
+++ b/lib/acpi/acpi_device.c
@@ -8,8 +8,10 @@
 
 #include <common.h>
 #include <dm.h>
+#include <irq.h>
 #include <log.h>
 #include <acpi/acpi_device.h>
+#include <acpi/acpigen.h>
 #include <dm/acpi.h>
 
 /**
@@ -86,3 +88,120 @@ enum acpi_dev_status acpi_device_status(const struct udevice *dev)
 {
 	return ACPI_DSTATUS_ALL_ON;
 }
+
+/**
+ * largeres_write_len_f() - Write a placeholder word value
+ *
+ * Write a forward length for a large resource (2 bytes)
+ *
+ * @return pointer to the zero word (for fixing up later)
+ */
+static void *largeres_write_len_f(struct acpi_ctx *ctx)
+{
+	u8 *p = acpigen_get_current(ctx);
+
+	acpigen_emit_word(ctx, 0);
+
+	return p;
+}
+
+/**
+ * largeres_fill_from_len() - Fill in a length value
+ *
+ * This calculated the number of bytes since the provided @start and writes it
+ * to @ptr, which was previous returned by largeres_write_len_f().
+ *
+ * @ptr: Word to update
+ * @start: Start address to count from to calculated the length
+ */
+static void largeres_fill_from_len(struct acpi_ctx *ctx, char *ptr, u8 *start)
+{
+	u16 len = acpigen_get_current(ctx) - start;
+
+	ptr[0] = len & 0xff;
+	ptr[1] = (len >> 8) & 0xff;
+}
+
+/**
+ * largeres_fill_len() - Fill in a length value, excluding the length itself
+ *
+ * Fill in the length field with the value calculated from after the 16bit
+ * field to acpigen current. This is useful since the length value does not
+ * include the length field itself.
+ *
+ * This calls acpi_device_largeres_fill_len() passing @ptr + 2 as @start
+ *
+ * @ptr: Word to update.
+ */
+static void largeres_fill_len(struct acpi_ctx *ctx, void *ptr)
+{
+	largeres_fill_from_len(ctx, ptr, ptr + sizeof(u16));
+}
+
+/* ACPI 6.3 section 6.4.3.6: Extended Interrupt Descriptor */
+static int acpi_device_write_interrupt(struct acpi_ctx *ctx,
+				       const struct acpi_irq *irq)
+{
+	void *desc_length;
+	u8 flags;
+
+	if (!irq->pin)
+		return -ENOENT;
+
+	/* This is supported by GpioInt() but not Interrupt() */
+	if (irq->polarity == ACPI_IRQ_ACTIVE_BOTH)
+		return -EINVAL;
+
+	/* Byte 0: Descriptor Type */
+	acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_INTERRUPT);
+
+	/* Byte 1-2: Length (filled in later) */
+	desc_length = largeres_write_len_f(ctx);
+
+	/*
+	 * Byte 3: Flags
+	 *  [7:5]: Reserved
+	 *    [4]: Wake     (0=NO_WAKE   1=WAKE)
+	 *    [3]: Sharing  (0=EXCLUSIVE 1=SHARED)
+	 *    [2]: Polarity (0=HIGH      1=LOW)
+	 *    [1]: Mode     (0=LEVEL     1=EDGE)
+	 *    [0]: Resource (0=PRODUCER  1=CONSUMER)
+	 */
+	flags = BIT(0); /* ResourceConsumer */
+	if (irq->mode == ACPI_IRQ_EDGE_TRIGGERED)
+		flags |= BIT(1);
+	if (irq->polarity == ACPI_IRQ_ACTIVE_LOW)
+		flags |= BIT(2);
+	if (irq->shared == ACPI_IRQ_SHARED)
+		flags |= BIT(3);
+	if (irq->wake == ACPI_IRQ_WAKE)
+		flags |= BIT(4);
+	acpigen_emit_byte(ctx, flags);
+
+	/* Byte 4: Interrupt Table Entry Count */
+	acpigen_emit_byte(ctx, 1);
+
+	/* Byte 5-8: Interrupt Number */
+	acpigen_emit_dword(ctx, irq->pin);
+
+	/* Fill in Descriptor Length (account for len word) */
+	largeres_fill_len(ctx, desc_length);
+
+	return 0;
+}
+
+int acpi_device_write_interrupt_irq(struct acpi_ctx *ctx,
+				    const struct irq *req_irq)
+{
+	struct acpi_irq irq;
+	int ret;
+
+	ret = irq_get_acpi(req_irq, &irq);
+	if (ret)
+		return log_msg_ret("get", ret);
+	ret = acpi_device_write_interrupt(ctx, &irq);
+	if (ret)
+		return log_msg_ret("write", ret);
+
+	return 0;
+}
diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c
index 9ff9b68532..a4adfbfdf8 100644
--- a/test/dm/acpigen.c
+++ b/test/dm/acpigen.c
@@ -8,8 +8,10 @@
 
 #include <common.h>
 #include <dm.h>
+#include <irq.h>
 #include <malloc.h>
 #include <acpi/acpigen.h>
+#include <acpi/acpi_device.h>
 #include <asm/unaligned.h>
 #include <dm/acpi.h>
 #include <dm/test.h>
@@ -70,3 +72,33 @@ static int dm_test_acpi_emit_simple(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_acpi_emit_simple, 0);
+
+/* Test emitting an interrupt descriptor */
+static int dm_test_acpi_interrupt(struct unit_test_state *uts)
+{
+	struct acpi_ctx *ctx;
+	struct udevice *dev;
+	struct irq irq;
+	u8 *ptr;
+
+	ut_assertok(alloc_context(&ctx));
+
+	ptr = acpigen_get_current(ctx);
+
+	ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
+	ut_assertok(irq_get_by_index(dev, 0, &irq));
+
+	/* See a-test, property interrupts-extended in the device tree */
+	ut_asserteq(3, acpi_device_write_interrupt_irq(ctx, &irq));
+	ut_asserteq(9, acpigen_get_current(ctx) - ptr);
+	ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]);
+	ut_asserteq(6, get_unaligned((u16 *)(ptr + 1)));
+	ut_asserteq(0x19, ptr[3]);
+	ut_asserteq(1, ptr[4]);
+	ut_asserteq(3, get_unaligned((u32 *)(ptr + 5)));
+
+	free_context(&ctx);
+
+	return 0;
+}
+DM_TEST(dm_test_acpi_interrupt, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.27.0.383.g050319c2ae-goog

  parent reply	other threads:[~2020-07-07 19:11 UTC|newest]

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

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=20200707191212.2542638-3-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.