aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/au1000
diff options
context:
space:
mode:
authorPete Popov <ppopov@embeddedalley.com>2005-07-19 03:05:36 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:31:56 -0400
commit3ce86ee14ba7c4b0f8ddae6030df9d0dee15b236 (patch)
tree9283cd659849be0deaea5fa80b7d8343edd5d926 /arch/mips/au1000
parent7ab1261f5fe421602fadeda1d89662303b08830b (diff)
Au1x PM fixes.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/au1000')
-rw-r--r--arch/mips/au1000/common/irq.c32
-rw-r--r--arch/mips/au1000/common/power.c16
-rw-r--r--arch/mips/au1000/common/time.c18
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);
83void (*board_init_irq)(void); 83void (*board_init_irq)(void);
84 84
85#ifdef CONFIG_PM 85#ifdef CONFIG_PM
86extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); 86extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
87#endif 87#endif
88 88
89static DEFINE_SPINLOCK(irq_lock); 89static 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
296void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)) 296void 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
53static void calibrate_delay(void); 55static void au1000_calibrate_delay(void);
54 56
55extern void set_au1x00_speed(unsigned int new_freq); 57extern void set_au1x00_speed(unsigned int new_freq);
56extern unsigned int get_au1x00_speed(void); 58extern unsigned int get_au1x00_speed(void);
@@ -260,7 +262,7 @@ int au_sleep(void)
260} 262}
261 263
262static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, 264static 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
296static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, 298static 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
315static int pm_do_freq(ctl_table * ctl, int write, struct file *file, 317static 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
458static void calibrate_delay(void) 460static 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 */
63static unsigned int timerhi = 0, timerlo = 0; 63static 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
67extern 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... */
70extern void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *));
68static unsigned long last_pc0, last_match20; 71static 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
119void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) 122irqreturn_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();