Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3701ca4 authored by Pete Popov's avatar Pete Popov Committed by Ralf Baechle
Browse files

When CONFIG_PM is enabled, it uses the TOY_MATCH2 interrupt as the system


timer tick. Prior to this patch, if IDE IRQ probing occured, then the
TOY_MATCH2 interrupt would be permanently disabled, and no system timer
tick occurs. This patch corrects this situation by correctly registering
the TOY_MATCH2 interrupt so that IDE IRQ probing doesn't have adverse
side effects.

Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 90a67b59
Loading
Loading
Loading
Loading
+24 −12
Original line number Diff line number Diff line
@@ -293,8 +293,30 @@ static struct hw_interrupt_type level_irq_type = {
};

#ifdef CONFIG_PM
void startup_match20_interrupt(void)
void startup_match20_interrupt(void (*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 :(

       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.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);

	local_enable_irq(AU1000_TOY_MATCH2_INT);
}
#endif
@@ -517,18 +539,8 @@ void intc0_req1_irqdispatch(struct pt_regs *regs)

	irq = au_ffs(intc0_req1) - 1;
	intc0_req1 &= ~(1<<irq);
#ifdef CONFIG_PM
	if (irq == AU1000_TOY_MATCH2_INT) {
		mask_and_ack_rise_edge_irq(irq);
		counter0_irq(irq, NULL, regs);
		local_enable_irq(irq);
	}
	else
#endif
	{
	do_IRQ(irq, regs);
}
}


/*
+2 −3
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@
#include <linux/mc146818rtc.h>
#include <linux/timex.h>

extern void startup_match20_interrupt(void);
extern void do_softirq(void);
extern volatile unsigned long wall_jiffies;
unsigned long missed_heart_beats = 0;
@@ -65,7 +64,7 @@ static unsigned int timerhi = 0, timerlo = 0;

#ifdef CONFIG_PM
#define MATCH20_INC 328
extern void startup_match20_interrupt(void);
extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *));
static unsigned long last_pc0, last_match20;
#endif

@@ -446,7 +445,7 @@ void au1xxx_timer_setup(struct irqaction *irq)
		au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
		au_sync();
		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
		startup_match20_interrupt();
		startup_match20_interrupt(counter0_irq);

		do_gettimeoffset = do_fast_pm_gettimeoffset;