summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-07-07 13:12:01 -0600
committerBin Meng <bmeng.cn@gmail.com>2020-07-17 14:32:24 +0800
commitf8054dd8ba533be0e2ebd7965b95446a1f573953 (patch)
tree3236d3b0505cb448f60289636a53643ee538a3a3 /test
parentf9189d5ada8d48932463dc1d56ea4d44c050ebbd (diff)
downloadu-boot-f8054dd8ba533be0e2ebd7965b95446a1f573953.tar.gz
u-boot-f8054dd8ba533be0e2ebd7965b95446a1f573953.tar.xz
u-boot-f8054dd8ba533be0e2ebd7965b95446a1f573953.zip
acpi: Add support for writing a GPIO power sequence
Power to some devices is controlled by GPIOs. Add a way to generate ACPI code to enable and disable a GPIO so that this can be handled within an ACPI method. 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 'test')
-rw-r--r--test/dm/acpigen.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c
index df062a210c..9b699fc26a 100644
--- a/test/dm/acpigen.c
+++ b/test/dm/acpigen.c
@@ -742,3 +742,67 @@ static int dm_test_acpi_power_res(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_acpi_power_res, 0);
+
+/* Test writing ACPI code to toggle a GPIO */
+static int dm_test_acpi_gpio_toggle(struct unit_test_state *uts)
+{
+ const uint addr = 0x80012;
+ const int txbit = BIT(2);
+ struct gpio_desc desc;
+ struct acpi_gpio gpio;
+ struct acpi_ctx *ctx;
+ struct udevice *dev;
+ u8 *ptr;
+
+ ut_assertok(alloc_context(&ctx));
+
+ ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+ ut_asserteq_str("a-test", dev->name);
+ ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0));
+ ut_assertok(gpio_get_acpi(&desc, &gpio));
+
+ /* Spot-check the results - see sb_gpio_get_acpi() */
+ ptr = acpigen_get_current(ctx);
+ acpigen_set_enable_tx_gpio(ctx, txbit, "\\_SB.GPC0", "\\_SB.SPC0",
+ &gpio, true);
+ acpigen_set_enable_tx_gpio(ctx, txbit, "\\_SB.GPC0", "\\_SB.SPC0",
+ &gpio, false);
+
+ /* Since this GPIO is active low, we expect it to be cleared here */
+ ut_asserteq(STORE_OP, *ptr);
+ ut_asserteq_strn("_SB_GPC0", (char *)ptr + 3);
+ ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0xc)));
+ ut_asserteq(LOCAL5_OP, ptr[0x10]);
+
+ ut_asserteq(STORE_OP, ptr[0x11]);
+ ut_asserteq(BYTE_PREFIX, ptr[0x12]);
+ ut_asserteq(txbit, ptr[0x13]);
+ ut_asserteq(LOCAL0_OP, ptr[0x14]);
+
+ ut_asserteq(NOT_OP, ptr[0x15]);
+ ut_asserteq(LOCAL0_OP, ptr[0x16]);
+ ut_asserteq(LOCAL6_OP, ptr[0x17]);
+ ut_asserteq(AND_OP, ptr[0x18]);
+ ut_asserteq_strn("_SB_SPC0", (char *)ptr + 0x1e);
+ ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0x27)));
+ ut_asserteq(LOCAL5_OP, ptr[0x2b]);
+
+ /* Now the second one, which should be set */
+ ut_asserteq_strn("_SB_GPC0", (char *)ptr + 0x2f);
+ ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0x38)));
+ ut_asserteq(LOCAL5_OP, ptr[0x3c]);
+
+ ut_asserteq(STORE_OP, ptr[0x3d]);
+
+ ut_asserteq(OR_OP, ptr[0x41]);
+ ut_asserteq(LOCAL0_OP, ptr[0x43]);
+ ut_asserteq_strn("_SB_SPC0", (char *)ptr + 0x47);
+ ut_asserteq(addr + desc.offset, get_unaligned((u32 *)(ptr + 0x50)));
+ ut_asserteq(LOCAL5_OP, ptr[0x54]);
+ ut_asserteq(0x55, acpigen_get_current(ctx) - ptr);
+
+ free_context(&ctx);
+
+ return 0;
+}
+DM_TEST(dm_test_acpi_gpio_toggle, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);