aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHui Wang <jason77.wang@gmail.com>2011-09-22 05:40:08 -0400
committerSascha Hauer <s.hauer@pengutronix.de>2011-09-23 02:32:14 -0400
commit3439a397a8190b7e8d319959ec30e28c7ca14bab (patch)
tree8feab81ed1c843020bf516d82f5518f88381e3e4
parent40d97b89bd3c902144a0757249d9d5d5cf314214 (diff)
ARM i.MX avic: convert to use generic irq chip
Convert i.MX avic irq handler to use generic irq chip. This not only provides a cleanup implementation of irq chip handler, but also implements suspend/resume interface with the help of generic irq chip interface. Change mxc_irq_chip to a new structure mxc_extra_irq to handle fiq and priority functions. Signed-off-by: Hui Wang <jason77.wang@gmail.com> Acked-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/arm/plat-mxc/avic.c79
-rw-r--r--arch/arm/plat-mxc/irq-common.c21
-rw-r--r--arch/arm/plat-mxc/irq-common.h3
-rw-r--r--arch/arm/plat-mxc/tzic.c8
4 files changed, 75 insertions, 36 deletions
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 55d2534ec727..846636a29bd3 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -50,6 +50,8 @@
50 50
51void __iomem *avic_base; 51void __iomem *avic_base;
52 52
53static u32 avic_saved_mask_reg[2];
54
53#ifdef CONFIG_MXC_IRQ_PRIOR 55#ifdef CONFIG_MXC_IRQ_PRIOR
54static int avic_irq_set_priority(unsigned char irq, unsigned char prio) 56static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
55{ 57{
@@ -90,24 +92,8 @@ static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
90} 92}
91#endif /* CONFIG_FIQ */ 93#endif /* CONFIG_FIQ */
92 94
93/* Disable interrupt number "irq" in the AVIC */
94static void mxc_mask_irq(struct irq_data *d)
95{
96 __raw_writel(d->irq, avic_base + AVIC_INTDISNUM);
97}
98
99/* Enable interrupt number "irq" in the AVIC */
100static void mxc_unmask_irq(struct irq_data *d)
101{
102 __raw_writel(d->irq, avic_base + AVIC_INTENNUM);
103}
104 95
105static struct mxc_irq_chip mxc_avic_chip = { 96static struct mxc_extra_irq avic_extra_irq = {
106 .base = {
107 .irq_ack = mxc_mask_irq,
108 .irq_mask = mxc_mask_irq,
109 .irq_unmask = mxc_unmask_irq,
110 },
111#ifdef CONFIG_MXC_IRQ_PRIOR 97#ifdef CONFIG_MXC_IRQ_PRIOR
112 .set_priority = avic_irq_set_priority, 98 .set_priority = avic_irq_set_priority,
113#endif 99#endif
@@ -116,6 +102,56 @@ static struct mxc_irq_chip mxc_avic_chip = {
116#endif 102#endif
117}; 103};
118 104
105
106#ifdef CONFIG_PM
107static void avic_irq_suspend(struct irq_data *d)
108{
109 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
110 struct irq_chip_type *ct = gc->chip_types;
111 int idx = gc->irq_base >> 5;
112
113 avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
114 __raw_writel(gc->wake_active, avic_base + ct->regs.mask);
115}
116
117static void avic_irq_resume(struct irq_data *d)
118{
119 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
120 struct irq_chip_type *ct = gc->chip_types;
121 int idx = gc->irq_base >> 5;
122
123 __raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
124}
125
126#else
127#define avic_irq_suspend NULL
128#define avic_irq_resume NULL
129#endif
130
131static __init void avic_init_gc(unsigned int irq_start)
132{
133 struct irq_chip_generic *gc;
134 struct irq_chip_type *ct;
135 int idx = irq_start >> 5;
136
137 gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
138 handle_level_irq);
139 gc->private = &avic_extra_irq;
140 gc->wake_enabled = IRQ_MSK(32);
141
142 ct = gc->chip_types;
143 ct->chip.irq_mask = irq_gc_mask_clr_bit;
144 ct->chip.irq_unmask = irq_gc_mask_set_bit;
145 ct->chip.irq_ack = irq_gc_mask_clr_bit;
146 ct->chip.irq_set_wake = irq_gc_set_wake;
147 ct->chip.irq_suspend = avic_irq_suspend;
148 ct->chip.irq_resume = avic_irq_resume;
149 ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
150 ct->regs.ack = ct->regs.mask;
151
152 irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
153}
154
119/* 155/*
120 * This function initializes the AVIC hardware and disables all the 156 * This function initializes the AVIC hardware and disables all the
121 * interrupts. It registers the interrupt enable and disable functions 157 * interrupts. It registers the interrupt enable and disable functions
@@ -140,11 +176,9 @@ void __init mxc_init_irq(void __iomem *irqbase)
140 /* all IRQ no FIQ */ 176 /* all IRQ no FIQ */
141 __raw_writel(0, avic_base + AVIC_INTTYPEH); 177 __raw_writel(0, avic_base + AVIC_INTTYPEH);
142 __raw_writel(0, avic_base + AVIC_INTTYPEL); 178 __raw_writel(0, avic_base + AVIC_INTTYPEL);
143 for (i = 0; i < AVIC_NUM_IRQS; i++) { 179
144 irq_set_chip_and_handler(i, &mxc_avic_chip.base, 180 for (i = 0; i < AVIC_NUM_IRQS; i += 32)
145 handle_level_irq); 181 avic_init_gc(i);
146 set_irq_flags(i, IRQF_VALID);
147 }
148 182
149 /* Set default priority value (0) for all IRQ's */ 183 /* Set default priority value (0) for all IRQ's */
150 for (i = 0; i < 8; i++) 184 for (i = 0; i < 8; i++)
@@ -157,4 +191,3 @@ void __init mxc_init_irq(void __iomem *irqbase)
157 191
158 printk(KERN_INFO "MXC IRQ initialized\n"); 192 printk(KERN_INFO "MXC IRQ initialized\n");
159} 193}
160
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
index 96953e2e4f11..b6e11458e5ae 100644
--- a/arch/arm/plat-mxc/irq-common.c
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -23,17 +23,17 @@
23 23
24int imx_irq_set_priority(unsigned char irq, unsigned char prio) 24int imx_irq_set_priority(unsigned char irq, unsigned char prio)
25{ 25{
26 struct mxc_irq_chip *chip; 26 struct irq_chip_generic *gc;
27 struct irq_chip *base; 27 struct mxc_extra_irq *exirq;
28 int ret; 28 int ret;
29 29
30 ret = -ENOSYS; 30 ret = -ENOSYS;
31 31
32 base = irq_get_chip(irq); 32 gc = irq_get_chip_data(irq);
33 if (base) { 33 if (gc && gc->private) {
34 chip = container_of(base, struct mxc_irq_chip, base); 34 exirq = gc->private;
35 if (chip->set_priority) 35 if (exirq->set_priority)
36 ret = chip->set_priority(irq, prio); 36 ret = exirq->set_priority(irq, prio);
37 } 37 }
38 38
39 return ret; 39 return ret;
@@ -43,15 +43,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
43int mxc_set_irq_fiq(unsigned int irq, unsigned int type) 43int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
44{ 44{
45 struct irq_chip_generic *gc; 45 struct irq_chip_generic *gc;
46 int (*set_irq_fiq)(unsigned int, unsigned int); 46 struct mxc_extra_irq *exirq;
47 int ret; 47 int ret;
48 48
49 ret = -ENOSYS; 49 ret = -ENOSYS;
50 50
51 gc = irq_get_chip_data(irq); 51 gc = irq_get_chip_data(irq);
52 if (gc && gc->private) { 52 if (gc && gc->private) {
53 set_irq_fiq = gc->private; 53 exirq = gc->private;
54 ret = set_irq_fiq(irq, type); 54 if (exirq->set_irq_fiq)
55 ret = exirq->set_irq_fiq(irq, type);
55 } 56 }
56 57
57 return ret; 58 return ret;
diff --git a/arch/arm/plat-mxc/irq-common.h b/arch/arm/plat-mxc/irq-common.h
index 7203543fb1b3..6ccb3a14c693 100644
--- a/arch/arm/plat-mxc/irq-common.h
+++ b/arch/arm/plat-mxc/irq-common.h
@@ -19,9 +19,8 @@
19#ifndef __PLAT_MXC_IRQ_COMMON_H__ 19#ifndef __PLAT_MXC_IRQ_COMMON_H__
20#define __PLAT_MXC_IRQ_COMMON_H__ 20#define __PLAT_MXC_IRQ_COMMON_H__
21 21
22struct mxc_irq_chip 22struct mxc_extra_irq
23{ 23{
24 struct irq_chip base;
25 int (*set_priority)(unsigned char irq, unsigned char prio); 24 int (*set_priority)(unsigned char irq, unsigned char prio);
26 int (*set_irq_fiq)(unsigned int irq, unsigned int type); 25 int (*set_irq_fiq)(unsigned int irq, unsigned int type);
27}; 26};
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index f257fccdc394..a5807509fc62 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -74,6 +74,12 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
74 74
75static unsigned int *wakeup_intr[4]; 75static unsigned int *wakeup_intr[4];
76 76
77static struct mxc_extra_irq tzic_extra_irq = {
78#ifdef CONFIG_FIQ
79 .set_irq_fiq = tzic_set_irq_fiq,
80#endif
81};
82
77static __init void tzic_init_gc(unsigned int irq_start) 83static __init void tzic_init_gc(unsigned int irq_start)
78{ 84{
79 struct irq_chip_generic *gc; 85 struct irq_chip_generic *gc;
@@ -82,7 +88,7 @@ static __init void tzic_init_gc(unsigned int irq_start)
82 88
83 gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base, 89 gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
84 handle_level_irq); 90 handle_level_irq);
85 gc->private = tzic_set_irq_fiq; 91 gc->private = &tzic_extra_irq;
86 gc->wake_enabled = IRQ_MSK(32); 92 gc->wake_enabled = IRQ_MSK(32);
87 wakeup_intr[idx] = &gc->wake_active; 93 wakeup_intr[idx] = &gc->wake_active;
88 94