Au1x PM fixes.
authorPete Popov <ppopov@embeddedalley.com>
Tue, 19 Jul 2005 07:05:36 +0000 (07:05 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Sat, 29 Oct 2005 18:31:56 +0000 (19:31 +0100)
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/au1000/common/irq.c
arch/mips/au1000/common/power.c
arch/mips/au1000/common/time.c

index 6a25677..112beb7 100644 (file)
@@ -83,7 +83,7 @@ inline void local_disable_irq(unsigned int irq_nr);
 void   (*board_init_irq)(void);
 
 #ifdef CONFIG_PM
-extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
 #endif
 
 static DEFINE_SPINLOCK(irq_lock);
@@ -293,29 +293,31 @@ static struct hw_interrupt_type level_irq_type = {
 };
 
 #ifdef CONFIG_PM
-void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *))
+void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *))
 {
-       static struct irqaction action;
-       /* This is a big problem.... since we didn't use request_irq
-          when kernel/irq.c calls probe_irq_xxx this interrupt will
-          be probed for usage. This will end up disabling the device :(
+       struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT];
 
-       Give it a bogus "action" pointer -- this will keep it from
-          getting auto-probed!
+       static struct irqaction action;
+       memset(&action, 0, sizeof(struct irqaction));
 
-       By setting the status to match that of request_irq() we
-       can avoid it.  --cgray
+       /* This is a big problem.... since we didn't use request_irq
+        * when kernel/irq.c calls probe_irq_xxx this interrupt will
+        * be probed for usage. This will end up disabling the device :(
+        * Give it a bogus "action" pointer -- this will keep it from
+        * getting auto-probed!
+        *
+        * By setting the status to match that of request_irq() we
+        * can avoid it.  --cgray
        */
        action.dev_id = handler;
-       action.flags = 0;
-       action.mask = 0;
+       action.flags = SA_INTERRUPT;
+       cpus_clear(action.mask);
        action.name = "Au1xxx TOY";
        action.handler = handler;
        action.next = NULL;
 
-       irq_desc[AU1000_TOY_MATCH2_INT].action = &action; 
-       irq_desc[AU1000_TOY_MATCH2_INT].status 
-                &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
+       desc->action = &action;
+       desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
 
        local_enable_irq(AU1000_TOY_MATCH2_INT);
 }
index d3aa067..f85093b 100644 (file)
 #include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/jiffies.h>
 
 #include <asm/string.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/cacheflush.h>
 #include <asm/mach-au1x00/au1000.h>
 
 #ifdef CONFIG_PM
@@ -50,7 +52,7 @@
 #  define DPRINTK(fmt, args...)
 #endif
 
-static void calibrate_delay(void);
+static void au1000_calibrate_delay(void);
 
 extern void set_au1x00_speed(unsigned int new_freq);
 extern unsigned int get_au1x00_speed(void);
@@ -260,7 +262,7 @@ int au_sleep(void)
 }
 
 static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
-                      void *buffer, size_t * len)
+                      void __user *buffer, size_t * len, loff_t *ppos)
 {
        int retval = 0;
 #ifdef SLEEP_TEST_TIMEOUT
@@ -294,7 +296,7 @@ static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
 }
 
 static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
-                        void *buffer, size_t * len)
+                        void __user *buffer, size_t * len, loff_t *ppos)
 {
        int retval = 0;
 
@@ -313,7 +315,7 @@ static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
 
 
 static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
-                     void *buffer, size_t * len)
+                     void __user *buffer, size_t * len, loff_t *ppos)
 {
        int retval = 0, i;
        unsigned long val, pll;
@@ -408,14 +410,14 @@ static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
 
 
        /* We don't want _any_ interrupts other than
-        * match20. Otherwise our calibrate_delay()
+        * match20. Otherwise our au1000_calibrate_delay()
         * calculation will be off, potentially a lot.
         */
        intc0_mask = save_local_and_disable(0);
        intc1_mask = save_local_and_disable(1);
        local_enable_irq(AU1000_TOY_MATCH2_INT);
        spin_unlock_irqrestore(&pm_lock, flags);
-       calibrate_delay();
+       au1000_calibrate_delay();
        restore_local_and_enable(0, intc0_mask);
        restore_local_and_enable(1, intc1_mask);
        return retval;
@@ -455,7 +457,7 @@ __initcall(pm_init);
    better than 1% */
 #define LPS_PREC 8
 
-static void calibrate_delay(void)
+static void au1000_calibrate_delay(void)
 {
        unsigned long ticks, loopbit;
        int lps_precision = LPS_PREC;
index 2f81a0c..883d3f3 100644 (file)
@@ -63,8 +63,11 @@ extern int allow_au1k_wait; /* default off for CP0 Counter */
 static unsigned int timerhi = 0, timerlo = 0;
 
 #ifdef CONFIG_PM
-#define MATCH20_INC 328
-extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *));
+#if HZ < 100 || HZ > 1000
+#error "unsupported HZ value! Must be in [100,1000]"
+#endif
+#define MATCH20_INC (328*100/HZ) /* magic number 328 is for HZ=100... */
+extern void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 static unsigned long last_pc0, last_match20;
 #endif
 
@@ -116,17 +119,16 @@ null:
 }
 
 #ifdef CONFIG_PM
-void counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
        unsigned long pc0;
        int time_elapsed;
        static int jiffie_drift = 0;
 
-       kstat.irqs[0][irq]++;
        if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
                /* should never happen! */
-               printk(KERN_WARNING "counter 0 w status eror\n");
-               return;
+               printk(KERN_WARNING "counter 0 w status error\n");
+               return IRQ_NONE;
        }
 
        pc0 = au_readl(SYS_TOYREAD);
@@ -163,6 +165,8 @@ void counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
                update_process_times(user_mode(regs));
 #endif
        }
+
+       return IRQ_HANDLED;
 }
 
 /* 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)
                au_sync();
                while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
 
-               /* setup match20 to interrupt once every 10ms */
+               /* setup match20 to interrupt once every HZ */
                last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
                au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
                au_sync();