From patchwork Thu Jun 5 09:53:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 4304221 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 734709F1D6 for ; Thu, 5 Jun 2014 09:56:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 69096202F8 for ; Thu, 5 Jun 2014 09:56:31 +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 74B552017A for ; Thu, 5 Jun 2014 09:56:30 +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 1WsUN9-0001Kx-Mm; Thu, 05 Jun 2014 09:54:11 +0000 Received: from mail-wi0-f172.google.com ([209.85.212.172]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WsUMs-0001Db-7d for linux-arm-kernel@lists.infradead.org; Thu, 05 Jun 2014 09:53:55 +0000 Received: by mail-wi0-f172.google.com with SMTP id hi2so10136795wib.5 for ; Thu, 05 Jun 2014 02:53:31 -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=wjTL2cu95LrQctJxMa50L5z8mdjdbp5V+4V8ht7ITiU=; b=m9mT+B4X9WQ7hlVVQM/ED3tEkqYfzCrdqYjwvKgjkZj8bsEAO/r+9BEikOPXgvnTKK 6LzwhHfzL5U3iMbYQY9NBj4z/j5mOcNo6cHy4IJU1OIbR5XFc9kZRIx58HEm6bh1PNsZ SCkr5ysRPFzbF+BzbpV25KHahjQ+8iv5At2SKPneTDRoOu/7G5ufLWQ2O949aKskfk8/ YkGf9XbRxBS2/TdUXCzDAtoCwmN0B98G1Sn8lmT1b55ZrJFimldAOoD/bjKe4CU0X2Rd o6ifrbMC+Vi/zDCpJoXYInMs9Ag2YyfIs2I+G9SgtFVPx3BJdRgX/0YQaqNl6ge232Vt 7xRQ== X-Gm-Message-State: ALoCoQmfBz4Xfhpq+fEpYPQ4HSg0wXdFiOV/tkC/bt6m3xd8XIp0zfnl+JH6Lpcummfyns2JPcJU X-Received: by 10.194.174.168 with SMTP id bt8mr14218814wjc.72.1401962011639; Thu, 05 Jun 2014 02:53:31 -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 s3sm7337863wje.36.2014.06.05.02.53.29 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Jun 2014 02:53:30 -0700 (PDT) From: Daniel Thompson To: Jason Wessel Subject: [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ Date: Thu, 5 Jun 2014 10:53:09 +0100 Message-Id: <1401961994-18033-5-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1401961994-18033-1-git-send-email-daniel.thompson@linaro.org> References: <1400853478-5824-1-git-send-email-daniel.thompson@linaro.org> <1401961994-18033-1-git-send-email-daniel.thompson@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140605_025354_567906_C09AD0E8 X-CRM114-Status: GOOD ( 21.54 ) 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 | 62 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index aa8efe4..9a4712d 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -42,12 +42,17 @@ #include #include +#ifdef CONFIG_FIQ +#include +#endif #include #include #include #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 +70,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 +149,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 +188,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 +198,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 +973,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 +1064,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,17 +1076,28 @@ 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->domain = irq_domain_add_linear(node, 2 * nr_routable_irqs, + &gic_irq_domain_ops, gic); } if (WARN_ON(!gic->domain)) return; +#ifdef CONFIG_FIQ + /* FIQ can only be supported on platforms without an extended irq_eoi + * method (otherwise we take a lock during irq_eoi handling). + */ + if (!gic_arch_extn.irq_eoi) + fiq_add_mapping( + irq_linear_revmap(gic->domain, hwirq_base), + irq_linear_revmap(gic->domain, hwirq_base + gic_irqs), + gic_irqs); +#endif + if (gic_nr == 0) { #ifdef CONFIG_SMP set_smp_cross_call(gic_raise_softirq);