[041/108] dm: acpi: Enhance acpi_get_name()

Message ID 20200126220508.41.I1a77e678d7c6973796cc651ac6d858e1122bb7ae@changeid
State New
Headers show
Series
  • RFC: dm: Add programatic generation of ACPI tables
Related show

Commit Message

Simon Glass Jan. 27, 2020, 5:05 a.m.
For many device types it is possible to figure out the name just by
looking at its uclass or parent. Add a function to handle this, since it
allows us to cover the vast majority of cases automatically.

However it is sometimes impossible to figure out an ACPI name for a device
just by looking at its uclass. For example a touch device may have a
vendor-specific name. Add a new "acpi,name" property to allow a custom
name to be created.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 arch/sandbox/dts/test.dts           |  1 +
 doc/device-tree-bindings/device.txt | 13 +++++++++
 drivers/core/acpi.c                 | 11 +++++++-
 include/dm/device.h                 |  2 +-
 test/dm/acpi.c                      | 42 ++++++++++++++++++++++++++++-
 5 files changed, 66 insertions(+), 3 deletions(-)

Patch

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index f60f0adc05..410235fae3 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -94,6 +94,7 @@ 
 		int-value = <1234>;
 		uint-value = <(-1234)>;
 		interrupts-extended = <&irq 3 0>;
+		acpi,name = "GHIJ";
 	};
 
 	junk {
diff --git a/doc/device-tree-bindings/device.txt b/doc/device-tree-bindings/device.txt
index e625e67f43..61ebd7a942 100644
--- a/doc/device-tree-bindings/device.txt
+++ b/doc/device-tree-bindings/device.txt
@@ -18,6 +18,8 @@  U-Boot provides for some optional properties which are documented here.
  - acpi,hid-desc-reg-offset : HID register offset (for Human Interface Devices)
  - acpi,probed : Tells U-Boot to add 'linux,probed' to the ACPI tables so that
     Linux will not re-init the device
+ - acpi,name : Provides the ACPI name for a device, which is a string consisting
+   of four alphanumeric character (upper case)
  - acpi,uid : _UID value for device
 
 
@@ -35,3 +37,14 @@  synaptics_touchpad: synaptics-touchpad at 2c {
 	acpi,probed;
 	acpi,hid-desc-reg-offset = <0x20>;
 };
+
+pcie-a0 at 14,0 {
+	reg = <0x0000a000 0 0 0 0>;
+	acpi,name = "RP01";
+	wifi: wifi {
+		compatible = "intel,generic-wifi";
+		acpi,desc = "Intel WiFi";
+		acpi,name = "WF00";
+		interrupts-extended = <&acpi_gpe 0x3c 0>;
+	};
+};
diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
index 657753ebb3..ba02b04636 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -9,6 +9,7 @@ 
 #define LOG_CATEOGRY	LOGC_ACPI
 
 #include <common.h>
+#include <acpi_device.h>
 #include <dm.h>
 #include <dm/acpi.h>
 #include <dm/device-internal.h>
@@ -51,12 +52,20 @@  int acpi_return_name(char *out_name, const char *name)
 int acpi_get_name(const struct udevice *dev, char *out_name)
 {
 	struct acpi_ops *aops;
+	const char *name;
+	int ret;
 
 	aops = device_get_acpi_ops(dev);
 	if (aops && aops->get_name)
 		return aops->get_name(dev, out_name);
+	name = dev_read_string(dev, "acpi,name");
+	if (name)
+		return acpi_return_name(out_name, name);
+	ret = acpi_device_get_name(dev, out_name);
+	if (ret)
+		return log_msg_ret("dev", ret);
 
-	return -ENOSYS;
+	return 0;
 }
 
 /**
diff --git a/include/dm/device.h b/include/dm/device.h
index c2e12cd151..03d7ef1bb3 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -713,7 +713,7 @@  int dev_enable_by_path(const char *path);
  */
 static inline bool device_is_on_pci_bus(const struct udevice *dev)
 {
-	return device_get_uclass_id(dev->parent) == UCLASS_PCI;
+	return dev->parent && device_get_uclass_id(dev->parent) == UCLASS_PCI;
 }
 
 /**
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index 16dc0955be..c87bd8569d 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -93,12 +93,52 @@  UCLASS_DRIVER(testacpi) = {
 static int dm_test_acpi_get_name(struct unit_test_state *uts)
 {
 	char name[ACPI_NAME_MAX];
-	struct udevice *dev;
+	struct udevice *dev, *dev2, *i2c, *spi, *serial, *timer, *sound;
+	struct udevice *pci, *root;
 
+	/* Test getting the name from the driver */
 	ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev));
 	ut_assertok(acpi_get_name(dev, name));
 	ut_asserteq_str(ACPI_TEST_DEV_NAME, name);
 
+	/* Test getting the name from the device tree */
+	ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test",
+					      &dev2));
+	ut_assertok(acpi_get_name(dev2, name));
+	ut_asserteq_str("GHIJ", name);
+
+	/* Test getting the name from acpi_device_get_name() */
+	ut_assertok(uclass_first_device(UCLASS_I2C, &i2c));
+	ut_assertok(acpi_get_name(i2c, name));
+	ut_asserteq_str("I2C0", name);
+
+	ut_assertok(uclass_first_device(UCLASS_SPI, &spi));
+	ut_assertok(acpi_get_name(spi, name));
+	ut_asserteq_str("SPI0", name);
+
+	/* The uart has no sequence number, so this should fail */
+	ut_assertok(uclass_first_device(UCLASS_SERIAL, &serial));
+	ut_asserteq(-ENXIO, acpi_get_name(serial, name));
+
+	/* ACPI doesn't know about the timer */
+	ut_assertok(uclass_first_device(UCLASS_TIMER, &timer));
+	ut_asserteq(-ENOENT, acpi_get_name(timer, name));
+
+	/* May as well test the rest of the cases */
+	ut_assertok(uclass_first_device(UCLASS_SOUND, &sound));
+	ut_assertok(acpi_get_name(sound, name));
+	ut_asserteq_str("HDAS", name);
+
+	ut_assertok(uclass_first_device(UCLASS_PCI, &pci));
+	ut_assertok(acpi_get_name(pci, name));
+	ut_asserteq_str("PCI0", name);
+
+	ut_assertok(uclass_first_device(UCLASS_ROOT, &root));
+	ut_assertok(acpi_get_name(root, name));
+	ut_asserteq_str("\\_SB", name);
+
+	/* Note that we don't have tests for acpi_name_from_id() */
+
 	return 0;
 }
 DM_TEST(dm_test_acpi_get_name, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);