From 740630ba73768667a2f87326f2a237d373a5093d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 7 Jul 2020 13:12:02 -0600 Subject: acpi: Add support for a generic power sequence Add a way for devices to enable and disable themselves using ACPI code that updates GPIOs. This takes several timing parameters and supports enable, reset and stop. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner Reviewed-by: Bin Meng --- test/dm/acpigen.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'test') diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index 9b699fc..9e7a928 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -806,3 +806,71 @@ static int dm_test_acpi_gpio_toggle(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_gpio_toggle, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test writing ACPI code to output power-sequence info */ +static int dm_test_acpi_power_seq(struct unit_test_state *uts) +{ + struct gpio_desc reset, enable, stop; + const uint addr = 0xc00dc, addr_act_low = 0x80012; + const int txbit = BIT(2); + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(acpi_test_alloc_context_size(&ctx, 400)); + + 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", 0, &reset, 0)); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 1, &enable, 0)); + ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &stop, 0)); + ptr = acpigen_get_current(ctx); + + ut_assertok(acpi_device_add_power_res(ctx, txbit, "\\_SB.GPC0", + "\\_SB.SPC0", &reset, 2, 3, + &enable, 4, 5, &stop, 6, 7)); + ut_asserteq(0x186, acpigen_get_current(ctx) - ptr); + ut_asserteq_strn("PRIC", (char *)ptr + 0x18); + + /* First the 'ON' sequence - spot check */ + ut_asserteq_strn("_ON_", (char *)ptr + 0x38); + + /* reset set */ + ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x49))); + ut_asserteq(OR_OP, ptr[0x52]); + + /* enable set */ + ut_asserteq(addr + enable.offset, get_unaligned((u32 *)(ptr + 0x72))); + ut_asserteq(OR_OP, ptr[0x7b]); + + /* reset clear */ + ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x9f))); + ut_asserteq(NOT_OP, ptr[0xa8]); + + /* stop set (disable, active low) */ + ut_asserteq(addr_act_low + stop.offset, + get_unaligned((u32 *)(ptr + 0xcf))); + ut_asserteq(OR_OP, ptr[0xd8]); + + /* Now the 'OFF' sequence */ + ut_asserteq_strn("_OFF", (char *)ptr + 0xf4); + + /* stop clear (enable, active low) */ + ut_asserteq(addr_act_low + stop.offset, + get_unaligned((u32 *)(ptr + 0x105))); + ut_asserteq(NOT_OP, ptr[0x10e]); + + /* reset clear */ + ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x135))); + ut_asserteq(OR_OP, ptr[0x13e]); + + /* enable clear */ + ut_asserteq(addr + enable.offset, get_unaligned((u32 *)(ptr + 0x162))); + ut_asserteq(NOT_OP, ptr[0x16b]); + + free_context(&ctx); + + return 0; +} + +DM_TEST(dm_test_acpi_power_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); -- cgit v1.1