diff options
author | Hui Wang <jason77.wang@gmail.com> | 2011-09-22 05:40:08 -0400 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2011-09-23 02:32:14 -0400 |
commit | 3439a397a8190b7e8d319959ec30e28c7ca14bab (patch) | |
tree | 8feab81ed1c843020bf516d82f5518f88381e3e4 | |
parent | 40d97b89bd3c902144a0757249d9d5d5cf314214 (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.c | 79 | ||||
-rw-r--r-- | arch/arm/plat-mxc/irq-common.c | 21 | ||||
-rw-r--r-- | arch/arm/plat-mxc/irq-common.h | 3 | ||||
-rw-r--r-- | arch/arm/plat-mxc/tzic.c | 8 |
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 | ||
51 | void __iomem *avic_base; | 51 | void __iomem *avic_base; |
52 | 52 | ||
53 | static u32 avic_saved_mask_reg[2]; | ||
54 | |||
53 | #ifdef CONFIG_MXC_IRQ_PRIOR | 55 | #ifdef CONFIG_MXC_IRQ_PRIOR |
54 | static int avic_irq_set_priority(unsigned char irq, unsigned char prio) | 56 | static 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 */ | ||
94 | static 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 */ | ||
100 | static void mxc_unmask_irq(struct irq_data *d) | ||
101 | { | ||
102 | __raw_writel(d->irq, avic_base + AVIC_INTENNUM); | ||
103 | } | ||
104 | 95 | ||
105 | static struct mxc_irq_chip mxc_avic_chip = { | 96 | static 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 | ||
107 | static 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 | |||
117 | static 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 | |||
131 | static __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 | ||
24 | int imx_irq_set_priority(unsigned char irq, unsigned char prio) | 24 | int 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); | |||
43 | int mxc_set_irq_fiq(unsigned int irq, unsigned int type) | 43 | int 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 | ||
22 | struct mxc_irq_chip | 22 | struct 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 | ||
75 | static unsigned int *wakeup_intr[4]; | 75 | static unsigned int *wakeup_intr[4]; |
76 | 76 | ||
77 | static struct mxc_extra_irq tzic_extra_irq = { | ||
78 | #ifdef CONFIG_FIQ | ||
79 | .set_irq_fiq = tzic_set_irq_fiq, | ||
80 | #endif | ||
81 | }; | ||
82 | |||
77 | static __init void tzic_init_gc(unsigned int irq_start) | 83 | static __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 | ||