devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Vladimir Zapolskiy <vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
To: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>,
	Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>,
	Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>,
	Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Cc: Russell King <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>,
	Roland Stigge <stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: [PATCH 09/10] irqchip: lpc32xx: add option to wakeup from an interrupt
Date: Fri, 20 Nov 2015 03:28:44 +0200	[thread overview]
Message-ID: <1447982925-30138-10-git-send-email-vz@mleia.com> (raw)
In-Reply-To: <1447982925-30138-1-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>

The change allows to set wakeup interrupts on client side.

Now all LPC32xx irq chips have assigned irq_set_wake callback, which
is rerouted to some platform specific wakeup controller.

Mapping between particular interrupts and wakeup sources is taken from
interrupt controller device tree node.

It is worth to mention that during initialization wakeup controller
driver may appear after initialization of interrupt controller driver,
this situation is correctly handled.

Signed-off-by: Vladimir Zapolskiy <vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
---
 drivers/irqchip/irq-lpc32xx.c | 103 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-lpc32xx.c b/drivers/irqchip/irq-lpc32xx.c
index fcf281b..e0f50da 100644
--- a/drivers/irqchip/irq-lpc32xx.c
+++ b/drivers/irqchip/irq-lpc32xx.c
@@ -19,6 +19,7 @@
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 #include <asm/exception.h>
+#include <mach/wakeup.h>
 
 #define LPC32XX_INTC_MASK		0x00
 #define LPC32XX_INTC_RAW		0x04
@@ -27,16 +28,53 @@
 #define LPC32XX_INTC_TYPE		0x10
 #define LPC32XX_INTC_FIQ		0x14
 
+struct irq_to_wakeup {
+	/*
+	 * wakeup controller driver initialization may be deferred,
+	 * get its platform driver in runtime by device node
+	 */
+	struct wakeup_controller *wakeup;
+	struct device_node *wakeup_node;
+	u32 bit;
+};
+
 #define IRQS_PER_CONTROLLER		32
 
 struct lpc32xx_irq_chip {
 	void __iomem *base;
 	struct irq_domain *domain;
 	struct irq_chip chip;
+	struct irq_to_wakeup i2w[IRQS_PER_CONTROLLER];
 };
 
 static struct lpc32xx_irq_chip *lpc32xx_mic_data;
 
+static struct wakeup_controller *get_wakeup_bit(struct irq_data *d, u32 *bit)
+{
+	struct irq_domain *id = d->domain;
+	struct lpc32xx_irq_chip *ic = (struct lpc32xx_irq_chip *)id->host_data;
+	struct irq_to_wakeup *i2w = &ic->i2w[d->hwirq];
+	struct platform_device *wakeup;
+
+	if (!i2w->wakeup_node)
+		return NULL;
+
+	if (!i2w->wakeup) {
+		pr_debug("searching wakeup device for interrupt %u\n",
+				 irq_find_mapping(id, d->hwirq));
+		wakeup = of_find_device_by_node(i2w->wakeup_node);
+		if (wakeup) {
+			i2w->wakeup = platform_get_drvdata(wakeup);
+			of_node_put(i2w->wakeup_node);
+		}
+	}
+
+	if (i2w->wakeup)
+		*bit = i2w->bit;
+
+	return i2w->wakeup;
+}
+
 static inline u32 lpc32xx_ic_read(struct irq_domain *id, u32 reg)
 {
 	struct lpc32xx_irq_chip *ic = (struct lpc32xx_irq_chip *)id->host_data;
@@ -77,8 +115,9 @@ static void lpc32xx_irq_ack(struct irq_data *d)
 static int lpc32xx_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct irq_domain *domain = d->domain;
-	u32 val, mask = BIT(d->hwirq);
+	u32 bit, val, mask = BIT(d->hwirq);
 	bool high, edge;
+	struct wakeup_controller *wuc;
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -121,6 +160,24 @@ static int lpc32xx_irq_set_type(struct irq_data *d, unsigned int type)
 	}
 	lpc32xx_ic_write(domain, LPC32XX_INTC_TYPE, val);
 
+	wuc = get_wakeup_bit(d, &bit);
+	if (wuc)
+		lpc32xx_wakeup_set_edge(wuc, bit, high);
+
+	return 0;
+}
+
+static int lpc32xx_irq_set_wake(struct irq_data *d, unsigned int state)
+{
+	struct wakeup_controller *wuc;
+	u32 bit;
+
+	wuc = get_wakeup_bit(d, &bit);
+	if (wuc)
+		lpc32xx_wakeup_enable(wuc, bit, state);
+	else
+		return -ENODEV;
+
 	return 0;
 }
 
@@ -174,11 +231,42 @@ static const struct irq_domain_ops lpc32xx_irq_domain_ops = {
 	.xlate  = irq_domain_xlate_twocell,
 };
 
+static void __init of_node_to_wakeup(struct irq_to_wakeup *i2w,
+				     struct of_phandle_args *args)
+{
+	struct platform_device *wakeup;
+	int wakeup_cells = 0;
+	u32 hwirq;
+
+	if (!of_device_is_available(args->np))
+		return;
+
+	of_property_read_u32(args->np, "#wakeup-cells", &wakeup_cells);
+	if (wakeup_cells != 2) {
+		pr_info("%s: unsupported format of wakeup data, got %d\n",
+			args->np->full_name, wakeup_cells);
+		return;
+	}
+
+	hwirq = args->args[1];
+
+	wakeup = of_find_device_by_node(args->np);
+	if (wakeup) {
+		i2w[hwirq].wakeup = platform_get_drvdata(wakeup);
+	} else {
+		i2w[hwirq].wakeup_node = args->np;
+		of_node_get(i2w[hwirq].wakeup_node);
+	}
+
+	i2w[hwirq].bit = args->args[0];
+}
+
 static int __init lpc32xx_of_ic_init(struct device_node *node,
 				     struct device_node *parent)
 {
-	int parent_irq, i;
+	int parent_irq, i, ret;
 	struct lpc32xx_irq_chip *irqc;
+	struct of_phandle_args args;
 
 	irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
 	if (!irqc)
@@ -188,9 +276,20 @@ static int __init lpc32xx_of_ic_init(struct device_node *node,
 	irqc->chip.irq_mask = lpc32xx_irq_mask;
 	irqc->chip.irq_unmask = lpc32xx_irq_unmask;
 	irqc->chip.irq_set_type = lpc32xx_irq_set_type;
+	irqc->chip.irq_set_wake = lpc32xx_irq_set_wake;
 	irqc->chip.name = of_get_property(node, "interrupt-controller-name",
 					  NULL);
 
+	for (i = 0; ; i++) {
+		ret = of_parse_phandle_with_args(node, "wakeup-sources",
+						 "#wakeup-cells", i, &args);
+		if (ret)
+			break;
+
+		of_node_to_wakeup(irqc->i2w, &args);
+		of_node_put(args.np);
+	}
+
 	irqc->base = of_iomap(node, 0);
 	if (!irqc->base) {
 		pr_err("%s: unable to map registers\n", node->full_name);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2015-11-20  1:28 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-20  1:28 [PATCH 00/10] irqchip: lpc32xx: add LPC32xx irqchip driver Vladimir Zapolskiy
     [not found] ` <1447982925-30138-1-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
2015-11-20  1:28   ` [PATCH 01/10] dt-bindings: create arm/nxp folder and move LPC32xx SoC description to it Vladimir Zapolskiy
     [not found]     ` <1447982925-30138-2-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
2015-11-20 16:43       ` Rob Herring
2015-11-20  1:28   ` [PATCH 02/10] dt-bindings: nxp: add description of wakeup controller on LPC32xx Vladimir Zapolskiy
     [not found]     ` <1447982925-30138-3-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
2015-11-20 16:55       ` Rob Herring
2015-11-20  1:28   ` [PATCH 03/10] dt-bindings: interrupt-controllers: add description of SIC1 and SIC2 Vladimir Zapolskiy
     [not found]     ` <1447982925-30138-4-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
2015-11-20 16:58       ` Rob Herring
2015-11-20 17:52         ` Vladimir Zapolskiy
     [not found]           ` <564F5DF8.7040908-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
2015-11-20 18:02             ` Marc Zyngier
     [not found]               ` <564F6021.7090000-5wv7dgnIgG8@public.gmane.org>
2015-11-20 18:16                 ` Vladimir Zapolskiy
2015-11-20  1:28   ` [PATCH 04/10] arm: lpc32xx: add wakeup platform driver Vladimir Zapolskiy
2015-11-20  1:28   ` [PATCH 05/10] arm: dts: lpc32xx: assign interrupt types Vladimir Zapolskiy
2015-11-20  1:28   ` [PATCH 06/10] arm: dts: lpc32xx: add description of IC wakeup controllers Vladimir Zapolskiy
2015-11-20  1:28   ` [PATCH 07/10] arm: dts: lpc32xx: reparent SIC1 and SIC2 interrupts from MIC Vladimir Zapolskiy
2015-11-20  1:28   ` [PATCH 08/10] irqchip: add LPC32xx interrupt controller driver Vladimir Zapolskiy
     [not found]     ` <1447982925-30138-9-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org>
2015-11-20 10:56       ` Marc Zyngier
2015-11-20  1:28   ` Vladimir Zapolskiy [this message]
2015-11-20  1:28   ` [PATCH 10/10] arm: dts: lpc32xx: enable SIC1 and SIC2 by default Vladimir Zapolskiy
2016-02-10 19:45 ` [PATCH 00/10] irqchip: lpc32xx: add LPC32xx irqchip driver Sylvain Lemieux
     [not found]   ` <loom.20160210T204046-649-eS7Uydv5nfjZ+VzJOa5vwg@public.gmane.org>
2016-04-04 17:37     ` Sylvain Lemieux
2016-04-05  1:24       ` Vladimir Zapolskiy

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=1447982925-30138-10-git-send-email-vz@mleia.com \
    --to=vz-chpfbgzjdbmavxtiumwx3w@public.gmane.org \
    --cc=arnd-r2nGTMty4D4@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org \
    --cc=marc.zyngier-5wv7dgnIgG8@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org \
    --cc=tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org \
    /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).