Add a /chosen property to control the order in which the data appears
in the SSDT. This allows matching up U-Boot's output from a dump of the
known-good data obtained from within Linux.

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

Changes in v1:
- Generalise the ACPI function recursion with acpi_recurse_method()

 arch/sandbox/dts/test.dts           |  5 ++-
 doc/device-tree-bindings/chosen.txt |  9 +++++
 drivers/core/acpi.c                 | 62 +++++++++++++++++++++++++++++
 test/dm/acpi.c                      | 15 ++++---
 4 files changed, 83 insertions(+), 8 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 7b95f9e952..268d3bea00 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -223,7 +223,7 @@
                compatible = "denx,u-boot-devres-test";
        };
 
-       acpi-test {
+       acpi_test1: acpi-test {
                compatible = "denx,u-boot-acpi-test";
                acpi-ssdt-test-data = "ab";
                child {
@@ -231,7 +231,7 @@
                };
        };
 
-       acpi-test2 {
+       acpi_test2: acpi-test2 {
                compatible = "denx,u-boot-acpi-test";
                acpi-ssdt-test-data = "cd";
        };
@@ -864,6 +864,7 @@
                setting = "sunrise ohoka";
                other-node = "/some-bus/c-test@5";
                int-values = <0x1937 72993>;
+               u-boot,acpi-ssdt-order = <&acpi_test2 &acpi_test1>;
                chosen-test {
                        compatible = "denx,u-boot-fdt-test";
                        reg = <9 1>;
diff --git a/doc/device-tree-bindings/chosen.txt 
b/doc/device-tree-bindings/chosen.txt
index 395c9501e3..d4dfc05847 100644
--- a/doc/device-tree-bindings/chosen.txt
+++ b/doc/device-tree-bindings/chosen.txt
@@ -134,3 +134,12 @@ Example
                phandlepart = <&mmc 1>;
        };
 };
+
+u-boot,acpi-ssdt-order
+----------------------
+
+This provides the ordering to use when writing device data to the ACPI SSDT
+(Secondary System Descriptor Table). Each cell is a phandle pointer to a device
+node to add. The ACPI information is written in this order.
+
+If the ordering does not include all nodes, an error is generated.
diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
index e5474970a4..ada8bb7de4 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -107,6 +107,63 @@ static int acpi_add_item(struct acpi_ctx *ctx, struct 
udevice *dev,
        return 0;
 }
 
+struct acpi_item *find_item(const char *devname)
+{
+       int i;
+
+       for (i = 0; i < item_count; i++) {
+               struct acpi_item *item = &acpi_item[i];
+
+               if (!strcmp(devname, item->dev->name))
+                       return item;
+       }
+
+       return NULL;
+}
+
+static int build_type(struct acpi_ctx *ctx, void *start, enum gen_type_t type)
+{
+       const u32 *order;
+       int size;
+       int count;
+       void *ptr;
+       void *end = ctx->current;
+
+       ptr = start;
+       order = ofnode_read_chosen_prop("u-boot,acpi-ssdt-order", &size);
+       if (!order) {
+               log_warning("Failed to find ordering, leaving as is\n");
+               return 0;
+       }
+
+       count = size / sizeof(u32);
+       while (count--) {
+               struct acpi_item *item;
+               const char *name;
+               ofnode node;
+
+               node = ofnode_get_by_phandle(fdt32_to_cpu(*order++));
+               name = ofnode_get_name(node);
+               item = find_item(name);
+               if (!item) {
+                       log_err("Failed to find item '%s'\n", name);
+                       return log_msg_ret("find", -ENOENT);
+               }
+               if (item->type == type) {
+                       log_debug("   - add %s\n", item->dev->name);
+                       memcpy(ptr, item->buf, item->size);
+                       ptr += item->size;
+               }
+       }
+
+       if (ptr != end) {
+               log_warning("*** Missing bytes: ptr=%p, end=%p\n", ptr, end);
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
 acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
 {
        struct acpi_ops *aops;
@@ -162,11 +219,16 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct 
udevice *parent,
 
 int acpi_fill_ssdt(struct acpi_ctx *ctx)
 {
+       void *start = ctx->current;
        int ret;
 
        log_debug("Writing SSDT tables\n");
+       item_count = 0;
        ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT);
        log_debug("Writing SSDT finished, err=%d\n", ret);
+       ret = build_type(ctx, start, TYPE_SSDT);
+       if (ret)
+               return log_msg_ret("build", ret);
 
        return ret;
 }
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index d1bd108223..8df128706d 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -425,13 +425,16 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state 
*uts)
        buf[4] = 'z';   /* sentinel */
        ut_assertok(acpi_fill_ssdt(&ctx));
 
-       /* These values come from acpi-test's acpi-ssdt-test-data property */
-       ut_asserteq('a', buf[0]);
-       ut_asserteq('b', buf[1]);
+       /*
+        * These values come from acpi-test2's acpi-ssdt-test-data property.
+        * This device comes first because of u-boot,acpi-ssdt-order
+        */
+       ut_asserteq('c', buf[0]);
+       ut_asserteq('d', buf[1]);
 
-       /* These values come from acpi-test2's acpi-ssdt-test-data property */
-       ut_asserteq('c', buf[2]);
-       ut_asserteq('d', buf[3]);
+       /* These values come from acpi-test's acpi-ssdt-test-data property */
+       ut_asserteq('a', buf[2]);
+       ut_asserteq('b', buf[3]);
 
        ut_asserteq('z', buf[4]);
 
-- 
2.26.2.303.gf8c07b1a785-goog

Reply via email to