aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-07-07 13:11:58 -0600
committerBin Meng <bmeng.cn@gmail.com>2020-07-17 14:32:24 +0800
commit06679000493a07eb643287d1adfa4ffe6c3fc87c (patch)
treef9e716cfaec1b8ce5af787ed5ac8e6ed56bfc47d
parent235723466628c32e30685363377e416696318e84 (diff)
downloadu-boot-06679000493a07eb643287d1adfa4ffe6c3fc87c.zip
u-boot-06679000493a07eb643287d1adfa4ffe6c3fc87c.tar.gz
u-boot-06679000493a07eb643287d1adfa4ffe6c3fc87c.tar.bz2
acpi: Support copying properties from device tree to ACPI
Some drivers in Linux support both device tree and ACPI. U-Boot itself uses Linux device-tree bindings for its own configuration but does not use ACPI. It is convenient to copy these values over to the ACPI DP table for passing to linux. Add some convenience functions to help with this. 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>
-rw-r--r--arch/sandbox/dts/test.dts1
-rw-r--r--include/acpi/acpi_dp.h50
-rw-r--r--lib/acpi/acpi_dp.c56
-rw-r--r--test/dm/acpi_dp.c67
4 files changed, 174 insertions, 0 deletions
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 0d8ffd1..f0d8f12 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -111,6 +111,7 @@
uint-value = <(-1234)>;
int64-value = /bits/ 64 <0x1111222233334444>;
int-array = <5678 9123 4567>;
+ str-value = "test string";
interrupts-extended = <&irq 3 0>;
};
diff --git a/include/acpi/acpi_dp.h b/include/acpi/acpi_dp.h
index b89e0b8..0b514bc 100644
--- a/include/acpi/acpi_dp.h
+++ b/include/acpi/acpi_dp.h
@@ -234,4 +234,54 @@ struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name,
*/
int acpi_dp_write(struct acpi_ctx *ctx, struct acpi_dp *table);
+/**
+ * acpi_dp_ofnode_copy_int() - Copy a property from device tree to DP
+ *
+ * This copies an integer property from the device tree to the ACPI DP table.
+ *
+ * @node: Node to copy from
+ * @dp: DP to copy to
+ * @prop: Property name to copy
+ * @return 0 if OK, -ve on error
+ */
+int acpi_dp_ofnode_copy_int(ofnode node, struct acpi_dp *dp, const char *prop);
+
+/**
+ * acpi_dp_ofnode_copy_str() - Copy a property from device tree to DP
+ *
+ * This copies a string property from the device tree to the ACPI DP table.
+ *
+ * @node: Node to copy from
+ * @dp: DP to copy to
+ * @prop: Property name to copy
+ * @return 0 if OK, -ve on error
+ */
+int acpi_dp_ofnode_copy_str(ofnode node, struct acpi_dp *dp, const char *prop);
+
+/**
+ * acpi_dp_dev_copy_int() - Copy a property from device tree to DP
+ *
+ * This copies an integer property from the device tree to the ACPI DP table.
+ *
+ * @dev: Device to copy from
+ * @dp: DP to copy to
+ * @prop: Property name to copy
+ * @return 0 if OK, -ve on error
+ */
+int acpi_dp_dev_copy_int(const struct udevice *dev, struct acpi_dp *dp,
+ const char *prop);
+
+/**
+ * acpi_dp_dev_copy_str() - Copy a property from device tree to DP
+ *
+ * This copies a string property from the device tree to the ACPI DP table.
+ *
+ * @dev: Device to copy from
+ * @dp: DP to copy to
+ * @prop: Property name to copy
+ * @return 0 if OK, -ve on error
+ */
+int acpi_dp_dev_copy_str(const struct udevice *dev, struct acpi_dp *dp,
+ const char *prop);
+
#endif
diff --git a/lib/acpi/acpi_dp.c b/lib/acpi/acpi_dp.c
index e8de565..579cab4 100644
--- a/lib/acpi/acpi_dp.c
+++ b/lib/acpi/acpi_dp.c
@@ -344,3 +344,59 @@ struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name,
return gpio;
}
+
+int acpi_dp_ofnode_copy_int(ofnode node, struct acpi_dp *dp, const char *prop)
+{
+ int ret;
+ u32 val = 0;
+
+ ret = ofnode_read_u32(node, prop, &val);
+ if (ret)
+ return ret;
+ if (!acpi_dp_add_integer(dp, prop, val))
+ return log_ret(-ENOMEM);
+
+ return 0;
+}
+
+int acpi_dp_ofnode_copy_str(ofnode node, struct acpi_dp *dp, const char *prop)
+{
+ const char *val;
+
+ val = ofnode_read_string(node, prop);
+ if (!val)
+ return -EINVAL;
+ if (!acpi_dp_add_string(dp, prop, val))
+ return log_ret(-ENOMEM);
+
+ return 0;
+}
+
+int acpi_dp_dev_copy_int(const struct udevice *dev, struct acpi_dp *dp,
+ const char *prop)
+{
+ int ret;
+ u32 val = 0;
+
+ ret = dev_read_u32(dev, prop, &val);
+ if (ret)
+ return ret;
+ if (!acpi_dp_add_integer(dp, prop, val))
+ return log_ret(-ENOMEM);
+
+ return ret;
+}
+
+int acpi_dp_dev_copy_str(const struct udevice *dev, struct acpi_dp *dp,
+ const char *prop)
+{
+ const char *val;
+
+ val = dev_read_string(dev, prop);
+ if (!val)
+ return -EINVAL;
+ if (!acpi_dp_add_string(dp, prop, val))
+ return log_ret(-ENOMEM);
+
+ return 0;
+}
diff --git a/test/dm/acpi_dp.c b/test/dm/acpi_dp.c
index 8b81226..93604b8 100644
--- a/test/dm/acpi_dp.c
+++ b/test/dm/acpi_dp.c
@@ -423,3 +423,70 @@ static int dm_test_acpi_dp_gpio(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_acpi_dp_gpio, 0);
+
+/* Test copying info from the device tree to ACPI tables */
+static int dm_test_acpi_dp_copy(struct unit_test_state *uts)
+{
+ struct acpi_ctx *ctx;
+ struct udevice *dev;
+ struct acpi_dp *dp;
+ ofnode node;
+ u8 *ptr;
+
+ ut_assertok(alloc_context(&ctx));
+
+ dp = acpi_dp_new_table("FRED");
+ ut_assertnonnull(dp);
+
+ ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+ ut_asserteq_str("a-test", dev->name);
+
+ ut_assertok(acpi_dp_dev_copy_int(dev, dp, "int-value"));
+ ut_asserteq(-EINVAL, acpi_dp_dev_copy_int(dev, dp, "missing-value"));
+ ut_assertok(acpi_dp_dev_copy_int(dev, dp, "uint-value"));
+
+ ut_assertok(acpi_dp_dev_copy_str(dev, dp, "str-value"));
+ ut_asserteq(-EINVAL, acpi_dp_dev_copy_str(dev, dp, "missing-value"));
+
+ node = ofnode_path("/chosen");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(acpi_dp_ofnode_copy_int(node, dp, "int-values"));
+ ut_asserteq(-EINVAL,
+ acpi_dp_ofnode_copy_int(node, dp, "missing-value"));
+
+ ut_assertok(acpi_dp_ofnode_copy_str(node, dp, "setting"));
+ ut_asserteq(-EINVAL,
+ acpi_dp_ofnode_copy_str(node, dp, "missing-value"));
+
+ ptr = acpigen_get_current(ctx);
+ ut_assertok(acpi_dp_write(ctx, dp));
+ ut_asserteq(0x9d, acpigen_get_current(ctx) - ptr);
+
+ ut_asserteq(STRING_PREFIX, ptr[0x2b]);
+ ut_asserteq_str("int-value", (char *)ptr + 0x2c);
+ ut_asserteq(WORD_PREFIX, ptr[0x36]);
+ ut_asserteq(1234, get_unaligned((u16 *)(ptr + 0x37)));
+
+ ut_asserteq(STRING_PREFIX, ptr[0x3e]);
+ ut_asserteq_str("uint-value", (char *)ptr + 0x3f);
+ ut_asserteq(DWORD_PREFIX, ptr[0x4a]);
+ ut_asserteq(-1234, get_unaligned((u32 *)(ptr + 0x4b)));
+
+ ut_asserteq(STRING_PREFIX, ptr[0x54]);
+ ut_asserteq_str("str-value", (char *)ptr + 0x55);
+ ut_asserteq(STRING_PREFIX, ptr[0x5f]);
+ ut_asserteq_str("test string", (char *)ptr + 0x60);
+
+ ut_asserteq(STRING_PREFIX, ptr[0x71]);
+ ut_asserteq_str("int-values", (char *)ptr + 0x72);
+ ut_asserteq(WORD_PREFIX, ptr[0x7d]);
+ ut_asserteq(0x1937, get_unaligned((u16 *)(ptr + 0x7e)));
+
+ ut_asserteq(STRING_PREFIX, ptr[0x85]);
+ ut_asserteq_str("setting", (char *)ptr + 0x86);
+ ut_asserteq(STRING_PREFIX, ptr[0x8e]);
+ ut_asserteq_str("sunrise ohoka", (char *)(ptr + 0x8f));
+
+ return 0;
+}
+DM_TEST(dm_test_acpi_dp_copy, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);