[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