From patchwork Wed Dec 5 13:33:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory CLEMENT X-Patchwork-Id: 1841311 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id F2939DF266 for ; Wed, 5 Dec 2012 13:36:49 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TgF6l-0006jB-PJ; Wed, 05 Dec 2012 13:33:51 +0000 Received: from mail.free-electrons.com ([88.190.12.23]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TgF6Y-0006iL-Pq for linux-arm-kernel@lists.infradead.org; Wed, 05 Dec 2012 13:33:46 +0000 Received: by mail.free-electrons.com (Postfix, from userid 106) id 380BA163; Wed, 5 Dec 2012 14:33:25 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-3.2 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 shortcircuit=no autolearn=ham version=3.3.1 Received: from localhost (tra42-5-83-152-246-54.fbx.proxad.net [83.152.246.54]) by mail.free-electrons.com (Postfix) with ESMTPSA id F0B4ADB; Wed, 5 Dec 2012 14:33:11 +0100 (CET) From: Gregory CLEMENT To: Jason Cooper , Andrew Lunn , Gregory Clement Subject: [PATCH] arm: mvebu: Improve the SMP support of the interrupt controller Date: Wed, 5 Dec 2012 14:33:14 +0100 Message-Id: <1354714394-11622-2-git-send-email-gregory.clement@free-electrons.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1354714394-11622-1-git-send-email-gregory.clement@free-electrons.com> References: <1354714394-11622-1-git-send-email-gregory.clement@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121205_083339_094614_7CDAF874 X-CRM114-Status: GOOD ( 15.32 ) X-Spam-Score: 0.4 (/) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- 3.0 KHOP_BIG_TO_CC Sent to 10+ recipients instaed of Bcc or a list -0.0 SPF_PASS SPF: sender matches SPF record -0.7 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] Cc: Thomas Petazzoni , Lior Amsalem , Yehuda Yitschak , Jani Monoses , Ike Pan , Tawfik Bayouk , Arnd Bergmann , Nicolas Pitre , Dan Frazier , Chris Van Hoof , David Marlin , Eran Ben-Avi , Nadav Haklai , Maen Suleiman , Shadi Ammouri , Jon Masters , Olof Johansson , Leif Lindholm , linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Yehuda Yitschak This patch makes the interrupt controller driver more SMP aware for the Armada XP SoCs. It adds the support for the per-CPU irq. It also adds the implementation for the set_affinity hook. Patch initialy wrote by Yehuda Yitschak and reworked by Gregory CLEMENT for submission. Signed-off-by: Yehuda Yitschak Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/armada-xp.dtsi | 2 +- arch/arm/mach-mvebu/irq-armada-370-xp.c | 49 ++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index 45a567c..088d280 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -23,7 +23,7 @@ compatible = "marvell,armadaxp", "marvell,armada-370-xp"; mpic: interrupt-controller@d0020000 { - reg = <0xd0020a00 0x1d0>, + reg = <0xd0020a00 0x2d0>, <0xd0021070 0x58>; }; diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c index 549b684..9f2fe84 100644 --- a/arch/arm/mach-mvebu/irq-armada-370-xp.c +++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c @@ -33,6 +33,7 @@ #define ARMADA_370_XP_INT_CONTROL (0x00) #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) +#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) @@ -40,28 +41,68 @@ #define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc) #define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8) +#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) + #define ACTIVE_DOORBELLS (8) +static DEFINE_RAW_SPINLOCK(irq_controller_lock); + static void __iomem *per_cpu_int_base; static void __iomem *main_int_base; static struct irq_domain *armada_370_xp_mpic_domain; +/* + * For shared global interrupts, mask/unmask global enable bit + * For CPU interrtups, mask/unmask the calling CPU's bit + */ static void armada_370_xp_irq_mask(struct irq_data *d) { - writel(irqd_to_hwirq(d), - per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS) + writel(hwirq, main_int_base + + ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); + else + writel(hwirq, main_int_base + + ARMADA_370_XP_INT_SET_MASK_OFFS); } static void armada_370_xp_irq_unmask(struct irq_data *d) { - writel(irqd_to_hwirq(d), - per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS) + writel(hwirq, main_int_base + + ARMADA_370_XP_INT_SET_ENABLE_OFFS); + else + writel(hwirq, main_int_base + + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); } #ifdef CONFIG_SMP static int armada_xp_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { + unsigned long reg; + unsigned long new_mask = 0; + unsigned long online_mask = 0; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + int cpu; + + for_each_cpu(cpu, cpu_online_mask) + online_mask |= 1 << cpu_logical_map(cpu); + + for_each_cpu(cpu, mask_val) + new_mask |= 1 << cpu_logical_map(cpu); + + raw_spin_lock(&irq_controller_lock); + + reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); + reg = (reg & (~online_mask)) | new_mask; + writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); + + raw_spin_unlock(&irq_controller_lock); + return 0; } #endif