All of lore.kernel.org
 help / color / mirror / Atom feed
From: Haojian Zhuang <haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
To: haojian.zhuang-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org,
	grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org,
	alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	devicetree-discuss@list
Cc: Haojian Zhuang <haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
Subject: [PATCH v2 1/7] ARM: mmp: parse irq from DT
Date: Thu, 28 Jul 2011 14:41:27 +0800	[thread overview]
Message-ID: <1311835293-18125-2-git-send-email-haojian.zhuang@marvell.com> (raw)
In-Reply-To: <1311835293-18125-1-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>

Parse irq sepcifier from DT and translate it to Linux irq number.
Remove the definition of NR_IRQS in irqs.h. Since sparse irq is
enabled, nr_irqs will be calculated automatically.

Signed-off-by: Haojian Zhuang <haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
---
 .../devicetree/bindings/arm/marvell/intc.txt       |  114 ++++++++++
 arch/arm/Kconfig                                   |    1 +
 arch/arm/mach-mmp/Makefile                         |    2 +
 arch/arm/mach-mmp/common.h                         |    1 +
 arch/arm/mach-mmp/include/mach/irqs.h              |    2 +-
 arch/arm/mach-mmp/intc.c                           |  224 ++++++++++++++++++++
 6 files changed, 343 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/intc.txt
 create mode 100644 arch/arm/mach-mmp/intc.c

diff --git a/Documentation/devicetree/bindings/arm/marvell/intc.txt b/Documentation/devicetree/bindings/arm/marvell/intc.txt
new file mode 100644
index 0000000..80cef58
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/marvell/intc.txt
@@ -0,0 +1,114 @@
+* Interrupt Controller Binding for ARCH-MMP
+
+This binding specifies what properties must be available in device tree representation of an ARCH-MMP compliant interrupt controller.
+
+Required properties:
+
+	- compatible: Specifies the compatibility list of the interrupt
+	  controller. The type shall be <string> and the value shall be
+	  "mrvl,pxa168-intc" or "mrvl,mmp2-mux-intc".
+	  "mrvl,pxa168-intc" is the base interrupt controller. It must be
+	  included. It's compatible for pxa910, mmp2. "mrvl,mmp2-mux-intc"
+	  is the expanded interrupt controller, and it's optional.
+
+	- reg: Specified the base physical address(s) and size(s) of the
+	  interrupt controller's addressable register space. The type
+	  should be <prop-encoded-array>.
+
+	- interrupt-controller: The presence of this property identifies
+	  the node as interrupt controller. No property value should be
+	  defined.
+
+	- #interrupt-cells: Specifies the number of cells needed to encode
+	  an interrupt source. The type should be <u32> and the value should
+	  be 1.
+
+	- mrvl,intc-numbers: Specifies the number of interrupts is supported
+	  in this interrupt controller. The type should be <u32>.
+
+Optional properties:
+
+	- mrvl,intc-priority: Specifies the which path the interrupt is routed
+	  and the priority of this interrupt. The property is used in
+	  pxa168-intc. The value should be <u32>.
+
+	- mrvl,status-offset: Specifies the offset of status register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mask-offset: Specifies the offset of mask register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mfp-edge: Specifies the address of mfp edge detection register.
+	  The property is used while acking specified interrupt. The type
+	  should be <prop-encoded-array>. The first cell indicates the address
+	  of mfp edge detection register. The second cell indicates the
+	  index of interrupt in current interrupt controller that should
+	  handle mfp edge detection.
+
+* Examples
+
+Example 1:
+
+	/*
+	 * base INTC
+	 */
+	mmp_intc: interrupt-controller@d4282000 {
+		/* Compatible with pxa168-intc. */
+		compatible = "mrvl,pxa168-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		/* Offset address of 0xd4282000 and size of 0x400. */
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+
+		/* 64 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <64>;
+
+		/* priority bits in configuration register */
+		mrvl,intc-priority = <0x20>;
+	};
+
+Example 2:
+
+	/*
+	 * mux INTC that is internal wired to base INTC
+	 */
+	mux_intc4: interrupt-controller@d4282150 {
+		compatible = "mrvl,mmp2-mux-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&mmp_intc>;
+
+		/* interrupt source '4' of parent INTC. */
+		interrupts = <4>;
+
+		/* 2 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <2>;
+
+		/* Status offset address of 0x150. */
+		mrvl,status-offset = <0x150>;
+
+		/* Mask offset address of 0x168. */
+		mrvl,mask-offset = <0x168>;
+
+		/* mfp register of 0xd401e2c4 & interrupt index of 1 */
+		mrvl,mfp-edge = <0xd401e2c4 1>;
+	};
+
+Example 3:
+	/*
+	 * An interrupt generating device that is wired to an INTC.
+	 */
+	uart0: uart@d4030000 {
+		/* parent's '#interrupt-cells' property. */
+		interrupts = <27>;
+
+		/* The INTC that this device is wired to. */
+		interrupt-parent = <&mmp_intc>;
+	};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 17507b8..f18eb14 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -542,6 +542,7 @@ config ARCH_MMP
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select PLAT_PXA
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 5c68382..e7862ea 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -4,6 +4,8 @@
 
 obj-y				+= common.o clock.o devices.o time.o
 
+obj-$(CONFIG_OF_IRQ)		+= intc.o
+
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
 obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index ec8d65d..1c563c2 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
 extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index a09d328..65ec176 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -224,6 +224,6 @@
 
 #define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS				(IRQ_BOARD_START)
+#define NR_IRQS				0
 
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-mmp/intc.c b/arch/arm/mach-mmp/intc.c
new file mode 100644
index 0000000..2e44057
--- /dev/null
+++ b/arch/arm/mach-mmp/intc.c
@@ -0,0 +1,224 @@
+/*
+ *  linux/arch/arm/mach-mmp/intc.c
+ *
+ *  Generic IRQ handling
+ *
+ *  Author:	Haojian Zhuang <haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
+ *  Copyright:	Marvell International Ltd. 2011
+ *
+ *  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.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+struct mmp_intc_info {
+	unsigned int		en_mask;
+	void __iomem		*virt_base;
+	void __iomem		*status;
+	void __iomem		*mfp_edge;
+	unsigned int		mfp_edge_index; /* index in irq domain */
+};
+
+static void mux_irq_ack(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct;
+	struct mmp_intc_info *info;
+	unsigned int data, irq_offs;
+
+	ct = gc->chip_types;
+	info = (struct mmp_intc_info *)ct->regs.ack;
+	irq_offs = d->irq - gc->irq_base;
+	/* clear MFP edge-detect */
+	if (info->mfp_edge && (info->mfp_edge_index == irq_offs)) {
+		data = __raw_readl(info->mfp_edge);
+		__raw_writel(data | (1 << 6), info->mfp_edge);
+		__raw_writel(data, info->mfp_edge);
+	}
+}
+
+static void mmp_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip_generic *gc = irq_get_handler_data(irq);
+	struct irq_chip_type *ct;
+	struct mmp_intc_info *info;
+	unsigned long status, n;
+
+	ct = gc->chip_types;
+	info = (struct mmp_intc_info *)ct->regs.ack;
+	while (1) {
+		status = __raw_readl(info->status) & ~gc->mask_cache;
+		if (status == 0)
+			break;
+		n = find_first_bit(&status, BITS_PER_LONG);
+		while (n < BITS_PER_LONG) {
+			generic_handle_irq(gc->irq_base + n);
+			n = find_next_bit(&status, BITS_PER_LONG, n + 1);
+		}
+	}
+}
+
+static void mux_init_intc(struct mmp_intc_info *mmp_info)
+{
+	struct device_node *np;
+	struct mmp_intc_info *mux_info;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	const __be32 *edge;
+	unsigned int addr = 0, offs = 0;
+	unsigned int status, mask, irq_base, nr, data;
+	int cascade;
+
+	for_each_compatible_node(np, NULL, "mrvl,mmp2-mux-intc") {
+		if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+			continue;
+		if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+			pr_warn("intc-numbers property is missed\n");
+			continue;
+		}
+		if (of_property_read_u32(np, "mrvl,status-offset", &status)
+			< 0) {
+			pr_warn("intc-status property is missed\n");
+			continue;
+		}
+		if (of_property_read_u32(np, "mrvl,mask-offset", &mask) < 0) {
+			pr_warn("intc-mask property is missed\n");
+			continue;
+		}
+
+		mux_info = kzalloc(sizeof(*mux_info), GFP_KERNEL);
+		if (mux_info == NULL)
+			goto out;
+		status += (unsigned int)mmp_info->virt_base;
+		mux_info->status = (void __iomem *)status;
+
+		edge = of_get_property(np, "mrvl,mfp-edge", NULL);
+		if (edge) {
+			addr = be32_to_cpu(*edge) & PAGE_MASK;
+			offs = be32_to_cpu(*edge) - addr;
+			mux_info->mfp_edge = ioremap(addr, PAGE_SIZE) + offs;
+			mux_info->mfp_edge_index = be32_to_cpu(*++edge);
+			/* clear mfp edge detection for initialization */
+			data = __raw_readl(mux_info->mfp_edge);
+			__raw_writel(data | (1 << 6), mux_info->mfp_edge);
+			__raw_writel(data, mux_info->mfp_edge);
+		}
+
+		/* allocate new irq */
+		cascade = irq_of_parse_and_map(np, 0);
+		irq_base = irq_alloc_descs(-1, 0, nr, 0);
+		irq_domain_add_simple(np, irq_base);
+
+		gc = irq_alloc_generic_chip("mux-intc", 1, irq_base,
+					mmp_info->virt_base, handle_level_irq);
+		ct = gc->chip_types;
+		ct->regs.ack = (unsigned int)mux_info;
+		ct->regs.mask = mask;
+		ct->chip.irq_ack = mux_irq_ack;
+		ct->chip.irq_mask = irq_gc_mask_set_bit;
+		ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+		irq_setup_generic_chip(gc, IRQ_MSK(nr), IRQ_GC_INIT_MASK_CACHE,
+					IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+
+		irq_set_handler_data(cascade, gc);
+		irq_set_chained_handler(cascade, mmp_irq_demux_handler);
+	}
+out:
+	return;
+}
+
+static void mmp_irq_unmask(struct irq_data *d)
+{
+	struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+	/* ICU_INT_CONF */
+	__raw_writel(info->en_mask, info->virt_base + (d->irq << 2));
+}
+
+static void mmp_irq_mask(struct irq_data *d)
+{
+	struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+	__raw_writel(0, info->virt_base + (d->irq << 2));
+}
+
+static struct irq_chip mmp_irq_chip = {
+	.name		= "mmp-intc",
+	.irq_unmask	= mmp_irq_unmask,
+	.irq_mask	= mmp_irq_mask,
+	.irq_ack	= mmp_irq_mask,
+};
+
+void __init mmp_init_intc(void)
+{
+	struct mmp_intc_info *info;
+	struct device_node *np;
+	struct resource rs;
+	unsigned int cells, nr, enable, irq_base;
+	int i;
+
+	np = of_find_compatible_node(NULL, NULL, "mrvl,pxa168-intc");
+
+	BUG_ON(!np);
+
+	of_node_get(np);
+	if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+		goto out;
+	if (of_property_read_u32(np, "#interrupt-cells", &cells) < 0) {
+		pr_warn("mmp-intc: interrupt-cells property is missed\n");
+		goto out;
+	}
+	if (cells != 1) {
+		pr_warn("mmp-intc: interrupt-cells property is incorrect\n");
+		goto out;
+	}
+	if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+		pr_warn("mmp-intc: mrvl,intc-numbers property is missed\n");
+		goto out;
+	}
+	if (of_property_read_u32(np, "mrvl,intc-priority", &enable) < 0) {
+		pr_warn("mmp-intc: mrvl,intc-priority property is missed\n");
+		goto out;
+	}
+	if (of_address_to_resource(np, 0, &rs) < 0) {
+		pr_warn("mmp-intc: invalid reg property\n");
+		goto out;
+	}
+
+	info = kzalloc(sizeof(struct mmp_intc_info), GFP_KERNEL);
+	if (info == NULL)
+		goto out;
+	info->en_mask = enable;
+	info->virt_base = ioremap(rs.start, PAGE_SIZE);
+	if (info->virt_base == NULL) {
+		pr_warn("mmp-intc: failed to remap reg base\n");
+		goto out_mem;
+	}
+
+	/* allocate new irq */
+	irq_base = irq_alloc_descs(-1, 0, nr, 0);
+	irq_domain_add_simple(np, 0);
+
+	for (i = irq_base; i < irq_base + nr; i++) {
+		irq_set_chip_data(i, info);
+		mmp_irq_mask(irq_get_irq_data(i));
+		irq_set_chip_and_handler(i, &mmp_irq_chip, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+	mux_init_intc(info);
+	of_node_put(np);
+	return;
+out_mem:
+	kfree(info);
+out:
+	of_node_put(np);
+	return;
+}
-- 
1.5.6.5

WARNING: multiple messages have this Message-ID (diff)
From: haojian.zhuang@marvell.com (Haojian Zhuang)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 1/7] ARM: mmp: parse irq from DT
Date: Thu, 28 Jul 2011 14:41:27 +0800	[thread overview]
Message-ID: <1311835293-18125-2-git-send-email-haojian.zhuang@marvell.com> (raw)
In-Reply-To: <1311835293-18125-1-git-send-email-haojian.zhuang@marvell.com>

Parse irq sepcifier from DT and translate it to Linux irq number.
Remove the definition of NR_IRQS in irqs.h. Since sparse irq is
enabled, nr_irqs will be calculated automatically.

Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
 .../devicetree/bindings/arm/marvell/intc.txt       |  114 ++++++++++
 arch/arm/Kconfig                                   |    1 +
 arch/arm/mach-mmp/Makefile                         |    2 +
 arch/arm/mach-mmp/common.h                         |    1 +
 arch/arm/mach-mmp/include/mach/irqs.h              |    2 +-
 arch/arm/mach-mmp/intc.c                           |  224 ++++++++++++++++++++
 6 files changed, 343 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/intc.txt
 create mode 100644 arch/arm/mach-mmp/intc.c

diff --git a/Documentation/devicetree/bindings/arm/marvell/intc.txt b/Documentation/devicetree/bindings/arm/marvell/intc.txt
new file mode 100644
index 0000000..80cef58
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/marvell/intc.txt
@@ -0,0 +1,114 @@
+* Interrupt Controller Binding for ARCH-MMP
+
+This binding specifies what properties must be available in device tree representation of an ARCH-MMP compliant interrupt controller.
+
+Required properties:
+
+	- compatible: Specifies the compatibility list of the interrupt
+	  controller. The type shall be <string> and the value shall be
+	  "mrvl,pxa168-intc" or "mrvl,mmp2-mux-intc".
+	  "mrvl,pxa168-intc" is the base interrupt controller. It must be
+	  included. It's compatible for pxa910, mmp2. "mrvl,mmp2-mux-intc"
+	  is the expanded interrupt controller, and it's optional.
+
+	- reg: Specified the base physical address(s) and size(s) of the
+	  interrupt controller's addressable register space. The type
+	  should be <prop-encoded-array>.
+
+	- interrupt-controller: The presence of this property identifies
+	  the node as interrupt controller. No property value should be
+	  defined.
+
+	- #interrupt-cells: Specifies the number of cells needed to encode
+	  an interrupt source. The type should be <u32> and the value should
+	  be 1.
+
+	- mrvl,intc-numbers: Specifies the number of interrupts is supported
+	  in this interrupt controller. The type should be <u32>.
+
+Optional properties:
+
+	- mrvl,intc-priority: Specifies the which path the interrupt is routed
+	  and the priority of this interrupt. The property is used in
+	  pxa168-intc. The value should be <u32>.
+
+	- mrvl,status-offset: Specifies the offset of status register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mask-offset: Specifies the offset of mask register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mfp-edge: Specifies the address of mfp edge detection register.
+	  The property is used while acking specified interrupt. The type
+	  should be <prop-encoded-array>. The first cell indicates the address
+	  of mfp edge detection register. The second cell indicates the
+	  index of interrupt in current interrupt controller that should
+	  handle mfp edge detection.
+
+* Examples
+
+Example 1:
+
+	/*
+	 * base INTC
+	 */
+	mmp_intc: interrupt-controller at d4282000 {
+		/* Compatible with pxa168-intc. */
+		compatible = "mrvl,pxa168-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		/* Offset address of 0xd4282000 and size of 0x400. */
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+
+		/* 64 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <64>;
+
+		/* priority bits in configuration register */
+		mrvl,intc-priority = <0x20>;
+	};
+
+Example 2:
+
+	/*
+	 * mux INTC that is internal wired to base INTC
+	 */
+	mux_intc4: interrupt-controller at d4282150 {
+		compatible = "mrvl,mmp2-mux-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&mmp_intc>;
+
+		/* interrupt source '4' of parent INTC. */
+		interrupts = <4>;
+
+		/* 2 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <2>;
+
+		/* Status offset address of 0x150. */
+		mrvl,status-offset = <0x150>;
+
+		/* Mask offset address of 0x168. */
+		mrvl,mask-offset = <0x168>;
+
+		/* mfp register of 0xd401e2c4 & interrupt index of 1 */
+		mrvl,mfp-edge = <0xd401e2c4 1>;
+	};
+
+Example 3:
+	/*
+	 * An interrupt generating device that is wired to an INTC.
+	 */
+	uart0: uart at d4030000 {
+		/* parent's '#interrupt-cells' property. */
+		interrupts = <27>;
+
+		/* The INTC that this device is wired to. */
+		interrupt-parent = <&mmp_intc>;
+	};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 17507b8..f18eb14 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -542,6 +542,7 @@ config ARCH_MMP
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select PLAT_PXA
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 5c68382..e7862ea 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -4,6 +4,8 @@
 
 obj-y				+= common.o clock.o devices.o time.o
 
+obj-$(CONFIG_OF_IRQ)		+= intc.o
+
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
 obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index ec8d65d..1c563c2 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
 extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index a09d328..65ec176 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -224,6 +224,6 @@
 
 #define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS				(IRQ_BOARD_START)
+#define NR_IRQS				0
 
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-mmp/intc.c b/arch/arm/mach-mmp/intc.c
new file mode 100644
index 0000000..2e44057
--- /dev/null
+++ b/arch/arm/mach-mmp/intc.c
@@ -0,0 +1,224 @@
+/*
+ *  linux/arch/arm/mach-mmp/intc.c
+ *
+ *  Generic IRQ handling
+ *
+ *  Author:	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *  Copyright:	Marvell International Ltd. 2011
+ *
+ *  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.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+struct mmp_intc_info {
+	unsigned int		en_mask;
+	void __iomem		*virt_base;
+	void __iomem		*status;
+	void __iomem		*mfp_edge;
+	unsigned int		mfp_edge_index; /* index in irq domain */
+};
+
+static void mux_irq_ack(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct;
+	struct mmp_intc_info *info;
+	unsigned int data, irq_offs;
+
+	ct = gc->chip_types;
+	info = (struct mmp_intc_info *)ct->regs.ack;
+	irq_offs = d->irq - gc->irq_base;
+	/* clear MFP edge-detect */
+	if (info->mfp_edge && (info->mfp_edge_index == irq_offs)) {
+		data = __raw_readl(info->mfp_edge);
+		__raw_writel(data | (1 << 6), info->mfp_edge);
+		__raw_writel(data, info->mfp_edge);
+	}
+}
+
+static void mmp_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip_generic *gc = irq_get_handler_data(irq);
+	struct irq_chip_type *ct;
+	struct mmp_intc_info *info;
+	unsigned long status, n;
+
+	ct = gc->chip_types;
+	info = (struct mmp_intc_info *)ct->regs.ack;
+	while (1) {
+		status = __raw_readl(info->status) & ~gc->mask_cache;
+		if (status == 0)
+			break;
+		n = find_first_bit(&status, BITS_PER_LONG);
+		while (n < BITS_PER_LONG) {
+			generic_handle_irq(gc->irq_base + n);
+			n = find_next_bit(&status, BITS_PER_LONG, n + 1);
+		}
+	}
+}
+
+static void mux_init_intc(struct mmp_intc_info *mmp_info)
+{
+	struct device_node *np;
+	struct mmp_intc_info *mux_info;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	const __be32 *edge;
+	unsigned int addr = 0, offs = 0;
+	unsigned int status, mask, irq_base, nr, data;
+	int cascade;
+
+	for_each_compatible_node(np, NULL, "mrvl,mmp2-mux-intc") {
+		if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+			continue;
+		if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+			pr_warn("intc-numbers property is missed\n");
+			continue;
+		}
+		if (of_property_read_u32(np, "mrvl,status-offset", &status)
+			< 0) {
+			pr_warn("intc-status property is missed\n");
+			continue;
+		}
+		if (of_property_read_u32(np, "mrvl,mask-offset", &mask) < 0) {
+			pr_warn("intc-mask property is missed\n");
+			continue;
+		}
+
+		mux_info = kzalloc(sizeof(*mux_info), GFP_KERNEL);
+		if (mux_info == NULL)
+			goto out;
+		status += (unsigned int)mmp_info->virt_base;
+		mux_info->status = (void __iomem *)status;
+
+		edge = of_get_property(np, "mrvl,mfp-edge", NULL);
+		if (edge) {
+			addr = be32_to_cpu(*edge) & PAGE_MASK;
+			offs = be32_to_cpu(*edge) - addr;
+			mux_info->mfp_edge = ioremap(addr, PAGE_SIZE) + offs;
+			mux_info->mfp_edge_index = be32_to_cpu(*++edge);
+			/* clear mfp edge detection for initialization */
+			data = __raw_readl(mux_info->mfp_edge);
+			__raw_writel(data | (1 << 6), mux_info->mfp_edge);
+			__raw_writel(data, mux_info->mfp_edge);
+		}
+
+		/* allocate new irq */
+		cascade = irq_of_parse_and_map(np, 0);
+		irq_base = irq_alloc_descs(-1, 0, nr, 0);
+		irq_domain_add_simple(np, irq_base);
+
+		gc = irq_alloc_generic_chip("mux-intc", 1, irq_base,
+					mmp_info->virt_base, handle_level_irq);
+		ct = gc->chip_types;
+		ct->regs.ack = (unsigned int)mux_info;
+		ct->regs.mask = mask;
+		ct->chip.irq_ack = mux_irq_ack;
+		ct->chip.irq_mask = irq_gc_mask_set_bit;
+		ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+		irq_setup_generic_chip(gc, IRQ_MSK(nr), IRQ_GC_INIT_MASK_CACHE,
+					IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+
+		irq_set_handler_data(cascade, gc);
+		irq_set_chained_handler(cascade, mmp_irq_demux_handler);
+	}
+out:
+	return;
+}
+
+static void mmp_irq_unmask(struct irq_data *d)
+{
+	struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+	/* ICU_INT_CONF */
+	__raw_writel(info->en_mask, info->virt_base + (d->irq << 2));
+}
+
+static void mmp_irq_mask(struct irq_data *d)
+{
+	struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+	__raw_writel(0, info->virt_base + (d->irq << 2));
+}
+
+static struct irq_chip mmp_irq_chip = {
+	.name		= "mmp-intc",
+	.irq_unmask	= mmp_irq_unmask,
+	.irq_mask	= mmp_irq_mask,
+	.irq_ack	= mmp_irq_mask,
+};
+
+void __init mmp_init_intc(void)
+{
+	struct mmp_intc_info *info;
+	struct device_node *np;
+	struct resource rs;
+	unsigned int cells, nr, enable, irq_base;
+	int i;
+
+	np = of_find_compatible_node(NULL, NULL, "mrvl,pxa168-intc");
+
+	BUG_ON(!np);
+
+	of_node_get(np);
+	if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+		goto out;
+	if (of_property_read_u32(np, "#interrupt-cells", &cells) < 0) {
+		pr_warn("mmp-intc: interrupt-cells property is missed\n");
+		goto out;
+	}
+	if (cells != 1) {
+		pr_warn("mmp-intc: interrupt-cells property is incorrect\n");
+		goto out;
+	}
+	if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+		pr_warn("mmp-intc: mrvl,intc-numbers property is missed\n");
+		goto out;
+	}
+	if (of_property_read_u32(np, "mrvl,intc-priority", &enable) < 0) {
+		pr_warn("mmp-intc: mrvl,intc-priority property is missed\n");
+		goto out;
+	}
+	if (of_address_to_resource(np, 0, &rs) < 0) {
+		pr_warn("mmp-intc: invalid reg property\n");
+		goto out;
+	}
+
+	info = kzalloc(sizeof(struct mmp_intc_info), GFP_KERNEL);
+	if (info == NULL)
+		goto out;
+	info->en_mask = enable;
+	info->virt_base = ioremap(rs.start, PAGE_SIZE);
+	if (info->virt_base == NULL) {
+		pr_warn("mmp-intc: failed to remap reg base\n");
+		goto out_mem;
+	}
+
+	/* allocate new irq */
+	irq_base = irq_alloc_descs(-1, 0, nr, 0);
+	irq_domain_add_simple(np, 0);
+
+	for (i = irq_base; i < irq_base + nr; i++) {
+		irq_set_chip_data(i, info);
+		mmp_irq_mask(irq_get_irq_data(i));
+		irq_set_chip_and_handler(i, &mmp_irq_chip, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+	mux_init_intc(info);
+	of_node_put(np);
+	return;
+out_mem:
+	kfree(info);
+out:
+	of_node_put(np);
+	return;
+}
-- 
1.5.6.5

  parent reply	other threads:[~2011-07-28  6:41 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-07-28  6:41 [PATCH v2 00/07] enable devicetree on arch-mmp Haojian Zhuang
2011-07-28  6:41 ` Haojian Zhuang
     [not found] ` <1311835293-18125-1-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2011-07-28  6:41   ` Haojian Zhuang [this message]
2011-07-28  6:41     ` [PATCH v2 1/7] ARM: mmp: parse irq from DT Haojian Zhuang
     [not found]     ` <1311835293-18125-2-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2011-07-28  6:41       ` [PATCH v2 2/7] ARM: mmp: parse timer configuration " Haojian Zhuang
2011-07-28  6:41         ` Haojian Zhuang
     [not found]         ` <1311835293-18125-3-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2011-07-28  6:41           ` [PATCH v2 3/7] ARM: mmp: support DT on both dkb and brownstone Haojian Zhuang
2011-07-28  6:41             ` Haojian Zhuang
     [not found]             ` <1311835293-18125-4-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2011-07-28  6:41               ` [PATCH v2 4/7] tty: serial: support device tree in pxa Haojian Zhuang
2011-07-28  6:41                 ` Haojian Zhuang
     [not found]                 ` <1311835293-18125-5-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2011-07-28  6:41                   ` [PATCH v2 5/7] tty: serial: check ops before registering console Haojian Zhuang
2011-07-28  6:41                     ` Haojian Zhuang
     [not found]                     ` <1311835293-18125-6-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2011-07-28  6:41                       ` [PATCH v2 6/7] i2c: pxa: support i2c controller from DT Haojian Zhuang
2011-07-28  6:41                         ` Haojian Zhuang
     [not found]                         ` <1311835293-18125-7-git-send-email-haojian.zhuang-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2011-07-28  6:41                           ` [PATCH v2 7/7] i2c: pxa: support to parse property Haojian Zhuang
2011-07-28  6:41                             ` Haojian Zhuang
2011-07-29 16:52                           ` [PATCH v2 6/7] i2c: pxa: support i2c controller from DT Grant Likely
2011-07-29 16:52                             ` Grant Likely
     [not found]                             ` <20110729165222.GN11164-e0URQFbLeQY2iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
2011-07-29 16:55                               ` Russell King - ARM Linux
2011-07-29 16:55                                 ` Russell King - ARM Linux
2011-07-30 14:29                                 ` Mitch Bradley
2011-07-30 14:29                                   ` Mitch Bradley
     [not found]                                   ` <4E34155E.8010606-D5eQfiDGL7eakBO8gow8eQ@public.gmane.org>
2011-07-30 15:37                                     ` Russell King - ARM Linux
2011-07-30 15:37                                       ` Russell King - ARM Linux
     [not found]                                       ` <20110730153728.GA17570-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2011-07-31  0:38                                         ` Grant Likely
2011-07-31  0:38                                           ` Grant Likely
2011-07-29 16:45                   ` [PATCH v2 4/7] tty: serial: support device tree in pxa Grant Likely
2011-07-29 16:45                     ` Grant Likely
2011-07-29 16:49                     ` Russell King - ARM Linux
2011-07-29 16:49                       ` Russell King - ARM Linux
     [not found]                       ` <20110729164922.GA30298-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2011-07-29 16:53                         ` Grant Likely
2011-07-29 16:53                           ` Grant Likely
2011-08-01  2:50                       ` Haojian Zhuang
2011-08-01  2:50                         ` Haojian Zhuang
     [not found]                         ` <CAN1soZwYjQp5c=4f=CbqjrXFxzSURSv6i9QHMyjyPszs=kzh9w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-08-01  8:27                           ` Russell King - ARM Linux
2011-08-01  8:27                             ` Russell King - ARM Linux
2011-07-29 16:42               ` [PATCH v2 3/7] ARM: mmp: support DT on both dkb and brownstone Grant Likely
2011-07-29 16:42                 ` Grant Likely
     [not found]                 ` <20110729164218.GL11164-e0URQFbLeQY2iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
2011-08-01  2:48                   ` Haojian Zhuang
2011-08-01  2:48                     ` Haojian Zhuang
2011-07-29 16:40           ` [PATCH v2 2/7] ARM: mmp: parse timer configuration from DT Grant Likely
2011-07-29 16:40             ` Grant Likely
2011-07-29 16:36       ` [PATCH v2 1/7] ARM: mmp: parse irq " Grant Likely
2011-07-29 16:36         ` Grant Likely
2011-08-01  2:47         ` Haojian Zhuang
2011-08-01  2:47           ` Haojian Zhuang
     [not found]           ` <CAN1soZxX6EBRPvzV_00njioBn1NfiAbLBoD7EYc-wV-uQM_VoQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-08-01 14:10             ` Grant Likely
2011-08-01 14:10               ` Grant Likely
     [not found]               ` <20110801141036.GA21627-e0URQFbLeQY2iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
2011-08-01 14:42                 ` Haojian Zhuang
2011-08-01 14:42                   ` Haojian Zhuang
2011-08-01 14:43                   ` Grant Likely
2011-08-01 14:43                     ` Grant Likely
2011-08-01  8:26     ` Russell King - ARM Linux
2011-08-01  8:26       ` Russell King - ARM Linux

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=1311835293-18125-2-git-send-email-haojian.zhuang@marvell.com \
    --to=haojian.zhuang-eyqppykdwxrbdgjk7y7tuq@public.gmane.org \
    --cc=alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
    --cc=devicetree-discuss@list \
    --cc=eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org \
    --cc=haojian.zhuang-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.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.