URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [mcfwatchdog.c] - Rev 1782
Compare with Previous | Blame | View Log
/***************************************************************************/ /* * linux/drivers/char/mcfwatchdog.c * * Copyright (C) 1999-2000, Greg Ungerer (gerg@moreton.com.au) */ /***************************************************************************/ #include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/param.h> #include <asm/irq.h> #include <asm/traps.h> #include <asm/machdep.h> #include <asm/coldfire.h> #include <asm/mcftimer.h> #include <asm/mcfsim.h> #include <asm/irq.h> #include <asm/delay.h> /***************************************************************************/ /* * Define the watchdog vector. */ #define IRQ_WATCHDOG 250 /***************************************************************************/ void watchdog_alive(unsigned long arg); void watchdog_init(void); void watchdog_timeout(int irq, void *dummy, struct pt_regs *fp); extern void dump(struct pt_regs *fp); /* * Data for registering the watchdog alive routine with ticker. */ struct timer_list watchdog_timerlist = { NULL, NULL, 0, 0, watchdog_alive }; #if CONFIG_OLDMASK /* * The old mask 5307 has a broken watchdog timer. It will interrupt * you regardless of writing to its "alive" register. It can still * be useful but you have to play some tricks with it. This code * supports a clock ticker timeout. If the right number of clock * ticks are not counted then it is assumed that the watchdog saved * us from a bad bus cycle. * * Hardwire the reference counts for different boards. Ugly, but * there is really no other way to hold it all together... */ #ifdef CONFIG_eLIA #define SWTREF_COUNT 37 #else #define SWTREF_COUNT 30 #endif int swt_doit = 0; /* Start delay before tripping */ int swt_lastjiffies = 0; /* Tick count at last watchdog */ int swt_reference = SWTREF_COUNT; /* Refereence tick count */ #endif /***************************************************************************/ /* * Software Watchdog Timer enable. Seems to be the same across all * ColdFire CPu members. */ void watchdog_enable(void) { volatile unsigned char *mbar; mbar = (volatile unsigned char *) MCF_MBAR; *(mbar + MCFSIM_SWSR) = 0x55; *(mbar + MCFSIM_SWSR) = 0xaa; *(mbar + MCFSIM_SYPCR) = 0xbe; } /***************************************************************************/ void watchdog_disable(void) { volatile unsigned char *mbar; mbar = (volatile unsigned char *) MCF_MBAR; *(mbar + MCFSIM_SWSR) = 0x55; *(mbar + MCFSIM_SWSR) = 0xaa; *(mbar + MCFSIM_SYPCR) = 0x00 /*0x3e*/; } /***************************************************************************/ #define TIMEDELAY 45 /* * Process a watchdog timeout interrupt. For a normal clean watchdog * we just do a process dump. For old broken 5307 we need to verify * if this was a real watchdog event or not... */ void watchdog_timeout(int irq, void *dummy, struct pt_regs *fp) { #ifdef CONFIG_OLDMASK /* * Debuging code for software watchdog. If we get in here * and timer interrupt counts don't match we know that a * bad external bus cycle must have locked the CPU. */ if ((swt_doit++ > TIMEDELAY) && ((swt_lastjiffies + swt_reference) > jiffies)) { static int inside = 0; if (inside) { cli(); watchdog_disable(); mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD); printk("%s(%d): Double WATCHDOG PANIC!!\n", __FILE__, __LINE__); for (;;) ; } inside++; swt_doit = TIMEDELAY - 8; /* 8 seconds grace */ printk("WATCHDOG: expired last=%d(%d) jiffies=%d!\n", swt_lastjiffies, swt_reference, jiffies); dump(fp); force_sig(SIGSEGV, current); inside = 0; } swt_lastjiffies = jiffies; #else printk("WATCHDOG: expired!\n"); dump(fp); #endif /* CONFIG_OLDMASK */ } /***************************************************************************/ void watchdog_init(void) { volatile unsigned char *mbar; printk("WATCHDOG: initializing at vector=%d\n", IRQ_WATCHDOG); request_irq(IRQ_WATCHDOG, watchdog_timeout, SA_INTERRUPT, "Watchdog Timer", NULL); watchdog_timerlist.expires = jiffies + 1; add_timer(&watchdog_timerlist); mbar = (volatile unsigned char *) MCF_MBAR; *(mbar + MCFSIM_SWDICR) = MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; *(mbar + MCFSIM_SWIVR) = IRQ_WATCHDOG; mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_SWD); watchdog_enable(); } /***************************************************************************/ void watchdog_alive(unsigned long arg) { volatile unsigned char *mbar; mbar = (volatile unsigned char *) MCF_MBAR; *(mbar + MCFSIM_SWSR) = 0x55; *(mbar + MCFSIM_SWSR) = 0xaa; /* Re-arm the watchdog alive poll */ watchdog_timerlist.expires = jiffies + 1; add_timer(&watchdog_timerlist); } /***************************************************************************/