[PATCH v2 36/39] acpi: Support ordering SSDT data by device
Simon Glass
sjg at chromium.org
Mon Mar 9 04:45:00 CET 2020
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 <sjg at chromium.org>
---
Changes in v2:
- 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 | 17 ++++----
4 files changed, 84 insertions(+), 9 deletions(-)
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fefa3af999..7d55d360f6 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -206,12 +206,12 @@
compatible = "denx,u-boot-devres-test";
};
- acpi-test {
+ acpi_test1: acpi-test {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "ab";
};
- acpi-test2 {
+ acpi_test2: acpi-test2 {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "cd";
};
@@ -829,6 +829,7 @@
setting = "sunrise ohoka";
other-node = "/some-bus/c-test at 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 7b295bf921..2f57ff9da2 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -106,6 +106,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;
@@ -160,11 +217,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_SDDT, 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 305d8395ff..b0d8d41e49 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -336,16 +336,19 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts)
ut_assertnonnull(buf);
ctx.current = buf;
- buf[4] = 'z'; /* sentinal */
+ 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.25.1.481.gfbce0eb801-goog
More information about the U-Boot
mailing list