aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86/acpi_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/acpi_device.c')
-rw-r--r--src/arch/x86/acpi_device.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/arch/x86/acpi_device.c b/src/arch/x86/acpi_device.c
index 073b938101..69d44f3f33 100644
--- a/src/arch/x86/acpi_device.c
+++ b/src/arch/x86/acpi_device.c
@@ -24,6 +24,15 @@
#include <gpio.h>
#endif
+/*
+ * Pointer to length field in device properties package
+ * Location is set in dp_header() and length filled in by dp_footer()
+ */
+static char *dp_count_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 void *acpi_device_write_zero_len(void)
{
@@ -453,3 +462,129 @@ void acpi_device_write_spi(const 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_count_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_count_ptr = dp_count;
+
+ acpigen_pop_len(); /* Inner package length */
+ acpigen_pop_len(); /* Outer package length */
+}
+
+void acpi_dp_write_value(const 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, const 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)
+{
+ const 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)
+{
+ const 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)
+{
+ const 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, const 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)
+{
+ const 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));
+}