aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/irqchip/qcom-pdc.c
diff options
context:
space:
mode:
authorJoonas Lahtinen <joonas.lahtinen@linux.intel.com>2021-01-15 08:49:57 +0200
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>2021-01-15 08:49:57 +0200
commitd263dfa7d2697a43f3299b9731cd568ee49cdd2c (patch)
treef5d993c7000ac41ee926acf0b357ec572ef7908f /drivers/irqchip/qcom-pdc.c
parentdrm/i915/gt: Prune inlines (diff)
parentMerge tag 'drm-intel-gt-next-2021-01-14' of git://anongit.freedesktop.org/drm/drm-intel into drm-next (diff)
downloadwireguard-linux-d263dfa7d2697a43f3299b9731cd568ee49cdd2c.tar.xz
wireguard-linux-d263dfa7d2697a43f3299b9731cd568ee49cdd2c.zip
Merge drm/drm-next into drm-intel-gt-next
Backmerging to get a common base for merging topic branches between drm-intel-next and drm-intel-gt-next. Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Diffstat (limited to 'drivers/irqchip/qcom-pdc.c')
-rw-r--r--drivers/irqchip/qcom-pdc.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index bd39e9de6ecf..5dc63c20b67e 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -159,6 +159,8 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
{
int pin_out = d->hwirq;
enum pdc_irq_config_bits pdc_type;
+ enum pdc_irq_config_bits old_pdc_type;
+ int ret;
if (pin_out == GPIO_NO_WAKE_IRQ)
return 0;
@@ -187,9 +189,26 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
+ old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out);
pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
- return irq_chip_set_type_parent(d, type);
+ ret = irq_chip_set_type_parent(d, type);
+ if (ret)
+ return ret;
+
+ /*
+ * When we change types the PDC can give a phantom interrupt.
+ * Clear it. Specifically the phantom shows up when reconfiguring
+ * polarity of interrupt without changing the state of the signal
+ * but let's be consistent and clear it always.
+ *
+ * Doing this works because we have IRQCHIP_SET_TYPE_MASKED so the
+ * interrupt will be cleared before the rest of the system sees it.
+ */
+ if (old_pdc_type != pdc_type)
+ irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false);
+
+ return 0;
}
static struct irq_chip qcom_pdc_gic_chip = {