Merge tag 'pinctrl-v5.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[sfrench/cifs-2.6.git] / drivers / pinctrl / qcom / pinctrl-msm.c
index 6e319bcc2326107962f020bf7e9d2f0028692298..7f35c196bb3e866500282d9aadb56ee7c48796ff 100644 (file)
@@ -599,8 +599,23 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *chip)
        int ret;
        unsigned int len, i;
        unsigned int max_gpios = pctrl->soc->ngpios;
+       const int *reserved = pctrl->soc->reserved_gpios;
        u16 *tmp;
 
+       /* Driver provided reserved list overrides DT and ACPI */
+       if (reserved) {
+               bitmap_fill(chip->valid_mask, max_gpios);
+               for (i = 0; reserved[i] >= 0; i++) {
+                       if (i >= max_gpios || reserved[i] >= max_gpios) {
+                               dev_err(pctrl->dev, "invalid list of reserved GPIOs\n");
+                               return -EINVAL;
+                       }
+                       clear_bit(reserved[i], chip->valid_mask);
+               }
+
+               return 0;
+       }
+
        /* The number of GPIOs in the ACPI tables */
        len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL,
                                                   0);
@@ -729,7 +744,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
        raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 }
 
-static void msm_gpio_irq_unmask(struct irq_data *d)
+static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
@@ -741,6 +756,17 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
 
        raw_spin_lock_irqsave(&pctrl->lock, flags);
 
+       if (status_clear) {
+               /*
+                * clear the interrupt status bit before unmask to avoid
+                * any erroneous interrupts that would have got latched
+                * when the interrupt is not in use.
+                */
+               val = msm_readl_intr_status(pctrl, g);
+               val &= ~BIT(g->intr_status_bit);
+               msm_writel_intr_status(val, pctrl, g);
+       }
+
        val = msm_readl_intr_cfg(pctrl, g);
        val |= BIT(g->intr_raw_status_bit);
        val |= BIT(g->intr_enable_bit);
@@ -751,6 +777,17 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
        raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 }
 
+static void msm_gpio_irq_enable(struct irq_data *d)
+{
+
+       msm_gpio_irq_clear_unmask(d, true);
+}
+
+static void msm_gpio_irq_unmask(struct irq_data *d)
+{
+       msm_gpio_irq_clear_unmask(d, false);
+}
+
 static void msm_gpio_irq_ack(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -956,6 +993,9 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
 
 static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
 {
+       if (pctrl->soc->reserved_gpios)
+               return true;
+
        return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0;
 }
 
@@ -978,6 +1018,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
        chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl);
 
        pctrl->irq_chip.name = "msmgpio";
+       pctrl->irq_chip.irq_enable = msm_gpio_irq_enable;
        pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;
        pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;
        pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;