From patchwork Thu May 2 18:25:04 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Hesselbarth X-Patchwork-Id: 2513431 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id D1E983FD85 for ; Thu, 2 May 2013 18:26:30 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UXyCh-0003C8-RL; Thu, 02 May 2013 18:26:04 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UXyCY-0007PX-53; Thu, 02 May 2013 18:25:54 +0000 Received: from mail-bk0-x232.google.com ([2a00:1450:4008:c01::232]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UXyCU-0007Ni-Vl for linux-arm-kernel@lists.infradead.org; Thu, 02 May 2013 18:25:52 +0000 Received: by mail-bk0-f50.google.com with SMTP id ik5so396081bkc.37 for ; Thu, 02 May 2013 11:25:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer; bh=Ozwfoo2Sz85Y2UeakNdpQASoZkkrZ1N+IFz7zj0KKcE=; b=BP2ntp5/diNLWwu+8wMhGrX/46mFWoW7Z13q/qvmDltLfq/1nVv/PMJZLGAvJFOiA5 a+oEW8SL3++XSqQOOHbNVPcFH8n1ZwZw3HXXHkRBQexoDQ8zj+acAkm7E9UnuSH6EntN C1q/y9vHMw6uZ+BXwaw+JQuKYMhlJrEGrjQHlFxR38P4qdgVhCXIq8Q4O4v84Bx0h4Mw Edyr2ODq0fDlrfhgNp53VrxcaXB6jOoE9EXXJS8tNfGHqRmZfvrClhXwO8DBigD87ssc 93YQn4ZTlSHl5UoGLbaoZDtrdOq2fhSoBbFAAZvhEsgs5DUJwCfIklhPJfGasXINZO1b OkkQ== X-Received: by 10.205.115.196 with SMTP id ff4mr2510154bkc.111.1367519126534; Thu, 02 May 2013 11:25:26 -0700 (PDT) Received: from topkick.lan (dslc-082-083-251-181.pools.arcor-ip.net. [82.83.251.181]) by mx.google.com with ESMTPSA id cm9sm1677439bkb.4.2013.05.02.11.25.24 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 02 May 2013 11:25:25 -0700 (PDT) Received: from picnic.unix.mst.uni-hannover.de (phire.mst.uni-hannover.de [130.75.30.51]) by topkick.lan (Postfix) with ESMTPSA id BB1DB605BE; Thu, 2 May 2013 20:24:58 +0200 (CEST) From: Sebastian Hesselbarth To: Sebastian Hesselbarth Subject: [PATCH] irqchip: add support for Marvell Orion SoCs Date: Thu, 2 May 2013 20:25:04 +0200 Message-Id: <1367519104-19677-1-git-send-email-sebastian.hesselbarth@gmail.com> X-Mailer: git-send-email 1.7.2.5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130502_142551_293734_E3877788 X-CRM114-Status: GOOD ( 26.50 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (sebastian.hesselbarth[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Thomas Petazzoni , Andrew Lunn , Russell King , Jason Cooper , Arnd Bergmann , Jean-Francois Moine , devicetree-discuss@lists.ozlabs.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Rob Herring , Gregory Clement , Rob Landley , Grant Likely , Thomas Gleixner , Ezequiel Garcia , linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth 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 This patch adds an irqchip driver for the main interrupt controller found on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation). Corresponding device tree documentation is also added. Signed-off-by: Sebastian Hesselbarth --- Note: This patch triggers a checkpatch warning for WARNING: Avoid CamelCase: Cc: Grant Likely Cc: Rob Herring Cc: Rob Landley Cc: Thomas Gleixner Cc: Russell King Cc: Arnd Bergmann Cc: Jason Cooper Cc: Andrew Lunn Cc: Thomas Petazzoni Cc: Gregory Clement Cc: Ezequiel Garcia Cc: Jean-Francois Moine Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- .../interrupt-controller/marvell,orion-mpic.txt | 22 ++++ drivers/irqchip/Kconfig | 5 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-orion.c | 129 ++++++++++++++++++++ include/linux/irqchip/orion.h | 18 +++ 5 files changed, 175 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt create mode 100644 drivers/irqchip/irq-orion.c create mode 100644 include/linux/irqchip/orion.h diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt new file mode 100644 index 0000000..3b303ec --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt @@ -0,0 +1,22 @@ +Marvell Orion SoC main interrupt controller + +Required properties: +- compatible: shall be "marvell,orion-mpic" +- reg: base address(es) of interrupt registers starting with CAUSE register +- interrupt-controller: identifies the node as an interrupt controller +- #interrupt-cells: number of cells to encode an interrupt source, shall be 1. + +The interrupt sources map to the corresponding bits in the interrupt +registers, i.e. +- 0 maps to bit 0 of first base address, +- 1 maps to bit 1 of first base address, +- 32 maps to bit 0 of second base address, and so on. + +Example: + intc: interrupt-controller { + compatible = "marvell,orion-mpic"; + interrupt-controller; + #interrupt-cells = <1>; + /* Dove has 64 primary interrupts */ + reg = <0x20200 0x10>, <0x20210 0x10>; + }; diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index a350969..8da3559 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -2,6 +2,11 @@ config IRQCHIP def_bool y depends on OF_IRQ +config IRQCHIP_ORION + bool + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + config ARM_GIC bool select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 98e3b87..8adbd43 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o +obj-$(CONFIG_IRQCHIP_ORION) += irq-orion.o obj-$(CONFIG_METAG) += irq-metag-ext.o obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c new file mode 100644 index 0000000..ea02e11 --- /dev/null +++ b/drivers/irqchip/irq-orion.c @@ -0,0 +1,129 @@ +/* + * Marvell Orion SoCs IRQ chip driver. + * + * Sebastian Hesselbarth + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* max number of handled irq register blocks */ +#define ORION_MAX_IRQREG 2 + +#define ORION_IRQ_CAUSE 0x00 +#define ORION_IRQ_MASK 0x04 +#define ORION_IRQ_FIQ_MASK 0x08 +#define ORION_IRQ_ENDP_MASK 0x0c + +static void __iomem *orion_irq_base[ORION_MAX_IRQREG]; +static unsigned int orion_irq_regs; +static struct irq_domain *orion_irq_domain; + +asmlinkage void __exception_irq_entry orion_handle_irq(struct pt_regs *regs) +{ + int n; + for (n = 0; n < orion_irq_regs; n++) { + u32 hwirq_base = n * 32; + u32 stat = readl_relaxed(orion_irq_base[n] + ORION_IRQ_CAUSE) & + readl_relaxed(orion_irq_base[n] + ORION_IRQ_MASK); + while (stat) { + u32 hwirq = ffs(stat) - 1; + u32 irq = irq_find_mapping(orion_irq_domain, + hwirq_base + hwirq); + handle_IRQ(irq, regs); + stat &= ~(1 << hwirq); + } + } +} + +static void orion_irq_mask(struct irq_data *irqd) +{ + unsigned int irq = irqd_to_hwirq(irqd); + unsigned int irq_off = irq % 32; + int reg = irq / 32; + u32 val; + + val = readl(orion_irq_base[reg] + ORION_IRQ_MASK); + writel(val & ~(1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK); +} + +static void orion_irq_unmask(struct irq_data *irqd) +{ + unsigned int irq = irqd_to_hwirq(irqd); + unsigned int irq_off = irq % 32; + int reg = irq / 32; + u32 val; + + val = readl(orion_irq_base[reg] + ORION_IRQ_MASK); + writel(val | (1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK); +} + +static struct irq_chip orion_irq_chip = { + .name = "orion_irq", + .irq_mask = orion_irq_mask, + .irq_unmask = orion_irq_unmask, +}; + +static int orion_irq_map(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw) +{ + irq_set_chip_and_handler(virq, &orion_irq_chip, + handle_level_irq); + set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); + + return 0; +} + +static struct irq_domain_ops orion_irq_ops = { + .map = orion_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int __init orion_of_init(struct device_node *np, + struct device_node *parent) +{ + int n; + + for (n = 0; n < ORION_MAX_IRQREG; n++) { + orion_irq_base[n] = of_iomap(np, n); + + if (!orion_irq_base[n]) + continue; + + /* mask all interrupts */ + writel(0, orion_irq_base[n] + ORION_IRQ_MASK); + orion_irq_regs++; + } + + /* at least one irq reg must be set */ + if (!orion_irq_regs) + panic("%s: unable to map IRQC registers\n", np->full_name); + + orion_irq_domain = irq_domain_add_linear(np, orion_irq_regs * 32, + &orion_irq_ops, NULL); + if (!orion_irq_domain) + panic("%s: unable to create IRQ domain\n", np->full_name); + + set_handle_irq(orion_handle_irq); + + return 0; +} + +static struct of_device_id orion_irq_dt_ids[] __initconst = { + { .compatible = "marvell,orion-mpic", .data = orion_of_init }, + { } +}; + +void __init orion_init_irq(void) +{ + of_irq_init(orion_irq_dt_ids); +} diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h new file mode 100644 index 0000000..04f7bab --- /dev/null +++ b/include/linux/irqchip/orion.h @@ -0,0 +1,18 @@ +/* + * Marvell Orion SoCs IRQ chip driver header. + * + * Sebastian Hesselbarth + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __LINUX_IRQCHIP_ORION_H +#define __LINUX_IRQCHIP_ORION_H + +#include + +extern void orion_init_irq(void); + +#endif