From patchwork Tue Mar 12 15:54:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= X-Patchwork-Id: 227067 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:4978:20e::2]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 1F2A22C0291 for ; Wed, 13 Mar 2013 03:00:53 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UFRXM-0003cm-V4; Tue, 12 Mar 2013 15:54:49 +0000 Received: from avalon.kleine-koenig.org ([2a01:4f8:d13:2543::2]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UFRXH-0003bb-Rh for linux-arm-kernel@lists.infradead.org; Tue, 12 Mar 2013 15:54:45 +0000 Received: by avalon.kleine-koenig.org (Postfix, from userid 1000) id 87A5640DCE; Tue, 12 Mar 2013 16:54:38 +0100 (CET) From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= To: Thomas Gleixner Subject: [PATCH] irqchip: Add support for ARMv7-M's NVIC Date: Tue, 12 Mar 2013 16:54:33 +0100 Message-Id: <1363103673-24720-1-git-send-email-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 1.8.2.rc2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130312_115444_403839_B87B7651 X-CRM114-Status: GOOD ( 18.44 ) X-Spam-Score: -4.5 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.6 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: Catalin Marinas , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org From: Catalin Marinas This interrupt controller is found on Cortex-M3 and Cortex-M4 machines. [ukleinek: drop locking, switch to fasteoi handler, add irqdomain and dt support, move to drivers/irq] Signed-off-by: Catalin Marinas Signed-off-by: Uwe Kleine-König --- drivers/irqchip/Kconfig | 4 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-nvic.c | 136 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 drivers/irqchip/irq-nvic.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index a350969..18657fd 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -10,6 +10,10 @@ config ARM_GIC config GIC_NON_BANKED bool +config ARM_NVIC + bool + select IRQ_DOMAIN + config ARM_VIC bool select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 98e3b87..7227c5f 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARM_GIC) += irq-gic.o +obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_VIC) += irq-vic.o obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c new file mode 100644 index 0000000..ddfb3d8 --- /dev/null +++ b/drivers/irqchip/irq-nvic.c @@ -0,0 +1,136 @@ +/* + * drivers/irq/irq-nvic.c + * + * Copyright (C) 2008 ARM Limited, All Rights Reserved. + * Copyright (C) 2013 Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Support for the Nested Vectored Interrupt Controller found on the + * ARMv7-M CPUs (Cortex-M3/M4) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "irqchip.h" + +#define NVIC_INTR_CTRL (0x004) +#define NVIC_ISER (0x100) +#define NVIC_ICER (0x180) +#define NVIC_IPRI (0x400) + +struct nvic_chip_data { + void __iomem *dist_base; + struct irq_domain *domain; +}; + +static struct nvic_chip_data nvic_data __read_mostly; + +static inline void __iomem *nvic_dist_base(struct irq_data *d) +{ + struct nvic_chip_data *nvic_data = irq_data_get_irq_chip_data(d); + return nvic_data->dist_base; +} + +static void nvic_mask_irq(struct irq_data *d) +{ + u32 mask = 1 << (d->hwirq % 32); + + writel_relaxed(mask, nvic_dist_base(d) + NVIC_ICER + d->irq / 32 * 4); +} + +static void nvic_unmask_irq(struct irq_data *d) +{ + u32 mask = 1 << (d->hwirq % 32); + + writel_relaxed(mask, nvic_dist_base(d) + NVIC_ISER + d->hwirq / 32 * 4); +} + +void nvic_eoi(struct irq_data *d) +{ + /* + * This is a no-op as end of interrupt is signaled by the exception + * return sequence. + */ +} + +static struct irq_chip nvic_chip = { + .name = "NVIC", + .irq_mask = nvic_mask_irq, + .irq_unmask = nvic_unmask_irq, + .irq_eoi = nvic_eoi, +}; + +static void __init nvic_init_bases(struct device_node *node, + void __iomem *dist_base) +{ + unsigned int irqs, i, irq_base; + + nvic_data.dist_base = dist_base; + + irqs = ((readl_relaxed(dist_base + NVIC_INTR_CTRL) & 0x0f) + 1) * 32; + if (irqs > 496) + irqs = 496; + + irq_base = irq_alloc_descs(-1, 16, irqs - 16, numa_node_id()); + if (IS_ERR_VALUE(irq_base)) { + WARN(1, "Cannot allocate irq_descs\n"); + irq_base = 16; + } + nvic_data.domain = irq_domain_add_legacy(node, irqs - 16, irq_base, 0, + &irq_domain_simple_ops, NULL); + if (WARN_ON(!nvic_data.domain)) + return; + + /* + * Set priority on all interrupts. + */ + for (i = 0; i < irqs; i += 4) + writel_relaxed(0, dist_base + NVIC_IPRI + i); + + /* + * Disable all interrupts + */ + for (i = 0; i < irqs; i += 32) + writel_relaxed(~0, dist_base + NVIC_ICER + i * 4 / 32); + + /* + * Setup the Linux IRQ subsystem. + */ + for (i = 0; i < irqs; i++) { + irq_set_chip_and_handler(irq_base + i, &nvic_chip, + handle_fasteoi_irq); + irq_set_chip_data(irq_base + i, &nvic_data); + set_irq_flags(irq_base + i, IRQF_VALID | IRQF_PROBE); + } +} + +static int __init nvic_of_init(struct device_node *node, + struct device_node *parent) +{ + void __iomem *dist_base; + + if (WARN_ON(!node)) + return -ENODEV; + + dist_base = of_iomap(node, 0); + WARN(!dist_base, "unable to map nvic dist registers\n"); + + nvic_init_bases(node, dist_base); + + return 0; +} +IRQCHIP_DECLARE(cortex_m3_nvic, "arm,cortex-m3-nvic", nvic_of_init);