Loading arch/mips/au1000/common/irq.c +17 −15 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); } Loading arch/mips/au1000/common/power.c +9 −7 Original line number Diff line number Diff line Loading @@ -34,11 +34,13 @@ #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 Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading arch/mips/au1000/common/time.c +11 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -116,17 +119,16 @@ void mips_timer_interrupt(struct pt_regs *regs) } #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); Loading Loading @@ -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 Loading Loading @@ -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(); Loading Loading
arch/mips/au1000/common/irq.c +17 −15 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); } Loading
arch/mips/au1000/common/power.c +9 −7 Original line number Diff line number Diff line Loading @@ -34,11 +34,13 @@ #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 Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading
arch/mips/au1000/common/time.c +11 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -116,17 +119,16 @@ void mips_timer_interrupt(struct pt_regs *regs) } #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); Loading Loading @@ -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 Loading Loading @@ -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(); Loading