summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/qcom/pinctrl-msm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/qcom/pinctrl-msm.c')
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 963da8e0c29a..ee8c09717597 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -30,6 +30,7 @@
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <linux/irqchip/msm-mpm-irq.h>
+#include <linux/wakeup_reason.h>
#include "../core.h"
#include "../pinconf.h"
#include "pinctrl-msm.h"
@@ -504,6 +505,10 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
unsigned i;
for (i = 0; i < chip->ngpio; i++, gpio++) {
+ /* Bypass GPIO pins owned by TZ */
+ switch (gpio)
+ case 81 ... 84: continue;
+
msm_gpio_dbg_show_one(s, NULL, chip, i, gpio);
seq_puts(s, "\n");
}
@@ -590,9 +595,43 @@ static void msm_gpio_irq_mask(struct irq_data *d)
pctrl->irq_chip_extn->irq_mask(d);
}
+static void msm_gpio_irq_enable(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
+ const struct msm_pingroup *g;
+ unsigned long flags;
+ u32 val;
+
+ g = &pctrl->soc->groups[d->hwirq];
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+ /* 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 = readl_relaxed(pctrl->regs + g->intr_status_reg);
+ if (g->intr_ack_high)
+ val |= BIT(g->intr_status_bit);
+ else
+ val &= ~BIT(g->intr_status_bit);
+ writel_relaxed(val, pctrl->regs + g->intr_status_reg);
+
+ val = readl_relaxed(pctrl->regs + g->intr_cfg_reg);
+ val |= BIT(g->intr_enable_bit);
+ writel_relaxed(val, pctrl->regs + g->intr_cfg_reg);
+
+ set_bit(d->hwirq, pctrl->enabled_irqs);
+
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+ if (pctrl->irq_chip_extn->irq_enable)
+ pctrl->irq_chip_extn->irq_enable(d);
+}
+
static void msm_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ uint32_t irqtype = irqd_get_trigger_type(d);
struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
const struct msm_pingroup *g;
unsigned long flags;
@@ -602,6 +641,12 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
spin_lock_irqsave(&pctrl->lock, flags);
+ if (irqtype & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
+ val = readl_relaxed(pctrl->regs + g->intr_status_reg);
+ val &= ~BIT(g->intr_status_bit);
+ writel_relaxed(val, pctrl->regs + g->intr_status_reg);
+ }
+
val = readl(pctrl->regs + g->intr_status_reg);
val &= ~BIT(g->intr_status_bit);
writel(val, pctrl->regs + g->intr_status_reg);
@@ -759,6 +804,8 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
static struct irq_chip msm_gpio_irq_chip = {
.name = "msmgpio",
+ .flags = IRQCHIP_MASK_ON_SUSPEND,
+ .irq_enable = msm_gpio_irq_enable,
.irq_mask = msm_gpio_irq_mask,
.irq_unmask = msm_gpio_irq_unmask,
.irq_ack = msm_gpio_irq_ack,
@@ -766,7 +813,7 @@ static struct irq_chip msm_gpio_irq_chip = {
.irq_set_wake = msm_gpio_irq_set_wake,
};
-static void msm_gpio_irq_handler(struct irq_desc *desc)
+static bool msm_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
const struct msm_pingroup *g;
@@ -776,6 +823,7 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
int handled = 0;
u32 val;
int i;
+ bool ret;
chained_irq_enter(chip, desc);
@@ -793,11 +841,13 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
}
}
+ ret = (handled != 0);
/* No interrupts were flagged */
if (handled == 0)
- handle_bad_irq(desc);
+ ret = handle_bad_irq(desc);
chained_irq_exit(chip, desc);
+ return ret;
}
/*
@@ -862,7 +912,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
ret = gpiochip_irqchip_add(chip,
&msm_gpio_irq_chip,
0,
- handle_edge_irq,
+ handle_fasteoi_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
@@ -942,7 +992,7 @@ static void msm_pinctrl_resume(void)
name = "stray irq";
else if (desc->action && desc->action->name)
name = desc->action->name;
-
+ log_base_wakeup_reason(irq);
pr_warn("%s: %d triggered %s\n", __func__, irq, name);
}
}