diff options
author | Pete Popov <ppopov@embeddedalley.com> | 2005-03-13 03:19:05 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:30:56 -0400 |
commit | a3701ca48763bbc681ee8db3d203827975849185 (patch) | |
tree | 9677ce80fb2dd3db49394665ddd1ca4f3bf8f2d5 /arch | |
parent | 90a67b5909ed39425fd2402b2b4c46ef1372b300 (diff) |
When CONFIG_PM is enabled, it uses the TOY_MATCH2 interrupt as the system
timer tick. Prior to this patch, if IDE IRQ probing occured, then the
TOY_MATCH2 interrupt would be permanently disabled, and no system timer
tick occurs. This patch corrects this situation by correctly registering
the TOY_MATCH2 interrupt so that IDE IRQ probing doesn't have adverse
side effects.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/au1000/common/irq.c | 36 | ||||
-rw-r--r-- | arch/mips/au1000/common/time.c | 5 |
2 files changed, 26 insertions, 15 deletions
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index ebf93bdbad14..6a25677bf3cb 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c | |||
@@ -293,8 +293,30 @@ static struct hw_interrupt_type level_irq_type = { | |||
293 | }; | 293 | }; |
294 | 294 | ||
295 | #ifdef CONFIG_PM | 295 | #ifdef CONFIG_PM |
296 | void startup_match20_interrupt(void) | 296 | void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)) |
297 | { | 297 | { |
298 | static struct irqaction action; | ||
299 | /* This is a big problem.... since we didn't use request_irq | ||
300 | when kernel/irq.c calls probe_irq_xxx this interrupt will | ||
301 | be probed for usage. This will end up disabling the device :( | ||
302 | |||
303 | Give it a bogus "action" pointer -- this will keep it from | ||
304 | getting auto-probed! | ||
305 | |||
306 | By setting the status to match that of request_irq() we | ||
307 | can avoid it. --cgray | ||
308 | */ | ||
309 | action.dev_id = handler; | ||
310 | action.flags = 0; | ||
311 | action.mask = 0; | ||
312 | action.name = "Au1xxx TOY"; | ||
313 | action.handler = handler; | ||
314 | action.next = NULL; | ||
315 | |||
316 | irq_desc[AU1000_TOY_MATCH2_INT].action = &action; | ||
317 | irq_desc[AU1000_TOY_MATCH2_INT].status | ||
318 | &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); | ||
319 | |||
298 | local_enable_irq(AU1000_TOY_MATCH2_INT); | 320 | local_enable_irq(AU1000_TOY_MATCH2_INT); |
299 | } | 321 | } |
300 | #endif | 322 | #endif |
@@ -517,17 +539,7 @@ void intc0_req1_irqdispatch(struct pt_regs *regs) | |||
517 | 539 | ||
518 | irq = au_ffs(intc0_req1) - 1; | 540 | irq = au_ffs(intc0_req1) - 1; |
519 | intc0_req1 &= ~(1<<irq); | 541 | intc0_req1 &= ~(1<<irq); |
520 | #ifdef CONFIG_PM | 542 | do_IRQ(irq, regs); |
521 | if (irq == AU1000_TOY_MATCH2_INT) { | ||
522 | mask_and_ack_rise_edge_irq(irq); | ||
523 | counter0_irq(irq, NULL, regs); | ||
524 | local_enable_irq(irq); | ||
525 | } | ||
526 | else | ||
527 | #endif | ||
528 | { | ||
529 | do_IRQ(irq, regs); | ||
530 | } | ||
531 | } | 543 | } |
532 | 544 | ||
533 | 545 | ||
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 57675b41480e..90a0755c832b 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <linux/mc146818rtc.h> | 50 | #include <linux/mc146818rtc.h> |
51 | #include <linux/timex.h> | 51 | #include <linux/timex.h> |
52 | 52 | ||
53 | extern void startup_match20_interrupt(void); | ||
54 | extern void do_softirq(void); | 53 | extern void do_softirq(void); |
55 | extern volatile unsigned long wall_jiffies; | 54 | extern volatile unsigned long wall_jiffies; |
56 | unsigned long missed_heart_beats = 0; | 55 | unsigned long missed_heart_beats = 0; |
@@ -65,7 +64,7 @@ static unsigned int timerhi = 0, timerlo = 0; | |||
65 | 64 | ||
66 | #ifdef CONFIG_PM | 65 | #ifdef CONFIG_PM |
67 | #define MATCH20_INC 328 | 66 | #define MATCH20_INC 328 |
68 | extern void startup_match20_interrupt(void); | 67 | extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)); |
69 | static unsigned long last_pc0, last_match20; | 68 | static unsigned long last_pc0, last_match20; |
70 | #endif | 69 | #endif |
71 | 70 | ||
@@ -446,7 +445,7 @@ void au1xxx_timer_setup(struct irqaction *irq) | |||
446 | au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); | 445 | au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); |
447 | au_sync(); | 446 | au_sync(); |
448 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); | 447 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); |
449 | startup_match20_interrupt(); | 448 | startup_match20_interrupt(counter0_irq); |
450 | 449 | ||
451 | do_gettimeoffset = do_fast_pm_gettimeoffset; | 450 | do_gettimeoffset = do_fast_pm_gettimeoffset; |
452 | 451 | ||