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

Duncan Laurie (dlaurie@google.com) gerrit at coreboot.org
Sun May 22 00:28:52 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/14937

-gerrit

commit f6f597fbfcfdd71ec73188188dbb40c997d9ceab
Author: Duncan Laurie <dlaurie at chromium.org>
Date:   Tue May 10 13:18:17 2016 -0700

    acpi_device: Add support for writing ACPI Device Properties
    
    The recent ACPI specification extensions have formally defined a
    method for describing device information with a key=value format that
    is modeled after the Devicetree/DTS format using a special crafted
    object named _DSD with a specific UUID for this format.
    
    There are three defined Device Property types: Integers, Strings, and
    References.  It is also possible to have arrays of these properties
    under one key=value pair.  Strings and References are both represented
    as character arrays but result in different generated ACPI OpCodes.
    
    Various helpers are provided for writing the Device Property header
    (to fill in the object name and UUID) and footer (to fill in the
    property count and device length values) as well as for writing the
    different Device Property types.  A specific helper is provided for
    writing the defined GPIO binding Device Property that is used to allow
    GPIOs to be referred to by name rather than resource index.
    
    This is all documented in the _DSD Device Properties UUID document:
    http://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
    
    This will be used by device drivers to provide device properties that
    are consumed by the operating system.  Devicetree bindings are often
    described in the linux kernel at Documentation/devicetree/bindings/
    
    A sample driver here has an input GPIO that it needs to describe to
    the kernel driver:
    
    chip.h:
      struct drivers_generic_sample_config {
        struct acpi_gpio mode_gpio;
      };
    
    sample.c:
      static void acpi_fill_ssdt_generator(struct device *dev) {
        struct drivers_generic_sample_config *config = dev->chip_info;
        const char *path = acpi_device_path(dev);
        ...
        acpi_device_write_gpio(&config->mode_gpio);
        ...
        acpi_dp_write_header();
        acpi_dp_write_gpio("mode-gpio", path, 0, 0, 0);
        acpi_dp_write_footer();
        ...
      }
    
    devicetree.cb:
      device pci 1f.0 on
        chip drivers/generic/sample
          register "mode_gpio" = "ACPI_GPIO_INPUT(GPP_B1)"
          device generic 0 on end
        end
      end
    
    SSDT.dsl:
      Name (_CRS, ResourceTemplate () {
        GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionInputOnly,
                "\\_SB.PCI0.GPIO", 0, ResourceConsumer) { 25 }
      })
      Name (_DSD, Package () {
        ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
        Package () {
          Package () {"mode-gpio", Package () { \_SB.PCI0.LPCB, 0, 0, 1 }}
        }
      })
    
    Change-Id: I93ffd09e59d05c09e38693e221a87085469be3ad
    Signed-off-by: Duncan Laurie <dlaurie at chromium.org>
---
 src/arch/x86/acpi_device.c              | 135 ++++++++++++++++++++++++++++++++
 src/arch/x86/include/arch/acpi_device.h |  60 ++++++++++++++
 2 files changed, 195 insertions(+)

diff --git a/src/arch/x86/acpi_device.c b/src/arch/x86/acpi_device.c
index 196c66d..1be618a 100644
--- a/src/arch/x86/acpi_device.c
+++ b/src/arch/x86/acpi_device.c
@@ -21,6 +21,15 @@
 #include <device/path.h>
 #include <gpio.h>
 
+/*
+ * Pointer to length field in device properties package
+ * Location is set in dp_header() and length filled in by dp_footer()
+ */
+static char *dp_ptr;
+
+/* Count of the number of device properties in the current set */
+static char dp_count;
+
 /* Write empty word value and return pointer to it */
 static char *acpi_device_write_len(void)
 {
@@ -442,3 +451,129 @@ void acpi_device_write_spi(struct acpi_spi *spi)
 	/* Fill in SPI Descriptor Length */
 	acpi_device_fill_len(desc_length);
 }
+
+/* Write a header for using _DSD to export Device Properties */
+void acpi_dp_write_header(void)
+{
+	/* Name (_DSD) */
+	acpigen_write_name("_DSD");
+
+	/* Package (2) */
+	acpigen_write_package(2);
+
+	/* ToUUID (ACPI_DP_UUID) */
+	acpigen_write_uuid(ACPI_DP_UUID);
+
+	/* Package (X) */
+	acpigen_emit_byte(0x12);
+	acpigen_write_len_f();
+	dp_ptr = acpigen_get_current();
+	acpigen_emit_byte(0); /* Number of elements, filled by dp_footer */
+
+	/* Reset element counter */
+	dp_count = 0;
+}
+
+/* Fill in length values from writing Device Properties */
+void acpi_dp_write_footer(void)
+{
+	/* Patch device property element count */
+	*dp_ptr = dp_count;
+
+	acpigen_pop_len(); /* Inner package length */
+	acpigen_pop_len(); /* Outer package length */
+}
+
+void acpi_dp_write_value(struct acpi_dp *prop)
+{
+	switch (prop->type) {
+	case ACPI_DP_TYPE_INTEGER:
+		acpigen_write_integer(prop->integer);
+		break;
+	case ACPI_DP_TYPE_STRING:
+		acpigen_write_string(prop->string);
+		break;
+	case ACPI_DP_TYPE_REFERENCE:
+		acpigen_emit_namestring(prop->string);
+		break;
+	}
+}
+
+/* Write Device Property key with value as an integer */
+void acpi_dp_write_keyval(const char *key, struct acpi_dp *prop)
+{
+	acpigen_write_package(2);
+	acpigen_write_string(key);
+	acpi_dp_write_value(prop);
+	acpigen_pop_len();
+	dp_count++;
+}
+
+/* Write Device Property key with value as an integer */
+void acpi_dp_write_integer(const char *key, uint64_t value)
+{
+	struct acpi_dp prop = ACPI_DP_INTEGER(value);
+	acpi_dp_write_keyval(key, &prop);
+}
+
+/* Write Device Property key with value as a string */
+void acpi_dp_write_string(const char *key, const char *value)
+{
+	struct acpi_dp prop = ACPI_DP_STRING(value);
+	acpi_dp_write_keyval(key, &prop);
+}
+
+/* Write Device Property key with value as a reference */
+void acpi_dp_write_reference(const char *key, const char *value)
+{
+	struct acpi_dp prop = ACPI_DP_REFERENCE(value);
+	acpi_dp_write_keyval(key, &prop);
+}
+
+/* Write array of Device Properties */
+void acpi_dp_write_array(const char *key, struct acpi_dp *array, int len)
+{
+	int i;
+	acpigen_write_package(2);
+	acpigen_write_string(key);
+	acpigen_write_package(len);
+	for (i = 0; i < len; i++)
+		acpi_dp_write_value(&array[i]);
+	acpigen_pop_len();
+	acpigen_pop_len();
+	dp_count++;
+}
+
+/* Write array of Device Properties with values as integers */
+void acpi_dp_write_integer_array(const char *key, uint64_t *array, int len)
+{
+	int i;
+	acpigen_write_package(2);
+	acpigen_write_string(key);
+	acpigen_write_package(len);
+	for (i = 0; i < len; i++)
+		acpigen_write_integer(array[i]);
+	acpigen_pop_len();
+	acpigen_pop_len();
+	dp_count++;
+}
+
+/*
+ * Device Properties for GPIO binding
+ * linux/Documentation/acpi/gpio-properties.txt
+ */
+void acpi_dp_write_gpio(const char *key, const char *ref, int index,
+			int pin, int active_low)
+{
+	struct acpi_dp gpio_prop[] = {
+		/* The device that has _CRS containing GpioIo()/GpioInt() */
+		ACPI_DP_REFERENCE(ref),
+		/* Index of the GPIO resource in _CRS starting from zero */
+		ACPI_DP_INTEGER(index),
+		/* Pin in the GPIO resource, typically zero */
+		ACPI_DP_INTEGER(pin),
+		/* Set if pin is active low */
+		ACPI_DP_INTEGER(active_low)
+	};
+	acpi_dp_write_array(key, gpio_prop, ARRAY_SIZE(gpio_prop));
+}
diff --git a/src/arch/x86/include/arch/acpi_device.h b/src/arch/x86/include/arch/acpi_device.h
index baa8d34..bee7322 100644
--- a/src/arch/x86/include/arch/acpi_device.h
+++ b/src/arch/x86/include/arch/acpi_device.h
@@ -240,4 +240,64 @@ struct acpi_spi {
 /* Write SPI Bus descriptor to SSDT AML output */
 void acpi_device_write_spi(struct acpi_spi *spi);
 
+/*
+ * Device Properties with _DSD
+ * http://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
+ */
+
+#define ACPI_DP_UUID "daffd814-6eba-4d8c-8a91-bc9bbf4aa301"
+
+enum acpi_dp_type {
+	ACPI_DP_TYPE_INTEGER,
+	ACPI_DP_TYPE_STRING,
+	ACPI_DP_TYPE_REFERENCE,
+};
+
+struct acpi_dp {
+	enum acpi_dp_type type;
+	union {
+		uint64_t integer;
+		const char *string;
+	};
+};
+
+#define ACPI_DP_INTEGER(x)   { .type = ACPI_DP_TYPE_INTEGER, .integer = x }
+#define ACPI_DP_STRING(x)    { .type = ACPI_DP_TYPE_STRING, .string = x }
+#define ACPI_DP_REFERENCE(x) { .type = ACPI_DP_TYPE_REFERENCE, .string = x }
+
+/*
+ * Writing Device Properties objects via _DSD
+ */
+
+/* Start a set of Device Properties with _DSD and UUID */
+void acpi_dp_write_header(void);
+
+/* End the Device Properties set and fill in length values */
+void acpi_dp_write_footer(void);
+
+/* Write a Device Property value, but not the key */
+void acpi_dp_write_value(struct acpi_dp *prop);
+
+/* Write a Device Property, both key and value */
+void acpi_dp_write_keyval(const char *key, struct acpi_dp *prop);
+
+/* Write an integer as a Device Property */
+void acpi_dp_write_integer(const char *key, uint64_t value);
+
+/* Write a string as a Device Property */
+void acpi_dp_write_string(const char *key, const char *value);
+
+/* Write an ACPI reference as a Device Property */
+void acpi_dp_write_reference(const char *key, const char *value);
+
+/* Write an array of Device Properties */
+void acpi_dp_write_array(const char *key, struct acpi_dp *array, int len);
+
+/* Write an array of integers as Device Properties */
+void acpi_dp_write_integer_array(const char *key, uint64_t *array, int len);
+
+/* Write a GPIO binding Device Property */
+void acpi_dp_write_gpio(const char *key, const char *ref, int index,
+			int pin, int active_low);
+
 #endif



More information about the coreboot-gerrit mailing list