diff options
author | Stephen Boyd <swboyd@chromium.org> | 2018-08-16 23:06:48 +0300 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2018-08-29 10:42:45 +0300 |
commit | fe2731211e784bff5a738631e5fd48041524239f (patch) | |
tree | 2a67d9643a6e784426214815e52971efa8cfbd7b /drivers/pinctrl/qcom | |
parent | 1de7ddb3a15c649fd15568d2056af295930656f8 (diff) | |
download | linux-fe2731211e784bff5a738631e5fd48041524239f.tar.xz |
pinctrl: msm: Configure interrupts as input and gpio mode
When requesting a gpio as an interrupt, we should make sure to mux the
pin as the GPIO function and configure it to be an input so that various
functions or output signals don't affect the interrupt state of the pin.
So far, we've relied on pinmux configurations in DT to handle this, but
let's explicitly configure this in the code so that DT implementers
don't have to get this part right.
Cc: Doug Anderson <dianders@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/qcom')
-rw-r--r-- | drivers/pinctrl/qcom/pinctrl-msm.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 00dfcf62b08b..cad74093f7ba 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -813,6 +813,41 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } +static int msm_gpio_irq_reqres(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct msm_pinctrl *pctrl = gpiochip_get_data(gc); + int ret; + + if (!try_module_get(gc->owner)) + return -ENODEV; + + ret = msm_pinmux_request_gpio(pctrl->pctrl, NULL, d->hwirq); + if (ret) + goto out; + msm_gpio_direction_input(gc, d->hwirq); + + if (gpiochip_lock_as_irq(gc, d->hwirq)) { + dev_err(gc->parent, + "unable to lock HW IRQ %lu for IRQ\n", + d->hwirq); + ret = -EINVAL; + goto out; + } + return 0; +out: + module_put(gc->owner); + return ret; +} + +static void msm_gpio_irq_relres(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + gpiochip_unlock_as_irq(gc, d->hwirq); + module_put(gc->owner); +} + static void msm_gpio_irq_handler(struct irq_desc *desc) { struct gpio_chip *gc = irq_desc_get_handler_data(desc); @@ -911,6 +946,8 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) pctrl->irq_chip.irq_ack = msm_gpio_irq_ack; pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type; pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake; + pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres; + pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres; ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { |