From patchwork Tue Apr 2 13:57:33 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: 2378631 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 3567FDF2A1 for ; Tue, 2 Apr 2013 13:57:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761031Ab3DBN56 (ORCPT ); Tue, 2 Apr 2013 09:57:58 -0400 Received: from bhuna.collabora.co.uk ([93.93.135.160]:50267 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1761019Ab3DBN55 (ORCPT ); Tue, 2 Apr 2013 09:57:57 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: javier) with ESMTPSA id 68FD7169854A From: Javier Martinez Canillas To: Grant Likely , Jon Hunter Cc: Rob Herring , Benjamin Herrenschmidt , Thomas Gleixner , devicetree-discuss@lists.ozlabs.org, Benoit Cousson , Tony Lindgren , Stephen Warren , linux-omap , linux-arm-kernel@lists.infradead.org, Javier Martinez Canillas Subject: [RFC 1/1] of/irq: store IRQ trigger/level in struct resource flags Date: Tue, 2 Apr 2013 15:57:33 +0200 Message-Id: <1364911053-27442-1-git-send-email-javier.martinez@collabora.co.uk> X-Mailer: git-send-email 1.7.7.6 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.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 --- Hello, This is a RFC since I don't know if this is the best approach to solve the issue. I've tested this patch a TI OMAP3 DM3735 SoC board and his working correctly both with and without DeviceTrees. I've added an indirection level to keep the patch as small as possible instead of changing dozens of files to update the callers. I think this make it easier to review the change. If you agree with this patch I can send a v2 that juse add a type param to irq_of_parse_and_map() and irq_create_of_mapping(), updating all the callers of this functions as well. Thanks a lot and best regards, 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); /**