Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: intel: Clear interrupt status in mask/unmask callback

Commit a939bb57cd47 ("pinctrl: intel: implement gpio_irq_enable") was
added because clearing interrupt status bit is required to avoid
unexpected behavior.

Turns out the unmask callback also needs the fix, which can solve weird
IRQ triggering issues on I2C touchpad ELAN1200.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

authored by

Kai-Heng Feng and committed by
Andy Shevchenko
670784fb e58926e7

+6 -31
+6 -31
drivers/pinctrl/intel/pinctrl-intel.c
··· 914 914 } 915 915 } 916 916 917 - static void intel_gpio_irq_enable(struct irq_data *d) 918 - { 919 - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 920 - struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 921 - const struct intel_community *community; 922 - const struct intel_padgroup *padgrp; 923 - int pin; 924 - 925 - pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp); 926 - if (pin >= 0) { 927 - unsigned int gpp, gpp_offset, is_offset; 928 - unsigned long flags; 929 - u32 value; 930 - 931 - gpp = padgrp->reg_num; 932 - gpp_offset = padgroup_offset(padgrp, pin); 933 - is_offset = community->is_offset + gpp * 4; 934 - 935 - raw_spin_lock_irqsave(&pctrl->lock, flags); 936 - /* Clear interrupt status first to avoid unexpected interrupt */ 937 - writel(BIT(gpp_offset), community->regs + is_offset); 938 - 939 - value = readl(community->regs + community->ie_offset + gpp * 4); 940 - value |= BIT(gpp_offset); 941 - writel(value, community->regs + community->ie_offset + gpp * 4); 942 - raw_spin_unlock_irqrestore(&pctrl->lock, flags); 943 - } 944 - } 945 - 946 917 static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask) 947 918 { 948 919 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ··· 926 955 if (pin >= 0) { 927 956 unsigned int gpp, gpp_offset; 928 957 unsigned long flags; 929 - void __iomem *reg; 958 + void __iomem *reg, *is; 930 959 u32 value; 931 960 932 961 gpp = padgrp->reg_num; 933 962 gpp_offset = padgroup_offset(padgrp, pin); 934 963 935 964 reg = community->regs + community->ie_offset + gpp * 4; 965 + is = community->regs + community->is_offset + gpp * 4; 936 966 937 967 raw_spin_lock_irqsave(&pctrl->lock, flags); 968 + 969 + /* Clear interrupt status first to avoid unexpected interrupt */ 970 + writel(BIT(gpp_offset), is); 971 + 938 972 value = readl(reg); 939 973 if (mask) 940 974 value &= ~BIT(gpp_offset); ··· 1083 1107 1084 1108 static struct irq_chip intel_gpio_irqchip = { 1085 1109 .name = "intel-gpio", 1086 - .irq_enable = intel_gpio_irq_enable, 1087 1110 .irq_ack = intel_gpio_irq_ack, 1088 1111 .irq_mask = intel_gpio_irq_mask, 1089 1112 .irq_unmask = intel_gpio_irq_unmask,