diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 6ae9e1f..c43715b 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -1,9 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/err.h>
+#include <linux/cpu_pm.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -17,6 +18,7 @@
 #include <linux/soc/qcom/irq.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 #include <linux/types.h>
 
 #define PDC_MAX_IRQS		168
@@ -36,6 +38,23 @@ struct pdc_pin_region {
 	u32 cnt;
 };
 
+struct pdc_pm_data {
+	struct cpumask cpus_in_pc;
+	spinlock_t pm_lock;
+	bool suspend_start;
+	bool from_pdc_suspend;
+	struct notifier_block pdc_pm_nfb;
+	struct notifier_block pdc_cpu_pm_nfb;
+
+	DECLARE_BITMAP(pdc_domain_enabled_irqs, PDC_MAX_IRQS);
+	DECLARE_BITMAP(pdc_domain_wake_irqs, PDC_MAX_IRQS);
+	DECLARE_BITMAP(pdc_gpio_domain_enabled_irqs, PDC_MAX_GPIO_IRQS);
+	DECLARE_BITMAP(pdc_gpio_domain_wake_irqs, PDC_MAX_GPIO_IRQS);
+
+	struct irq_domain *pdc_domain;
+	struct irq_domain *pdc_gpio_domain;
+};
+
 static DEFINE_RAW_SPINLOCK(pdc_lock);
 static void __iomem *pdc_base;
 static struct pdc_pin_region *pdc_region;
@@ -89,18 +108,38 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
 
 static void qcom_pdc_gic_disable(struct irq_data *d)
 {
+	struct pdc_pm_data *p;
+
 	if (d->hwirq == GPIO_NO_WAKE_IRQ)
 		return;
 
+	p = irq_data_get_irq_chip_data(d);
+	if (!p->from_pdc_suspend) {
+		if (irq_domain_qcom_handle_wakeup(d->domain))
+			clear_bit(d->hwirq, p->pdc_gpio_domain_enabled_irqs);
+		else
+			clear_bit(d->hwirq, p->pdc_domain_enabled_irqs);
+	}
+
 	pdc_enable_intr(d, false);
 	irq_chip_disable_parent(d);
 }
 
 static void qcom_pdc_gic_enable(struct irq_data *d)
 {
+	struct pdc_pm_data *p;
+
 	if (d->hwirq == GPIO_NO_WAKE_IRQ)
 		return;
 
+	p = irq_data_get_irq_chip_data(d);
+	if (!p->from_pdc_suspend) {
+		if (irq_domain_qcom_handle_wakeup(d->domain))
+			set_bit(d->hwirq, p->pdc_gpio_domain_enabled_irqs);
+		else
+			set_bit(d->hwirq, p->pdc_domain_enabled_irqs);
+	}
+
 	pdc_enable_intr(d, true);
 	irq_chip_enable_parent(d);
 }
@@ -145,6 +184,39 @@ enum pdc_irq_config_bits {
 };
 
 /**
+ * qcom_pdc_gic_set_wake: Mark IRQ as wakeup capable
+ *
+ * @d: the interrupt data
+ * @on: enable or disable wakeup capability
+ *
+ * Mark IRQ as wake up capable at either pdc_domain or pdc_gpio_domain.
+ * This will be used when entering to suspend where if any wakeup capable
+ * IRQ is already disabled in SW, such IRQ needs to be re-enabled at HW.
+ */
+static int qcom_pdc_gic_set_wake(struct irq_data *d, unsigned int on)
+{
+	struct pdc_pm_data *p;
+
+	if (d->hwirq == GPIO_NO_WAKE_IRQ)
+		return 0;
+
+	p = irq_data_get_irq_chip_data(d);
+	if (on) {
+		if (irq_domain_qcom_handle_wakeup(d->domain))
+			set_bit(d->hwirq, p->pdc_gpio_domain_wake_irqs);
+		else
+			set_bit(d->hwirq, p->pdc_domain_wake_irqs);
+	} else {
+		if (irq_domain_qcom_handle_wakeup(d->domain))
+			clear_bit(d->hwirq, p->pdc_gpio_domain_wake_irqs);
+		else
+			clear_bit(d->hwirq, p->pdc_domain_wake_irqs);
+	}
+
+	return irq_chip_set_wake_parent(d, on);
+}
+
+/**
  * qcom_pdc_gic_set_type: Configure PDC for the interrupt
  *
  * @d: the interrupt data
@@ -202,14 +274,162 @@ static struct irq_chip qcom_pdc_gic_chip = {
 	.irq_get_irqchip_state	= qcom_pdc_gic_get_irqchip_state,
 	.irq_set_irqchip_state	= qcom_pdc_gic_set_irqchip_state,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_set_wake		= qcom_pdc_gic_set_wake,
 	.irq_set_type		= qcom_pdc_gic_set_type,
 	.flags			= IRQCHIP_MASK_ON_SUSPEND |
-				  IRQCHIP_SET_TYPE_MASKED |
-				  IRQCHIP_SKIP_SET_WAKE,
+				  IRQCHIP_SET_TYPE_MASKED,
 	.irq_set_vcpu_affinity	= irq_chip_set_vcpu_affinity_parent,
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 };
 
+static struct irq_data *pdc_find_irq_data(struct irq_domain *domain,
+					  int wake_irq)
+{
+	int irq = irq_find_mapping(domain, wake_irq);
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	return &desc->irq_data;
+}
+
+/**
+ * pdc_suspend: Enable IRQs marked for wakeup
+ *
+ * @p: pdc_pm_data
+ *
+ * The SW expects that an IRQ that's disabled with disable_irq() can still
+ * wake the system from sleep states such as "suspend to RAM", if it has
+ * been marked for wakeup.
+ *
+ * While the SW may choose to differ status for "wake" and "enabled" interrupts,
+ * its not the case with HW. There is no dedicated config in HW to differ "wake"
+ * and "enabled". Same is case for PDC's parent irq_chip (ARM GIC) which has
+ * only GICD_ISENABLER to indicate "enabled" or "disabled" status.
+ *
+ * So, the HW ONLY understands either "enabled" or "disabled".
+ * The final status in HW should be an "OR" of "enable" and "wake" status.
+ * i.e. PDC (and GIC) irq enable in HW = irq enable | irq wake in SW
+ */
+static void pdc_suspend(struct pdc_pm_data *p)
+{
+	int wake_irq;
+	bool enabled;
+	struct irq_data *d;
+
+	p->from_pdc_suspend = true;
+	for_each_set_bit(wake_irq, p->pdc_domain_wake_irqs, PDC_MAX_IRQS) {
+		enabled = test_bit(wake_irq, p->pdc_domain_enabled_irqs);
+		if (!enabled) {
+			d = pdc_find_irq_data(p->pdc_domain, wake_irq);
+
+			pdc_enable_intr(d, true);
+			irq_chip_enable_parent(d);
+		}
+	}
+
+	for_each_set_bit(wake_irq, p->pdc_gpio_domain_wake_irqs,
+			 PDC_MAX_GPIO_IRQS) {
+		enabled = test_bit(wake_irq, p->pdc_gpio_domain_enabled_irqs);
+		if (!enabled) {
+			d = pdc_find_irq_data(p->pdc_gpio_domain, wake_irq);
+
+			irq_chip_enable_parent(d);
+		}
+	}
+}
+
+static void pdc_resume(struct pdc_pm_data *p)
+{
+	int wake_irq;
+	bool enabled, pending;
+	struct irq_data *d;
+
+	for_each_set_bit(wake_irq, p->pdc_domain_wake_irqs, PDC_MAX_IRQS) {
+		enabled = test_bit(wake_irq, p->pdc_domain_enabled_irqs);
+		if (!enabled) {
+			d = pdc_find_irq_data(p->pdc_domain, wake_irq);
+
+			pdc_enable_intr(d, false);
+			irq_chip_disable_parent(d);
+		}
+	}
+
+	for_each_set_bit(wake_irq, p->pdc_gpio_domain_wake_irqs,
+			 PDC_MAX_GPIO_IRQS) {
+		enabled = test_bit(wake_irq, p->pdc_gpio_domain_enabled_irqs);
+		if (!enabled) {
+			d = pdc_find_irq_data(p->pdc_gpio_domain, wake_irq);
+
+			/*
+			 * When the drivers invoke enablie_irq() on a GPIO IRQ,
+			 * the pending interrupt gets cleared at GIC before
+			 * enabling it from msm_gpio_irq_enable(). So CPU will
+			 * never see pending IRQ after resume if we disable them
+			 * here.
+			 *
+			 * If wakeup is due to GPIO interrupt do not disable it.
+			 * By not disabling, The IRQ will be delivered to CPU
+			 * and when driver invokes enable_irq(), The softirq
+			 * tasklet does resend_irqs() to call irq handler.
+			 */
+			irq_chip_get_parent_state(d, IRQCHIP_STATE_PENDING,
+						  &pending);
+			if (pending) {
+				pending = false;
+				continue;
+			}
+
+			irq_chip_disable_parent(d);
+		}
+	}
+	p->from_pdc_suspend = false;
+}
+
+static int pdc_cpu_pm_callback(struct notifier_block *nfb,
+			       unsigned long action, void *v)
+{
+	struct pdc_pm_data *p = container_of(nfb, struct pdc_pm_data,
+					     pdc_cpu_pm_nfb);
+	unsigned long flags;
+
+	if (!p->suspend_start)
+		return NOTIFY_OK;
+
+	spin_lock_irqsave(&p->pm_lock, flags);
+	switch (action) {
+	case CPU_PM_ENTER:
+		cpumask_set_cpu(raw_smp_processor_id(), &p->cpus_in_pc);
+		if (cpumask_equal(&p->cpus_in_pc, cpu_online_mask))
+			pdc_suspend(p);
+		break;
+	case CPU_PM_ENTER_FAILED:
+	case CPU_PM_EXIT:
+		if (cpumask_equal(&p->cpus_in_pc, cpu_online_mask))
+			pdc_resume(p);
+		cpumask_clear_cpu(raw_smp_processor_id(), &p->cpus_in_pc);
+		break;
+	}
+	spin_unlock_irqrestore(&p->pm_lock, flags);
+
+	return NOTIFY_OK;
+}
+
+static int pdc_pm_callback(struct notifier_block *nfb,
+			   unsigned long event, void *unused)
+{
+	struct pdc_pm_data *p = container_of(nfb, struct pdc_pm_data,
+					     pdc_pm_nfb);
+	switch (event) {
+	case PM_SUSPEND_PREPARE:
+		p->suspend_start = true;
+		break;
+	case PM_POST_SUSPEND:
+		p->suspend_start = false;
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
 static irq_hw_number_t get_parent_hwirq(int pin)
 {
 	int i;
@@ -254,7 +474,8 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
 		return ret;
 
 	ret  = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
-					     &qcom_pdc_gic_chip, NULL);
+					     &qcom_pdc_gic_chip,
+					     domain->host_data);
 	if (ret)
 		return ret;
 
@@ -298,7 +519,8 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
 		return ret;
 
 	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
-					    &qcom_pdc_gic_chip, NULL);
+					    &qcom_pdc_gic_chip,
+					    domain->host_data);
 	if (ret)
 		return ret;
 
@@ -376,7 +598,8 @@ static int pdc_setup_pin_mapping(struct device_node *np)
 
 static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
 {
-	struct irq_domain *parent_domain, *pdc_domain, *pdc_gpio_domain;
+	struct pdc_pm_data *p;
+	struct irq_domain *parent_domain;
 	int ret;
 
 	pdc_base = of_iomap(node, 0);
@@ -385,6 +608,10 @@ static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
 		return -ENXIO;
 	}
 
+	p = kzalloc(sizeof(struct pdc_pm_data), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
 	parent_domain = irq_find_host(parent);
 	if (!parent_domain) {
 		pr_err("%pOF: unable to find PDC's parent domain\n", node);
@@ -398,33 +625,47 @@ static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
 		goto fail;
 	}
 
-	pdc_domain = irq_domain_create_hierarchy(parent_domain, 0, PDC_MAX_IRQS,
-						 of_fwnode_handle(node),
-						 &qcom_pdc_ops, NULL);
-	if (!pdc_domain) {
+	p->pdc_domain = irq_domain_create_hierarchy(parent_domain, 0,
+						    PDC_MAX_IRQS,
+						    of_fwnode_handle(node),
+						    &qcom_pdc_ops, p);
+	if (!p->pdc_domain) {
 		pr_err("%pOF: GIC domain add failed\n", node);
 		ret = -ENOMEM;
 		goto fail;
 	}
 
-	pdc_gpio_domain = irq_domain_create_hierarchy(parent_domain,
+	p->pdc_gpio_domain = irq_domain_create_hierarchy(parent_domain,
 					IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP,
 					PDC_MAX_GPIO_IRQS,
 					of_fwnode_handle(node),
-					&qcom_pdc_gpio_ops, NULL);
-	if (!pdc_gpio_domain) {
+					&qcom_pdc_gpio_ops, p);
+	if (!p->pdc_gpio_domain) {
 		pr_err("%pOF: PDC domain add failed for GPIO domain\n", node);
 		ret = -ENOMEM;
 		goto remove;
 	}
 
-	irq_domain_update_bus_token(pdc_gpio_domain, DOMAIN_BUS_WAKEUP);
+	irq_domain_update_bus_token(p->pdc_gpio_domain, DOMAIN_BUS_WAKEUP);
+
+	/* Register for PM-transition events */
+	p->pdc_pm_nfb.notifier_call = pdc_pm_callback;
+	ret = register_pm_notifier(&p->pdc_pm_nfb);
+	if (ret)
+		goto remove;
+
+	spin_lock_init(&p->pm_lock);
+
+	/* Register for CPU PM notifications */
+	p->pdc_cpu_pm_nfb.notifier_call = pdc_cpu_pm_callback;
+	cpu_pm_register_notifier(&p->pdc_cpu_pm_nfb);
 
 	return 0;
 
 remove:
-	irq_domain_remove(pdc_domain);
+	irq_domain_remove(p->pdc_domain);
 fail:
+	kfree(p);
 	kfree(pdc_region);
 	iounmap(pdc_base);
 	return ret;
