From: Lina Iyer <ilina@codeaurora.org>
To: sboyd@kernel.org, evgreen@chromium.org, marc.zyngier@arm.com
Cc: linux-kernel@vger.kernel.org, rplsssn@codeaurora.org,
linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org,
thierry.reding@gmail.com, Lina Iyer <ilina@codeaurora.org>
Subject: [RFC v3 1/3] drivers: pinctrl: msm: setup gpio irqchip in hierarchy with pdc irqchip
Date: Tue, 20 Nov 2018 17:06:46 -0700 [thread overview]
Message-ID: <20181121000648.29262-2-ilina@codeaurora.org> (raw)
In-Reply-To: <20181121000648.29262-1-ilina@codeaurora.org>
Signed-off-by: Lina Iyer <ilina@codeaurora.org>
---
drivers/pinctrl/qcom/pinctrl-msm.c | 125 ++++++++++++++++++++++++++++-
1 file changed, 121 insertions(+), 4 deletions(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 7c7d083e2c0d..3857aa5539e0 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
@@ -735,6 +736,9 @@ static void msm_gpio_irq_mask(struct irq_data *d)
clear_bit(d->hwirq, pctrl->enabled_irqs);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ if (d->parent_data)
+ irq_chip_mask_parent(d);
}
static void msm_gpio_irq_unmask(struct irq_data *d)
@@ -757,6 +761,9 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
set_bit(d->hwirq, pctrl->enabled_irqs);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ if (d->parent_data)
+ irq_chip_unmask_parent(d);
}
static void msm_gpio_irq_ack(struct irq_data *d)
@@ -875,6 +882,9 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
irq_set_handler_locked(d, handle_edge_irq);
+ if (d->parent_data)
+ irq_chip_set_type_parent(d, type);
+
return 0;
}
@@ -890,6 +900,9 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+ if (d->parent_data)
+ irq_chip_set_wake_parent(d, on);
+
return 0;
}
@@ -967,11 +980,103 @@ static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0;
}
+static int get_parent_hwirq(struct msm_pinctrl *pctrl, unsigned int hwirq)
+{
+ int i, n, ret;
+ int gpio, pdc = -EINVAL;
+ struct device_node *np = pctrl->dev->of_node;
+
+ n = of_property_count_elems_of_size(np, "wake-irq", sizeof(u32));
+ if (n <= 0 || n % 2)
+ return -EINVAL;
+
+ for (i = 0; i < n / 2; i++) {
+ ret = of_property_read_u32_index(np, "wake-irq", 2 * i, &gpio);
+ if (ret)
+ return ret;
+ if (gpio != hwirq)
+ continue;
+ ret = of_property_read_u32_index(np, "wake-irq", 2 * i + 1,
+ &pdc);
+ if (ret)
+ return ret;
+ }
+
+ return pdc;
+}
+
+static int msm_gpio_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq, unsigned int *type)
+{
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count < 2)
+ return -EINVAL;
+ *hwirq = fwspec->param[0];
+ *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int msm_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ int ret = 0;
+ irq_hw_number_t hwirq;
+ int parent_hwirq;
+ struct gpio_chip *gc = domain->host_data;
+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+ struct irq_fwspec parent_fwspec, *fwspec = arg;
+ unsigned int type;
+
+ ret = msm_gpio_domain_translate(domain, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ parent_hwirq = get_parent_hwirq(pctrl, hwirq);
+ if (parent_hwirq < 0)
+ return 0;
+
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+ &pctrl->irq_chip, gc);
+ if (ret < 0)
+ return ret;
+
+ parent_fwspec.fwnode = domain->parent->fwnode;
+ parent_fwspec.param_count = 2;
+ parent_fwspec.param[0] = parent_hwirq;
+ parent_fwspec.param[1] = type;
+
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+ &parent_fwspec);
+}
+
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+ struct irq_fwspec fwspec;
+
+ fwspec.fwnode = of_node_to_fwnode(chip->of_node);
+ fwspec.param[0] = offset;
+ fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
+ fwspec.param_count = 2;
+
+ return irq_create_fwspec_mapping(&fwspec);
+}
+
+static const struct irq_domain_ops msm_gpiod_ops = {
+ .translate = msm_gpio_domain_translate,
+ .alloc = msm_gpio_domain_alloc,
+ .free = irq_domain_free_irqs_top,
+};
+
static int msm_gpio_init(struct msm_pinctrl *pctrl)
{
struct gpio_chip *chip;
int ret;
unsigned ngpio = pctrl->soc->ngpios;
+ struct device_node *dn;
if (WARN_ON(ngpio > MAX_NR_GPIO))
return -EINVAL;
@@ -1015,9 +1120,19 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
dev_name(pctrl->dev), 0, 0, chip->ngpio);
if (ret) {
dev_err(pctrl->dev, "Failed to add pin range\n");
- gpiochip_remove(&pctrl->chip);
- return ret;
+ goto fail;
+ }
+ }
+
+ dn = of_parse_phandle(pctrl->dev->of_node, "wakeup-parent", 0);
+ if (dn) {
+ chip->irq.parent_domain = irq_find_host(dn);
+ of_node_put(dn);
+ if (!chip->irq.parent_domain) {
+ ret = -EPROBE_DEFER;
+ goto fail;
}
+ chip->to_irq = msm_gpio_to_irq;
}
ret = gpiochip_irqchip_add(chip,
@@ -1027,14 +1142,16 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
IRQ_TYPE_NONE);
if (ret) {
dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
- gpiochip_remove(&pctrl->chip);
- return -ENOSYS;
+ goto fail;
}
gpiochip_set_chained_irqchip(chip, &pctrl->irq_chip, pctrl->irq,
msm_gpio_irq_handler);
return 0;
+fail:
+ gpiochip_remove(&pctrl->chip);
+ return ret;
}
static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action,
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
next prev parent reply other threads:[~2018-11-21 0:07 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-21 0:06 [RFC v3 0/3] qcom: GPIO IRQ wakeup using PDC irqchip Lina Iyer
2018-11-21 0:06 ` Lina Iyer [this message]
2018-11-21 0:06 ` [RFC v3 2/3] dt-bindings: sdm845-pinctrl: add wakeup interrupt parent for GPIO Lina Iyer
2018-11-21 21:36 ` Stephen Boyd
2018-11-26 16:14 ` Lina Iyer
2018-11-27 9:12 ` Stephen Boyd
2018-11-27 18:21 ` Lina Iyer
2018-11-27 21:45 ` Stephen Boyd
2018-11-28 17:39 ` Lina Iyer
2018-11-29 0:24 ` Bjorn Andersson
2018-11-29 21:45 ` Lina Iyer
2018-11-30 7:10 ` Bjorn Andersson
2018-11-30 18:33 ` Lina Iyer
2018-12-03 23:48 ` Stephen Boyd
2018-12-18 18:01 ` Lina Iyer
2018-11-21 0:06 ` [RFC v3 3/3] arm64: dts: msm: add PDC wake irq maps for GPIOs for SDM845 Lina Iyer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181121000648.29262-2-ilina@codeaurora.org \
--to=ilina@codeaurora.org \
--cc=devicetree@vger.kernel.org \
--cc=evgreen@chromium.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=marc.zyngier@arm.com \
--cc=rplsssn@codeaurora.org \
--cc=sboyd@kernel.org \
--cc=thierry.reding@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).