diff options
Diffstat (limited to 'arch/mn10300/kernel/irq.c')
| -rw-r--r-- | arch/mn10300/kernel/irq.c | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 761c434a248..56c64ccc9c2 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c | |||
| @@ -20,22 +20,8 @@ EXPORT_SYMBOL(__mn10300_irq_enabled_epsw); | |||
| 20 | atomic_t irq_err_count; | 20 | atomic_t irq_err_count; |
| 21 | 21 | ||
| 22 | /* | 22 | /* |
| 23 | * MN10300 INTC controller operations | 23 | * MN10300 interrupt controller operations |
| 24 | */ | 24 | */ |
| 25 | static void mn10300_cpupic_disable(unsigned int irq) | ||
| 26 | { | ||
| 27 | u16 tmp = GxICR(irq); | ||
| 28 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; | ||
| 29 | tmp = GxICR(irq); | ||
| 30 | } | ||
| 31 | |||
| 32 | static void mn10300_cpupic_enable(unsigned int irq) | ||
| 33 | { | ||
| 34 | u16 tmp = GxICR(irq); | ||
| 35 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; | ||
| 36 | tmp = GxICR(irq); | ||
| 37 | } | ||
| 38 | |||
| 39 | static void mn10300_cpupic_ack(unsigned int irq) | 25 | static void mn10300_cpupic_ack(unsigned int irq) |
| 40 | { | 26 | { |
| 41 | u16 tmp; | 27 | u16 tmp; |
| @@ -60,26 +46,54 @@ static void mn10300_cpupic_mask_ack(unsigned int irq) | |||
| 60 | static void mn10300_cpupic_unmask(unsigned int irq) | 46 | static void mn10300_cpupic_unmask(unsigned int irq) |
| 61 | { | 47 | { |
| 62 | u16 tmp = GxICR(irq); | 48 | u16 tmp = GxICR(irq); |
| 63 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | 49 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; |
| 64 | tmp = GxICR(irq); | 50 | tmp = GxICR(irq); |
| 65 | } | 51 | } |
| 66 | 52 | ||
| 67 | static void mn10300_cpupic_end(unsigned int irq) | 53 | static void mn10300_cpupic_unmask_clear(unsigned int irq) |
| 68 | { | 54 | { |
| 55 | /* the MN10300 PIC latches its interrupt request bit, even after the | ||
| 56 | * device has ceased to assert its interrupt line and the interrupt | ||
| 57 | * channel has been disabled in the PIC, so for level-triggered | ||
| 58 | * interrupts we need to clear the request bit when we re-enable */ | ||
| 69 | u16 tmp = GxICR(irq); | 59 | u16 tmp = GxICR(irq); |
| 70 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; | 60 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; |
| 71 | tmp = GxICR(irq); | 61 | tmp = GxICR(irq); |
| 72 | } | 62 | } |
| 73 | 63 | ||
| 74 | static struct irq_chip mn10300_cpu_pic = { | 64 | /* |
| 75 | .name = "cpu", | 65 | * MN10300 PIC level-triggered IRQ handling. |
| 76 | .disable = mn10300_cpupic_disable, | 66 | * |
| 77 | .enable = mn10300_cpupic_enable, | 67 | * The PIC has no 'ACK' function per se. It is possible to clear individual |
| 68 | * channel latches, but each latch relatches whether or not the channel is | ||
| 69 | * masked, so we need to clear the latch when we unmask the channel. | ||
| 70 | * | ||
| 71 | * Also for this reason, we don't supply an ack() op (it's unused anyway if | ||
| 72 | * mask_ack() is provided), and mask_ack() just masks. | ||
| 73 | */ | ||
| 74 | static struct irq_chip mn10300_cpu_pic_level = { | ||
| 75 | .name = "cpu_l", | ||
| 76 | .disable = mn10300_cpupic_mask, | ||
| 77 | .enable = mn10300_cpupic_unmask_clear, | ||
| 78 | .ack = NULL, | ||
| 79 | .mask = mn10300_cpupic_mask, | ||
| 80 | .mask_ack = mn10300_cpupic_mask, | ||
| 81 | .unmask = mn10300_cpupic_unmask_clear, | ||
| 82 | }; | ||
| 83 | |||
| 84 | /* | ||
| 85 | * MN10300 PIC edge-triggered IRQ handling. | ||
| 86 | * | ||
| 87 | * We use the latch clearing function of the PIC as the 'ACK' function. | ||
| 88 | */ | ||
| 89 | static struct irq_chip mn10300_cpu_pic_edge = { | ||
| 90 | .name = "cpu_e", | ||
| 91 | .disable = mn10300_cpupic_mask, | ||
| 92 | .enable = mn10300_cpupic_unmask, | ||
| 78 | .ack = mn10300_cpupic_ack, | 93 | .ack = mn10300_cpupic_ack, |
| 79 | .mask = mn10300_cpupic_mask, | 94 | .mask = mn10300_cpupic_mask, |
| 80 | .mask_ack = mn10300_cpupic_mask_ack, | 95 | .mask_ack = mn10300_cpupic_mask_ack, |
| 81 | .unmask = mn10300_cpupic_unmask, | 96 | .unmask = mn10300_cpupic_unmask, |
| 82 | .end = mn10300_cpupic_end, | ||
| 83 | }; | 97 | }; |
| 84 | 98 | ||
| 85 | /* | 99 | /* |
| @@ -114,7 +128,8 @@ void set_intr_level(int irq, u16 level) | |||
| 114 | */ | 128 | */ |
| 115 | void set_intr_postackable(int irq) | 129 | void set_intr_postackable(int irq) |
| 116 | { | 130 | { |
| 117 | set_irq_handler(irq, handle_level_irq); | 131 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, |
| 132 | handle_level_irq); | ||
| 118 | } | 133 | } |
| 119 | 134 | ||
| 120 | /* | 135 | /* |
| @@ -126,8 +141,12 @@ void __init init_IRQ(void) | |||
| 126 | 141 | ||
| 127 | for (irq = 0; irq < NR_IRQS; irq++) | 142 | for (irq = 0; irq < NR_IRQS; irq++) |
| 128 | if (irq_desc[irq].chip == &no_irq_type) | 143 | if (irq_desc[irq].chip == &no_irq_type) |
| 129 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic, | 144 | /* due to the PIC latching interrupt requests, even |
| 130 | handle_edge_irq); | 145 | * when the IRQ is disabled, IRQ_PENDING is superfluous |
| 146 | * and we can use handle_level_irq() for edge-triggered | ||
| 147 | * interrupts */ | ||
| 148 | set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, | ||
| 149 | handle_level_irq); | ||
| 131 | unit_init_IRQ(); | 150 | unit_init_IRQ(); |
| 132 | } | 151 | } |
| 133 | 152 | ||
