linux/drivers/watchdog/sp5100_tco.c
<<
>>
Prefs
   1/*
   2 *      sp5100_tco :    TCO timer driver for sp5100 chipsets
   3 *
   4 *      (c) Copyright 2009 Google Inc., All Rights Reserved.
   5 *
   6 *      Based on i8xx_tco.c:
   7 *      (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights
   8 *      Reserved.
   9 *                              http://www.kernelconcepts.de
  10 *
  11 *      This program is free software; you can redistribute it and/or
  12 *      modify it under the terms of the GNU General Public License
  13 *      as published by the Free Software Foundation; either version
  14 *      2 of the License, or (at your option) any later version.
  15 *
  16 *      See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide",
  17 *          AMD Publication 45482 "AMD SB800-Series Southbridges Register
  18 *                                                            Reference Guide"
  19 */
  20
  21/*
  22 *      Includes, defines, variables, module parameters, ...
  23 */
  24
  25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  26
  27#include <linux/module.h>
  28#include <linux/moduleparam.h>
  29#include <linux/types.h>
  30#include <linux/miscdevice.h>
  31#include <linux/watchdog.h>
  32#include <linux/init.h>
  33#include <linux/fs.h>
  34#include <linux/pci.h>
  35#include <linux/ioport.h>
  36#include <linux/platform_device.h>
  37#include <linux/uaccess.h>
  38#include <linux/io.h>
  39
  40#include "sp5100_tco.h"
  41
  42/* Module and version information */
  43#define TCO_VERSION "0.03"
  44#define TCO_MODULE_NAME "SP5100 TCO timer"
  45#define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
  46
  47/* internal variables */
  48static u32 tcobase_phys;
  49static u32 resbase_phys;
  50static u32 tco_wdt_fired;
  51static void __iomem *tcobase;
  52static unsigned int pm_iobase;
  53static DEFINE_SPINLOCK(tco_lock);       /* Guards the hardware */
  54static unsigned long timer_alive;
  55static char tco_expect_close;
  56static struct pci_dev *sp5100_tco_pci;
  57static struct resource wdt_res = {
  58        .name = "Watchdog Timer",
  59        .flags = IORESOURCE_MEM,
  60};
  61
  62/* the watchdog platform device */
  63static struct platform_device *sp5100_tco_platform_device;
  64
  65/* module parameters */
  66
  67#define WATCHDOG_HEARTBEAT 60   /* 60 sec default heartbeat. */
  68static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
  69module_param(heartbeat, int, 0);
  70MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
  71                 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
  72
  73static bool nowayout = WATCHDOG_NOWAYOUT;
  74module_param(nowayout, bool, 0);
  75MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started."
  76                " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  77
  78static unsigned int force_addr;
  79module_param(force_addr, uint, 0);
  80MODULE_PARM_DESC(force_addr, "Force the use of specified MMIO address."
  81                " ONLY USE THIS PARAMETER IF YOU REALLY KNOW"
  82                " WHAT YOU ARE DOING (default=none)");
  83
  84/*
  85 * Some TCO specific functions
  86 */
  87static void tco_timer_start(void)
  88{
  89        u32 val;
  90        unsigned long flags;
  91
  92        spin_lock_irqsave(&tco_lock, flags);
  93        val = readl(SP5100_WDT_CONTROL(tcobase));
  94        val |= SP5100_WDT_START_STOP_BIT;
  95        writel(val, SP5100_WDT_CONTROL(tcobase));
  96        spin_unlock_irqrestore(&tco_lock, flags);
  97}
  98
  99static void tco_timer_stop(void)
 100{
 101        u32 val;
 102        unsigned long flags;
 103
 104        spin_lock_irqsave(&tco_lock, flags);
 105        val = readl(SP5100_WDT_CONTROL(tcobase));
 106        val &= ~SP5100_WDT_START_STOP_BIT;
 107        writel(val, SP5100_WDT_CONTROL(tcobase));
 108        spin_unlock_irqrestore(&tco_lock, flags);
 109}
 110
 111static void tco_timer_keepalive(void)
 112{
 113        u32 val;
 114        unsigned long flags;
 115
 116        spin_lock_irqsave(&tco_lock, flags);
 117        val = readl(SP5100_WDT_CONTROL(tcobase));
 118        val |= SP5100_WDT_TRIGGER_BIT;
 119        writel(val, SP5100_WDT_CONTROL(tcobase));
 120        spin_unlock_irqrestore(&tco_lock, flags);
 121}
 122
 123static int tco_timer_set_heartbeat(int t)
 124{
 125        unsigned long flags;
 126
 127        if (t < 0 || t > 0xffff)
 128                return -EINVAL;
 129
 130        /* Write new heartbeat to watchdog */
 131        spin_lock_irqsave(&tco_lock, flags);
 132        writel(t, SP5100_WDT_COUNT(tcobase));
 133        spin_unlock_irqrestore(&tco_lock, flags);
 134
 135        heartbeat = t;
 136        return 0;
 137}
 138
 139static void tco_timer_enable(void)
 140{
 141        int val;
 142
 143        if (sp5100_tco_pci->revision >= 0x40) {
 144                /* For SB800 or later */
 145                /* Set the Watchdog timer resolution to 1 sec */
 146                outb(SB800_PM_WATCHDOG_CONFIG, SB800_IO_PM_INDEX_REG);
 147                val = inb(SB800_IO_PM_DATA_REG);
 148                val |= SB800_PM_WATCHDOG_SECOND_RES;
 149                outb(val, SB800_IO_PM_DATA_REG);
 150
 151                /* Enable watchdog decode bit and watchdog timer */
 152                outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG);
 153                val = inb(SB800_IO_PM_DATA_REG);
 154                val |= SB800_PCI_WATCHDOG_DECODE_EN;
 155                val &= ~SB800_PM_WATCHDOG_DISABLE;
 156                outb(val, SB800_IO_PM_DATA_REG);
 157        } else {
 158                /* For SP5100 or SB7x0 */
 159                /* Enable watchdog decode bit */
 160                pci_read_config_dword(sp5100_tco_pci,
 161                                      SP5100_PCI_WATCHDOG_MISC_REG,
 162                                      &val);
 163
 164                val |= SP5100_PCI_WATCHDOG_DECODE_EN;
 165
 166                pci_write_config_dword(sp5100_tco_pci,
 167                                       SP5100_PCI_WATCHDOG_MISC_REG,
 168                                       val);
 169
 170                /* Enable Watchdog timer and set the resolution to 1 sec */
 171                outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
 172                val = inb(SP5100_IO_PM_DATA_REG);
 173                val |= SP5100_PM_WATCHDOG_SECOND_RES;
 174                val &= ~SP5100_PM_WATCHDOG_DISABLE;
 175                outb(val, SP5100_IO_PM_DATA_REG);
 176        }
 177}
 178
 179static void tco_timer_disable(void)
 180{
 181        int val;
 182
 183        if (sp5100_tco_pci->revision >= 0x40) {
 184                /* For SB800 or later */
 185                /* Enable watchdog decode bit and Disable watchdog timer */
 186                outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG);
 187                val = inb(SB800_IO_PM_DATA_REG);
 188                val |= SB800_PCI_WATCHDOG_DECODE_EN;
 189                val |= SB800_PM_WATCHDOG_DISABLE;
 190                outb(val, SB800_IO_PM_DATA_REG);
 191        } else {
 192                /* For SP5100 or SB7x0 */
 193                /* Enable watchdog decode bit */
 194                pci_read_config_dword(sp5100_tco_pci,
 195                                      SP5100_PCI_WATCHDOG_MISC_REG,
 196                                      &val);
 197
 198                val |= SP5100_PCI_WATCHDOG_DECODE_EN;
 199
 200                pci_write_config_dword(sp5100_tco_pci,
 201                                       SP5100_PCI_WATCHDOG_MISC_REG,
 202                                       val);
 203
 204                /* Disable Watchdog timer */
 205                outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
 206                val = inb(SP5100_IO_PM_DATA_REG);
 207                val |= SP5100_PM_WATCHDOG_DISABLE;
 208                outb(val, SP5100_IO_PM_DATA_REG);
 209        }
 210}
 211
 212/*
 213 *      /dev/watchdog handling
 214 */
 215
 216static int sp5100_tco_open(struct inode *inode, struct file *file)
 217{
 218        /* /dev/watchdog can only be opened once */
 219        if (test_and_set_bit(0, &timer_alive))
 220                return -EBUSY;
 221
 222        /* Reload and activate timer */
 223        tco_timer_start();
 224        tco_timer_keepalive();
 225        return nonseekable_open(inode, file);
 226}
 227
 228static int sp5100_tco_release(struct inode *inode, struct file *file)
 229{
 230        /* Shut off the timer. */
 231        if (tco_expect_close == 42) {
 232                tco_timer_stop();
 233        } else {
 234                pr_crit("Unexpected close, not stopping watchdog!\n");
 235                tco_timer_keepalive();
 236        }
 237        clear_bit(0, &timer_alive);
 238        tco_expect_close = 0;
 239        return 0;
 240}
 241
 242static ssize_t sp5100_tco_write(struct file *file, const char __user *data,
 243                                size_t len, loff_t *ppos)
 244{
 245        /* See if we got the magic character 'V' and reload the timer */
 246        if (len) {
 247                if (!nowayout) {
 248                        size_t i;
 249
 250                        /* note: just in case someone wrote the magic character
 251                         * five months ago... */
 252                        tco_expect_close = 0;
 253
 254                        /* scan to see whether or not we got the magic character
 255                         */
 256                        for (i = 0; i != len; i++) {
 257                                char c;
 258                                if (get_user(c, data + i))
 259                                        return -EFAULT;
 260                                if (c == 'V')
 261                                        tco_expect_close = 42;
 262                        }
 263                }
 264
 265                /* someone wrote to us, we should reload the timer */
 266                tco_timer_keepalive();
 267        }
 268        return len;
 269}
 270
 271static long sp5100_tco_ioctl(struct file *file, unsigned int cmd,
 272                             unsigned long arg)
 273{
 274        int new_options, retval = -EINVAL;
 275        int new_heartbeat;
 276        void __user *argp = (void __user *)arg;
 277        int __user *p = argp;
 278        static const struct watchdog_info ident = {
 279                .options =              WDIOF_SETTIMEOUT |
 280                                        WDIOF_KEEPALIVEPING |
 281                                        WDIOF_MAGICCLOSE,
 282                .firmware_version =     0,
 283                .identity =             TCO_MODULE_NAME,
 284        };
 285
 286        switch (cmd) {
 287        case WDIOC_GETSUPPORT:
 288                return copy_to_user(argp, &ident,
 289                        sizeof(ident)) ? -EFAULT : 0;
 290        case WDIOC_GETSTATUS:
 291        case WDIOC_GETBOOTSTATUS:
 292                return put_user(0, p);
 293        case WDIOC_SETOPTIONS:
 294                if (get_user(new_options, p))
 295                        return -EFAULT;
 296                if (new_options & WDIOS_DISABLECARD) {
 297                        tco_timer_stop();
 298                        retval = 0;
 299                }
 300                if (new_options & WDIOS_ENABLECARD) {
 301                        tco_timer_start();
 302                        tco_timer_keepalive();
 303                        retval = 0;
 304                }
 305                return retval;
 306        case WDIOC_KEEPALIVE:
 307                tco_timer_keepalive();
 308                return 0;
 309        case WDIOC_SETTIMEOUT:
 310                if (get_user(new_heartbeat, p))
 311                        return -EFAULT;
 312                if (tco_timer_set_heartbeat(new_heartbeat))
 313                        return -EINVAL;
 314                tco_timer_keepalive();
 315                /* Fall through */
 316        case WDIOC_GETTIMEOUT:
 317                return put_user(heartbeat, p);
 318        default:
 319                return -ENOTTY;
 320        }
 321}
 322
 323/*
 324 * Kernel Interfaces
 325 */
 326
 327static const struct file_operations sp5100_tco_fops = {
 328        .owner =                THIS_MODULE,
 329        .llseek =               no_llseek,
 330        .write =                sp5100_tco_write,
 331        .unlocked_ioctl =       sp5100_tco_ioctl,
 332        .open =                 sp5100_tco_open,
 333        .release =              sp5100_tco_release,
 334};
 335
 336static struct miscdevice sp5100_tco_miscdev = {
 337        .minor =        WATCHDOG_MINOR,
 338        .name =         "watchdog",
 339        .fops =         &sp5100_tco_fops,
 340};
 341
 342/*
 343 * Data for PCI driver interface
 344 *
 345 * This data only exists for exporting the supported
 346 * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
 347 * register a pci_driver, because someone else might
 348 * want to register another driver on the same PCI id.
 349 */
 350static DEFINE_PCI_DEVICE_TABLE(sp5100_tco_pci_tbl) = {
 351        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
 352          PCI_ANY_ID, },
);
 */
 334};
          <* PCI ids via MODULode=PCI_ANY_ID"* PCI ids via MODULI_DEVICE_TABLE(sp510miscdevice sp5100_tc334"> 334};
 326
 347/*
 348
 349 */
                        char < class="sresetupef="+code=miscdevice" class="sresetupef="+cI_DEVr_disable(void)
) = {
 2336static struct < * re5100_tco_miscdev" * re51me="Lf">__user *__user *ENOTTY;
 2ef">file__user *__user *ENOTTY;
 224        val;
 224        L332" id=ioctl"index_t">sp510miscdevice L332" id=ioctl"ment_t">sp510miscdevice val;
 326
 2ame="L336"EG);
 * f="+cass="comment"> */
 238        () {
 319                if (< * rmref=_ite_config_dword" clamref=_itI_DEVICE_TABLE(sp5100_t0miscdevice i != ) {
 250           CE_TABLE(00_tco_">__user *val;
 311          break"sref">val;
 272  L321"> 321}
 23321"> 321}
 264
 27             if (!00_tsable(void)
 296                return 0;
 227
 238         =          *Rf="">fi ID: 0x%xping watchdog!\0miscdevice 00_t->=         &fi"+code=release" c="">fi00_tc334"> 334};
 249
 230         */
 251 342 */
 2              if (00_t->=         &fi"+code=release" c="">fi00_t >== 0x40ENABLECARD) {
 314                __user *val;
 235                L332" id=ioctl"index_t">sp51co_">__user *val;
 266                L332" id=ioctl"ment_t">sp51co_">__user *val;
 307                __user *SP510BAWDIOF_MAGICCLOSE"SB8/wa"sref">SP510BAWD00_t"sref">val;
 233        } else {
 289                __user *val;
 250                L332" id=ioctl"index_t">sp51co_">__user *SP5100_IO_PM"sref">val;
 311                L332" id=ioctl"ment_t">sp51co_">__user *SP5100_IO_P"sref">val;
 292                __user *SP510BAWDIOF_MAGICCLOSE"Sclass="sref">SP510BAWDIO_P"sref">val;
 23321"> 321}
 264
 222         */
 238        __user *SP5100_IO_PM"sref">val;
 27             if (!>fi"+code=release" cquesr_t">>fiI_DEVICE_TABLE( WDS_SIZDIOF_MAGICCLOSE"Sclass="srIO">WDS_SIZD00_t0miscdevice ) {
 298  38         =          334};
 299  gotomiscdevice val;
 320        }
 341
 330         */
 343 344 */
 224        ( L332" id=ioctl"index_t">sp51c334"> 334};
 238        __user *(L332" id=ioctl"ment_t">sp51c334"> 334};
 324        ( L332" id=ioctl"index_t">sp51c334"> 334};
 238        __user *__user *(L332" id=ioctl"ment_t">sp51c334"> 334};
 324        ( L332" id=ioctl"index_t">sp51c334"> 334};
 338        __user *__user *(L332" id=ioctl"ment_t">sp51c334"> 334};
 324        (put_user(0, L332" id=ioctl"index_t">sp51c334"> 334};
 330         */
 338        __user *(L332" id=ioctl"ment_t">sp51cew_opti0xf8c334"> 334};
 264
 224        < r+debu>L332" id=ioctl" r+debu>I_DEVIa> =          334};
 326
 2ame="L336"EG);
 */
 3              if (< cquesr_mem_t">>fi_excluso_timer_keepalive" cquesr_mem_t">>fi_excluso_tI_DEVICE_TABLE(  */
 319                                                  iscdevice  */
 250  gotomiscdevice val;
 3sref">val;
 292                < r+debu>L332" id=ioctl" r+debu>I_DEVIa> =          334};
 253
 2ame="L336"EG);
 */
 325 */
 346SBResource_MMIO t"> * wahe same PCI id.
 347 */
 3              if (00_t->=         &fi"+code=release" c="">fi00_t >== 0x40ENABLECARD) {
 289   2         */
 250                (  334};
 311                __user *( 334};
 292                (  334};
 313  38        __user *__user *( 334};
 314                (  334};
 235                __user *__user *( 334};
 266                (put_user(0,  334};
 307                __user *__user *( 334};
 233        } else {
 289   2         *config( claReg: 9Ch)ass="comment"> */
 250                sread_config_dworte_config_dword" claread_config_dwortI_DEVICE_TABLE(00_t0nt"> */
 281                        iscdevice  =         & 334};
 220        }
 253
 2ame="L336"EG);
SBResource_MMIO is enabled and mapped memory me=ce?ass="comment"> */
 27   VICE_TABLE((__user * */
 266  "> 281                        iscdevice ) {
 307   me="L336"EG);
 */
 298  38         334};
 289   2         */
 250                __user *val;
 311   me="L336"EG);
 */
 352222222              if (< cquesr_mem_t">>fi_excluso_timer_keepalive" cquesr_mem_t">>fi_excluso_tI_DEVICE_TABLE(  */
 313                                                     iscdevice ) {
 314          iscdevice < r+debu>L332" id=ioctl" r+debu>I_DEVIa> =          * waping watchdog!\0BLECARD) {
 295                  iscdevice  334};
 266  "> 281 val;
 307  }3sref">val;
 298                        < r+debu>L332" id=ioctl" r+debu>I_DEVIa> =          334};
 2}3sref">val;
 250                L332" id=ioctl" r+debu>I_DEVIa> =          334};
 341
 330         */
 343 */
 344 325
 346 347 348 */
 324         334};
 334};
 3              if () {
 272  30         */
 343 */
 344
 325 */
 296            if ( 334};
 307                __user * 334};
 334};
 289                 =          334};
 233        } else {
 311   me="L336"EG);
 */
 342
 343 */
 314                if ( =         & */
 235                        /a> =         & */
 266                        iscdevice  */
 307                        0xf00000000nt"> */
 298                        0xfffffff80nt"> */
 289                        0x80nt"> */
 250                        iscdevice  */
 311                        iscdevice ) {
 292          iscdevice  =          334};
 313          gotomiscdevice >fi"+code=release"unreg_t">>fiass=334"> 334};
 314  20        }
 335
 296            if (__user *__user *        . 334};
 307                < r+debu>L332" id=ioctl" r+debu>I_DEVIa> =          334};
 220        }
 249
 230         */
 3              if (00_t->=         &fi"+code=release" c="">fi00_t >== 0x40ENABLECARD) {
 292                __user * 334};
sp55line"50ers/watchdog/sp5O_SEf4c#L273" id="L273" class=4line"47ame="L343 onlater)ass="c="L307"> 307 335
val;
 292                 344 334};
   334(50#L316" id="L316" class=4line"41ame="L3Rpan>
 230         L332" id=ioctl"index_t">sp51c334"> 334};
 324        ((5aent_t">L332" i=ioctl"index_t">sp51c334"> 334};
 L332" id=ioctl"index_t">sp51c334"> 334};
 */
 224        ((5aent_t">L332" id=ioctl"ment_t">sp51c334"> 334};
 324        (put_user50, L332" id=ioctl"index_t">sp51c334"> 334};
 */
 224        (        sp51c334"> 334};
 324        ((L3351r *sp51c334"> 334};
 */
 224        ( */
 224        (/*5irect I/Oping watchdog!\5miscd51ex_t">L332" id=ioctl"index_t">sp51c334"> 334};
 */
 224        ( 296                retur5"41ame="L567"> 2ame="L336"EG);5 233        } else {
 5m51_a  that for href="druld ree same PCItchdog/5p5100_tco5c#L300" idlse {
 230         */
 3             _tco4c#L312" id="L312" class=4line"41ame=5"de=releasdy>/* useping watchdog!\5miscd52NDEX_REG" B8/wa"+code=SP5100_I00_tc334"> 334};
};
sp51cew_opti0xf8c334"> 334
 352222222              if (< cquesr_mem_t">>fi_excluso_timer_keepalive" cquesr_mem_t">>fi_excluso_tI_DEVICE_TABLE( */
 313                            5"42ame="L546"> 346 298                        < r+debu>L332" id=ioctl" r+debu>I_DEVIa> =                             dog!\c334"> 334};
 314    ;
 292                00_t5>=         & 334};
 334  334(L332" id=ioctl"index_t> 30_tco4c#L296" id="L296" > 30_tco4c#Lg/5p5100_tco52" id=iocatchdog/sp5100_tco.c#L264" id="L264" class=3line"36ame="L224"> 224<5iscdevice5/a>  220     5EVICE_TAB5E( * 30_tc296" id="L296" > 30_tcg/5p5100_tco52" id=ioctoremap4"> 314      remap=4line"4name="L352"> 352222222              if (< cquesr_mem_t">>fi_excluso_timer_keepalive" cquesr_mem_t">>fi_excluso_tI_DEVIC> =          30_tc296" id="L296" > 30_tcg/5p="L313"> 313                            5EVICE_TAB5E(                > =          334};
 314    ;
 224<5ic#L327" 5E(  334};
 220             L332" id=ioctl"index_t34"> 334};
 289                 =           3345=    54#L261" id="L261" class=4line"46ame="L Sog/4"drivers/watchdog/4png/4p5100_tco4c#L312" id="L312" class=4line"41ame=5ef="drive5s/watchdog/4p5100_tco4c#5342" 54 biis of BAWD are eeserved *drivers/warivers296" id="L296" > 3vers/wariversrs/wa       sp51cew_opti0xf8c334"> 334);
SBResource_MMIO i5 enab5ed and mapped MIO_OFFSEDO_PM"sref">val;
 *L332" id=ioctl"index_t">sp51c334"> 334};
 334mem_t">>fi_CONTROICE_TABLE(>fi_CONTROI=4line"4name="L352">> 30_tc296" id="L296" > 30_tcg/5p=       );
 298  38     5   342      5  *5SB8/wa"sreDT_MMIO_OFFSED5OC_GE55ent_t">L332" id=ioctl"ment_t> 3v="+cfir="296" id="L296" > 3v="+cfir="g/5p5100_tco52" id=iocatchdog/sp5100_tco.c#L264e=val" e"4name="L352">mem_t">/a>         FIREDCE_TABLE(/a>         FIREDL264" id="L264" class=3line"36ame="L224"> 224<5L311"> 315   me="L336"EG);5L332" id=ioctl"index_t34"> 334};
mem_t">/a>         ACTIONs=4l50" class=4line"45em_t">/a>         ACTIONs=4l50L264" id="L264" class=3line"36ame="L224"> 224<5Lf="drive5  334};
 352222222              if (< cquesr_mem_t">>fi_excluCONTROICE_TABLE(>fi_CONTROI=4line"4name="L352">> 30_tc296" id="L296" > 30_tcg/5p=       sp51cew_opti0xf8c334"> 334SB55d and mapped MIO_OFFSEDO_PM"sref">val                5 iscd55ex_t">L332" id=ioctl"index_t> 3vers/wa/wo_heartbedo296" id="L296" > 3vers/wa/wo_heartbedo=4line"4name="L352">heartbedo296" id="L296" heartbedo=4li        281 <55ine"37ame="L296"> 296                retur5atchdog/455100_tco4c#L257" id="L255" cla55hecklMMIO add230"> 233        } else {
 342 230        };
L332" id=ioctl"index_t> 3vers/wa/to4296" id="L296" > 3vers/wa/to4rs/wa        220     5pan claaa5aaaaa* Lastly t"-program5sts f56#L343" id="L343" class=4line"44ame="L2Doneeng/4p5100_tco4c#L312" id="L312" class=4line"41ame=5>     344  334 334};
 314    ;
 334 347<5a>L332" id=ioctl"index_tre) {seh352" id="L4"> 314    re) {seh352" id="L=4line"4name="L352">> 30_tco4c#L296" id="L296" > 30_tco4c#Lg/5pf (< cquesr_mem_t">>fi_excluso_timer_keepalive" cquesr_mem_t">>fi_excluso_tI_DEVIC> =          34c334"> 334};
 314    ;
 334 3245/a>        L332" iflic ass="comment"> *00_tco4c#L296" id="L296" class=4line"49am _tco4c#L312" id="L312" class=4line"41ame=5>};
 314    re) {sehree="L31=4lin
 =          3              if 5 334};
 334 2757 biis of BAWD are eeserved *re) {sehred="L4"> 314    re) {seh id="L=4line"4name="L352">ode=put_user" r+er"I_DEVIa> =        f (< cquesr_mem_t">>fi_ea"srOPORTSr_keepalive" cquesr_mem_t">a"srOPORTSr_kee85" > =         };
 334 344 3255/a> 334};
 2965           if ( 296                retur5f="+code=5al" class=co_">__user 334};ivers/watcin4};
 334}platid.m_devi314"> 314    platid.m_devi31 and *ass=3line"3name=c# id="L353" class=449am _tco4c#L312" id="L312" class=4line"41ame=5>c#L268" 5f="drivers/watchdog/4p5150_tco5c#L278L313"> 313                            504x aslMM5O addeessping watchdog!\5miscd5vice  334}rog4"> 314    reline"50ame="L292"> 292                 334}89 292                 315  0ame="L292"> 292                 233        } else {
 34358 href="druld relMMIO addeess,="comment/a>;
 2ame="L336"EG);
 342 =     5   &a585"> 325 314    ;ivers/watcdog/4devi31rs/wa  _tco4c#L312" id="L312" class=4line"41ame=5id="L287"5class=4line"48ame="L307"5 307<5a>                    rog/rn -lass=3line"37amENODEV4"> 314    ENODEVine"50ame="L292"> 292                 220      #L289" id5"L289" class=4line"4name5"L28959#L299" id="L299" class=4line"49ame="L2/a>;
 250                       5iscde59ent_t">L332" id=ioctl"ment_t34"> 334};
 < r+debu>L332" id=ioctl" r+debu>I_DEVIa> =   5 311 5                      is5devic5  3v="+cfir="296" id="L296" > 3v="+cfir="g/5p5? tchdog/4p5100_tco4c#L279" ievice < r : tchdog/4p5100_tco4c#L279" inoog             > =          =          220     5     5    gotomiscdevice <5nreg_59#L343" id="L343" class=4line"44ame="L/4p5100_tco4c#L351" id="L351" class=4line"45ame=50     2ame="L336"EG);
 342 325
 342  59rom>SBResource_MMIO t"> * wahe same PCI id.
 347 3vers/wa/wo_heartbedo=4line"4name="L352">heartbedo296" id="L296" heartbedo=4li ="L313"> 313                            5ef="drive5s/watchdog/4p5100_tco4c#5298" 59#L278" id="L278" class=4line"47ame="heartbedo296" id="L296" heartbedo=4li5100_tco52" id=ioc         HEARTBEA0" class=4line"4         HEARTBEA0ine"50ame="L292"> 292                 2}3> 3vers/wa/wo_heartbedo296" id="L296" > 3vers/wa/wo_heartbedo=4line"4name="L352">heartbedo296" id="L296" heartbedo=4li        334};
00_t6>=         &  0ame="L292"> 292                __user *<6"serv60 biis of BAWD are eeserved *reg4"> 314    reline"5100_tco52" id=iocmisc_      is4"> 314    misc_      is=4lin
 *g4"> 314    reline"5!=    if ( 344L332" id=ioctl"ment_t34") {
  314    reline"       (60NDEX_REG" B8/wa"+codedog!\c334"> 334}334};
   334};
(60="L298" class=4line"4name="L298"> 220     6=minor"ba6e_addeass=+10miscdevice<6a> L332" id=ioctl"index_tc) {
_tco5c#L302" id="L3c) {
_tcochdog081                ers/waalrs/watchdog/4p5100ers/waalrs/ine"       (61ice  334put_user60,  230                 334};
 30_tco4c#L296" id="L296" > 30_tco4c#Lg/5p _tco4c#L312" id="L312" class=4line"41ame=6lease"inb6_DEVICE_TABLE(L3361r *f="drivers9isgvailhdog/4p5100_tco4c#L312" id="L312" class=4line"41ame=6i5aaaaa* 6f="drivers/watchdog/4p5160_tco61"> 344L332" id=ioctl"ment_tsp292tf id="L353" clas;i292tf=4line"4name="L352">89 334};
L332" i="+code=val" class=c334"> 334};
89 =          2ame="L336"EG);6 334 348 334};
 334 629" class=4line"45ame="4p5100_tco4c#L292" id="L29n="drivers= classa>               f ( 30_tc296" id="L296" > 30_tcg/5p  0ame="L292"> 292                /* useping watchdog!\6miscd62NDEX_REG" B8/rog/rn 0 =         sp51cew_opti0xf8c334"> 334};
 334L332" id=ioctl"index_tiounmap4"> 314      unmap=4line"4name="L352">> 30_tc296" id="L296" > 30_tcg/5p> =          346 314    re) {seh352" id="L=4line"4name="L352">> 30_tco4c#L296" id="L296" > 30_tco4c#Lg/5pf (< cquesr_mem_t">>fi_excluso_timer_keepalive" cquesr_mem_t">>fi_excluso_tI_DEVIC> =          34700_t6>=         & 314    re) {sehree="L31=4lin
 =         SBResource6MMIO 63ex_t">L332" id=ioctl"index_tre) {sehred="L4"> 314    re) {seh id="L=4line"4name="L352">ode=put_user" r+er"I_DEVIa> =        f (< cquesr_mem_t">>fi_ea"srOPORTSr_keepalive" cquesr_mem_t">a"srOPORTSr_kee85" > =          334}rog4"> 314    reline"50ame="L292"> 292                ( 334};
  220     6EVICE_TAB6E(staticdvoid=c334"> 334};ivers/watcc) {nup4"> 314    ;ivers/watcc) {nup=4linvoid _tco4c#L312" id="L312" class=4line"41ame=6iscdevice6/a> (                    "L289"> 2}3> 3vers/wa/to4296" id="L296" > 3vers/wa/to4rs/wa        220     6       (L332" id=ioctl"ment_tmisc_de      is4"> 314    misc_de      is=4lin
L332" id=ioctl"index_tiounmap4"> 314      unmap=4line"4name="L352">> 30_tc296" id="L296" > 30_tcg/5p> =          314    re) {seh352" id="L=4line"4name="L352">> 30_tco4c#L296" id="L296" > 30_tco4c#Lg/5pf (< cquesr_mem_t">>fi_excluso_timer_keepalive" cquesr_mem_t">>fi_excluso_tI_DEVIC> =          *00_tco4c#L296" id="L296" class=4line"49am _tco4c#L312" id="L312" class=4line"41ame=6);
SBResource_MMIO i6 enab64"> 344L332" id=ioctl"ment_tre) {sehree="L314"> 314    re) {sehree="L31=4lin
 =         L332" id=ioctl"index_tre) {sehred="L4"> 314    re) {seh id="L=4line"4name="L352">ode=put_user" r+er"I_DEVIa> =        f (< cquesr_mem_t">>fi_ea"srOPORTSr_keepalive" cquesr_mem_t">a"srOPORTSr_kee85" > =          334};
);
 334 298  38     6   334};ivers/watcremos/watchdog/4p5100;ivers/watcremos/=4linstrucv=c334"> 334}platid.m_devi314"> 314    platid.m_devi31 and *ass=3line"3name=c# id="L353" class=449am _tco4c#L312" id="L312" class=4line"41ame=6/a>      6  30_tcg/5p>f ();6  314    ;ivers/watcc) {nup=4lin> =          334};
 314  20     6me="L295"6 295                6 iscd65ex_t"staticdvoid=c334"> 334};ivers/watcshutdowL4"> 314    ;ivers/watcshutdowL=4linstrucv=c334"> 334}platid.m_devi314"> 314    platid.m_devi31 and *ass=3line"3name=c# id="L353" class=449am _tco4c#L312" id="L312" class=4line"41ame=6/42ame="L6  "> 281 <65ine"3if (L332" id=ioctl"index_t> 3vers/wa/to4296" id="L296" > 3vers/wa/to4rs/wa        334};
 334 2staticdstrucv=c334"> 334}platid.m_dss="s4"> 314    platid.m_dss="sx_t">c334"> 334};ivers/watcdss="s4"> 314    ;ivers/watcdss="sine"510if (L332" i" class=co_">__uprob14"> 314    prob1a> };
L332" i" class=co_">__uremos/watchdog/4p5100remos/=4liULf="+cod100_tco52" id=ioc;ivers/watcremos/watchdog/4p5100;ivers/watcremos/=4li f (__ushutdowL4"> 314    ;hutdowL=4lif="+cod100_tco52" id=ioc;ivers/watcshutdowL4"> 314    ;ivers/watcshutdowL=4li f ( 344__udss="s4"> 314    dss="sine"5Lf="+cod10if (__uowL"s4"> 314    owL"sEINVAL100_tco52" id=iocTHIS_MODULepalive" cquesr_THIS_MODULe=4li f (__uogra296" id="L296" nam/=4liULf100_tco52" id=iocTCO_MODULe_NAMepalive" cquesr_TCO_MODULe_NAMe=4li f (L332" i} f ( 34}       3246/a>         334};
 2staticdriv=c334"> 334}_cin4};
};
 3              if 6 2767 biis of BAWDriv=c334"> 334}) {
sp51cew_opti0xf8c334"> 334 344 334};
sp5 v class                =          32567ice  334 2966           if ( 314    platid.m_dss="s_      is=4lin
 314    ;ivers/watcdss="sine"> =         __user 347 334}) {
 334L332" id=ioctl"ment_t;ivers/watcplatid.m_devi314"> 314    ;ivers/watcplatid.m_devi31chdof100_tco52" id=iocplatid.m_devi31_      is_simple/a>};
 334 3168/a> ( =         ;ivers/watcplatid.m_devi314"> 314    ;ivers/watcplatid.m_devi31chdo ="L313"> 313                            6 id="L2836 class=4line"48ame="L3436> 34368_DATA_REG" B8/wa"+code=SP5100_00_tc3) {
;ivers/watcplatid.m_devi314"> 314    ;ivers/watcplatid.m_devi31chdo  =          344L332" dog!\c334"> 334};
 314    ;
 =     6   &a68=EINVAL"SB8/wef="+code=val" class=c334"> 334};
 296                retur6id="L287"6class=4line"48ame="L307"6 307<6a>            rog/rn 0 =          220     6#L289" id6"L289" class=4line"4name6"L28969#L299c334"> 334};
 314    ;
 334 250                       6iscde69ent_t">L332" id=ioctl"ment_t3latid.m_dss="s_;
 314    platid.m_dss="s_;

 314    ;ivers/watcdss="sine"> =          334}) {
 =          334};
     6    gotomiscdevice <6nreg_69 id=ioctl"ment_t">sp51cew_opti0xf8c334"> 334 2staticdvoid=c334"> 334}__334};
};
 3L313"> 313                            6 evice  69    . 314    platid.m_devi31_;
;ivers/watcplatid.m_devi314"> 314    ;ivers/watcplatid.m_devi31chdo  =         L332" id=ioctl"index_t3latid.m_dss="s_;
 314    platid.m_dss="s_;

 314    ;ivers/watcdss="sine"> =          348 334};
 =          334};
  33400_t7>=         & 334}modulecin4};
;ivers/watcin4<_module/a>};
00_t7&VIa> =          334}modulec334};
;ivers/watcc) {nup_module/a>};
00_t7&   gotomiscdevice <7d rel70 id=ioctl"ment_t">sp51cew_opti0xf8c334"> 334 =           =         (70nsure 334"> 334}MODULe_LICENSepalive" cquesr_MODULe_LICENSers/watchdog/4p5100_tco4c#L279" iGPL             > =          314    MODULe_ALIAS_MISCDEV=4line"4name="L352">         MINOR" class=4line"4         MINOR    > =         


53">original LXR softwrivebivers/ http://e="L31icoge.net/projects/lxs4>LXR ne"4un4lxs@4p5ux.no=4li.
lxs.4p5ux.no kindly ho id4biv http://www.redpill-4p5pro.no">Redpill Lp5pro AS=4li providir of Lp5ux nensultef="and operaine"s hdrvi31s hince 1995.