Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S263097AbTI3EA3 (ORCPT ); Tue, 30 Sep 2003 00:00:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S263100AbTI3EA3 (ORCPT ); Tue, 30 Sep 2003 00:00:29 -0400 Received: from dsl-082-082-146-170.arcor-ip.net ([82.82.146.170]:17416 "HELO obi.mine.nu") by vger.kernel.org with SMTP id S263097AbTI3EAA (ORCPT ); Tue, 30 Sep 2003 00:00:00 -0400 Subject: [PATCH] mpc8xx watchdog timer (2.4.22-bk26) From: Andreas Oberritter To: linux-kernel@vger.kernel.org Cc: Tom Rini , Florian Schirmer Content-Type: multipart/mixed; boundary="=-4RsDp59Ksh2QAtrQwGfm" Message-Id: <1064894394.821.107.camel@shiva.eth.saftware.de> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.4.3 Date: 30 Sep 2003 05:59:55 +0200 Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org --=-4RsDp59Ksh2QAtrQwGfm Content-Type: text/plain Content-Transfer-Encoding: 7bit Hi, the attached patch adds support for the internal watchdog of the mpc8xx series of CPUs including the watchdog user space interface. It has been tested on the D-Box2 board which requires this patch because the watchdog timer is enabled by its boot loader. It should work on other 8xx boards as well. Any comments? Regards, Andreas --=-4RsDp59Ksh2QAtrQwGfm Content-Disposition: attachment; filename=linux-2.4.22-bk26-m8xxwdt.diff Content-Type: text/plain; name=linux-2.4.22-bk26-m8xxwdt.diff; charset=iso-8859-15 Content-Transfer-Encoding: 7bit ===== arch/ppc/kernel/Makefile 1.34 vs edited ===== --- 1.34/arch/ppc/kernel/Makefile Fri Aug 29 06:31:27 2003 +++ edited/arch/ppc/kernel/Makefile Tue Sep 30 05:01:44 2003 @@ -64,6 +64,9 @@ obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o +ifdef CONFIG_8xx_WDT +obj-y += m8xx_wdt.o +endif ifeq ($(CONFIG_8xx),y) obj-$(CONFIG_PCI) += qspan_pci.o ifndef CONFIG_MATH_EMULATION ===== arch/ppc/kernel/m8xx_setup.c 1.22 vs edited ===== --- 1.22/arch/ppc/kernel/m8xx_setup.c Thu Jul 3 18:56:34 2003 +++ edited/arch/ppc/kernel/m8xx_setup.c Tue Sep 30 05:01:46 2003 @@ -58,6 +58,7 @@ extern unsigned long find_available_memory(void); extern void m8xx_cpm_reset(uint); +extern void m8xx_wdt_handler_install(bd_t *bp); void __init m8xx_setup_arch(void) @@ -184,6 +185,13 @@ if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0) panic("Could not allocate timer IRQ!"); + +#ifdef CONFIG_8xx_WDT + /* Install watchdog timer handler early because it might be + * already enabled by the bootloader + */ + m8xx_wdt_handler_install(binfo); +#endif } /* The RTC on the MPC8xx is an internal register. ===== arch/ppc/kernel/ppc_ksyms.c 1.36 vs edited ===== --- 1.36/arch/ppc/kernel/ppc_ksyms.c Sat Sep 27 06:10:40 2003 +++ edited/arch/ppc/kernel/ppc_ksyms.c Tue Sep 30 05:33:27 2003 @@ -357,6 +357,12 @@ EXPORT_SYMBOL(cpm_free_handler); EXPORT_SYMBOL(m8xx_cpm_hostalloc); EXPORT_SYMBOL(m8xx_cpm_dpalloc); +#ifdef CONFIG_8xx_WDT +extern int m8xx_wdt_get_timeout(void); +extern void m8xx_wdt_reset(void); +EXPORT_SYMBOL(m8xx_wdt_get_timeout); +EXPORT_SYMBOL(m8xx_wdt_reset); +#endif /* CONFIG_8xx_WDT */ #endif /* CONFIG_8xx */ /* Those should really be inline */ ===== drivers/char/Config.in 1.58 vs edited ===== --- 1.58/drivers/char/Config.in Thu Sep 25 05:54:18 2003 +++ edited/drivers/char/Config.in Tue Sep 30 05:01:48 2003 @@ -254,6 +254,7 @@ fi tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT dep_tristate ' AMD 766/768 TCO Timer/Watchdog' CONFIG_AMD7XX_TCO $CONFIG_EXPERIMENTAL + dep_tristate ' MPC8xx Watchdog Timer' CONFIG_8xx_WDT $CONFIG_8xx fi endmenu ===== drivers/char/Makefile 1.37 vs edited ===== --- 1.37/drivers/char/Makefile Wed Aug 27 22:18:26 2003 +++ edited/drivers/char/Makefile Tue Sep 30 05:01:49 2003 @@ -305,6 +305,7 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o +obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o subdir-$(CONFIG_MWAVE) += mwave ifeq ($(CONFIG_MWAVE),y) ===== arch/ppc/kernel/m8xx_wdt.c 1.0 vs 1.1 ===== --- /dev/null Thu Jan 1 01:00:00 1970 +++ 1.1/arch/ppc/kernel/m8xx_wdt.c Tue Sep 30 05:34:45 2003 @@ -0,0 +1,103 @@ +/* + * m8xx_wdt.c - MPC8xx watchdog driver + * + * Copyright (C) 2002 Florian Schirmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +static int wdt_timeout; + +void m8xx_wdt_reset(void) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + imap->im_siu_conf.sc_swsr = 0x556c; /* write magic1 */ + imap->im_siu_conf.sc_swsr = 0xaa39; /* write magic2 */ +} + +static void m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + m8xx_wdt_reset(); + + imap->im_sit.sit_piscr |= PISCR_PS; /* clear irq */ +} + +void __init m8xx_wdt_handler_install(bd_t *binfo) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + u32 pitc; + u32 sypcr; + u32 pitrtclk; + + sypcr = imap->im_siu_conf.sc_sypcr; + + if (!(sypcr & 0x04)) { + printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n", sypcr); + return; + } + + m8xx_wdt_reset(); + + printk(KERN_NOTICE "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n", + (sypcr >> 16), sypcr & 0x01); + + wdt_timeout = (sypcr >> 16) & 0xFFFF; + + if (!wdt_timeout) + wdt_timeout = 0xFFFF; + + if (sypcr & 0x01) + wdt_timeout *= 2048; + + /* + * Fire trigger if half of the wdt ticked down + */ + + if (imap->im_sit.sit_rtcsc & RTCSC_38K) + pitrtclk = 9600; + else + pitrtclk = 8192; + + if ((wdt_timeout) > (UINT_MAX / pitrtclk)) + pitc = wdt_timeout / binfo->bi_intfreq * pitrtclk / 2; + else + pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2; + + imap->im_sit.sit_pitc = pitc << 16; + imap->im_sit.sit_piscr = (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE; + + if (request_irq(PIT_INTERRUPT, m8xx_wdt_interrupt, 0, "watchdog", NULL)) + panic("m8xx_wdt: could not allocate watchdog irq!"); + + printk(KERN_NOTICE "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc); + + wdt_timeout /= binfo->bi_intfreq; +} + +int m8xx_wdt_get_timeout(void) +{ + return wdt_timeout; +} + ===== drivers/char/mpc8xx_wdt.c 1.0 vs 1.1 ===== --- /dev/null Thu Jan 1 01:00:00 1970 +++ 1.1/drivers/char/mpc8xx_wdt.c Tue Sep 30 05:34:51 2003 @@ -0,0 +1,183 @@ +/* + * mpc8xx_wdt.c - MPC8xx watchdog userspace interface + * + * Copyright (C) 2002 Florian Schirmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int m8xx_wdt_get_timeout(void); +extern void m8xx_wdt_reset(void); + +static struct semaphore wdt_sem; +static int wdt_status; + +static struct watchdog_info ident = { + .identity = "MPC8xx watchdog", + .options = WDIOF_KEEPALIVEPING, +}; + +static void mpc8xx_wdt_handler_disable(void) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE); + + printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); +} + +static void mpc8xx_wdt_handler_enable(void) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE; + + printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); +} + +static int mpc8xx_wdt_open(struct inode *inode, struct file *file) +{ + switch (MINOR(inode->i_rdev)) { + case WATCHDOG_MINOR: + if (down_trylock(&wdt_sem)) + return -EBUSY; + + m8xx_wdt_reset(); + mpc8xx_wdt_handler_disable(); + break; + + default: + return -ENODEV; + } + + return 0; +} + +static int mpc8xx_wdt_release(struct inode *inode, struct file *file) +{ + m8xx_wdt_reset(); + +#if !defined(CONFIG_WATCHDOG_NOWAYOUT) + mpc8xx_wdt_handler_enable(); +#endif + + up(&wdt_sem); + + return 0; +} + +static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, + size_t len, loff_t * ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (!len) + return 0; + + m8xx_wdt_reset(); + + return 1; +} + +static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user((void *)arg, &ident, sizeof(ident))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + if (put_user(wdt_status, (int *)arg)) + return -EFAULT; + wdt_status &= ~WDIOF_KEEPALIVEPING; + break; + + case WDIOC_KEEPALIVE: + m8xx_wdt_reset(); + wdt_status |= WDIOF_KEEPALIVEPING; + break; + + case WDIOC_GETTIMEOUT: + { + int timeout = m8xx_wdt_get_timeout(); + if (put_user(timeout, (int *)arg)) + return -EFAULT; + break; + } + + default: + return -ENOTTY; + } + + return 0; +} + +static struct file_operations mpc8xx_wdt_fops = { + .owner = THIS_MODULE, + .write = mpc8xx_wdt_write, + .ioctl = mpc8xx_wdt_ioctl, + .open = mpc8xx_wdt_open, + .release = mpc8xx_wdt_release, +}; + +static struct miscdevice mpc8xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &mpc8xx_wdt_fops, +}; + +static int __init mpc8xx_wdt_init(void) +{ + int ret; + + sema_init(&wdt_sem, 1); + + if ((ret = misc_register(&mpc8xx_wdt_miscdev))) { + printk(KERN_WARNING "mpc8xx_wdt: cound not register userspace interface\n"); + return ret; + } + + return 0; +} + +static void __exit mpc8xx_wdt_exit(void) +{ + misc_deregister(&mpc8xx_wdt_miscdev); + + m8xx_wdt_reset(); + mpc8xx_wdt_handler_enable(); +} + +module_init(mpc8xx_wdt_init); +module_exit(mpc8xx_wdt_exit); + +MODULE_AUTHOR("Florian Schirmer "); +MODULE_DESCRIPTION("MPC8xx watchdog driver"); +MODULE_LICENSE("GPL"); --=-4RsDp59Ksh2QAtrQwGfm-- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/