diff options
Diffstat (limited to 'arch/mips/au1000/common/time.c')
-rw-r--r-- | arch/mips/au1000/common/time.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 57675b41480e..883d3f3d8c53 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; |
@@ -58,14 +57,17 @@ unsigned long missed_heart_beats = 0; | |||
58 | static unsigned long r4k_offset; /* Amount to increment compare reg each time */ | 57 | static unsigned long r4k_offset; /* Amount to increment compare reg each time */ |
59 | static unsigned long r4k_cur; /* What counter should be at next timer irq */ | 58 | static unsigned long r4k_cur; /* What counter should be at next timer irq */ |
60 | int no_au1xxx_32khz; | 59 | int no_au1xxx_32khz; |
61 | void (*au1k_wait_ptr)(void); | 60 | extern int allow_au1k_wait; /* default off for CP0 Counter */ |
62 | 61 | ||
63 | /* Cycle counter value at the previous timer interrupt.. */ | 62 | /* Cycle counter value at the previous timer interrupt.. */ |
64 | static unsigned int timerhi = 0, timerlo = 0; | 63 | static unsigned int timerhi = 0, timerlo = 0; |
65 | 64 | ||
66 | #ifdef CONFIG_PM | 65 | #ifdef CONFIG_PM |
67 | #define MATCH20_INC 328 | 66 | #if HZ < 100 || HZ > 1000 |
68 | extern void startup_match20_interrupt(void); | 67 | #error "unsupported HZ value! Must be in [100,1000]" |
68 | #endif | ||
69 | #define MATCH20_INC (328*100/HZ) /* magic number 328 is for HZ=100... */ | ||
70 | extern void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *)); | ||
69 | static unsigned long last_pc0, last_match20; | 71 | static unsigned long last_pc0, last_match20; |
70 | #endif | 72 | #endif |
71 | 73 | ||
@@ -117,17 +119,16 @@ null: | |||
117 | } | 119 | } |
118 | 120 | ||
119 | #ifdef CONFIG_PM | 121 | #ifdef CONFIG_PM |
120 | void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) | 122 | irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs) |
121 | { | 123 | { |
122 | unsigned long pc0; | 124 | unsigned long pc0; |
123 | int time_elapsed; | 125 | int time_elapsed; |
124 | static int jiffie_drift = 0; | 126 | static int jiffie_drift = 0; |
125 | 127 | ||
126 | kstat.irqs[0][irq]++; | ||
127 | if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { | 128 | if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { |
128 | /* should never happen! */ | 129 | /* should never happen! */ |
129 | printk(KERN_WARNING "counter 0 w status eror\n"); | 130 | printk(KERN_WARNING "counter 0 w status error\n"); |
130 | return; | 131 | return IRQ_NONE; |
131 | } | 132 | } |
132 | 133 | ||
133 | pc0 = au_readl(SYS_TOYREAD); | 134 | pc0 = au_readl(SYS_TOYREAD); |
@@ -164,6 +165,8 @@ void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
164 | update_process_times(user_mode(regs)); | 165 | update_process_times(user_mode(regs)); |
165 | #endif | 166 | #endif |
166 | } | 167 | } |
168 | |||
169 | return IRQ_HANDLED; | ||
167 | } | 170 | } |
168 | 171 | ||
169 | /* When we wakeup from sleep, we have to "catch up" on all of the | 172 | /* When we wakeup from sleep, we have to "catch up" on all of the |
@@ -388,7 +391,6 @@ void au1xxx_timer_setup(struct irqaction *irq) | |||
388 | { | 391 | { |
389 | unsigned int est_freq; | 392 | unsigned int est_freq; |
390 | extern unsigned long (*do_gettimeoffset)(void); | 393 | extern unsigned long (*do_gettimeoffset)(void); |
391 | extern void au1k_wait(void); | ||
392 | 394 | ||
393 | printk("calculating r4koff... "); | 395 | printk("calculating r4koff... "); |
394 | r4k_offset = cal_r4koff(); | 396 | r4k_offset = cal_r4koff(); |
@@ -441,18 +443,18 @@ void au1xxx_timer_setup(struct irqaction *irq) | |||
441 | au_sync(); | 443 | au_sync(); |
442 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); | 444 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); |
443 | 445 | ||
444 | /* setup match20 to interrupt once every 10ms */ | 446 | /* setup match20 to interrupt once every HZ */ |
445 | last_pc0 = last_match20 = au_readl(SYS_TOYREAD); | 447 | last_pc0 = last_match20 = au_readl(SYS_TOYREAD); |
446 | au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); | 448 | au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); |
447 | au_sync(); | 449 | au_sync(); |
448 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); | 450 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); |
449 | startup_match20_interrupt(); | 451 | startup_match20_interrupt(counter0_irq); |
450 | 452 | ||
451 | do_gettimeoffset = do_fast_pm_gettimeoffset; | 453 | do_gettimeoffset = do_fast_pm_gettimeoffset; |
452 | 454 | ||
453 | /* We can use the real 'wait' instruction. | 455 | /* We can use the real 'wait' instruction. |
454 | */ | 456 | */ |
455 | au1k_wait_ptr = au1k_wait; | 457 | allow_au1k_wait = 1; |
456 | } | 458 | } |
457 | 459 | ||
458 | #else | 460 | #else |