From patchwork Tue Jan 31 11:45:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yuriy Kolerov X-Patchwork-Id: 721917 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (unknown [IPv6:2001:1868:a000:17::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vCPbl70qdz9sCG for ; Tue, 31 Jan 2017 22:46:11 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cYWt0-0005i4-Dg; Tue, 31 Jan 2017 11:46:10 +0000 Received: from smtprelay4.synopsys.com ([198.182.47.9] helo=smtprelay.synopsys.com) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cYWsv-0005co-Gg for linux-snps-arc@lists.infradead.org; Tue, 31 Jan 2017 11:46:07 +0000 Received: from mailhost.synopsys.com (mailhost1.synopsys.com [10.12.238.239]) by smtprelay.synopsys.com (Postfix) with ESMTP id 2F8A524E0F53; Tue, 31 Jan 2017 03:45:46 -0800 (PST) Received: from mailhost.synopsys.com (localhost [127.0.0.1]) by mailhost.synopsys.com (Postfix) with ESMTP id 12285D7F; Tue, 31 Jan 2017 03:45:46 -0800 (PST) Received: from ykolerov-vm.internal.synopsys.com (ykolerov-840g3.internal.synopsys.com [10.225.2.227]) by mailhost.synopsys.com (Postfix) with ESMTP id 6204AD55; Tue, 31 Jan 2017 03:45:44 -0800 (PST) From: Yuriy Kolerov To: linux-snps-arc@lists.infradead.org Subject: [PATCH v2 3/4] ARCv2: IRQ: Use build registers for getting numbers of interrupts Date: Tue, 31 Jan 2017 14:45:23 +0300 Message-Id: <1485863124-26426-4-git-send-email-yuriy.kolerov@synopsys.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485863124-26426-1-git-send-email-yuriy.kolerov@synopsys.com> References: <1485863124-26426-1-git-send-email-yuriy.kolerov@synopsys.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170131_034605_591174_BD0B1B2D X-CRM114-Status: GOOD ( 15.56 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [198.182.47.9 listed in wl.mailspike.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [198.182.47.9 listed in list.dnswl.org] -0.0 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 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-snps-arc@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux on Synopsys ARC Processors List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marc.zyngier@arm.com, Vineet.Gupta1@synopsys.com, Alexey.Brodkin@synopsys.com, linux-kernel@vger.kernel.org, Yuriy Kolerov MIME-Version: 1.0 Sender: "linux-snps-arc" Errors-To: linux-snps-arc-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This enhancement allows to mask all available common interrupts in IDU interrupt controller in boot time since the kernel can discover a number of them from the build register. Also now there is no need to specify in device tree a list of used core interrupts by IDU. E.g. before: idu_intc: idu-interrupt-controller { compatible = "snps,archs-idu-intc"; interrupt-controller; interrupt-parent = <&core_intc>; #interrupt-cells = <2>; interrupts = <24 25 26 27 28 29 30 31>; }; and after: idu_intc: idu-interrupt-controller { compatible = "snps,archs-idu-intc"; interrupt-controller; interrupt-parent = <&core_intc>; #interrupt-cells = <2>; }; Signed-off-by: Yuriy Kolerov --- arch/arc/include/asm/irq.h | 4 ++++ arch/arc/kernel/intc-arcv2.c | 9 +++++++-- arch/arc/kernel/mcip.c | 31 +++++++++++++++++++------------ include/soc/arc/mcip.h | 17 +++++++++++++++++ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index d28499a..1970d78c 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -18,6 +18,9 @@ */ #define NR_CPU_IRQS 240 +/* A fixed number of exceptions which occupy first interrupt lines */ +#define NR_EXCEPTIONS 16 + /* * ARCv2 can support 240 interrupts in the core interrupts controllers and * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most @@ -28,6 +31,7 @@ /* Platform Independent IRQs */ #define IPI_IRQ 19 #define SOFTIRQ_IRQ 21 +#define FIRST_EXT_IRQ 24 #else diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 9de0665..31246cc 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c @@ -109,7 +109,7 @@ static int arcv2_irq_map(struct irq_domain *d, unsigned int irq, * core intc IRQs [16, 23]: * Statically assigned always private-per-core (Timers, WDT, IPI, PCT) */ - if (hw < 24) { + if (hw < FIRST_EXT_IRQ) { /* * A subsequent request_percpu_irq() fails if percpu_devid is * not set. That in turns sets NOAUTOEN, meaning each core needs @@ -134,11 +134,16 @@ static int __init init_onchip_IRQ(struct device_node *intc, struct device_node *parent) { struct irq_domain *root_domain; + struct bcr_irq_arcv2 irq_bcr; + unsigned int nr_cpu_irqs; + + READ_BCR(ARC_REG_IRQ_BCR, irq_bcr); + nr_cpu_irqs = irq_bcr.irqs + NR_EXCEPTIONS; if (parent) panic("DeviceTree incore intc not a root irq controller\n"); - root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, &arcv2_irq_ops, NULL); + root_domain = irq_domain_add_linear(intc, nr_cpu_irqs, &arcv2_irq_ops, NULL); if (!root_domain) panic("root irq domain not avail\n"); diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index 9988b42..45d45fc 100644 --- a/arch/arc/kernel/mcip.c +++ b/arch/arc/kernel/mcip.c @@ -157,15 +157,20 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl, __mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word); } -static void idu_irq_mask(struct irq_data *data) +static void idu_irq_mask_raw(irq_hw_number_t hwirq) { unsigned long flags; raw_spin_lock_irqsave(&mcip_lock, flags); - __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1); + __mcip_cmd_data(CMD_IDU_SET_MASK, hwirq, 1); raw_spin_unlock_irqrestore(&mcip_lock, flags); } +static void idu_irq_mask(struct irq_data *data) +{ + idu_irq_mask_raw(data->hwirq); +} + static void idu_irq_unmask(struct irq_data *data) { unsigned long flags; @@ -231,14 +236,12 @@ static struct irq_chip idu_irq_chip = { }; -static irq_hw_number_t idu_first_hwirq; - static void idu_cascade_isr(struct irq_desc *desc) { struct irq_domain *idu_domain = irq_desc_get_handler_data(desc); struct irq_chip *core_chip = irq_desc_get_chip(desc); irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc)); - irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq; + irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ; chained_irq_enter(core_chip, desc); generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq)); @@ -284,33 +287,37 @@ static int __init idu_of_init(struct device_node *intc, struct device_node *parent) { struct irq_domain *domain; - /* Read IDU BCR to confirm nr_irqs */ - int nr_irqs = of_irq_count(intc); + int nr_irqs; int i, virq; struct mcip_bcr mp; + struct mcip_idu_bcr idu_bcr; READ_BCR(ARC_REG_MCIP_BCR, mp); if (!mp.idu) panic("IDU not detected, but DeviceTree using it"); - pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs); + READ_BCR(ARC_REG_MCIP_IDU_BCR, idu_bcr); + nr_irqs = mcip_idu_bcr_to_nr_irqs(idu_bcr); + + pr_info("MCIP: IDU supports %u common irqs\n", nr_irqs); domain = irq_domain_add_linear(intc, nr_irqs, &idu_irq_ops, NULL); /* Parent interrupts (core-intc) are already mapped */ for (i = 0; i < nr_irqs; i++) { + /* Mask all common interrupts by default */ + idu_irq_mask_raw(i); + /* * Return parent uplink IRQs (towards core intc) 24,25,..... * this step has been done before already * however we need it to get the parent virq and set IDU handler * as first level isr */ - virq = irq_of_parse_and_map(intc, i); - if (!i) - idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq)); - + virq = irq_create_mapping(NULL, i + FIRST_EXT_IRQ); + BUG_ON(!virq); irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain); } diff --git a/include/soc/arc/mcip.h b/include/soc/arc/mcip.h index 6902c2a..798c01b 100644 --- a/include/soc/arc/mcip.h +++ b/include/soc/arc/mcip.h @@ -14,6 +14,7 @@ #include #define ARC_REG_MCIP_BCR 0x0d0 +#define ARC_REG_MCIP_IDU_BCR 0x0D5 #define ARC_REG_MCIP_CMD 0x600 #define ARC_REG_MCIP_WDATA 0x601 #define ARC_REG_MCIP_READBACK 0x602 @@ -69,6 +70,22 @@ struct mcip_bcr { #endif }; +struct mcip_idu_bcr { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:21, cirqnum:3, ver:8; +#else + unsigned int ver:8, cirqnum:3, pad:21; +#endif +}; + + +/* + * Build register for IDU contains not an actual number of supported common + * interrupts but an exponent of 2 which must be multiplied by 4 to + * get a number of supported common interrupts. + */ +#define mcip_idu_bcr_to_nr_irqs(bcr) (4 * (1 << (bcr).cirqnum)) + /* * MCIP programming model *