aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSimon Glass2020-07-07 13:11:39 -0600
committerBin Meng2020-07-17 14:32:24 +0800
commit1361a53c1ae1f0534825e12ed41fb44aefd2c224 (patch)
tree628a4f293065b7b549edadc42868d10a190d8019 /lib
parent4b724a13770c39ee3806dd30d349b6f8d03cfbc6 (diff)
acpi: Add a function to get a device path and scope
Add a function to build up the ACPI path for a device and another for its scope. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/acpi/Makefile1
-rw-r--r--lib/acpi/acpi_device.c83
2 files changed, 84 insertions, 0 deletions
diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile
index 660491ef711..caae6c01bd9 100644
--- a/lib/acpi/Makefile
+++ b/lib/acpi/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
#
+obj-y += acpi_device.o
obj-y += acpi_table.o
diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c
new file mode 100644
index 00000000000..3a9424e7ee5
--- /dev/null
+++ b/lib/acpi/acpi_device.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generation of tables for particular device types
+ *
+ * Copyright 2019 Google LLC
+ * Mostly taken from coreboot file of the same name
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <acpi/acpi_device.h>
+#include <dm/acpi.h>
+
+/**
+ * acpi_device_path_fill() - Find the root device and build a path from there
+ *
+ * This recursively reaches back to the root device and progressively adds path
+ * elements until the device is reached.
+ *
+ * @dev: Device to return path of
+ * @buf: Buffer to hold the path
+ * @buf_len: Length of buffer
+ * @cur: Current position in the buffer
+ * @return new position in buffer after adding @dev, or -ve on error
+ */
+static int acpi_device_path_fill(const struct udevice *dev, char *buf,
+ size_t buf_len, int cur)
+{
+ char name[ACPI_NAME_MAX];
+ int next = 0;
+ int ret;
+
+ ret = acpi_get_name(dev, name);
+ if (ret)
+ return ret;
+
+ /*
+ * Make sure this name segment will fit, including the path segment
+ * separator and possible NULL terminator, if this is the last segment.
+ */
+ if (cur + strlen(name) + 2 > buf_len)
+ return -ENOSPC;
+
+ /* Walk up the tree to the root device */
+ if (dev_get_parent(dev)) {
+ next = acpi_device_path_fill(dev_get_parent(dev), buf, buf_len,
+ cur);
+ if (next < 0)
+ return next;
+ }
+
+ /* Fill in the path from the root device */
+ next += snprintf(buf + next, buf_len - next, "%s%s",
+ dev_get_parent(dev) && *name ? "." : "", name);
+
+ return next;
+}
+
+int acpi_device_path(const struct udevice *dev, char *buf, int maxlen)
+{
+ int ret;
+
+ ret = acpi_device_path_fill(dev, buf, maxlen, 0);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int acpi_device_scope(const struct udevice *dev, char *scope, int maxlen)
+{
+ int ret;
+
+ if (!dev_get_parent(dev))
+ return log_msg_ret("noparent", -EINVAL);
+
+ ret = acpi_device_path_fill(dev_get_parent(dev), scope, maxlen, 0);
+ if (ret < 0)
+ return log_msg_ret("fill", ret);
+
+ return 0;
+}