diff options
| -rw-r--r-- | arch/mips/vr41xx/common/irq.c | 12 | ||||
| -rw-r--r-- | drivers/char/vr41xx_giu.c | 114 |
2 files changed, 61 insertions, 65 deletions
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 397ba94cd7ec..16decf4ac2f4 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Interrupt handing routines for NEC VR4100 series. | 2 | * Interrupt handing routines for NEC VR4100 series. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq) | |||
| 73 | if (cascade->get_irq != NULL) { | 73 | if (cascade->get_irq != NULL) { |
| 74 | unsigned int source_irq = irq; | 74 | unsigned int source_irq = irq; |
| 75 | desc = irq_desc + source_irq; | 75 | desc = irq_desc + source_irq; |
| 76 | desc->chip->ack(source_irq); | 76 | if (desc->chip->mask_ack) |
| 77 | desc->chip->mask_ack(source_irq); | ||
| 78 | else { | ||
| 79 | desc->chip->mask(source_irq); | ||
| 80 | desc->chip->ack(source_irq); | ||
| 81 | } | ||
| 77 | irq = cascade->get_irq(irq); | 82 | irq = cascade->get_irq(irq); |
| 78 | if (irq < 0) | 83 | if (irq < 0) |
| 79 | atomic_inc(&irq_err_count); | 84 | atomic_inc(&irq_err_count); |
| 80 | else | 85 | else |
| 81 | irq_dispatch(irq); | 86 | irq_dispatch(irq); |
| 82 | desc->chip->end(source_irq); | 87 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) |
| 88 | desc->chip->unmask(source_irq); | ||
| 83 | } else | 89 | } else |
| 84 | do_IRQ(irq); | 90 | do_IRQ(irq); |
| 85 | } | 91 | } |
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index a744dad9cf45..0cea8d4907df 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 MontaVista Software Inc. | 4 | * Copyright (C) 2002 MontaVista Software Inc. |
| 5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | 5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> |
| 6 | * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 6 | * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
| 7 | * | 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
| @@ -125,30 +125,17 @@ static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) | |||
| 125 | return data; | 125 | return data; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | static unsigned int startup_giuint_low_irq(unsigned int irq) | 128 | static void ack_giuint_low(unsigned int irq) |
| 129 | { | 129 | { |
| 130 | unsigned int pin; | 130 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); |
| 131 | |||
| 132 | pin = GPIO_PIN_OF_IRQ(irq); | ||
| 133 | giu_write(GIUINTSTATL, 1 << pin); | ||
| 134 | giu_set(GIUINTENL, 1 << pin); | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | 131 | } |
| 138 | 132 | ||
| 139 | static void shutdown_giuint_low_irq(unsigned int irq) | 133 | static void mask_giuint_low(unsigned int irq) |
| 140 | { | 134 | { |
| 141 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | 135 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); |
| 142 | } | 136 | } |
| 143 | 137 | ||
| 144 | static void enable_giuint_low_irq(unsigned int irq) | 138 | static void mask_ack_giuint_low(unsigned int irq) |
| 145 | { | ||
| 146 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 147 | } | ||
| 148 | |||
| 149 | #define disable_giuint_low_irq shutdown_giuint_low_irq | ||
| 150 | |||
| 151 | static void ack_giuint_low_irq(unsigned int irq) | ||
| 152 | { | 139 | { |
| 153 | unsigned int pin; | 140 | unsigned int pin; |
| 154 | 141 | ||
| @@ -157,46 +144,30 @@ static void ack_giuint_low_irq(unsigned int irq) | |||
| 157 | giu_write(GIUINTSTATL, 1 << pin); | 144 | giu_write(GIUINTSTATL, 1 << pin); |
| 158 | } | 145 | } |
| 159 | 146 | ||
| 160 | static void end_giuint_low_irq(unsigned int irq) | 147 | static void unmask_giuint_low(unsigned int irq) |
| 161 | { | 148 | { |
| 162 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 149 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); |
| 163 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 164 | } | 150 | } |
| 165 | 151 | ||
| 166 | static struct hw_interrupt_type giuint_low_irq_type = { | 152 | static struct irq_chip giuint_low_irq_chip = { |
| 167 | .typename = "GIUINTL", | 153 | .name = "GIUINTL", |
| 168 | .startup = startup_giuint_low_irq, | 154 | .ack = ack_giuint_low, |
| 169 | .shutdown = shutdown_giuint_low_irq, | 155 | .mask = mask_giuint_low, |
| 170 | .enable = enable_giuint_low_irq, | 156 | .mask_ack = mask_ack_giuint_low, |
| 171 | .disable = disable_giuint_low_irq, | 157 | .unmask = unmask_giuint_low, |
| 172 | .ack = ack_giuint_low_irq, | ||
| 173 | .end = end_giuint_low_irq, | ||
| 174 | }; | 158 | }; |
| 175 | 159 | ||
| 176 | static unsigned int startup_giuint_high_irq(unsigned int irq) | 160 | static void ack_giuint_high(unsigned int irq) |
| 177 | { | 161 | { |
| 178 | unsigned int pin; | 162 | giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
| 179 | |||
| 180 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
| 181 | giu_write(GIUINTSTATH, 1 << pin); | ||
| 182 | giu_set(GIUINTENH, 1 << pin); | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | 163 | } |
| 186 | 164 | ||
| 187 | static void shutdown_giuint_high_irq(unsigned int irq) | 165 | static void mask_giuint_high(unsigned int irq) |
| 188 | { | 166 | { |
| 189 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | 167 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
| 190 | } | 168 | } |
| 191 | 169 | ||
| 192 | static void enable_giuint_high_irq(unsigned int irq) | 170 | static void mask_ack_giuint_high(unsigned int irq) |
| 193 | { | ||
| 194 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 195 | } | ||
| 196 | |||
| 197 | #define disable_giuint_high_irq shutdown_giuint_high_irq | ||
| 198 | |||
| 199 | static void ack_giuint_high_irq(unsigned int irq) | ||
| 200 | { | 171 | { |
| 201 | unsigned int pin; | 172 | unsigned int pin; |
| 202 | 173 | ||
| @@ -205,20 +176,17 @@ static void ack_giuint_high_irq(unsigned int irq) | |||
| 205 | giu_write(GIUINTSTATH, 1 << pin); | 176 | giu_write(GIUINTSTATH, 1 << pin); |
| 206 | } | 177 | } |
| 207 | 178 | ||
| 208 | static void end_giuint_high_irq(unsigned int irq) | 179 | static void unmask_giuint_high(unsigned int irq) |
| 209 | { | 180 | { |
| 210 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 181 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
| 211 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 212 | } | 182 | } |
| 213 | 183 | ||
| 214 | static struct hw_interrupt_type giuint_high_irq_type = { | 184 | static struct irq_chip giuint_high_irq_chip = { |
| 215 | .typename = "GIUINTH", | 185 | .name = "GIUINTH", |
| 216 | .startup = startup_giuint_high_irq, | 186 | .ack = ack_giuint_high, |
| 217 | .shutdown = shutdown_giuint_high_irq, | 187 | .mask = mask_giuint_high, |
| 218 | .enable = enable_giuint_high_irq, | 188 | .mask_ack = mask_ack_giuint_high, |
| 219 | .disable = disable_giuint_high_irq, | 189 | .unmask = unmask_giuint_high, |
| 220 | .ack = ack_giuint_high_irq, | ||
| 221 | .end = end_giuint_high_irq, | ||
| 222 | }; | 190 | }; |
| 223 | 191 | ||
| 224 | static int giu_get_irq(unsigned int irq) | 192 | static int giu_get_irq(unsigned int irq) |
| @@ -282,9 +250,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
| 282 | break; | 250 | break; |
| 283 | } | 251 | } |
| 284 | } | 252 | } |
| 253 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 254 | &giuint_low_irq_chip, | ||
| 255 | handle_edge_irq); | ||
| 285 | } else { | 256 | } else { |
| 286 | giu_clear(GIUINTTYPL, mask); | 257 | giu_clear(GIUINTTYPL, mask); |
| 287 | giu_clear(GIUINTHTSELL, mask); | 258 | giu_clear(GIUINTHTSELL, mask); |
| 259 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 260 | &giuint_low_irq_chip, | ||
| 261 | handle_level_irq); | ||
| 288 | } | 262 | } |
| 289 | giu_write(GIUINTSTATL, mask); | 263 | giu_write(GIUINTSTATL, mask); |
| 290 | } else if (pin < GIUINT_HIGH_MAX) { | 264 | } else if (pin < GIUINT_HIGH_MAX) { |
| @@ -311,9 +285,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
| 311 | break; | 285 | break; |
| 312 | } | 286 | } |
| 313 | } | 287 | } |
| 288 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 289 | &giuint_high_irq_chip, | ||
| 290 | handle_edge_irq); | ||
| 314 | } else { | 291 | } else { |
| 315 | giu_clear(GIUINTTYPH, mask); | 292 | giu_clear(GIUINTTYPH, mask); |
| 316 | giu_clear(GIUINTHTSELH, mask); | 293 | giu_clear(GIUINTHTSELH, mask); |
| 294 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 295 | &giuint_high_irq_chip, | ||
| 296 | handle_level_irq); | ||
| 317 | } | 297 | } |
| 318 | giu_write(GIUINTSTATH, mask); | 298 | giu_write(GIUINTSTATH, mask); |
| 319 | } | 299 | } |
| @@ -617,10 +597,11 @@ static const struct file_operations gpio_fops = { | |||
| 617 | static int __devinit giu_probe(struct platform_device *dev) | 597 | static int __devinit giu_probe(struct platform_device *dev) |
| 618 | { | 598 | { |
| 619 | unsigned long start, size, flags = 0; | 599 | unsigned long start, size, flags = 0; |
| 620 | unsigned int nr_pins = 0; | 600 | unsigned int nr_pins = 0, trigger, i, pin; |
| 621 | struct resource *res1, *res2 = NULL; | 601 | struct resource *res1, *res2 = NULL; |
| 622 | void *base; | 602 | void *base; |
| 623 | int retval, i; | 603 | struct irq_chip *chip; |
| 604 | int retval; | ||
| 624 | 605 | ||
| 625 | switch (current_cpu_data.cputype) { | 606 | switch (current_cpu_data.cputype) { |
| 626 | case CPU_VR4111: | 607 | case CPU_VR4111: |
| @@ -688,11 +669,20 @@ static int __devinit giu_probe(struct platform_device *dev) | |||
| 688 | giu_write(GIUINTENL, 0); | 669 | giu_write(GIUINTENL, 0); |
| 689 | giu_write(GIUINTENH, 0); | 670 | giu_write(GIUINTENH, 0); |
| 690 | 671 | ||
| 672 | trigger = giu_read(GIUINTTYPH) << 16; | ||
| 673 | trigger |= giu_read(GIUINTTYPL); | ||
| 691 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | 674 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { |
| 692 | if (i < GIU_IRQ(GIUINT_HIGH_OFFSET)) | 675 | pin = GPIO_PIN_OF_IRQ(i); |
| 693 | irq_desc[i].chip = &giuint_low_irq_type; | 676 | if (pin < GIUINT_HIGH_OFFSET) |
| 677 | chip = &giuint_low_irq_chip; | ||
| 694 | else | 678 | else |
| 695 | irq_desc[i].chip = &giuint_high_irq_type; | 679 | chip = &giuint_high_irq_chip; |
| 680 | |||
| 681 | if (trigger & (1 << pin)) | ||
| 682 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
| 683 | else | ||
| 684 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
| 685 | |||
| 696 | } | 686 | } |
| 697 | 687 | ||
| 698 | return cascade_irq(GIUINT_IRQ, giu_get_irq); | 688 | return cascade_irq(GIUINT_IRQ, giu_get_irq); |
