From patchwork Fri May 23 13:57:51 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 4232871 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B8488BF90B for ; Fri, 23 May 2014 14:01:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BFE0D20303 for ; Fri, 23 May 2014 14:01:53 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0735920295 for ; Fri, 23 May 2014 14:01:51 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wnq0C-00016b-W5; Fri, 23 May 2014 13:59:17 +0000 Received: from mail-wg0-f48.google.com ([74.125.82.48]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wnpze-0000mZ-P3 for linux-arm-kernel@lists.infradead.org; Fri, 23 May 2014 13:58:43 +0000 Received: by mail-wg0-f48.google.com with SMTP id k14so635685wgh.7 for ; Fri, 23 May 2014 06:58:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gsyEaOxEzuaSfLkAGX6WCS1oGwLiUtHmUjsdrZ/PVrA=; b=EmyHvOG/K3yPyu2CoHCqewSVk24HFgH7KG7/q+9UXhTvhP6l2CTVKeQBcd5du1GRNm dLprj90WXAjOHfcgRADvanKx46smfnrNsHT089+QDcdWQgnqKufGsfKqa3KcXNmcERXj MA7Lcpasw3XZOEJJyMkWXUnNFh2Tl7Gu7iZJPYSIDFzkiymp1LS+11nQUM+r5fcKnFoF 0qwB0RTs0PjFj0bIlN2hWv1arzDqelToC4p5+pzsAdQsHzjBBfJf/7wF2lVRc3l973Fv UbzFCeQWM6iKM7XFz4N0BWudgEmEgXqTE61dwS9elpuo+7MXDe/JyDa7g+NCcE90wvDs CAZA== X-Gm-Message-State: ALoCoQltCPx0/x/6s/7aDoGLf2DK03T6R87JlBhab2PPJkUp1GqeuRt5NZILJVhAyNTnsDM8a/io X-Received: by 10.194.246.234 with SMTP id xz10mr2350124wjc.77.1400853500271; Fri, 23 May 2014 06:58:20 -0700 (PDT) Received: from sundance.lan (cpc4-aztw19-0-0-cust157.18-1.cable.virginm.net. [82.33.25.158]) by mx.google.com with ESMTPSA id l4sm4016261wjf.14.2014.05.23.06.58.17 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 May 2014 06:58:19 -0700 (PDT) From: Daniel Thompson To: Jason Wessel Subject: [RFC v2 03/10] irqchip: gic: Introduce shadow irqs for FIQ Date: Fri, 23 May 2014 14:57:51 +0100 Message-Id: <1400853478-5824-4-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1400853478-5824-1-git-send-email-daniel.thompson@linaro.org> References: <1400083125-1464-1-git-send-email-daniel.thompson@linaro.org> <1400853478-5824-1-git-send-email-daniel.thompson@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140523_065843_138209_EF4FEEF5 X-CRM114-Status: GOOD ( 20.23 ) X-Spam-Score: -0.7 (/) Cc: Mark Rutland , Nicolas Pitre , kernel@stlinux.com, kgdb-bugreport@lists.sourceforge.net, Linus Walleij , Sricharan R , Jiri Slaby , Daniel Thompson , Dirk Behme , Russell King , Nicolas Pitre , Ian Campbell , Anton Vorontsov , "David A. Long" , linux-serial@vger.kernel.org, Catalin Marinas , kernel-team@android.com, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Jason Cooper , Pawel Moll , patches@linaro.org, Kumar Gala , Rob Herring , John Stultz , Thomas Gleixner , linux-arm-kernel@lists.infradead.org, Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Colin Cross , Frederic Weisbecker , Christoffer Dall 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 X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch registers two virqs for each interrupt source it supports. Using multiple virqs allows the GIC driver to automatically modify the group register, allowing the new virqs to be used as argument to enable_fiq(). This also allows FIQ resources to be described in the device tree's interrupt list using a special flag (currently 0x80). Both these aspects combine and allow a driver to deploy a FIQ handler without any machine specific knowledge; it can be used effectively on multi-arch kernels. Signed-off-by: Daniel Thompson Cc:: Thomas Gleixner Cc: Jason Cooper Cc: Nicolas Pitre Cc: Christoffer Dall Cc: Sricharan R --- drivers/irqchip/irq-gic.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index aa8efe4..0c259ac 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -48,6 +48,8 @@ #include "irqchip.h" +#define GIC_INTSPEC_IRQ_IS_FIQ (1 << 7) + union gic_base { void __iomem *common_base; void __percpu * __iomem *percpu_base; @@ -65,6 +67,7 @@ struct gic_chip_data { #endif struct irq_domain *domain; unsigned int gic_irqs; + unsigned int fiq_shadow_offset; #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif @@ -143,11 +146,34 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d) return gic_data_cpu_base(gic_data); } +static inline bool gic_is_fiq(struct irq_data *d) +{ + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); + return d->hwirq > gic_data->gic_irqs; +} + static inline unsigned int gic_irq(struct irq_data *d) { + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); + if (gic_is_fiq(d)) + return d->hwirq - gic_data->fiq_shadow_offset; return d->hwirq; } +static void gic_set_group_irq(struct irq_data *d, int group) +{ + unsigned int reg = gic_irq(d) / 32 * 4; + u32 mask = 1 << (gic_irq(d) % 32); + u32 val; + + val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + reg); + if (group) + val |= mask; + else + val &= ~mask; + writel_relaxed(val, gic_dist_base(d) + GIC_DIST_IGROUP + reg); +} + /* * Routines to acknowledge, disable and enable interrupts */ @@ -159,6 +185,8 @@ static void gic_mask_irq(struct irq_data *d) writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); if (gic_arch_extn.irq_mask) gic_arch_extn.irq_mask(d); + if (gic_is_fiq(d)) + gic_set_group_irq(d, 1); raw_spin_unlock(&irq_controller_lock); } @@ -167,6 +195,8 @@ static void gic_unmask_irq(struct irq_data *d) u32 mask = 1 << (gic_irq(d) % 32); raw_spin_lock(&irq_controller_lock); + if (gic_is_fiq(d)) + gic_set_group_irq(d, 0); if (gic_arch_extn.irq_unmask) gic_arch_extn.irq_unmask(d); writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); @@ -940,7 +970,12 @@ static int gic_routable_irq_domain_xlate(struct irq_domain *d, unsigned long *out_hwirq, unsigned int *out_type) { + struct gic_chip_data *gic_data = d->host_data; *out_hwirq += 16; + + if (intspec[2] & GIC_INTSPEC_IRQ_IS_FIQ) + *out_hwirq += gic_data->fiq_shadow_offset; + return 0; } @@ -1026,10 +1061,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic->gic_irqs = gic_irqs; gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ + gic->fiq_shadow_offset = gic_irqs; if (of_property_read_u32(node, "arm,routable-irqs", &nr_routable_irqs)) { - irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, + irq_base = irq_alloc_descs(irq_start, 16, 2 * gic_irqs, numa_node_id()); if (IS_ERR_VALUE(irq_base)) { WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", @@ -1037,12 +1073,12 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, irq_base = irq_start; } - gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, - hwirq_base, &gic_irq_domain_ops, gic); + gic->domain = + irq_domain_add_legacy(node, 2 * gic_irqs, irq_base, + hwirq_base, &gic_irq_domain_ops, gic); } else { gic->domain = irq_domain_add_linear(node, nr_routable_irqs, - &gic_irq_domain_ops, - gic); + &gic_irq_domain_ops, gic); } if (WARN_ON(!gic->domain))