[coreboot-gerrit] New patch to review for coreboot: acpi_device: Add support for writing ACPI Interrupt descriptors

Duncan Laurie (dlaurie@google.com) gerrit at coreboot.org
Sun May 22 00:28:39 CEST 2016


Duncan Laurie (dlaurie at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14933

-gerrit

commit 0ec0489ae7f249eed971cb61729f0c5b47029e5a
Author: Duncan Laurie <dlaurie at chromium.org>
Date:   Mon May 9 15:38:36 2016 -0700

    acpi_device: Add support for writing ACPI Interrupt descriptors
    
    Add definitions for ACPI device extended interrupts and a method to
    write an Interrupt() descriptor to the SSDT output stream.
    
    Interrupts are often tied together with other resources and some
    configuration items are shared (though not always compatibly) with
    other constructs like GPIOs and GPEs.
    
    These will get used by device drivers to write _CRS sections for
    devices into the SSDT.  One usage is to include a "struct acpi_irq"
    inside a config struct for a device so it can be initialized based
    on settings in devicetree.
    
    Example usage:
    
    chip.h:
      struct drivers_i2c_generic_config {
        struct acpi_irq irq;
      };
    
    generic.c:
      void acpi_fill_ssdt_generator(struct device *dev) {
        struct drivers_i2c_generic_config *config = dev->chip_info;
        ...
        acpi_device_write_interrupt(&config->irq);
        ...
      }
    
    devicetree.cb:
      device pci 15.0 on
        chip drivers/i2c/generic
          register "irq" = "IRQ_EDGE_LOW(GPP_E7_IRQ)"
          device i2c 10 on end
        end
      end
    
    SSDT.dsl:
      Interrupt (ResourceConsumer, Edge, ActiveLow, Exclusive,,,) { 31 }
    
    Change-Id: I3b64170cc2ebac178e7a17df479eda7670a42703
    Signed-off-by: Duncan Laurie <dlaurie at chromium.org>
---
 src/arch/x86/acpi_device.c              | 71 +++++++++++++++++++++++++++++++++
 src/arch/x86/include/arch/acpi_device.h | 60 ++++++++++++++++++++++++++++
 2 files changed, 131 insertions(+)

diff --git a/src/arch/x86/acpi_device.c b/src/arch/x86/acpi_device.c
index b3861a2..66585d7 100644
--- a/src/arch/x86/acpi_device.c
+++ b/src/arch/x86/acpi_device.c
@@ -20,6 +20,28 @@
 #include <device/device.h>
 #include <device/path.h>
 
+/* Write empty word value and return pointer to it */
+static char *acpi_device_write_len(void)
+{
+	char *p = acpigen_get_current();
+	acpigen_emit_word(0);
+	return p;
+}
+
+/* Fill in length value from start to current at specified location */
+static void acpi_device_fill_from(char *ptr, char *start)
+{
+	uint16_t len = acpigen_get_current() - start;
+	ptr[0] = len & 0xff;
+	ptr[1] = (len >> 8) & 0xff;
+}
+
+/* Fill in length from after word pointer to current */
+static void acpi_device_fill_len(char *ptr)
+{
+	acpi_device_fill_from(ptr, ptr + sizeof(uint16_t));
+}
+
 /* Locate and return the ACPI name for this device */
 const char *acpi_device_name(struct device *dev)
 {
@@ -109,3 +131,52 @@ const char *acpi_device_path_join(struct device *dev, const char *name)
 
 	return buf;
 }
+
+/* ACPI 6.1 section 6.4.3.6: Extended Interrupt Descriptor */
+void acpi_device_write_interrupt(struct acpi_irq *irq)
+{
+	char *desc_length;
+	uint8_t flags;
+
+	if (!irq || !irq->pin)
+		return;
+
+	/* This is supported by GpioInt() but not Interrupt() */
+	if (irq->polarity == IRQ_ACTIVE_BOTH)
+		return;
+
+	/* Byte 0: Descriptor Type */
+	acpigen_emit_byte(ACPI_DESCRIPTOR_INTERRUPT);
+
+	/* Byte 1-2: Length (filled in later) */
+	desc_length = acpi_device_write_len();
+
+	/*
+	 * 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 = 1 << 0; /* ResourceConsumer */
+	if (irq->mode == IRQ_EDGE_TRIGGERED)
+		flags |= 1 << 1;
+	if (irq->polarity == IRQ_ACTIVE_LOW)
+		flags |= 1 << 2;
+	if (irq->shared == IRQ_SHARED)
+		flags |= 1 << 3;
+	if (irq->wake == IRQ_WAKE)
+		flags |= 1 << 4;
+	acpigen_emit_byte(flags);
+
+	/* Byte 4: Interrupt Table Entry Count */
+	acpigen_emit_byte(1);
+
+	/* Byte 5-8: Interrupt Number */
+	acpigen_emit_dword(irq->pin);
+
+	/* Fill in Descriptor Length (account for len word) */
+	acpi_device_fill_len(desc_length);
+}
diff --git a/src/arch/x86/include/arch/acpi_device.h b/src/arch/x86/include/arch/acpi_device.h
index 2cad9b5..98a99d3 100644
--- a/src/arch/x86/include/arch/acpi_device.h
+++ b/src/arch/x86/include/arch/acpi_device.h
@@ -16,10 +16,70 @@
 #ifndef __ACPI_DEVICE_H
 #define __ACPI_DEVICE_H
 
+#define ACPI_DESCRIPTOR_LARGE		(1 << 7)
+#define ACPI_DESCRIPTOR_INTERRUPT	ACPI_DESCRIPTOR_LARGE | 9
+
 struct device;
 const char *acpi_device_name(struct device *dev);
 const char *acpi_device_path(struct device *dev);
 const char *acpi_device_scope(struct device *dev);
 const char *acpi_device_path_join(struct device *dev, const char *name);
 
+/*
+ * ACPI Descriptor for extended Interrupt()
+ */
+
+enum irq_mode {
+	IRQ_EDGE_TRIGGERED,
+	IRQ_LEVEL_TRIGGERED
+};
+
+enum irq_polarity {
+	IRQ_ACTIVE_LOW,
+	IRQ_ACTIVE_HIGH,
+	IRQ_ACTIVE_BOTH
+};
+
+enum irq_shared {
+	IRQ_EXCLUSIVE,
+	IRQ_SHARED
+};
+
+enum irq_wake {
+	IRQ_NO_WAKE,
+	IRQ_WAKE
+};
+
+struct acpi_irq {
+	unsigned int pin;
+	enum irq_mode mode;
+	enum irq_polarity polarity;
+	enum irq_shared shared;
+	enum irq_wake wake;
+};
+
+#define IRQ_EDGE_LOW(x) { \
+	.pin = (x), \
+	.mode = IRQ_EDGE_TRIGGERED, \
+	.polarity = IRQ_ACTIVE_LOW, \
+	.shared = IRQ_EXCLUSIVE, \
+	.wake = IRQ_NO_WAKE }
+
+#define IRQ_EDGE_HIGH(x) { \
+	.pin = (x), \
+	.mode = IRQ_EDGE_TRIGGERED, \
+	.polarity = IRQ_ACTIVE_HIGH, \
+	.shared = IRQ_EXCLUSIVE, \
+	.wake = IRQ_NO_WAKE }
+
+#define IRQ_LEVEL_LOW(x) { \
+	.pin = (x), \
+	.mode = IRQ_LEVEL_TRIGGERED, \
+	.polarity = IRQ_ACTIVE_LOW, \
+	.shared = IRQ_SHARED, \
+	.wake = IRQ_NO_WAKE }
+
+/* Write extended Interrupt() descriptor to SSDT AML output */
+void acpi_device_write_interrupt(struct acpi_irq *irq);
+
 #endif



More information about the coreboot-gerrit mailing list