All of lore.kernel.org
 help / color / mirror / Atom feed
From: linux@prisktech.co.nz (Tony Prisk)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/2] irqchip: vt8500: Move irq code to drivers/irqchip
Date: Thu,  3 Jan 2013 16:25:10 +1300	[thread overview]
Message-ID: <1357183510-8476-3-git-send-email-linux@prisktech.co.nz> (raw)
In-Reply-To: <1357183510-8476-1-git-send-email-linux@prisktech.co.nz>

Move mach-vt8500/irq.c to drivers/irqchip/irq-vt8500.c and make
necessary Makefile changes. No code changes required.

Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
---
CC: Thomas Gleixner <tglx@linutronix.de>
 arch/arm/mach-vt8500/Makefile |    2 +-
 arch/arm/mach-vt8500/common.h |    7 +-
 arch/arm/mach-vt8500/irq.c    |  253 -----------------------------------------
 drivers/irqchip/Makefile      |    1 +
 drivers/irqchip/irq-vt8500.c  |  253 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 258 insertions(+), 258 deletions(-)
 delete mode 100644 arch/arm/mach-vt8500/irq.c
 create mode 100644 drivers/irqchip/irq-vt8500.c

diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile
index 92ceb24..4c8a846 100644
--- a/arch/arm/mach-vt8500/Makefile
+++ b/arch/arm/mach-vt8500/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_ARCH_VT8500) += irq.o vt8500.o
+obj-$(CONFIG_ARCH_VT8500) += vt8500.o
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
index 5d37a4f..b198a81 100644
--- a/arch/arm/mach-vt8500/common.h
+++ b/arch/arm/mach-vt8500/common.h
@@ -18,13 +18,12 @@
 
 #include <linux/of.h>
 
-int __init vt8500_irq_init(struct device_node *node,
-				struct device_node *parent);
-
 /* defined in drivers/clk/clk-vt8500.c */
 void __init vtwm_clk_init(void __iomem *pmc_base);
 
-/* defined in irq.c */
+/* defined in drivers/irqchip/irq.c */
+int __init vt8500_irq_init(struct device_node *node,
+				struct device_node *parent);
 asmlinkage void vt8500_handle_irq(struct pt_regs *regs);
 
 /* defined in drivers/clocksource/vt8500_timer.c */
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
deleted file mode 100644
index b9cf5ce..0000000
--- a/arch/arm/mach-vt8500/irq.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/irq.c
- *
- *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * This file is copied and modified from the original irq.c provided by
- * Alexey Charkov. Minor changes have been made for Device Tree Support.
- */
-
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-
-#include <asm/irq.h>
-#include <asm/exception.h>
-
-#define VT8500_ICPC_IRQ		0x20
-#define VT8500_ICPC_FIQ		0x24
-#define VT8500_ICDC		0x40		/* Destination Control 64*u32 */
-#define VT8500_ICIS		0x80		/* Interrupt status, 16*u32 */
-
-/* ICPC */
-#define ICPC_MASK		0x3F
-#define ICPC_ROTATE		BIT(6)
-
-/* IC_DCTR */
-#define ICDC_IRQ		0x00
-#define ICDC_FIQ		0x01
-#define ICDC_DSS0		0x02
-#define ICDC_DSS1		0x03
-#define ICDC_DSS2		0x04
-#define ICDC_DSS3		0x05
-#define ICDC_DSS4		0x06
-#define ICDC_DSS5		0x07
-
-#define VT8500_INT_DISABLE	0
-#define VT8500_INT_ENABLE	BIT(3)
-
-#define VT8500_TRIGGER_HIGH	0
-#define VT8500_TRIGGER_RISING	BIT(5)
-#define VT8500_TRIGGER_FALLING	BIT(6)
-#define VT8500_EDGE		( VT8500_TRIGGER_RISING \
-				| VT8500_TRIGGER_FALLING)
-
-/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */
-#define VT8500_INTC_MAX		2
-
-struct vt8500_irq_data {
-	void __iomem 		*base;		/* IO Memory base address */
-	struct irq_domain	*domain;	/* Domain for this controller */
-};
-
-/* Global variable for accessing io-mem addresses */
-static struct vt8500_irq_data intc[VT8500_INTC_MAX];
-static u32 active_cnt = 0;
-
-static void vt8500_irq_mask(struct irq_data *d)
-{
-	struct vt8500_irq_data *priv = d->domain->host_data;
-	void __iomem *base = priv->base;
-	void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
-	u8 edge, dctr;
-	u32 status;
-
-	edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
-	if (edge) {
-		status = readl(stat_reg);
-
-		status |= (1 << (d->hwirq & 0x1f));
-		writel(status, stat_reg);
-	} else {
-		dctr = readb(base + VT8500_ICDC + d->hwirq);
-		dctr &= ~VT8500_INT_ENABLE;
-		writeb(dctr, base + VT8500_ICDC + d->hwirq);
-	}
-}
-
-static void vt8500_irq_unmask(struct irq_data *d)
-{
-	struct vt8500_irq_data *priv = d->domain->host_data;
-	void __iomem *base = priv->base;
-	u8 dctr;
-
-	dctr = readb(base + VT8500_ICDC + d->hwirq);
-	dctr |= VT8500_INT_ENABLE;
-	writeb(dctr, base + VT8500_ICDC + d->hwirq);
-}
-
-static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct vt8500_irq_data *priv = d->domain->host_data;
-	void __iomem *base = priv->base;
-	u8 dctr;
-
-	dctr = readb(base + VT8500_ICDC + d->hwirq);
-	dctr &= ~VT8500_EDGE;
-
-	switch (flow_type) {
-	case IRQF_TRIGGER_LOW:
-		return -EINVAL;
-	case IRQF_TRIGGER_HIGH:
-		dctr |= VT8500_TRIGGER_HIGH;
-		__irq_set_handler_locked(d->irq, handle_level_irq);
-		break;
-	case IRQF_TRIGGER_FALLING:
-		dctr |= VT8500_TRIGGER_FALLING;
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
-		break;
-	case IRQF_TRIGGER_RISING:
-		dctr |= VT8500_TRIGGER_RISING;
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
-		break;
-	}
-	writeb(dctr, base + VT8500_ICDC + d->hwirq);
-
-	return 0;
-}
-
-static struct irq_chip vt8500_irq_chip = {
-	.name = "vt8500",
-	.irq_ack = vt8500_irq_mask,
-	.irq_mask = vt8500_irq_mask,
-	.irq_unmask = vt8500_irq_unmask,
-	.irq_set_type = vt8500_irq_set_type,
-};
-
-static void __init vt8500_init_irq_hw(void __iomem *base)
-{
-	u32 i;
-
-	/* Enable rotating priority for IRQ */
-	writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
-	writel(0x00, base + VT8500_ICPC_FIQ);
-
-	/* Disable all interrupts and route them to IRQ */
-	for (i = 0; i < 64; i++)
-		writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
-}
-
-static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
-							irq_hw_number_t hw)
-{
-	irq_set_chip_and_handler(virq, &vt8500_irq_chip, handle_level_irq);
-	set_irq_flags(virq, IRQF_VALID);
-
-	return 0;
-}
-
-static struct irq_domain_ops vt8500_irq_domain_ops = {
-	.map = vt8500_irq_map,
-	.xlate = irq_domain_xlate_onecell,
-};
-
-asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
-{
-	u32 stat, i;
-	int irqnr, virq;
-	void __iomem *base;
-
-	/* Loop through each active controller */
-	for (i=0; i<active_cnt; i++) {
-		base = intc[i].base;
-		irqnr = readl_relaxed(base) & 0x3F;
-		/*
-		  Highest Priority register default = 63, so check that this
-		  is a real interrupt by checking the status register
-		*/
-		if (irqnr == 63) {
-			stat = readl_relaxed(base + VT8500_ICIS + 4);
-			if (!(stat & BIT(31)))
-				continue;
-		}
-
-		virq = irq_find_mapping(intc[i].domain, irqnr);
-		handle_IRQ(virq, regs);
-	}
-}
-
-int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
-{
-	int irq, i;
-	struct device_node *np = node;
-
-	if (active_cnt == VT8500_INTC_MAX) {
-		pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
-								__func__);
-		goto out;
-	}
-
-	intc[active_cnt].base = of_iomap(np, 0);
-	intc[active_cnt].domain = irq_domain_add_linear(node, 64,
-			&vt8500_irq_domain_ops,	&intc[active_cnt]);
-
-	if (!intc[active_cnt].base) {
-		pr_err("%s: Unable to map IO memory\n", __func__);
-		goto out;
-	}
-
-	if (!intc[active_cnt].domain) {
-		pr_err("%s: Unable to add irq domain!\n", __func__);
-		goto out;
-	}
-
-	vt8500_init_irq_hw(intc[active_cnt].base);
-
-	pr_info("vt8500-irq: Added interrupt controller\n");
-
-	active_cnt++;
-
-	/* check if this is a slaved controller */
-	if (of_irq_count(np) != 0) {
-		/* check that we have the correct number of interrupts */
-		if (of_irq_count(np) != 8) {
-			pr_err("%s: Incorrect IRQ map for slaved controller\n",
-					__func__);
-			return -EINVAL;
-		}
-
-		for (i = 0; i < 8; i++) {
-			irq = irq_of_parse_and_map(np, i);
-			enable_irq(irq);
-		}
-
-		pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
-	}
-out:
-	return 0;
-}
-
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bf4609a..4b0da48 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi.o
+obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
diff --git a/drivers/irqchip/irq-vt8500.c b/drivers/irqchip/irq-vt8500.c
new file mode 100644
index 0000000..b9cf5ce
--- /dev/null
+++ b/drivers/irqchip/irq-vt8500.c
@@ -0,0 +1,253 @@
+/*
+ *  arch/arm/mach-vt8500/irq.c
+ *
+ *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file is copied and modified from the original irq.c provided by
+ * Alexey Charkov. Minor changes have been made for Device Tree Support.
+ */
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/irq.h>
+#include <asm/exception.h>
+
+#define VT8500_ICPC_IRQ		0x20
+#define VT8500_ICPC_FIQ		0x24
+#define VT8500_ICDC		0x40		/* Destination Control 64*u32 */
+#define VT8500_ICIS		0x80		/* Interrupt status, 16*u32 */
+
+/* ICPC */
+#define ICPC_MASK		0x3F
+#define ICPC_ROTATE		BIT(6)
+
+/* IC_DCTR */
+#define ICDC_IRQ		0x00
+#define ICDC_FIQ		0x01
+#define ICDC_DSS0		0x02
+#define ICDC_DSS1		0x03
+#define ICDC_DSS2		0x04
+#define ICDC_DSS3		0x05
+#define ICDC_DSS4		0x06
+#define ICDC_DSS5		0x07
+
+#define VT8500_INT_DISABLE	0
+#define VT8500_INT_ENABLE	BIT(3)
+
+#define VT8500_TRIGGER_HIGH	0
+#define VT8500_TRIGGER_RISING	BIT(5)
+#define VT8500_TRIGGER_FALLING	BIT(6)
+#define VT8500_EDGE		( VT8500_TRIGGER_RISING \
+				| VT8500_TRIGGER_FALLING)
+
+/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */
+#define VT8500_INTC_MAX		2
+
+struct vt8500_irq_data {
+	void __iomem 		*base;		/* IO Memory base address */
+	struct irq_domain	*domain;	/* Domain for this controller */
+};
+
+/* Global variable for accessing io-mem addresses */
+static struct vt8500_irq_data intc[VT8500_INTC_MAX];
+static u32 active_cnt = 0;
+
+static void vt8500_irq_mask(struct irq_data *d)
+{
+	struct vt8500_irq_data *priv = d->domain->host_data;
+	void __iomem *base = priv->base;
+	void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
+	u8 edge, dctr;
+	u32 status;
+
+	edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
+	if (edge) {
+		status = readl(stat_reg);
+
+		status |= (1 << (d->hwirq & 0x1f));
+		writel(status, stat_reg);
+	} else {
+		dctr = readb(base + VT8500_ICDC + d->hwirq);
+		dctr &= ~VT8500_INT_ENABLE;
+		writeb(dctr, base + VT8500_ICDC + d->hwirq);
+	}
+}
+
+static void vt8500_irq_unmask(struct irq_data *d)
+{
+	struct vt8500_irq_data *priv = d->domain->host_data;
+	void __iomem *base = priv->base;
+	u8 dctr;
+
+	dctr = readb(base + VT8500_ICDC + d->hwirq);
+	dctr |= VT8500_INT_ENABLE;
+	writeb(dctr, base + VT8500_ICDC + d->hwirq);
+}
+
+static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct vt8500_irq_data *priv = d->domain->host_data;
+	void __iomem *base = priv->base;
+	u8 dctr;
+
+	dctr = readb(base + VT8500_ICDC + d->hwirq);
+	dctr &= ~VT8500_EDGE;
+
+	switch (flow_type) {
+	case IRQF_TRIGGER_LOW:
+		return -EINVAL;
+	case IRQF_TRIGGER_HIGH:
+		dctr |= VT8500_TRIGGER_HIGH;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+		break;
+	case IRQF_TRIGGER_FALLING:
+		dctr |= VT8500_TRIGGER_FALLING;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+		break;
+	case IRQF_TRIGGER_RISING:
+		dctr |= VT8500_TRIGGER_RISING;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+		break;
+	}
+	writeb(dctr, base + VT8500_ICDC + d->hwirq);
+
+	return 0;
+}
+
+static struct irq_chip vt8500_irq_chip = {
+	.name = "vt8500",
+	.irq_ack = vt8500_irq_mask,
+	.irq_mask = vt8500_irq_mask,
+	.irq_unmask = vt8500_irq_unmask,
+	.irq_set_type = vt8500_irq_set_type,
+};
+
+static void __init vt8500_init_irq_hw(void __iomem *base)
+{
+	u32 i;
+
+	/* Enable rotating priority for IRQ */
+	writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
+	writel(0x00, base + VT8500_ICPC_FIQ);
+
+	/* Disable all interrupts and route them to IRQ */
+	for (i = 0; i < 64; i++)
+		writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
+}
+
+static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
+							irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &vt8500_irq_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops vt8500_irq_domain_ops = {
+	.map = vt8500_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
+{
+	u32 stat, i;
+	int irqnr, virq;
+	void __iomem *base;
+
+	/* Loop through each active controller */
+	for (i=0; i<active_cnt; i++) {
+		base = intc[i].base;
+		irqnr = readl_relaxed(base) & 0x3F;
+		/*
+		  Highest Priority register default = 63, so check that this
+		  is a real interrupt by checking the status register
+		*/
+		if (irqnr == 63) {
+			stat = readl_relaxed(base + VT8500_ICIS + 4);
+			if (!(stat & BIT(31)))
+				continue;
+		}
+
+		virq = irq_find_mapping(intc[i].domain, irqnr);
+		handle_IRQ(virq, regs);
+	}
+}
+
+int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
+{
+	int irq, i;
+	struct device_node *np = node;
+
+	if (active_cnt == VT8500_INTC_MAX) {
+		pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
+								__func__);
+		goto out;
+	}
+
+	intc[active_cnt].base = of_iomap(np, 0);
+	intc[active_cnt].domain = irq_domain_add_linear(node, 64,
+			&vt8500_irq_domain_ops,	&intc[active_cnt]);
+
+	if (!intc[active_cnt].base) {
+		pr_err("%s: Unable to map IO memory\n", __func__);
+		goto out;
+	}
+
+	if (!intc[active_cnt].domain) {
+		pr_err("%s: Unable to add irq domain!\n", __func__);
+		goto out;
+	}
+
+	vt8500_init_irq_hw(intc[active_cnt].base);
+
+	pr_info("vt8500-irq: Added interrupt controller\n");
+
+	active_cnt++;
+
+	/* check if this is a slaved controller */
+	if (of_irq_count(np) != 0) {
+		/* check that we have the correct number of interrupts */
+		if (of_irq_count(np) != 8) {
+			pr_err("%s: Incorrect IRQ map for slaved controller\n",
+					__func__);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < 8; i++) {
+			irq = irq_of_parse_and_map(np, i);
+			enable_irq(irq);
+		}
+
+		pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
+	}
+out:
+	return 0;
+}
+
-- 
1.7.9.5

WARNING: multiple messages have this Message-ID (diff)
From: Tony Prisk <linux@prisktech.co.nz>
To: Arnd Bergmann <arnd@arndb.de>, Olof Johansson <olof@lixom.net>
Cc: linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	vt8500-wm8505-linux-kernel@googlegroups.com,
	Tony Prisk <linux@prisktech.co.nz>,
	Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH 2/2] irqchip: vt8500: Move irq code to drivers/irqchip
Date: Thu,  3 Jan 2013 16:25:10 +1300	[thread overview]
Message-ID: <1357183510-8476-3-git-send-email-linux@prisktech.co.nz> (raw)
In-Reply-To: <1357183510-8476-1-git-send-email-linux@prisktech.co.nz>

Move mach-vt8500/irq.c to drivers/irqchip/irq-vt8500.c and make
necessary Makefile changes. No code changes required.

Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
---
CC: Thomas Gleixner <tglx@linutronix.de>
 arch/arm/mach-vt8500/Makefile |    2 +-
 arch/arm/mach-vt8500/common.h |    7 +-
 arch/arm/mach-vt8500/irq.c    |  253 -----------------------------------------
 drivers/irqchip/Makefile      |    1 +
 drivers/irqchip/irq-vt8500.c  |  253 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 258 insertions(+), 258 deletions(-)
 delete mode 100644 arch/arm/mach-vt8500/irq.c
 create mode 100644 drivers/irqchip/irq-vt8500.c

diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile
index 92ceb24..4c8a846 100644
--- a/arch/arm/mach-vt8500/Makefile
+++ b/arch/arm/mach-vt8500/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_ARCH_VT8500) += irq.o vt8500.o
+obj-$(CONFIG_ARCH_VT8500) += vt8500.o
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
index 5d37a4f..b198a81 100644
--- a/arch/arm/mach-vt8500/common.h
+++ b/arch/arm/mach-vt8500/common.h
@@ -18,13 +18,12 @@
 
 #include <linux/of.h>
 
-int __init vt8500_irq_init(struct device_node *node,
-				struct device_node *parent);
-
 /* defined in drivers/clk/clk-vt8500.c */
 void __init vtwm_clk_init(void __iomem *pmc_base);
 
-/* defined in irq.c */
+/* defined in drivers/irqchip/irq.c */
+int __init vt8500_irq_init(struct device_node *node,
+				struct device_node *parent);
 asmlinkage void vt8500_handle_irq(struct pt_regs *regs);
 
 /* defined in drivers/clocksource/vt8500_timer.c */
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
deleted file mode 100644
index b9cf5ce..0000000
--- a/arch/arm/mach-vt8500/irq.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/irq.c
- *
- *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * This file is copied and modified from the original irq.c provided by
- * Alexey Charkov. Minor changes have been made for Device Tree Support.
- */
-
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-
-#include <asm/irq.h>
-#include <asm/exception.h>
-
-#define VT8500_ICPC_IRQ		0x20
-#define VT8500_ICPC_FIQ		0x24
-#define VT8500_ICDC		0x40		/* Destination Control 64*u32 */
-#define VT8500_ICIS		0x80		/* Interrupt status, 16*u32 */
-
-/* ICPC */
-#define ICPC_MASK		0x3F
-#define ICPC_ROTATE		BIT(6)
-
-/* IC_DCTR */
-#define ICDC_IRQ		0x00
-#define ICDC_FIQ		0x01
-#define ICDC_DSS0		0x02
-#define ICDC_DSS1		0x03
-#define ICDC_DSS2		0x04
-#define ICDC_DSS3		0x05
-#define ICDC_DSS4		0x06
-#define ICDC_DSS5		0x07
-
-#define VT8500_INT_DISABLE	0
-#define VT8500_INT_ENABLE	BIT(3)
-
-#define VT8500_TRIGGER_HIGH	0
-#define VT8500_TRIGGER_RISING	BIT(5)
-#define VT8500_TRIGGER_FALLING	BIT(6)
-#define VT8500_EDGE		( VT8500_TRIGGER_RISING \
-				| VT8500_TRIGGER_FALLING)
-
-/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */
-#define VT8500_INTC_MAX		2
-
-struct vt8500_irq_data {
-	void __iomem 		*base;		/* IO Memory base address */
-	struct irq_domain	*domain;	/* Domain for this controller */
-};
-
-/* Global variable for accessing io-mem addresses */
-static struct vt8500_irq_data intc[VT8500_INTC_MAX];
-static u32 active_cnt = 0;
-
-static void vt8500_irq_mask(struct irq_data *d)
-{
-	struct vt8500_irq_data *priv = d->domain->host_data;
-	void __iomem *base = priv->base;
-	void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
-	u8 edge, dctr;
-	u32 status;
-
-	edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
-	if (edge) {
-		status = readl(stat_reg);
-
-		status |= (1 << (d->hwirq & 0x1f));
-		writel(status, stat_reg);
-	} else {
-		dctr = readb(base + VT8500_ICDC + d->hwirq);
-		dctr &= ~VT8500_INT_ENABLE;
-		writeb(dctr, base + VT8500_ICDC + d->hwirq);
-	}
-}
-
-static void vt8500_irq_unmask(struct irq_data *d)
-{
-	struct vt8500_irq_data *priv = d->domain->host_data;
-	void __iomem *base = priv->base;
-	u8 dctr;
-
-	dctr = readb(base + VT8500_ICDC + d->hwirq);
-	dctr |= VT8500_INT_ENABLE;
-	writeb(dctr, base + VT8500_ICDC + d->hwirq);
-}
-
-static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct vt8500_irq_data *priv = d->domain->host_data;
-	void __iomem *base = priv->base;
-	u8 dctr;
-
-	dctr = readb(base + VT8500_ICDC + d->hwirq);
-	dctr &= ~VT8500_EDGE;
-
-	switch (flow_type) {
-	case IRQF_TRIGGER_LOW:
-		return -EINVAL;
-	case IRQF_TRIGGER_HIGH:
-		dctr |= VT8500_TRIGGER_HIGH;
-		__irq_set_handler_locked(d->irq, handle_level_irq);
-		break;
-	case IRQF_TRIGGER_FALLING:
-		dctr |= VT8500_TRIGGER_FALLING;
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
-		break;
-	case IRQF_TRIGGER_RISING:
-		dctr |= VT8500_TRIGGER_RISING;
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
-		break;
-	}
-	writeb(dctr, base + VT8500_ICDC + d->hwirq);
-
-	return 0;
-}
-
-static struct irq_chip vt8500_irq_chip = {
-	.name = "vt8500",
-	.irq_ack = vt8500_irq_mask,
-	.irq_mask = vt8500_irq_mask,
-	.irq_unmask = vt8500_irq_unmask,
-	.irq_set_type = vt8500_irq_set_type,
-};
-
-static void __init vt8500_init_irq_hw(void __iomem *base)
-{
-	u32 i;
-
-	/* Enable rotating priority for IRQ */
-	writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
-	writel(0x00, base + VT8500_ICPC_FIQ);
-
-	/* Disable all interrupts and route them to IRQ */
-	for (i = 0; i < 64; i++)
-		writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
-}
-
-static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
-							irq_hw_number_t hw)
-{
-	irq_set_chip_and_handler(virq, &vt8500_irq_chip, handle_level_irq);
-	set_irq_flags(virq, IRQF_VALID);
-
-	return 0;
-}
-
-static struct irq_domain_ops vt8500_irq_domain_ops = {
-	.map = vt8500_irq_map,
-	.xlate = irq_domain_xlate_onecell,
-};
-
-asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
-{
-	u32 stat, i;
-	int irqnr, virq;
-	void __iomem *base;
-
-	/* Loop through each active controller */
-	for (i=0; i<active_cnt; i++) {
-		base = intc[i].base;
-		irqnr = readl_relaxed(base) & 0x3F;
-		/*
-		  Highest Priority register default = 63, so check that this
-		  is a real interrupt by checking the status register
-		*/
-		if (irqnr == 63) {
-			stat = readl_relaxed(base + VT8500_ICIS + 4);
-			if (!(stat & BIT(31)))
-				continue;
-		}
-
-		virq = irq_find_mapping(intc[i].domain, irqnr);
-		handle_IRQ(virq, regs);
-	}
-}
-
-int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
-{
-	int irq, i;
-	struct device_node *np = node;
-
-	if (active_cnt == VT8500_INTC_MAX) {
-		pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
-								__func__);
-		goto out;
-	}
-
-	intc[active_cnt].base = of_iomap(np, 0);
-	intc[active_cnt].domain = irq_domain_add_linear(node, 64,
-			&vt8500_irq_domain_ops,	&intc[active_cnt]);
-
-	if (!intc[active_cnt].base) {
-		pr_err("%s: Unable to map IO memory\n", __func__);
-		goto out;
-	}
-
-	if (!intc[active_cnt].domain) {
-		pr_err("%s: Unable to add irq domain!\n", __func__);
-		goto out;
-	}
-
-	vt8500_init_irq_hw(intc[active_cnt].base);
-
-	pr_info("vt8500-irq: Added interrupt controller\n");
-
-	active_cnt++;
-
-	/* check if this is a slaved controller */
-	if (of_irq_count(np) != 0) {
-		/* check that we have the correct number of interrupts */
-		if (of_irq_count(np) != 8) {
-			pr_err("%s: Incorrect IRQ map for slaved controller\n",
-					__func__);
-			return -EINVAL;
-		}
-
-		for (i = 0; i < 8; i++) {
-			irq = irq_of_parse_and_map(np, i);
-			enable_irq(irq);
-		}
-
-		pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
-	}
-out:
-	return 0;
-}
-
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bf4609a..4b0da48 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi.o
+obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
diff --git a/drivers/irqchip/irq-vt8500.c b/drivers/irqchip/irq-vt8500.c
new file mode 100644
index 0000000..b9cf5ce
--- /dev/null
+++ b/drivers/irqchip/irq-vt8500.c
@@ -0,0 +1,253 @@
+/*
+ *  arch/arm/mach-vt8500/irq.c
+ *
+ *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file is copied and modified from the original irq.c provided by
+ * Alexey Charkov. Minor changes have been made for Device Tree Support.
+ */
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/irq.h>
+#include <asm/exception.h>
+
+#define VT8500_ICPC_IRQ		0x20
+#define VT8500_ICPC_FIQ		0x24
+#define VT8500_ICDC		0x40		/* Destination Control 64*u32 */
+#define VT8500_ICIS		0x80		/* Interrupt status, 16*u32 */
+
+/* ICPC */
+#define ICPC_MASK		0x3F
+#define ICPC_ROTATE		BIT(6)
+
+/* IC_DCTR */
+#define ICDC_IRQ		0x00
+#define ICDC_FIQ		0x01
+#define ICDC_DSS0		0x02
+#define ICDC_DSS1		0x03
+#define ICDC_DSS2		0x04
+#define ICDC_DSS3		0x05
+#define ICDC_DSS4		0x06
+#define ICDC_DSS5		0x07
+
+#define VT8500_INT_DISABLE	0
+#define VT8500_INT_ENABLE	BIT(3)
+
+#define VT8500_TRIGGER_HIGH	0
+#define VT8500_TRIGGER_RISING	BIT(5)
+#define VT8500_TRIGGER_FALLING	BIT(6)
+#define VT8500_EDGE		( VT8500_TRIGGER_RISING \
+				| VT8500_TRIGGER_FALLING)
+
+/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */
+#define VT8500_INTC_MAX		2
+
+struct vt8500_irq_data {
+	void __iomem 		*base;		/* IO Memory base address */
+	struct irq_domain	*domain;	/* Domain for this controller */
+};
+
+/* Global variable for accessing io-mem addresses */
+static struct vt8500_irq_data intc[VT8500_INTC_MAX];
+static u32 active_cnt = 0;
+
+static void vt8500_irq_mask(struct irq_data *d)
+{
+	struct vt8500_irq_data *priv = d->domain->host_data;
+	void __iomem *base = priv->base;
+	void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
+	u8 edge, dctr;
+	u32 status;
+
+	edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
+	if (edge) {
+		status = readl(stat_reg);
+
+		status |= (1 << (d->hwirq & 0x1f));
+		writel(status, stat_reg);
+	} else {
+		dctr = readb(base + VT8500_ICDC + d->hwirq);
+		dctr &= ~VT8500_INT_ENABLE;
+		writeb(dctr, base + VT8500_ICDC + d->hwirq);
+	}
+}
+
+static void vt8500_irq_unmask(struct irq_data *d)
+{
+	struct vt8500_irq_data *priv = d->domain->host_data;
+	void __iomem *base = priv->base;
+	u8 dctr;
+
+	dctr = readb(base + VT8500_ICDC + d->hwirq);
+	dctr |= VT8500_INT_ENABLE;
+	writeb(dctr, base + VT8500_ICDC + d->hwirq);
+}
+
+static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct vt8500_irq_data *priv = d->domain->host_data;
+	void __iomem *base = priv->base;
+	u8 dctr;
+
+	dctr = readb(base + VT8500_ICDC + d->hwirq);
+	dctr &= ~VT8500_EDGE;
+
+	switch (flow_type) {
+	case IRQF_TRIGGER_LOW:
+		return -EINVAL;
+	case IRQF_TRIGGER_HIGH:
+		dctr |= VT8500_TRIGGER_HIGH;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+		break;
+	case IRQF_TRIGGER_FALLING:
+		dctr |= VT8500_TRIGGER_FALLING;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+		break;
+	case IRQF_TRIGGER_RISING:
+		dctr |= VT8500_TRIGGER_RISING;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+		break;
+	}
+	writeb(dctr, base + VT8500_ICDC + d->hwirq);
+
+	return 0;
+}
+
+static struct irq_chip vt8500_irq_chip = {
+	.name = "vt8500",
+	.irq_ack = vt8500_irq_mask,
+	.irq_mask = vt8500_irq_mask,
+	.irq_unmask = vt8500_irq_unmask,
+	.irq_set_type = vt8500_irq_set_type,
+};
+
+static void __init vt8500_init_irq_hw(void __iomem *base)
+{
+	u32 i;
+
+	/* Enable rotating priority for IRQ */
+	writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
+	writel(0x00, base + VT8500_ICPC_FIQ);
+
+	/* Disable all interrupts and route them to IRQ */
+	for (i = 0; i < 64; i++)
+		writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
+}
+
+static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
+							irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &vt8500_irq_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops vt8500_irq_domain_ops = {
+	.map = vt8500_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
+{
+	u32 stat, i;
+	int irqnr, virq;
+	void __iomem *base;
+
+	/* Loop through each active controller */
+	for (i=0; i<active_cnt; i++) {
+		base = intc[i].base;
+		irqnr = readl_relaxed(base) & 0x3F;
+		/*
+		  Highest Priority register default = 63, so check that this
+		  is a real interrupt by checking the status register
+		*/
+		if (irqnr == 63) {
+			stat = readl_relaxed(base + VT8500_ICIS + 4);
+			if (!(stat & BIT(31)))
+				continue;
+		}
+
+		virq = irq_find_mapping(intc[i].domain, irqnr);
+		handle_IRQ(virq, regs);
+	}
+}
+
+int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
+{
+	int irq, i;
+	struct device_node *np = node;
+
+	if (active_cnt == VT8500_INTC_MAX) {
+		pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
+								__func__);
+		goto out;
+	}
+
+	intc[active_cnt].base = of_iomap(np, 0);
+	intc[active_cnt].domain = irq_domain_add_linear(node, 64,
+			&vt8500_irq_domain_ops,	&intc[active_cnt]);
+
+	if (!intc[active_cnt].base) {
+		pr_err("%s: Unable to map IO memory\n", __func__);
+		goto out;
+	}
+
+	if (!intc[active_cnt].domain) {
+		pr_err("%s: Unable to add irq domain!\n", __func__);
+		goto out;
+	}
+
+	vt8500_init_irq_hw(intc[active_cnt].base);
+
+	pr_info("vt8500-irq: Added interrupt controller\n");
+
+	active_cnt++;
+
+	/* check if this is a slaved controller */
+	if (of_irq_count(np) != 0) {
+		/* check that we have the correct number of interrupts */
+		if (of_irq_count(np) != 8) {
+			pr_err("%s: Incorrect IRQ map for slaved controller\n",
+					__func__);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < 8; i++) {
+			irq = irq_of_parse_and_map(np, i);
+			enable_irq(irq);
+		}
+
+		pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
+	}
+out:
+	return 0;
+}
+
-- 
1.7.9.5


  parent reply	other threads:[~2013-01-03  3:25 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-03  3:25 [PATCH 0/2] Move some mach-vt8500 functions to new directories Tony Prisk
2013-01-03  3:25 ` Tony Prisk
2013-01-03  3:25 ` [PATCH 1/2] timer: vt8500: Move system timer to clocksource Tony Prisk
2013-01-03  3:25   ` Tony Prisk
2013-01-03  7:35   ` Dmitry Torokhov
2013-01-03  7:35     ` Dmitry Torokhov
2013-01-03  7:45     ` Joe Perches
2013-01-03  7:45       ` Joe Perches
2013-01-03  8:07       ` Arnd Bergmann
2013-01-03  8:07         ` Arnd Bergmann
2013-01-03 17:29   ` Stephen Warren
2013-01-03 17:29     ` Stephen Warren
2013-01-03  3:25 ` Tony Prisk [this message]
2013-01-03  3:25   ` [PATCH 2/2] irqchip: vt8500: Move irq code to drivers/irqchip Tony Prisk
2013-01-03  4:38   ` Rob Herring
2013-01-03  4:38     ` Rob Herring
2013-01-03  4:53     ` Tony Prisk
2013-01-03  4:53       ` Tony Prisk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1357183510-8476-3-git-send-email-linux@prisktech.co.nz \
    --to=linux@prisktech.co.nz \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.