All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH v3 25/35] acpi: Add support for a generic power sequence
Date: Sat, 13 Jun 2020 20:55:13 -0600	[thread overview]
Message-ID: <20200614025523.40183-14-sjg@chromium.org> (raw)
In-Reply-To: <20200614025523.40183-1-sjg@chromium.org>

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 <sjg@chromium.org>
Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com>
---

(no changes since v1)

 include/acpi/acpi_device.h | 41 ++++++++++++++++
 lib/acpi/acpi_device.c     | 99 ++++++++++++++++++++++++++++++++++++++
 test/dm/acpigen.c          | 68 ++++++++++++++++++++++++++
 3 files changed, 208 insertions(+)

diff --git a/include/acpi/acpi_device.h b/include/acpi/acpi_device.h
index c0c96183e4..5019a79528 100644
--- a/include/acpi/acpi_device.h
+++ b/include/acpi/acpi_device.h
@@ -342,4 +342,45 @@ int acpi_device_write_i2c_dev(struct acpi_ctx *ctx, const struct udevice *dev);
  */
 int acpi_device_write_spi_dev(struct acpi_ctx *ctx, const struct udevice *dev);
 
+/**
+ * acpi_device_add_power_res() - Add a basic PowerResource block for a device
+ *
+ * This includes GPIOs to control enable, reset and stop operation of the
+ * device. Each GPIO is optional, but at least one must be provided.
+ * This can be applied to any device that has power control, so is fairly
+ * generic.
+ *
+ * Reset - Put the device into / take the device out of reset.
+ * Enable - Enable / disable power to device.
+ * Stop - Stop / start operation of device.
+ *
+ * @ctx: ACPI context pointer
+ * @tx_state_val: Mask to use to toggle the TX state on the GPIO pin, e,g.
+ *	PAD_CFG0_TX_STATE
+ * @dw0_name: Name to use for access to dw0, e.g. "\\_SB.GPC0"
+ * @reset_gpio: GPIO used to take device out of reset or to put it into reset
+ * @reset_delay_ms: Delay to be inserted after device is taken out of reset
+ *	(_ON method delay)
+ * @reset_off_delay_ms: Delay to be inserted after device is put into reset
+ *	(_OFF method delay)
+ * @enable_gpio: GPIO used to enable device
+ * @enable_delay_ms: Delay to be inserted after device is enabled
+ * @enable_off_delay_ms: Delay to be inserted after device is disabled
+ *	(_OFF method delay)
+ * @stop_gpio: GPIO used to stop operation of device
+ * @stop_delay_ms: Delay to be inserted after disabling stop (_ON method delay)
+ * @stop_off_delay_ms: Delay to be inserted after enabling stop.
+ *	(_OFF method delay)
+ *
+ * @return 0 if OK, -ve if at least one GPIO is not provided
+ */
+int acpi_device_add_power_res(struct acpi_ctx *ctx, u32 tx_state_val,
+			      const char *dw0_name,
+			      const struct gpio_desc *reset_gpio,
+			      uint reset_delay_ms, uint reset_off_delay_ms,
+			      const struct gpio_desc *enable_gpio,
+			      uint enable_delay_ms, uint enable_off_delay_ms,
+			      const struct gpio_desc *stop_gpio,
+			      uint stop_delay_ms, uint stop_off_delay_ms);
+
 #endif
diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c
index 38101c8b96..912369498a 100644
--- a/lib/acpi/acpi_device.c
+++ b/lib/acpi/acpi_device.c
@@ -382,6 +382,105 @@ int acpi_device_write_interrupt_or_gpio(struct acpi_ctx *ctx,
 	return 0;
 }
 
+/* PowerResource() with Enable and/or Reset control */
+int acpi_device_add_power_res(struct acpi_ctx *ctx, u32 tx_state_val,
+			      const char *dw0_name,
+			      const struct gpio_desc *reset_gpio,
+			      uint reset_delay_ms, uint reset_off_delay_ms,
+			      const struct gpio_desc *enable_gpio,
+			      uint enable_delay_ms, uint enable_off_delay_ms,
+			      const struct gpio_desc *stop_gpio,
+			      uint stop_delay_ms, uint stop_off_delay_ms)
+{
+	static const char *const power_res_dev_states[] = { "_PR0", "_PR3" };
+	struct acpi_gpio reset, enable, stop;
+	bool has_reset, has_enable, has_stop;
+	int ret;
+
+	gpio_get_acpi(reset_gpio, &reset);
+	gpio_get_acpi(enable_gpio, &enable);
+	gpio_get_acpi(stop_gpio, &stop);
+	has_reset = reset.pins[0];
+	has_enable = enable.pins[0];
+	has_stop = stop.pins[0];
+
+	if (!has_reset && !has_enable && !has_stop)
+		return -EINVAL;
+
+	/* PowerResource (PRIC, 0, 0) */
+	acpigen_write_power_res(ctx, "PRIC", 0, 0, power_res_dev_states,
+				ARRAY_SIZE(power_res_dev_states));
+
+	/* Method (_STA, 0, NotSerialized) { Return (0x1) } */
+	acpigen_write_sta(ctx, 0x1);
+
+	/* Method (_ON, 0, Serialized) */
+	acpigen_write_method_serialized(ctx, "_ON", 0);
+	if (reset_gpio) {
+		ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_name,
+						 &reset, true);
+		if (ret)
+			return log_msg_ret("reset1", ret);
+	}
+	if (has_enable) {
+		ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_name,
+						 &enable, true);
+		if (ret)
+			return log_msg_ret("enable1", ret);
+		if (enable_delay_ms)
+			acpigen_write_sleep(ctx, enable_delay_ms);
+	}
+	if (has_reset) {
+		ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_name,
+						 &reset, false);
+		if (ret)
+			return log_msg_ret("reset2", ret);
+		if (reset_delay_ms)
+			acpigen_write_sleep(ctx, reset_delay_ms);
+	}
+	if (has_stop) {
+		ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_name,
+						 &stop, false);
+		if (ret)
+			return log_msg_ret("stop1", ret);
+		if (stop_delay_ms)
+			acpigen_write_sleep(ctx, stop_delay_ms);
+	}
+	acpigen_pop_len(ctx);		/* _ON method */
+
+	/* Method (_OFF, 0, Serialized) */
+	acpigen_write_method_serialized(ctx, "_OFF", 0);
+	if (has_stop) {
+		ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_name,
+						 &stop, true);
+		if (ret)
+			return log_msg_ret("stop2", ret);
+		if (stop_off_delay_ms)
+			acpigen_write_sleep(ctx, stop_off_delay_ms);
+	}
+	if (has_reset) {
+		ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_name,
+						 &reset, true);
+		if (ret)
+			return log_msg_ret("reset3", ret);
+		if (reset_off_delay_ms)
+			acpigen_write_sleep(ctx, reset_off_delay_ms);
+	}
+	if (has_enable) {
+		ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_name,
+						 &enable, false);
+		if (ret)
+			return log_msg_ret("enable2", ret);
+		if (enable_off_delay_ms)
+			acpigen_write_sleep(ctx, enable_off_delay_ms);
+	}
+	acpigen_pop_len(ctx);		/* _OFF method */
+
+	acpigen_pop_len(ctx);		/* PowerResource PRIC */
+
+	return 0;
+}
+
 /* ACPI 6.3 section 6.4.3.8.2.1 - I2cSerialBus() */
 static void acpi_device_write_i2c(struct acpi_ctx *ctx,
 				  const struct acpi_i2c *i2c)
diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c
index cbd0007365..3999825953 100644
--- a/test/dm/acpigen.c
+++ b/test/dm/acpigen.c
@@ -795,3 +795,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(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",
+					      &reset, 2, 3, &enable, 4, 5,
+					      &stop, 6, 7));
+	ut_asserteq(0x16a, 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[0x4e]);
+
+	/* enable set */
+	ut_asserteq(addr + enable.offset, get_unaligned((u32 *)(ptr + 0x6e)));
+	ut_asserteq(OR_OP, ptr[0x73]);
+
+	/* reset clear */
+	ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x97)));
+	ut_asserteq(NOT_OP, ptr[0x9c]);
+
+	/* stop set (disable, active low) */
+	ut_asserteq(addr_act_low + stop.offset,
+		    get_unaligned((u32 *)(ptr + 0xc3)));
+	ut_asserteq(OR_OP, ptr[0xc8]);
+
+	/* Now the 'OFF' sequence */
+	ut_asserteq_strn("_OFF", (char *)ptr + 0xe4);
+
+	/* stop clear (enable, active low) */
+	ut_asserteq(addr_act_low + stop.offset,
+		    get_unaligned((u32 *)(ptr + 0xf5)));
+	ut_asserteq(NOT_OP, ptr[0xfa]);
+
+	/* reset clear */
+	ut_asserteq(addr + reset.offset, get_unaligned((u32 *)(ptr + 0x121)));
+	ut_asserteq(OR_OP, ptr[0x126]);
+
+	/* enable clear */
+	ut_asserteq(addr + enable.offset, get_unaligned((u32 *)(ptr + 0x14a)));
+	ut_asserteq(NOT_OP, ptr[0x14f]);
+
+	free_context(&ctx);
+
+	return 0;
+}
+
+DM_TEST(dm_test_acpi_power_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.27.0.290.gba653c62da-goog

  parent reply	other threads:[~2020-06-14  2:55 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-14  2:54 [PATCH v3 00/35] dm: Add programmatic generation of ACPI tables (part B) Simon Glass
2020-06-14  2:54 ` [PATCH v3 01/35] dm: core: Add an ACPI name for the root node Simon Glass
2020-06-14  2:54 ` [PATCH v3 02/35] acpi: Add a function to get a device path and scope Simon Glass
2020-06-14  2:54 ` [PATCH v3 03/35] acpi: Add a way to check device status Simon Glass
2020-06-28  9:13   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 04/35] irq: Add a method to convert an interrupt to ACPI Simon Glass
2020-06-28  9:13   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 05/35] acpi: Support generation of ACPI code Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-28  9:13   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 06/35] acpi: Support generation of interrupt descriptor Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 07/35] gpio: Add a method to convert a GPIO to ACPI Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 08/35] acpi: Support string output Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:54 ` [PATCH v3 09/35] acpi: Support generation of GPIO descriptor Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:54 ` [PATCH v3 10/35] acpi: Support generation of a GPIO/irq for a device Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 11/35] acpi: Support generation of I2C descriptor Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 12/35] acpi: Support generation of SPI descriptor Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  1:27   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:55 ` [PATCH v3 13/35] acpigen: Support writing a length Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 14/35] acpigen: Support writing a package Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 15/35] acpi: Support writing an integer Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 16/35] acpi: Support writing a string Simon Glass
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 17/35] acpi: Support writing a name Simon Glass
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 18/35] acpi: Support writing a UUID Simon Glass
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 19/35] acpi: Support writing Device Properties objects via _DSD Simon Glass
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 20/35] acpi: Support writing a GPIO Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 21/35] acpi: Support copying properties from device tree to ACPI Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 22/35] acpi: Add support for various misc ACPI opcodes Simon Glass
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 23/35] acpi: Add support for writing a Power Resource Simon Glass
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 24/35] acpi: Add support for writing a GPIO power sequence Simon Glass
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` Simon Glass [this message]
2020-06-14  2:55 ` [PATCH v3 26/35] acpi: Add support for SSDT generation Simon Glass
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 27/35] x86: acpi: Move MADT down a bit Simon Glass
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 28/35] acpi: Record the items added to SSDT Simon Glass
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 29/35] acpi: Support ordering SSDT data by device Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 30/35] x86: Allow devices to write an SSDT Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 31/35] acpi: Add support for DSDT generation Simon Glass
2020-06-29  5:39   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:55 ` [PATCH v3 32/35] x86: Allow devices to write to DSDT Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  5:39   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 33/35] pci: Avoid a crash in device_is_on_pci_bus() Simon Glass
2020-06-29  5:39   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 34/35] dm: acpi: Enhance acpi_get_name() Simon Glass
2020-06-29  5:39   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:55 ` [PATCH v3 35/35] acpi: Add an acpi command to list/dump generated ACPI items Simon Glass
2020-06-29  5:39   ` Bin Meng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200614025523.40183-14-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.