[PATCH v2 2/7] ARM: imx5: adopt generic_chip irq_domain support for tzic

Shawn Guo shawn.guo at linaro.org
Wed Feb 15 13:47:43 EST 2012


It separates the DT initialization for tzic and gpt from non-DT code
path, so that base address and irq can retrieved from device tree
rather than static definition.

With the DT initialization flow corrected as above, the generic_chip
irq_domain support is adopted for tzic interrupt controller, so that
the irq_domain initialization for tzic in imx5 DT platform code can be
removed.

Signed-off-by: Shawn Guo <shawn.guo at linaro.org>
---
 arch/arm/boot/dts/imx51.dtsi            |    6 ++++
 arch/arm/boot/dts/imx53.dtsi            |    6 ++++
 arch/arm/mach-mx5/clock-mx51-mx53.c     |   47 ++++++++++++++++++++++++++++--
 arch/arm/mach-mx5/imx51-dt.c            |   22 ++++++++++----
 arch/arm/mach-mx5/imx53-dt.c            |   22 ++++++++++----
 arch/arm/mach-mx5/mm.c                  |    6 ++--
 arch/arm/plat-mxc/include/mach/common.h |    3 +-
 arch/arm/plat-mxc/tzic.c                |   32 ++++++++++-----------
 8 files changed, 105 insertions(+), 39 deletions(-)

diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 6663986..a5fda43 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -171,6 +171,12 @@
 				status = "disabled";
 			};
 
+			gpt at 73fa0000 {
+				compatible = "fsl,imx51-gpt", "fsl,gpt";
+				reg = <0x73fa0000 0x4000>;
+				interrupts = <39>;
+			};
+
 			uart1: uart at 73fbc000 {
 				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 				reg = <0x73fbc000 0x4000>;
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 5dd91b9..05e6412 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -173,6 +173,12 @@
 				status = "disabled";
 			};
 
+			gpt at 53fa0000 {
+				compatible = "fsl,imx53-gpt", "fsl,gpt";
+				reg = <0x53fa0000 0x4000>;
+				interrupts = <39>;
+			};
+
 			uart1: uart at 53fbc000 {
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53fbc000 0x4000>;
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 4cb2769..200a3d7 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -16,6 +16,8 @@
 #include <linux/io.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/div64.h>
 
@@ -1555,10 +1557,16 @@ static void clk_tree_init(void)
 	__raw_writel(reg, MXC_CCM_CBCDR);
 }
 
+static inline void __iomem *get_gpt_base_dt(struct device_node *np);
+static inline int get_gpt_irq_dt(struct device_node *np);
+
 int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2)
 {
 	int i;
+	int gpt_irq = MX51_INT_GPT;
+	void __iomem *gpt_base = MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR);
+	struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,gpt");
 
 	external_low_reference = ckil;
 	external_high_reference = ckih1;
@@ -1592,8 +1600,12 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 	clk_set_rate(&esdhc2_clk, 166250000);
 
 	/* System timer */
-	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_INT_GPT);
+	if (np) {
+		gpt_base = get_gpt_base_dt(np);
+		gpt_irq = get_gpt_irq_dt(np);
+	}
+	WARN_ON(!gpt_base);
+	mxc_timer_init(&gpt_clk, gpt_base, gpt_irq);
 	return 0;
 }
 
@@ -1601,6 +1613,9 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2)
 {
 	int i;
+	int gpt_irq = MX53_INT_GPT;
+	void __iomem *gpt_base = MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR);
+	struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,gpt");
 
 	external_low_reference = ckil;
 	external_high_reference = ckih1;
@@ -1629,8 +1644,12 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 	clk_set_rate(&esdhc3_mx53_clk, 200000000);
 
 	/* System timer */
-	mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
-		MX53_INT_GPT);
+	if (np) {
+		gpt_base = get_gpt_base_dt(np);
+		gpt_irq = get_gpt_irq_dt(np);
+	}
+	WARN_ON(!gpt_base);
+	mxc_timer_init(&gpt_clk, gpt_base, gpt_irq);
 	return 0;
 }
 
@@ -1672,4 +1691,24 @@ int __init mx53_clocks_init_dt(void)
 	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
 	return mx53_clocks_init(ckil, osc, ckih1, ckih2);
 }
+
+static inline void __iomem *get_gpt_base_dt(struct device_node *np)
+{
+	return of_iomap(np, 0);
+}
+
+static inline int get_gpt_irq_dt(struct device_node *np)
+{
+	return irq_of_parse_and_map(np, 0);
+}
+#else
+static inline void __iomem *get_gpt_base_dt(struct device_node *np)
+{
+	return NULL;
+}
+
+static inline int get_gpt_irq_dt(struct device_node *np)
+{
+	return -ENODEV;
+}
 #endif
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
index 1e03ef4..636ef34 100644
--- a/arch/arm/mach-mx5/imx51-dt.c
+++ b/arch/arm/mach-mx5/imx51-dt.c
@@ -12,6 +12,7 @@
 
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
@@ -44,10 +45,14 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
 	{ /* sentinel */ }
 };
 
-static int __init imx51_tzic_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
+static int __init imx51_tzic_init_cb(struct device_node *np,
+				     struct device_node *interrupt_parent)
 {
-	irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
+	void __iomem *base = of_iomap(np, 0);
+
+	WARN_ON(!base);
+	tzic_init_irq(base, np);
+
 	return 0;
 }
 
@@ -63,7 +68,7 @@ static int __init imx51_gpio_add_irq_domain(struct device_node *np,
 }
 
 static const struct of_device_id imx51_irq_match[] __initconst = {
-	{ .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx51-tzic", .data = imx51_tzic_init_cb, },
 	{ .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
 	{ /* sentinel */ }
 };
@@ -73,14 +78,17 @@ static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
 	{ /* sentinel */ }
 };
 
+static void __init imx51_dt_irq_init(void)
+{
+	of_irq_init(imx51_irq_match);
+}
+
 static void __init imx51_dt_init(void)
 {
 	struct device_node *node;
 	const struct of_device_id *of_id;
 	void (*func)(void);
 
-	of_irq_init(imx51_irq_match);
-
 	node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
 	if (node) {
 		of_id = of_match_node(imx51_iomuxc_of_match, node);
@@ -110,7 +118,7 @@ static const char *imx51_dt_board_compat[] __initdata = {
 DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
 	.map_io		= mx51_map_io,
 	.init_early	= imx51_init_early,
-	.init_irq	= mx51_init_irq,
+	.init_irq	= imx51_dt_irq_init,
 	.handle_irq	= imx51_handle_irq,
 	.timer		= &imx51_timer,
 	.init_machine	= imx51_dt_init,
diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c
index fd5be0f..ce2b700 100644
--- a/arch/arm/mach-mx5/imx53-dt.c
+++ b/arch/arm/mach-mx5/imx53-dt.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
@@ -48,10 +49,14 @@ static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
 	{ /* sentinel */ }
 };
 
-static int __init imx53_tzic_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
+static int __init imx53_tzic_init_cb(struct device_node *np,
+				     struct device_node *interrupt_parent)
 {
-	irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
+	void __iomem *base = of_iomap(np, 0);
+
+	WARN_ON(!base);
+	tzic_init_irq(base, np);
+
 	return 0;
 }
 
@@ -67,7 +72,7 @@ static int __init imx53_gpio_add_irq_domain(struct device_node *np,
 }
 
 static const struct of_device_id imx53_irq_match[] __initconst = {
-	{ .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx53-tzic", .data = imx53_tzic_init_cb, },
 	{ .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
 	{ /* sentinel */ }
 };
@@ -80,14 +85,17 @@ static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
 	{ /* sentinel */ }
 };
 
+static void __init imx53_dt_irq_init(void)
+{
+	of_irq_init(imx53_irq_match);
+}
+
 static void __init imx53_dt_init(void)
 {
 	struct device_node *node;
 	const struct of_device_id *of_id;
 	void (*func)(void);
 
-	of_irq_init(imx53_irq_match);
-
 	node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
 	if (node) {
 		of_id = of_match_node(imx53_iomuxc_of_match, node);
@@ -120,7 +128,7 @@ static const char *imx53_dt_board_compat[] __initdata = {
 DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
 	.map_io		= mx53_map_io,
 	.init_early	= imx53_init_early,
-	.init_irq	= mx53_init_irq,
+	.init_irq	= imx53_dt_irq_init,
 	.handle_irq	= imx53_handle_irq,
 	.timer		= &imx53_timer,
 	.init_machine	= imx53_dt_init,
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index bc17dfe..bed8562 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -120,17 +120,17 @@ void __init imx53_init_early(void)
 
 void __init mx50_init_irq(void)
 {
-	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR), NULL);
 }
 
 void __init mx51_init_irq(void)
 {
-	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
+	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR), NULL);
 }
 
 void __init mx53_init_irq(void)
 {
-	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
+	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR), NULL);
 }
 
 static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 1bf0df8..4291992 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -11,6 +11,7 @@
 #ifndef __ASM_ARCH_MXC_COMMON_H__
 #define __ASM_ARCH_MXC_COMMON_H__
 
+struct device_node;
 struct platform_device;
 struct clk;
 enum mxc_cpu_pwr_mode;
@@ -34,7 +35,7 @@ extern void imx50_init_early(void);
 extern void imx51_init_early(void);
 extern void imx53_init_early(void);
 extern void mxc_init_irq(void __iomem *);
-extern void tzic_init_irq(void __iomem *);
+extern void tzic_init_irq(void __iomem *, struct device_node *np);
 extern void mx1_init_irq(void);
 extern void mx21_init_irq(void);
 extern void mx25_init_irq(void);
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index 98308ec..8288187 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
@@ -49,6 +50,7 @@
 #define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
 
 void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
+static struct irq_chip_generic *tzic_gc;
 
 #define TZIC_NUM_IRQS 128
 
@@ -77,15 +79,14 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 static void tzic_irq_suspend(struct irq_data *d)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	int idx = gc->irq_base >> 5;
+	int idx = d->hwirq / 32;
 
 	__raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx));
 }
 
 static void tzic_irq_resume(struct irq_data *d)
 {
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	int idx = gc->irq_base >> 5;
+	int idx = d->hwirq / 32;
 
 	__raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)),
 		     tzic_base + TZIC_WAKEUP0(idx));
@@ -102,18 +103,14 @@ static struct mxc_extra_irq tzic_extra_irq = {
 #endif
 };
 
-static __init void tzic_init_gc(unsigned int irq_start)
+static __init void tzic_init_gc(struct irq_chip_generic *gc)
 {
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-	int idx = irq_start >> 5;
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = gc->hwirq_base / 32;
 
-	gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
-				    handle_level_irq);
-	gc->private = &tzic_extra_irq;
+	tzic_gc = gc;
 	gc->wake_enabled = IRQ_MSK(32);
 
-	ct = gc->chip_types;
 	ct->chip.irq_mask = irq_gc_mask_disable_reg;
 	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
 	ct->chip.irq_set_wake = irq_gc_set_wake;
@@ -121,8 +118,6 @@ static __init void tzic_init_gc(unsigned int irq_start)
 	ct->chip.irq_resume = tzic_irq_resume;
 	ct->regs.disable = TZIC_ENCLEAR0(idx);
 	ct->regs.enable = TZIC_ENSET0(idx);
-
-	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
 }
 
 asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
@@ -140,7 +135,8 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
 			while (stat) {
 				handled = 1;
 				irqofs = fls(stat) - 1;
-				handle_IRQ(irqofs + i * 32, regs);
+				handle_IRQ(irq_find_mapping(tzic_gc->domain,
+						irqofs + i * 32), regs);
 				stat &= ~(1 << irqofs);
 			}
 		}
@@ -152,7 +148,7 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
  * interrupts. It registers the interrupt enable and disable functions
  * to the kernel for each interrupt source.
  */
-void __init tzic_init_irq(void __iomem *irqbase)
+void __init tzic_init_irq(void __iomem *irqbase, struct device_node *np)
 {
 	int i;
 
@@ -175,8 +171,10 @@ void __init tzic_init_irq(void __iomem *irqbase)
 
 	/* all IRQ no FIQ Warning :: No selection */
 
-	for (i = 0; i < TZIC_NUM_IRQS; i += 32)
-		tzic_init_gc(i);
+	irq_setup_generic_chip_domain("tzic", np, 1, 0, tzic_base,
+				      handle_level_irq, TZIC_NUM_IRQS, 0,
+				      IRQ_NOREQUEST, 0,
+				      tzic_init_gc, &tzic_extra_irq);
 
 #ifdef CONFIG_FIQ
 	/* Initialize FIQ */
-- 
1.7.5.4




More information about the linux-arm-kernel mailing list