diff options
Diffstat (limited to 'arch/arm/mach-ixp4xx/common.c')
| -rw-r--r-- | arch/arm/mach-ixp4xx/common.c | 60 |
1 files changed, 22 insertions, 38 deletions
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index c7513f6eb50c..fbe288a8da65 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
| @@ -86,7 +86,8 @@ enum ixp4xx_irq_type { | |||
| 86 | IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE | 86 | IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE |
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); | 89 | /* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */ |
| 90 | static unsigned long long ixp4xx_irq_edge = 0; | ||
| 90 | 91 | ||
| 91 | /* | 92 | /* |
| 92 | * IRQ -> GPIO mapping table | 93 | * IRQ -> GPIO mapping table |
| @@ -135,7 +136,11 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) | |||
| 135 | default: | 136 | default: |
| 136 | return -EINVAL; | 137 | return -EINVAL; |
| 137 | } | 138 | } |
| 138 | ixp4xx_config_irq(irq, irq_type); | 139 | |
| 140 | if (irq_type == IXP4XX_IRQ_EDGE) | ||
| 141 | ixp4xx_irq_edge |= (1 << irq); | ||
| 142 | else | ||
| 143 | ixp4xx_irq_edge &= ~(1 << irq); | ||
| 139 | 144 | ||
| 140 | if (line >= 8) { /* pins 8-15 */ | 145 | if (line >= 8) { /* pins 8-15 */ |
| 141 | line -= 8; | 146 | line -= 8; |
| @@ -167,14 +172,6 @@ static void ixp4xx_irq_mask(unsigned int irq) | |||
| 167 | *IXP4XX_ICMR &= ~(1 << irq); | 172 | *IXP4XX_ICMR &= ~(1 << irq); |
| 168 | } | 173 | } |
| 169 | 174 | ||
| 170 | static void ixp4xx_irq_unmask(unsigned int irq) | ||
| 171 | { | ||
| 172 | if (cpu_is_ixp46x() && irq >= 32) | ||
| 173 | *IXP4XX_ICMR2 |= (1 << (irq - 32)); | ||
| 174 | else | ||
| 175 | *IXP4XX_ICMR |= (1 << irq); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void ixp4xx_irq_ack(unsigned int irq) | 175 | static void ixp4xx_irq_ack(unsigned int irq) |
| 179 | { | 176 | { |
| 180 | int line = (irq < 32) ? irq2gpio[irq] : -1; | 177 | int line = (irq < 32) ? irq2gpio[irq] : -1; |
| @@ -187,41 +184,25 @@ static void ixp4xx_irq_ack(unsigned int irq) | |||
| 187 | * Level triggered interrupts on GPIO lines can only be cleared when the | 184 | * Level triggered interrupts on GPIO lines can only be cleared when the |
| 188 | * interrupt condition disappears. | 185 | * interrupt condition disappears. |
| 189 | */ | 186 | */ |
| 190 | static void ixp4xx_irq_level_unmask(unsigned int irq) | 187 | static void ixp4xx_irq_unmask(unsigned int irq) |
| 191 | { | 188 | { |
| 192 | ixp4xx_irq_ack(irq); | 189 | if (!(ixp4xx_irq_edge & (1 << irq))) |
| 193 | ixp4xx_irq_unmask(irq); | 190 | ixp4xx_irq_ack(irq); |
| 194 | } | ||
| 195 | 191 | ||
| 196 | static struct irqchip ixp4xx_irq_level_chip = { | 192 | if (cpu_is_ixp46x() && irq >= 32) |
| 197 | .ack = ixp4xx_irq_mask, | 193 | *IXP4XX_ICMR2 |= (1 << (irq - 32)); |
| 198 | .mask = ixp4xx_irq_mask, | 194 | else |
| 199 | .unmask = ixp4xx_irq_level_unmask, | 195 | *IXP4XX_ICMR |= (1 << irq); |
| 200 | .set_type = ixp4xx_set_irq_type, | 196 | } |
| 201 | }; | ||
| 202 | 197 | ||
| 203 | static struct irqchip ixp4xx_irq_edge_chip = { | 198 | static struct irqchip ixp4xx_irq_chip = { |
| 199 | .name = "IXP4xx", | ||
| 204 | .ack = ixp4xx_irq_ack, | 200 | .ack = ixp4xx_irq_ack, |
| 205 | .mask = ixp4xx_irq_mask, | 201 | .mask = ixp4xx_irq_mask, |
| 206 | .unmask = ixp4xx_irq_unmask, | 202 | .unmask = ixp4xx_irq_unmask, |
| 207 | .set_type = ixp4xx_set_irq_type, | 203 | .set_type = ixp4xx_set_irq_type, |
| 208 | }; | 204 | }; |
| 209 | 205 | ||
| 210 | static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) | ||
| 211 | { | ||
| 212 | switch (type) { | ||
| 213 | case IXP4XX_IRQ_LEVEL: | ||
| 214 | set_irq_chip(irq, &ixp4xx_irq_level_chip); | ||
| 215 | set_irq_handler(irq, do_level_IRQ); | ||
| 216 | break; | ||
| 217 | case IXP4XX_IRQ_EDGE: | ||
| 218 | set_irq_chip(irq, &ixp4xx_irq_edge_chip); | ||
| 219 | set_irq_handler(irq, do_edge_IRQ); | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | set_irq_flags(irq, IRQF_VALID); | ||
| 223 | } | ||
| 224 | |||
| 225 | void __init ixp4xx_init_irq(void) | 206 | void __init ixp4xx_init_irq(void) |
| 226 | { | 207 | { |
| 227 | int i = 0; | 208 | int i = 0; |
| @@ -241,8 +222,11 @@ void __init ixp4xx_init_irq(void) | |||
| 241 | } | 222 | } |
| 242 | 223 | ||
| 243 | /* Default to all level triggered */ | 224 | /* Default to all level triggered */ |
| 244 | for(i = 0; i < NR_IRQS; i++) | 225 | for(i = 0; i < NR_IRQS; i++) { |
| 245 | ixp4xx_config_irq(i, IXP4XX_IRQ_LEVEL); | 226 | set_irq_chip(i, &ixp4xx_irq_chip); |
| 227 | set_irq_handler(i, do_level_IRQ); | ||
| 228 | set_irq_flags(i, IRQF_VALID); | ||
| 229 | } | ||
| 246 | } | 230 | } |
| 247 | 231 | ||
| 248 | 232 | ||
