diff options
author | Pete Popov <ppopov@embeddedalley.com> | 2005-07-19 03:05:36 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:31:56 -0400 |
commit | 3ce86ee14ba7c4b0f8ddae6030df9d0dee15b236 (patch) | |
tree | 9283cd659849be0deaea5fa80b7d8343edd5d926 | |
parent | 7ab1261f5fe421602fadeda1d89662303b08830b (diff) |
Au1x PM fixes.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/au1000/common/irq.c | 32 | ||||
-rw-r--r-- | arch/mips/au1000/common/power.c | 16 | ||||
-rw-r--r-- | arch/mips/au1000/common/time.c | 18 |
3 files changed, 37 insertions, 29 deletions
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 6a25677bf3cb..112beb7fe001 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c | |||
@@ -83,7 +83,7 @@ inline void local_disable_irq(unsigned int irq_nr); | |||
83 | void (*board_init_irq)(void); | 83 | void (*board_init_irq)(void); |
84 | 84 | ||
85 | #ifdef CONFIG_PM | 85 | #ifdef CONFIG_PM |
86 | extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); | 86 | extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs); |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | static DEFINE_SPINLOCK(irq_lock); | 89 | static DEFINE_SPINLOCK(irq_lock); |
@@ -293,29 +293,31 @@ 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 (*handler)(int, void *, struct pt_regs *)) | 296 | void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *)) |
297 | { | 297 | { |
298 | static struct irqaction action; | 298 | struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT]; |
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 | 299 | ||
303 | Give it a bogus "action" pointer -- this will keep it from | 300 | static struct irqaction action; |
304 | getting auto-probed! | 301 | memset(&action, 0, sizeof(struct irqaction)); |
305 | 302 | ||
306 | By setting the status to match that of request_irq() we | 303 | /* This is a big problem.... since we didn't use request_irq |
307 | can avoid it. --cgray | 304 | * when kernel/irq.c calls probe_irq_xxx this interrupt will |
305 | * be probed for usage. This will end up disabling the device :( | ||
306 | * Give it a bogus "action" pointer -- this will keep it from | ||
307 | * getting auto-probed! | ||
308 | * | ||
309 | * By setting the status to match that of request_irq() we | ||
310 | * can avoid it. --cgray | ||
308 | */ | 311 | */ |
309 | action.dev_id = handler; | 312 | action.dev_id = handler; |
310 | action.flags = 0; | 313 | action.flags = SA_INTERRUPT; |
311 | action.mask = 0; | 314 | cpus_clear(action.mask); |
312 | action.name = "Au1xxx TOY"; | 315 | action.name = "Au1xxx TOY"; |
313 | action.handler = handler; | 316 | action.handler = handler; |
314 | action.next = NULL; | 317 | action.next = NULL; |
315 | 318 | ||
316 | irq_desc[AU1000_TOY_MATCH2_INT].action = &action; | 319 | desc->action = &action; |
317 | irq_desc[AU1000_TOY_MATCH2_INT].status | 320 | desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); |
318 | &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); | ||
319 | 321 | ||
320 | local_enable_irq(AU1000_TOY_MATCH2_INT); | 322 | local_enable_irq(AU1000_TOY_MATCH2_INT); |
321 | } | 323 | } |
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c index d3aa067505b4..f85093b8d54d 100644 --- a/arch/mips/au1000/common/power.c +++ b/arch/mips/au1000/common/power.c | |||
@@ -34,11 +34,13 @@ | |||
34 | #include <linux/pm.h> | 34 | #include <linux/pm.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/sysctl.h> | 36 | #include <linux/sysctl.h> |
37 | #include <linux/jiffies.h> | ||
37 | 38 | ||
38 | #include <asm/string.h> | 39 | #include <asm/string.h> |
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
41 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | #include <asm/cacheflush.h> | ||
42 | #include <asm/mach-au1x00/au1000.h> | 44 | #include <asm/mach-au1x00/au1000.h> |
43 | 45 | ||
44 | #ifdef CONFIG_PM | 46 | #ifdef CONFIG_PM |
@@ -50,7 +52,7 @@ | |||
50 | # define DPRINTK(fmt, args...) | 52 | # define DPRINTK(fmt, args...) |
51 | #endif | 53 | #endif |
52 | 54 | ||
53 | static void calibrate_delay(void); | 55 | static void au1000_calibrate_delay(void); |
54 | 56 | ||
55 | extern void set_au1x00_speed(unsigned int new_freq); | 57 | extern void set_au1x00_speed(unsigned int new_freq); |
56 | extern unsigned int get_au1x00_speed(void); | 58 | extern unsigned int get_au1x00_speed(void); |
@@ -260,7 +262,7 @@ int au_sleep(void) | |||
260 | } | 262 | } |
261 | 263 | ||
262 | static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, | 264 | static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, |
263 | void *buffer, size_t * len) | 265 | void __user *buffer, size_t * len, loff_t *ppos) |
264 | { | 266 | { |
265 | int retval = 0; | 267 | int retval = 0; |
266 | #ifdef SLEEP_TEST_TIMEOUT | 268 | #ifdef SLEEP_TEST_TIMEOUT |
@@ -294,7 +296,7 @@ static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, | |||
294 | } | 296 | } |
295 | 297 | ||
296 | static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, | 298 | static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, |
297 | void *buffer, size_t * len) | 299 | void __user *buffer, size_t * len, loff_t *ppos) |
298 | { | 300 | { |
299 | int retval = 0; | 301 | int retval = 0; |
300 | 302 | ||
@@ -313,7 +315,7 @@ static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, | |||
313 | 315 | ||
314 | 316 | ||
315 | static int pm_do_freq(ctl_table * ctl, int write, struct file *file, | 317 | static int pm_do_freq(ctl_table * ctl, int write, struct file *file, |
316 | void *buffer, size_t * len) | 318 | void __user *buffer, size_t * len, loff_t *ppos) |
317 | { | 319 | { |
318 | int retval = 0, i; | 320 | int retval = 0, i; |
319 | unsigned long val, pll; | 321 | unsigned long val, pll; |
@@ -408,14 +410,14 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file, | |||
408 | 410 | ||
409 | 411 | ||
410 | /* We don't want _any_ interrupts other than | 412 | /* We don't want _any_ interrupts other than |
411 | * match20. Otherwise our calibrate_delay() | 413 | * match20. Otherwise our au1000_calibrate_delay() |
412 | * calculation will be off, potentially a lot. | 414 | * calculation will be off, potentially a lot. |
413 | */ | 415 | */ |
414 | intc0_mask = save_local_and_disable(0); | 416 | intc0_mask = save_local_and_disable(0); |
415 | intc1_mask = save_local_and_disable(1); | 417 | intc1_mask = save_local_and_disable(1); |
416 | local_enable_irq(AU1000_TOY_MATCH2_INT); | 418 | local_enable_irq(AU1000_TOY_MATCH2_INT); |
417 | spin_unlock_irqrestore(&pm_lock, flags); | 419 | spin_unlock_irqrestore(&pm_lock, flags); |
418 | calibrate_delay(); | 420 | au1000_calibrate_delay(); |
419 | restore_local_and_enable(0, intc0_mask); | 421 | restore_local_and_enable(0, intc0_mask); |
420 | restore_local_and_enable(1, intc1_mask); | 422 | restore_local_and_enable(1, intc1_mask); |
421 | return retval; | 423 | return retval; |
@@ -455,7 +457,7 @@ __initcall(pm_init); | |||
455 | better than 1% */ | 457 | better than 1% */ |
456 | #define LPS_PREC 8 | 458 | #define LPS_PREC 8 |
457 | 459 | ||
458 | static void calibrate_delay(void) | 460 | static void au1000_calibrate_delay(void) |
459 | { | 461 | { |
460 | unsigned long ticks, loopbit; | 462 | unsigned long ticks, loopbit; |
461 | int lps_precision = LPS_PREC; | 463 | int lps_precision = LPS_PREC; |
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 2f81a0c00442..883d3f3d8c53 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c | |||
@@ -63,8 +63,11 @@ extern int allow_au1k_wait; /* default off for CP0 Counter */ | |||
63 | static unsigned int timerhi = 0, timerlo = 0; | 63 | static unsigned int timerhi = 0, timerlo = 0; |
64 | 64 | ||
65 | #ifdef CONFIG_PM | 65 | #ifdef CONFIG_PM |
66 | #define MATCH20_INC 328 | 66 | #if HZ < 100 || HZ > 1000 |
67 | extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)); | 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 *)); | ||
68 | static unsigned long last_pc0, last_match20; | 71 | static unsigned long last_pc0, last_match20; |
69 | #endif | 72 | #endif |
70 | 73 | ||
@@ -116,17 +119,16 @@ null: | |||
116 | } | 119 | } |
117 | 120 | ||
118 | #ifdef CONFIG_PM | 121 | #ifdef CONFIG_PM |
119 | 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) |
120 | { | 123 | { |
121 | unsigned long pc0; | 124 | unsigned long pc0; |
122 | int time_elapsed; | 125 | int time_elapsed; |
123 | static int jiffie_drift = 0; | 126 | static int jiffie_drift = 0; |
124 | 127 | ||
125 | kstat.irqs[0][irq]++; | ||
126 | if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { | 128 | if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { |
127 | /* should never happen! */ | 129 | /* should never happen! */ |
128 | printk(KERN_WARNING "counter 0 w status eror\n"); | 130 | printk(KERN_WARNING "counter 0 w status error\n"); |
129 | return; | 131 | return IRQ_NONE; |
130 | } | 132 | } |
131 | 133 | ||
132 | pc0 = au_readl(SYS_TOYREAD); | 134 | pc0 = au_readl(SYS_TOYREAD); |
@@ -163,6 +165,8 @@ void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
163 | update_process_times(user_mode(regs)); | 165 | update_process_times(user_mode(regs)); |
164 | #endif | 166 | #endif |
165 | } | 167 | } |
168 | |||
169 | return IRQ_HANDLED; | ||
166 | } | 170 | } |
167 | 171 | ||
168 | /* 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 |
@@ -439,7 +443,7 @@ void au1xxx_timer_setup(struct irqaction *irq) | |||
439 | au_sync(); | 443 | au_sync(); |
440 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); | 444 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); |
441 | 445 | ||
442 | /* setup match20 to interrupt once every 10ms */ | 446 | /* setup match20 to interrupt once every HZ */ |
443 | last_pc0 = last_match20 = au_readl(SYS_TOYREAD); | 447 | last_pc0 = last_match20 = au_readl(SYS_TOYREAD); |
444 | au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); | 448 | au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); |
445 | au_sync(); | 449 | au_sync(); |