From patchwork Fri Apr 5 07:48:08 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Javier Martinez Canillas X-Patchwork-Id: 2397111 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id BF36E3FD40 for ; Fri, 5 Apr 2013 07:50:00 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UO1PJ-000640-9Q for patchwork-linux-arm@patchwork.kernel.org; Fri, 05 Apr 2013 07:49:57 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UO1O0-00006N-I9; Fri, 05 Apr 2013 07:48:36 +0000 Received: from bhuna.collabora.co.uk ([93.93.135.160]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UO1Nw-00005u-G7 for linux-arm-kernel@lists.infradead.org; Fri, 05 Apr 2013 07:48:33 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: javier) with ESMTPSA id 0CEC016985A5 From: Javier Martinez Canillas To: Grant Likely , Jon Hunter Subject: [PATCH 1/1] of/irq: store IRQ trigger/level in struct resource flags Date: Fri, 5 Apr 2013 09:48:08 +0200 Message-Id: <1365148088-11175-1-git-send-email-javier.martinez@collabora.co.uk> X-Mailer: git-send-email 1.7.7.6 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130405_034832_703972_5977D422 X-CRM114-Status: GOOD ( 19.67 ) X-Spam-Score: -1.5 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- 1.7 KHOP_BIG_TO_CC Sent to 10+ recipients instaed of Bcc or a list -2.4 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 1.0 FILL_THIS_FORM_SHORT Fill in a short form with personal information Cc: Stephen Warren , Benoit Cousson , Tony Lindgren , Benjamin Herrenschmidt , devicetree-discuss@lists.ozlabs.org, Rob Herring , Thomas Gleixner , linux-omap , Javier Martinez Canillas , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org According to Documentation/devicetree/bindings/interrupt-controller/interrupts.txt the "#interrupt-cells" property of an "interrupt-controller" is used to define the number of cells needed to specify a single interrupt. A commonly used variant is two cell on which #interrupt-cells = <2> and the first cell defines the index of the interrupt in the controller and the second cell is used to specify any of the following flags: - bits[3:0] trigger type and level flags 1 = low-to-high edge triggered 2 = high-to-low edge triggered 4 = active high level-sensitive 8 = active low level-sensitive An example of an interrupt controller which use the two cell format is the OMAP GPIO controller that allows GPIO lines to be used as IRQ (Documentation/devicetree/bindings/gpio/gpio-omap.txt) But setting #interrupt-cells = <2> on the OMAP GPIO device node and specifying the GPIO-IRQ type and level flags on the second cell does not store this value on the populated IORESOURCE_IRQ struct resource. This is because when using an IRQ from an interrupt controller and setting both cells (e.g:) interrupt-parent = <&gpio6>; interrupts = <16 8>; A call to of_irq_to_resource() is made and this function calls to irq_of_parse_and_map_type() to get the virtual IRQ mapped to the real index for this interrupt controller. This IRQ number is populated on the struct resource: int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) { int irq = irq_of_parse_and_map(dev, index); .. r->start = r->end = irq; } irq_of_parse_and_map() calls to irq_create_of_mapping() which calls to the correct xlate function handler according to "#interrupt-cells" (irq_domain_xlate_onecell or irq_domain_xlate_twocell) and to irq_set_irq_type() to set the IRQ type. But the type is never returned so it can't be saved on the IRQ struct resource flags member. This means that drivers that need the IRQ type/level flags defined in the DT won't be able to get it. Signed-off-by: Javier Martinez Canillas --- drivers/of/irq.c | 30 ++++++++++++++++++++++++------ include/linux/of_irq.h | 4 ++++ kernel/irq/irqdomain.c | 14 ++++++++++++-- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index a3c1c5a..6f6aa75 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -27,22 +27,39 @@ #include /** - * irq_of_parse_and_map - Parse and map an interrupt into linux virq space + * irq_of_parse_and_map_type - Parse and map an interrupt into linux virq space * @device: Device node of the device whose interrupt is to be mapped * @index: Index of the interrupt to map + * @type: Interrupt trigger type and level flags filled by this function * * This function is a wrapper that chains of_irq_map_one() and * irq_create_of_mapping() to make things easier to callers */ -unsigned int irq_of_parse_and_map(struct device_node *dev, int index) +static unsigned int irq_of_parse_and_map_type(struct device_node *dev, + int index, unsigned int *type) { struct of_irq oirq; + unsigned int virq; if (of_irq_map_one(dev, index, &oirq)) return 0; - return irq_create_of_mapping(oirq.controller, oirq.specifier, - oirq.size); + virq = irq_create_of_mapping_type(oirq.controller, oirq.specifier, + oirq.size, type); + return virq; +} + +/** + * irq_of_parse_and_map - Parse and map an interrupt into linux virq space + * @device: Device node of the device whose interrupt is to be mapped + * @index: Index of the interrupt to map + * + * This function is a wrapper of irq_of_parse_and_map_type() when the IRQ + * type and level flags are not needed + */ +unsigned int irq_of_parse_and_map(struct device_node *dev, int index) +{ + return irq_of_parse_and_map_type(dev, index, NULL); } EXPORT_SYMBOL_GPL(irq_of_parse_and_map); @@ -338,7 +355,8 @@ EXPORT_SYMBOL_GPL(of_irq_map_one); */ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) { - int irq = irq_of_parse_and_map(dev, index); + int type = IRQ_TYPE_NONE; + int irq = irq_of_parse_and_map_type(dev, index, &type); /* Only dereference the resource if both the * resource and the irq are valid. */ @@ -353,7 +371,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) &name); r->start = r->end = irq; - r->flags = IORESOURCE_IRQ; + r->flags = (IORESOURCE_IRQ | type); r->name = name ? name : dev->full_name; } diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 535cecf..98aec57 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -66,6 +66,10 @@ extern int of_irq_map_one(struct device_node *device, int index, extern unsigned int irq_create_of_mapping(struct device_node *controller, const u32 *intspec, unsigned int intsize); +extern unsigned int irq_create_of_mapping_type(struct device_node *controller, + const u32 *intspec, + unsigned int intsize, + unsigned int *otype); extern int of_irq_to_resource(struct device_node *dev, int index, struct resource *r); extern int of_irq_count(struct device_node *dev); diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 96f3a1d..4a2f222 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -636,8 +636,9 @@ int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base, } EXPORT_SYMBOL_GPL(irq_create_strict_mappings); -unsigned int irq_create_of_mapping(struct device_node *controller, - const u32 *intspec, unsigned int intsize) +unsigned int irq_create_of_mapping_type(struct device_node *controller, + const u32 *intspec, unsigned int intsize, + unsigned int *otype) { struct irq_domain *domain; irq_hw_number_t hwirq; @@ -681,8 +682,17 @@ unsigned int irq_create_of_mapping(struct device_node *controller, if (type != IRQ_TYPE_NONE && type != (irqd_get_trigger_type(irq_get_irq_data(virq)))) irq_set_irq_type(virq, type); + if (otype) + *otype = type; return virq; } +EXPORT_SYMBOL_GPL(irq_create_of_mapping_type); + +unsigned int irq_create_of_mapping(struct device_node *controller, + const u32 *intspec, unsigned int intsize) +{ + return irq_create_of_mapping_type(controller, intspec, intsize, NULL); +} EXPORT_SYMBOL_GPL(irq_create_of_mapping); /**