aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/vr41xx/common/irq.c12
-rw-r--r--drivers/char/vr41xx_giu.c114
2 files changed, 61 insertions, 65 deletions
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 397ba94cd7e..16decf4ac2f 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 a744dad9cf4..0cea8d4907d 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
128static unsigned int startup_giuint_low_irq(unsigned int irq) 128static 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
139static void shutdown_giuint_low_irq(unsigned int irq) 133static 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
144static void enable_giuint_low_irq(unsigned int irq) 138static 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
151static 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
160static void end_giuint_low_irq(unsigned int irq) 147static 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
166static struct hw_interrupt_type giuint_low_irq_type = { 152static 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
176static unsigned int startup_giuint_high_irq(unsigned int irq) 160static 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
187static void shutdown_giuint_high_irq(unsigned int irq) 165static 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
192static void enable_giuint_high_irq(unsigned int irq) 170static 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
199static 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
208static void end_giuint_high_irq(unsigned int irq) 179static 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
214static struct hw_interrupt_type giuint_high_irq_type = { 184static 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
224static int giu_get_irq(unsigned int irq) 192static 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 = {
617static int __devinit giu_probe(struct platform_device *dev) 597static 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);