Ticket #2511: rb500_watchdog_patch.diff

File rb500_watchdog_patch.diff, 11.8 KB (added by strasak@…, 10 years ago)

patch which provides RB532's integrated watchdog support

  • drivers/char/watchdog/Kconfig

    diff -Naur linux-2.6.22.10-ng-rb532/drivers/char/watchdog/Kconfig linux-2.6.22.10/drivers/char/watchdog/Kconfig
    old new  
    575575          To compile this driver as a module, choose M here: the 
    576576          module will be called rm9k_wdt. 
    577577 
     578 
     579config RC32434_WDT 
     580        tristate "IDT RC32434 Hardware Watchdog" 
     581        depends on WATCHDOG && MIKROTIK_RB500 
     582        help 
     583          Hardware driver for the IDT RC32434 integrated watchdog. 
     584 
    578585# S390 Architecture 
    579586 
    580587config ZVM_WATCHDOG 
  • drivers/char/watchdog/Makefile

    diff -Naur linux-2.6.22.10-ng-rb532/drivers/char/watchdog/Makefile linux-2.6.22.10/drivers/char/watchdog/Makefile
    old new  
    7575obj-$(CONFIG_INDYDOG) += indydog.o 
    7676obj-$(CONFIG_WDT_MTX1)  += mtx-1_wdt.o 
    7777obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o 
     78obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o 
    7879 
    7980# S390 Architecture 
    8081 
  • drivers/char/watchdog/rc32434_wdt.c

    diff -Naur linux-2.6.22.10-ng-rb532/drivers/char/watchdog/rc32434_wdt.c linux-2.6.22.10/drivers/char/watchdog/rc32434_wdt.c
    old new  
     1/* 
     2 * rc32434_wdt 0.1: Hardware Watchdog integrated into the IDT RC32434 
     3 * 
     4 * Copyright (c) 2007 Phil Sutter <n0-1@freewrt.org> 
     5 * 
     6 * This program is free software; you can redistribute it and/or 
     7 * modify it under the terms of the GNU General Public License 
     8 * as published by the Free Software Foundation; either version 2 
     9 * of the License, or (at your option) any later version. 
     10 * 
     11 * This program is distributed in the hope that it will be useful, 
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     14 * GNU General Public License for more details. 
     15 * 
     16 * You should have received a copy of the GNU General Public License 
     17 * along with this program; if not, write to the Free Software 
     18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
     19 * 
     20 * based on indydog.c by Guido Guenther <agx@sigxcpu.org> 
     21 */ 
     22#include <linux/init.h> 
     23#include <linux/fs.h> 
     24#include <linux/miscdevice.h> 
     25#include <linux/module.h> 
     26#include <linux/notifier.h> 
     27#include <linux/watchdog.h> 
     28#include <linux/reboot.h> 
     29#include <asm/rc32434/integ.h> 
     30 
     31#define PFX "rc32434_wdt: " 
     32#define WATCHDOG_TIMEOUT 15             /* 30 sec default timeout */ 
     33 
     34/* Board internal cpu clock speed in Hz. 
     35 * The Watchdog timer ticks at IPBus clock rate, 
     36 * which is exactly half of it.  */ 
     37extern unsigned int idt_cpu_freq; 
     38 
     39static int rcwdt_alive; 
     40volatile INTEG_t idt_integ = (volatile INTEG_t)INTEG_VirtualAddress; 
     41static int nowayout = WATCHDOG_NOWAYOUT; 
     42static int timeout = WATCHDOG_TIMEOUT; 
     43static int verbose = 1; 
     44static int noclose = 0; 
     45 
     46module_param(nowayout, int, 0); 
     47MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 
     48module_param(timeout, int, 0); 
     49MODULE_PARM_DESC(timeout, "Watchdog timeout value, in seconds (default=15, maximum=20)"); 
     50module_param(verbose, int, 0); 
     51MODULE_PARM_DESC(verbose, "Set level of verbosity, 0 - 2 (default=1))"); 
     52module_param(noclose, int, 0); 
     53MODULE_PARM_DESC(noclose, "For simple watchdog scripts, which doesn't keep device open, use 1 (default=0))"); 
     54 
     55 
     56/* set the timeout in seconds */ 
     57static int rcwdt_settimeout(int t) 
     58{ 
     59        if((t < 0) || (t > 20)) { 
     60                printk(KERN_ERR PFX "timeout value must be between 0 and 52"); 
     61                return -EINVAL; 
     62        } 
     63        idt_integ->wtcompare = (u32)t  * (u32)idt_cpu_freq; 
     64        if (verbose > 1) printk(KERN_INFO PFX "timeout set to %u (%i seconds)\n", idt_integ->wtcompare, t); 
     65        return 0; 
     66} 
     67 
     68static void rcwdt_start(void) 
     69{ 
     70        u32 tmp; 
     71 
     72        /* zero the counter before enabling */ 
     73        idt_integ->wtcount = 0; 
     74 
     75        /* on timeout: 
     76         * - don't generate a non-maskable interrupt 
     77         * - do a warm reset 
     78         */ 
     79        tmp = idt_integ->errcs; 
     80        tmp &= ~ERRCS_wne_m; 
     81        tmp |= ERRCS_wre_m; 
     82        tmp &= ~ERRCS_wto_m; 
     83        idt_integ->errcs = tmp; 
     84 
     85        /* set the timeout (either default or based on module param) */ 
     86        rcwdt_settimeout(timeout); 
     87 
     88        /* finally reset TO and enable the watchdog */ 
     89        tmp = idt_integ->wtc; 
     90        tmp &= ~WTC_to_m; 
     91        tmp |= WTC_en_m; 
     92        idt_integ->wtc = tmp; 
     93        if (verbose > 0) printk(KERN_INFO "Started watchdog timer.\n"); 
     94} 
     95 
     96static void rcwdt_stop(void) 
     97{ 
     98        u32 tmp = idt_integ->wtc; 
     99 
     100        tmp &= ~WTC_en_m; 
     101        idt_integ->wtc = tmp; 
     102 
     103        if (verbose > 0) printk(KERN_INFO "Stopped watchdog timer.\n"); 
     104} 
     105 
     106static void rcwdt_ping(void) 
     107{ 
     108        idt_integ->wtcount = 0; 
     109        if (verbose > 1) printk(KERN_INFO "Watchdog timer has been reset, will not reboot for now.\n"); 
     110} 
     111 
     112/* Allow only one person to hold it open */ 
     113static int rcwdt_open(struct inode *inode, struct file *file) 
     114{ 
     115 
     116        if ((rcwdt_alive) && (!noclose)) 
     117                return -EBUSY; 
     118 
     119        if ((nowayout) && (!noclose)) 
     120                __module_get(THIS_MODULE); 
     121 
     122        /* Activate timer */ 
     123        rcwdt_start(); 
     124        rcwdt_ping(); 
     125 
     126        rcwdt_alive = 1; 
     127 
     128 
     129        return nonseekable_open(inode, file); 
     130} 
     131 
     132static int rcwdt_release(struct inode *inode, struct file *file) 
     133{ 
     134        /* Shut off the timer. 
     135         * Lock it in if it's a module and we defined ...NOWAYOUT */ 
     136        if ((!nowayout) && (!noclose)) 
     137                rcwdt_stop();           /* Turn the WDT off */ 
     138 
     139        rcwdt_alive = 0; 
     140 
     141        return 0; 
     142} 
     143 
     144static ssize_t rcwdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) 
     145{ 
     146        /* Refresh the timer. */ 
     147        if (len) { 
     148                if (!noclose) rcwdt_ping(); 
     149        } 
     150        return len; 
     151} 
     152 
     153static int rcwdt_ioctl(struct inode *inode, struct file *file, 
     154        unsigned int cmd, unsigned long arg) 
     155{ 
     156        int options, retval = -EINVAL; 
     157        static struct watchdog_info ident = { 
     158                .options                = WDIOF_KEEPALIVEPING | 
     159                                          WDIOF_MAGICCLOSE, 
     160                .firmware_version       = 0, 
     161                .identity               = "Watchdog for IDT RC32434", 
     162        }; 
     163 
     164        switch (cmd) { 
     165                default: 
     166                        return -ENOTTY; 
     167                case WDIOC_GETSUPPORT: 
     168                        if (copy_to_user((struct watchdog_info *)arg, 
     169                                         &ident, sizeof(ident))) 
     170                                return -EFAULT; 
     171                        return 0; 
     172                case WDIOC_GETSTATUS: 
     173                case WDIOC_GETBOOTSTATUS: 
     174                        return put_user(0,(int *)arg); 
     175                case WDIOC_KEEPALIVE: 
     176                        rcwdt_ping(); 
     177                        return 0; 
     178                case WDIOC_GETTIMEOUT: 
     179                        return put_user(WATCHDOG_TIMEOUT,(int *)arg); 
     180                case WDIOC_SETOPTIONS: 
     181                        if (get_user(options, (int *)arg)) 
     182                                return -EFAULT; 
     183 
     184                        if (options & WDIOS_DISABLECARD) { 
     185                                rcwdt_stop(); 
     186                                retval = 0; 
     187                        } 
     188 
     189                        if (options & WDIOS_ENABLECARD) { 
     190                                rcwdt_start(); 
     191                                retval = 0; 
     192                        } 
     193 
     194                        return retval; 
     195                case WDIOC_SETTIMEOUT: 
     196                        if(get_user(options, (int *)arg)) 
     197                                return -EFAULT; 
     198                        if(rcwdt_settimeout(options)) 
     199                                return -EINVAL; 
     200                        rcwdt_ping(); 
     201                        return 0; 
     202        } 
     203} 
     204 
     205static int rcwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 
     206{ 
     207        if (code == SYS_DOWN || code == SYS_HALT) 
     208                rcwdt_stop();           /* Turn the WDT off */ 
     209 
     210        return NOTIFY_DONE; 
     211} 
     212 
     213static const struct file_operations rcwdt_fops = { 
     214        .owner          = THIS_MODULE, 
     215        .llseek         = no_llseek, 
     216        .write          = rcwdt_write, 
     217        .ioctl          = rcwdt_ioctl, 
     218        .open           = rcwdt_open, 
     219        .release        = rcwdt_release, 
     220}; 
     221 
     222static struct miscdevice rcwdt_miscdev = { 
     223        .minor          = WATCHDOG_MINOR, 
     224        .name           = "watchdog", 
     225        .fops           = &rcwdt_fops, 
     226}; 
     227 
     228static struct notifier_block rcwdt_notifier = { 
     229        .notifier_call = rcwdt_notify_sys, 
     230}; 
     231 
     232static char banner[] __initdata = 
     233        KERN_INFO PFX "Hardware Watchdog Timer for IDT RC32434 v0.1\n"; 
     234 
     235static int __init watchdog_init(void) 
     236{ 
     237        int ret; 
     238 
     239        ret = register_reboot_notifier(&rcwdt_notifier); 
     240        if (ret) { 
     241                printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 
     242                        ret); 
     243                return ret; 
     244        } 
     245 
     246        ret = misc_register(&rcwdt_miscdev); 
     247        if (ret) { 
     248                printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 
     249                        WATCHDOG_MINOR, ret); 
     250                unregister_reboot_notifier(&rcwdt_notifier); 
     251                return ret; 
     252        } 
     253 
     254        printk(banner); 
     255 
     256        return 0; 
     257} 
     258 
     259static void __exit watchdog_exit(void) 
     260{ 
     261        if(noclose) { 
     262                rcwdt_stop(); 
     263        } 
     264        misc_deregister(&rcwdt_miscdev); 
     265        unregister_reboot_notifier(&rcwdt_notifier); 
     266} 
     267 
     268module_init(watchdog_init); 
     269module_exit(watchdog_exit); 
     270 
     271MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>"); 
     272MODULE_DESCRIPTION("Hardware Watchdog Timer for IDT RC32434"); 
     273MODULE_LICENSE("GPL"); 
     274MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 
  • include/asm/rc32434/integ.h

    diff -Naur linux-2.6.22.10-ng-rb532/include/asm/rc32434/integ.h linux-2.6.22.10/include/asm/rc32434/integ.h
    old new  
     1/************************************************************************** 
     2 * 
     3 *  BRIEF MODULE DESCRIPTION 
     4 *   System Integrity register definition 
     5 * 
     6 *  Copyright 2004 IDT Inc. (rischelp@idt.com) 
     7 * 
     8 *  This program is free software; you can redistribute  it and/or modify it 
     9 *  under  the terms of  the GNU General  Public License as published by the 
     10 *  Free Software Foundation;  either version 2 of the  License, or (at your 
     11 *  option) any later version. 
     12 * 
     13 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED 
     14 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF 
     15 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN 
     16 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, 
     17 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
     18 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF 
     19 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
     20 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT 
     21 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
     22 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * 
     24 *  You should have received a copy of the  GNU General Public License along 
     25 *  with this program; if not, write  to the Free Software Foundation, Inc., 
     26 *  675 Mass Ave, Cambridge, MA 02139, USA. 
     27 * 
     28 * 
     29 ************************************************************************** 
     30 * May 2004 rkt, neb 
     31 * 
     32 * Initial Release 
     33 * 
     34 * 
     35 * 
     36 ************************************************************************** 
     37 */ 
     38 
     39#ifndef __IDT_INTEG_H__ 
     40#define __IDT_INTEG_H__ 
     41 
     42enum 
     43{ 
     44        INTEG0_PhysicalAddress  = 0x18030000, 
     45        INTEG_PhysicalAddress   = INTEG0_PhysicalAddress,       // Default 
     46 
     47        INTEG0_VirtualAddress   = 0xB8030000, 
     48        INTEG_VirtualAddress    = INTEG0_VirtualAddress,        // Default 
     49} ; 
     50 
     51// if you are looking for CEA, try rst.h 
     52typedef struct 
     53{ 
     54        u32 filler [0xc] ;              // 0x30 bytes unused. 
     55        u32 errcs ;                     // sticky use ERRCS_ 
     56        u32 wtcount ;                   // Watchdog timer count reg. 
     57        u32 wtcompare ;                 // Watchdog timer timeout value. 
     58        u32 wtc ;                       // Watchdog timer control. use WTC_ 
     59} volatile *INTEG_t ; 
     60 
     61enum 
     62{ 
     63        ERRCS_wto_b             = 0,            // In INTEG_t -> errcs 
     64        ERRCS_wto_m             = 0x00000001, 
     65        ERRCS_wne_b             = 1,            // In INTEG_t -> errcs 
     66        ERRCS_wne_m             = 0x00000002, 
     67        ERRCS_ucw_b             = 2,            // In INTEG_t -> errcs 
     68        ERRCS_ucw_m             = 0x00000004, 
     69        ERRCS_ucr_b             = 3,            // In INTEG_t -> errcs 
     70        ERRCS_ucr_m             = 0x00000008, 
     71        ERRCS_upw_b             = 4,            // In INTEG_t -> errcs 
     72        ERRCS_upw_m             = 0x00000010, 
     73        ERRCS_upr_b             = 5,            // In INTEG_t -> errcs 
     74        ERRCS_upr_m             = 0x00000020, 
     75        ERRCS_udw_b             = 6,            // In INTEG_t -> errcs 
     76        ERRCS_udw_m             = 0x00000040, 
     77        ERRCS_udr_b             = 7,            // In INTEG_t -> errcs 
     78        ERRCS_udr_m             = 0x00000080, 
     79        ERRCS_sae_b             = 8,            // In INTEG_t -> errcs 
     80        ERRCS_sae_m             = 0x00000100, 
     81        ERRCS_wre_b             = 9,            // In INTEG_t -> errcs 
     82        ERRCS_wre_m             = 0x00000200, 
     83 
     84        WTC_en_b                = 0,            // In INTEG_t -> wtc 
     85        WTC_en_m                = 0x00000001, 
     86        WTC_to_b                = 1,            // In INTEG_t -> wtc 
     87        WTC_to_m                = 0x00000002, 
     88} ; 
     89 
     90#endif  // __IDT_INTEG_H__