diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c
index badc68bbae8cc..080b479f39a94 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/cros_ec_commands.h>
 #include <linux/platform_data/cros_ec_proto.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
 
@@ -168,6 +169,35 @@ static int cros_ec_ready_event(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+static int enable_irq_for_wake(struct cros_ec_device *ec_dev)
+{
+	struct device *dev = ec_dev->dev;
+	int ret = device_init_wakeup(dev, true);
+
+	if (ret) {
+		dev_err(dev, "Failed to enable device for wakeup");
+		return ret;
+	}
+	ret = dev_pm_set_wake_irq(dev, ec_dev->irq);
+	if (ret)
+		device_init_wakeup(dev, false);
+
+	return ret;
+}
+
+static int disable_irq_for_wake(struct cros_ec_device *ec_dev)
+{
+	int ret;
+	struct device *dev = ec_dev->dev;
+
+	dev_pm_clear_wake_irq(dev);
+	ret = device_init_wakeup(dev, false);
+	if (ret)
+		dev_err(dev, "Failed to disable device for wakeup");
+
+	return ret;
+}
+
 /**
  * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
  * @ec_dev: Device to register.
@@ -221,6 +251,13 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 				ec_dev->irq, err);
 			goto exit;
 		}
+		dev_dbg(dev, "IRQ: %i, wake_capable: %s\n", ec_dev->irq,
+			str_yes_no(ec_dev->irq_wake));
+		if (ec_dev->irq_wake) {
+			err = enable_irq_for_wake(ec_dev);
+			if (err)
+				goto exit;
+		}
 	}
 
 	/* Register a platform device for the main EC instance */
@@ -313,6 +350,8 @@ EXPORT_SYMBOL(cros_ec_register);
  */
 void cros_ec_unregister(struct cros_ec_device *ec_dev)
 {
+	if (ec_dev->irq_wake)
+		disable_irq_for_wake(ec_dev);
 	platform_device_unregister(ec_dev->pd);
 	platform_device_unregister(ec_dev->ec);
 	mutex_destroy(&ec_dev->lock);
@@ -353,12 +392,6 @@ EXPORT_SYMBOL(cros_ec_suspend_prepare);
 
 static void cros_ec_disable_irq(struct cros_ec_device *ec_dev)
 {
-	struct device *dev = ec_dev->dev;
-	if (device_may_wakeup(dev))
-		ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq);
-	else
-		ec_dev->wake_enabled = false;
-
 	disable_irq(ec_dev->irq);
 	ec_dev->suspended = true;
 }
@@ -440,9 +473,6 @@ static void cros_ec_enable_irq(struct cros_ec_device *ec_dev)
 	ec_dev->suspended = false;
 	enable_irq(ec_dev->irq);
 
-	if (ec_dev->wake_enabled)
-		disable_irq_wake(ec_dev->irq);
-
 	/*
 	 * Let the mfd devices know about events that occur during
 	 * suspend. This way the clients know what to do with them.
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index f0f3d3d561572..0204593d7b1c9 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -48,6 +48,27 @@ struct lpc_driver_ops {
 
 static struct lpc_driver_ops cros_ec_lpc_ops = { };
 
+static const struct dmi_system_id untrusted_fw_irq_wake_capable[] = {
+	{
+		.ident = "Brya",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
+		},
+	},
+	{
+		.ident = "Brask",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brask"),
+		},
+	},
+	{ }
+};
+
+static bool should_force_irq_wake_capable(void)
+{
+	return dmi_first_match(untrusted_fw_irq_wake_capable);
+}
+
 /*
  * A generic instance of the read function of struct lpc_driver_ops, used for
  * the LPC EC.
@@ -353,8 +374,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
 	struct acpi_device *adev;
 	acpi_status status;
 	struct cros_ec_device *ec_dev;
+	struct resource r = {};
 	u8 buf[2] = {};
-	int irq, ret;
+	int ret;
 
 	/*
 	 * The Framework Laptop (and possibly other non-ChromeOS devices)
@@ -428,12 +450,16 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
 	 * Some boards do not have an IRQ allotted for cros_ec_lpc,
 	 * which makes ENXIO an expected (and safe) scenario.
 	 */
-	irq = platform_get_irq_optional(pdev, 0);
-	if (irq > 0)
-		ec_dev->irq = irq;
-	else if (irq != -ENXIO) {
-		dev_err(dev, "couldn't retrieve IRQ number (%d)\n", irq);
-		return irq;
+	ret = platform_get_irq_resource_optional(pdev, 0, &r);
+	if (!ret) {
+		ec_dev->irq = r.start;
+		if (should_force_irq_wake_capable())
+			ec_dev->irq_wake = true;
+		else
+			ec_dev->irq_wake = r.flags & IORESOURCE_IRQ_WAKECAPABLE;
+	} else if (ret != -ENXIO) {
+		dev_err(dev, "couldn't retrieve IRQ number (%d)\n", ret);
+		return ret;
 	}
 
 	ret = cros_ec_register(ec_dev);
diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c
index 3e88cc92e8192..102cdc3d1956d 100644
--- a/drivers/platform/chrome/cros_ec_spi.c
+++ b/drivers/platform/chrome/cros_ec_spi.c
@@ -7,6 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/platform_data/cros_ec_commands.h>
 #include <linux/platform_data/cros_ec_proto.h>
 #include <linux/platform_device.h>
@@ -70,6 +71,7 @@
  * @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
  *      is sent when we want to turn off CS at the end of a transaction.
  * @high_pri_worker: Used to schedule high priority work.
+ * @irq_wake: Whether or not irq assertion should wake the system.
  */
 struct cros_ec_spi {
 	struct spi_device *spi;
@@ -77,6 +79,7 @@ struct cros_ec_spi {
 	unsigned int start_of_msg_delay;
 	unsigned int end_of_msg_delay;
 	struct kthread_worker *high_pri_worker;
+	bool irq_wake;
 };
 
 typedef int (*cros_ec_xfer_fn_t) (struct cros_ec_device *ec_dev,
@@ -689,9 +692,10 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
 	return cros_ec_xfer_high_pri(ec_dev, ec_msg, do_cros_ec_cmd_xfer_spi);
 }
 
-static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev)
+static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi)
 {
-	struct device_node *np = dev->of_node;
+	struct spi_device *spi = ec_spi->spi;
+	struct device_node *np = spi->dev.of_node;
 	u32 val;
 	int ret;
 
@@ -702,6 +706,8 @@ static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev)
 	ret = of_property_read_u32(np, "google,cros-ec-spi-msg-delay", &val);
 	if (!ret)
 		ec_spi->end_of_msg_delay = val;
+
+	ec_spi->irq_wake = spi->irq > 0 && of_property_present(np, "wakeup-source");
 }
 
 static void cros_ec_spi_high_pri_release(void *worker)
@@ -754,12 +760,13 @@ static int cros_ec_spi_probe(struct spi_device *spi)
 		return -ENOMEM;
 
 	/* Check for any DT properties */
-	cros_ec_spi_dt_probe(ec_spi, dev);
+	cros_ec_spi_dt_probe(ec_spi);
 
 	spi_set_drvdata(spi, ec_dev);
 	ec_dev->dev = dev;
 	ec_dev->priv = ec_spi;
 	ec_dev->irq = spi->irq;
+	ec_dev->irq_wake = ec_spi->irq_wake;
 	ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
 	ec_dev->pkt_xfer = cros_ec_pkt_xfer_spi;
 	ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
@@ -780,8 +787,6 @@ static int cros_ec_spi_probe(struct spi_device *spi)
 		return err;
 	}
 
-	device_init_wakeup(&spi->dev, true);
-
 	return 0;
 }
 
diff --git a/drivers/platform/chrome/cros_ec_uart.c b/drivers/platform/chrome/cros_ec_uart.c
index 68d80559fddc2..5de346a078745 100644
--- a/drivers/platform/chrome/cros_ec_uart.c
+++ b/drivers/platform/chrome/cros_ec_uart.c
@@ -69,6 +69,7 @@ struct response_info {
  * @serdev:		serdev uart device we are connected to.
  * @baudrate:		UART baudrate of attached EC device.
  * @flowcontrol:	UART flowcontrol of attached device.
+ * @irq_wake:		Whether or not irq assertion should wake the system.
  * @irq:		Linux IRQ number of associated serial device.
  * @response:		Response info passing between cros_ec_uart_pkt_xfer()
  *			and cros_ec_uart_rx_bytes()
@@ -77,6 +78,7 @@ struct cros_ec_uart {
 	struct serdev_device *serdev;
 	u32 baudrate;
 	u8 flowcontrol;
+	bool irq_wake;
 	u32 irq;
 	struct response_info response;
 };
@@ -224,8 +226,10 @@ static int cros_ec_uart_resource(struct acpi_resource *ares, void *data)
 static int cros_ec_uart_acpi_probe(struct cros_ec_uart *ec_uart)
 {
 	int ret;
+	struct resource irqres;
 	LIST_HEAD(resources);
-	struct acpi_device *adev = ACPI_COMPANION(&ec_uart->serdev->dev);
+	struct device *dev = &ec_uart->serdev->dev;
+	struct acpi_device *adev = ACPI_COMPANION(dev);
 
 	ret = acpi_dev_get_resources(adev, &resources, cros_ec_uart_resource, ec_uart);
 	if (ret < 0)
@@ -234,12 +238,12 @@ static int cros_ec_uart_acpi_probe(struct cros_ec_uart *ec_uart)
 	acpi_dev_free_resource_list(&resources);
 
 	/* Retrieve GpioInt and translate it to Linux IRQ number */
-	ret = acpi_dev_gpio_irq_get(adev, 0);
+	ret = acpi_dev_get_gpio_irq_resource(adev, NULL, 0, &irqres);
 	if (ret < 0)
 		return ret;
 
-	ec_uart->irq = ret;
-	dev_dbg(&ec_uart->serdev->dev, "IRQ number %d\n", ec_uart->irq);
+	ec_uart->irq = irqres.start;
+	ec_uart->irq_wake = irqres.flags & IORESOURCE_IRQ_WAKECAPABLE;
 
 	return 0;
 }
@@ -293,6 +297,7 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
 	ec_dev->dev = dev;
 	ec_dev->priv = ec_uart;
 	ec_dev->irq = ec_uart->irq;
+	ec_dev->irq_wake = ec_uart->irq_wake;
 	ec_dev->cmd_xfer = NULL;
 	ec_dev->pkt_xfer = cros_ec_uart_pkt_xfer;
 	ec_dev->din_size = sizeof(struct ec_host_response) +
@@ -301,6 +306,7 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
 
 	serdev_device_set_client_ops(serdev, &cros_ec_uart_client_ops);
 
+	/* Register a new cros_ec device */
 	return cros_ec_register(ec_dev);
 }
 
diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h
index 8865e350c12a5..0fb2781b602d6 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -100,6 +100,7 @@ struct cros_ec_command {
  * @proto_version: The protocol version used for this device.
  * @priv: Private data.
  * @irq: Interrupt to use.
+ * @irq_wake: Whether or not irq assertion should wake the system.
  * @id: Device id.
  * @din: Input buffer (for data from EC). This buffer will always be
  *       dword-aligned and include enough space for up to 7 word-alignment
@@ -115,7 +116,6 @@ struct cros_ec_command {
  *        performance advantage to using dword.
  * @din_size: Size of din buffer to allocate (zero to use static din).
  * @dout_size: Size of dout buffer to allocate (zero to use static dout).
- * @wake_enabled: True if this device can wake the system from sleep.
  * @suspended: True if this device had been suspended.
  * @cmd_xfer: Send command to EC and get response.
  *            Returns the number of bytes received if the communication
@@ -169,11 +169,11 @@ struct cros_ec_device {
 	u16 proto_version;
 	void *priv;
 	int irq;
+	bool irq_wake;
 	u8 *din;
 	u8 *dout;
 	int din_size;
 	int dout_size;
-	bool wake_enabled;
 	bool suspended;
 	int (*cmd_xfer)(struct cros_ec_device *ec,
 			struct cros_ec_command *msg);
