This source file includes following definitions.
- pnx833x_wdt_start
- pnx833x_wdt_stop
- pnx833x_wdt_ping
- pnx833x_wdt_open
- pnx833x_wdt_release
- pnx833x_wdt_write
- pnx833x_wdt_ioctl
- pnx833x_wdt_notify_sys
- watchdog_init
- watchdog_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  17 
  18 #include <linux/module.h>
  19 #include <linux/moduleparam.h>
  20 #include <linux/types.h>
  21 #include <linux/kernel.h>
  22 #include <linux/fs.h>
  23 #include <linux/mm.h>
  24 #include <linux/miscdevice.h>
  25 #include <linux/watchdog.h>
  26 #include <linux/notifier.h>
  27 #include <linux/reboot.h>
  28 #include <linux/init.h>
  29 #include <asm/mach-pnx833x/pnx833x.h>
  30 
  31 #define WATCHDOG_TIMEOUT 30             
  32 #define WATCHDOG_COUNT_FREQUENCY 68000000U 
  33 #define PNX_WATCHDOG_TIMEOUT    (WATCHDOG_TIMEOUT * WATCHDOG_COUNT_FREQUENCY)
  34 #define PNX_TIMEOUT_VALUE       2040000000U
  35 
  36 
  37 #define PNX833X_CONFIG                      (0x07000U)
  38 #define PNX833X_CONFIG_CPU_WATCHDOG         (0x54)
  39 #define PNX833X_CONFIG_CPU_WATCHDOG_COMPARE (0x58)
  40 #define PNX833X_CONFIG_CPU_COUNTERS_CONTROL (0x1c)
  41 
  42 
  43 #define PNX833X_RESET                       (0x08000U)
  44 #define PNX833X_RESET_CONFIG                (0x08)
  45 
  46 static int pnx833x_wdt_alive;
  47 
  48 
  49 static int pnx833x_wdt_timeout = PNX_WATCHDOG_TIMEOUT;
  50 module_param(pnx833x_wdt_timeout, int, 0);
  51 MODULE_PARM_DESC(timeout, "Watchdog timeout in Mhz. (68Mhz clock), default="
  52                         __MODULE_STRING(PNX_TIMEOUT_VALUE) "(30 seconds).");
  53 
  54 static bool nowayout = WATCHDOG_NOWAYOUT;
  55 module_param(nowayout, bool, 0);
  56 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
  57                                         __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  58 
  59 #define START_DEFAULT   1
  60 static int start_enabled = START_DEFAULT;
  61 module_param(start_enabled, int, 0);
  62 MODULE_PARM_DESC(start_enabled, "Watchdog is started on module insertion "
  63                                 "(default=" __MODULE_STRING(START_DEFAULT) ")");
  64 
  65 static void pnx833x_wdt_start(void)
  66 {
  67         
  68         PNX833X_REG(PNX833X_RESET + PNX833X_RESET_CONFIG) |= 0x1;
  69         
  70         PNX833X_REG(PNX833X_CONFIG +
  71                 PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = pnx833x_wdt_timeout;
  72         
  73         PNX833X_REG(PNX833X_CONFIG +
  74                                 PNX833X_CONFIG_CPU_COUNTERS_CONTROL) |= 0x1;
  75 
  76         pr_info("Started watchdog timer\n");
  77 }
  78 
  79 static void pnx833x_wdt_stop(void)
  80 {
  81         
  82         PNX833X_REG(PNX833X_RESET + PNX833X_CONFIG) &= 0xFFFFFFFE;
  83         
  84         PNX833X_REG(PNX833X_CONFIG +
  85                         PNX833X_CONFIG_CPU_COUNTERS_CONTROL) &= 0xFFFFFFFE;
  86 
  87         pr_info("Stopped watchdog timer\n");
  88 }
  89 
  90 static void pnx833x_wdt_ping(void)
  91 {
  92         PNX833X_REG(PNX833X_CONFIG +
  93                 PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = pnx833x_wdt_timeout;
  94 }
  95 
  96 
  97 
  98 
  99 static int pnx833x_wdt_open(struct inode *inode, struct file *file)
 100 {
 101         if (test_and_set_bit(0, &pnx833x_wdt_alive))
 102                 return -EBUSY;
 103 
 104         if (nowayout)
 105                 __module_get(THIS_MODULE);
 106 
 107         
 108         if (!start_enabled)
 109                 pnx833x_wdt_start();
 110 
 111         pnx833x_wdt_ping();
 112 
 113         pr_info("Started watchdog timer\n");
 114 
 115         return stream_open(inode, file);
 116 }
 117 
 118 static int pnx833x_wdt_release(struct inode *inode, struct file *file)
 119 {
 120         
 121 
 122         if (!nowayout)
 123                 pnx833x_wdt_stop(); 
 124 
 125         clear_bit(0, &pnx833x_wdt_alive);
 126         return 0;
 127 }
 128 
 129 static ssize_t pnx833x_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
 130 {
 131         
 132         if (len)
 133                 pnx833x_wdt_ping();
 134 
 135         return len;
 136 }
 137 
 138 static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd,
 139                                                         unsigned long arg)
 140 {
 141         int options, new_timeout = 0;
 142         uint32_t timeout, timeout_left = 0;
 143 
 144         static const struct watchdog_info ident = {
 145                 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
 146                 .firmware_version = 0,
 147                 .identity = "Hardware Watchdog for PNX833x",
 148         };
 149 
 150         switch (cmd) {
 151         default:
 152                 return -ENOTTY;
 153 
 154         case WDIOC_GETSUPPORT:
 155                 if (copy_to_user((struct watchdog_info *)arg,
 156                                  &ident, sizeof(ident)))
 157                         return -EFAULT;
 158                 return 0;
 159 
 160         case WDIOC_GETSTATUS:
 161         case WDIOC_GETBOOTSTATUS:
 162                 return put_user(0, (int *)arg);
 163 
 164         case WDIOC_SETOPTIONS:
 165                 if (get_user(options, (int *)arg))
 166                         return -EFAULT;
 167 
 168                 if (options & WDIOS_DISABLECARD)
 169                         pnx833x_wdt_stop();
 170 
 171                 if (options & WDIOS_ENABLECARD)
 172                         pnx833x_wdt_start();
 173 
 174                 return 0;
 175 
 176         case WDIOC_KEEPALIVE:
 177                 pnx833x_wdt_ping();
 178                 return 0;
 179 
 180         case WDIOC_SETTIMEOUT:
 181         {
 182                 if (get_user(new_timeout, (int *)arg))
 183                         return -EFAULT;
 184 
 185                 pnx833x_wdt_timeout = new_timeout;
 186                 PNX833X_REG(PNX833X_CONFIG +
 187                         PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = new_timeout;
 188                 return put_user(new_timeout, (int *)arg);
 189         }
 190 
 191         case WDIOC_GETTIMEOUT:
 192                 timeout = PNX833X_REG(PNX833X_CONFIG +
 193                                         PNX833X_CONFIG_CPU_WATCHDOG_COMPARE);
 194                 return put_user(timeout, (int *)arg);
 195 
 196         case WDIOC_GETTIMELEFT:
 197                 timeout_left = PNX833X_REG(PNX833X_CONFIG +
 198                                                 PNX833X_CONFIG_CPU_WATCHDOG);
 199                 return put_user(timeout_left, (int *)arg);
 200 
 201         }
 202 }
 203 
 204 static int pnx833x_wdt_notify_sys(struct notifier_block *this,
 205                                         unsigned long code, void *unused)
 206 {
 207         if (code == SYS_DOWN || code == SYS_HALT)
 208                 pnx833x_wdt_stop(); 
 209 
 210         return NOTIFY_DONE;
 211 }
 212 
 213 static const struct file_operations pnx833x_wdt_fops = {
 214         .owner          = THIS_MODULE,
 215         .llseek         = no_llseek,
 216         .write          = pnx833x_wdt_write,
 217         .unlocked_ioctl = pnx833x_wdt_ioctl,
 218         .open           = pnx833x_wdt_open,
 219         .release        = pnx833x_wdt_release,
 220 };
 221 
 222 static struct miscdevice pnx833x_wdt_miscdev = {
 223         .minor          = WATCHDOG_MINOR,
 224         .name           = "watchdog",
 225         .fops           = &pnx833x_wdt_fops,
 226 };
 227 
 228 static struct notifier_block pnx833x_wdt_notifier = {
 229         .notifier_call = pnx833x_wdt_notify_sys,
 230 };
 231 
 232 static int __init watchdog_init(void)
 233 {
 234         int ret, cause;
 235 
 236         
 237         cause = PNX833X_REG(PNX833X_RESET);
 238         
 239         if (cause & 0x80000000) {
 240                 pr_info("The system was previously reset due to the watchdog firing - please investigate...\n");
 241         }
 242 
 243         ret = register_reboot_notifier(&pnx833x_wdt_notifier);
 244         if (ret) {
 245                 pr_err("cannot register reboot notifier (err=%d)\n", ret);
 246                 return ret;
 247         }
 248 
 249         ret = misc_register(&pnx833x_wdt_miscdev);
 250         if (ret) {
 251                 pr_err("cannot register miscdev on minor=%d (err=%d)\n",
 252                        WATCHDOG_MINOR, ret);
 253                 unregister_reboot_notifier(&pnx833x_wdt_notifier);
 254                 return ret;
 255         }
 256 
 257         pr_info("Hardware Watchdog Timer for PNX833x: Version 0.1\n");
 258 
 259         if (start_enabled)
 260                 pnx833x_wdt_start();
 261 
 262         return 0;
 263 }
 264 
 265 static void __exit watchdog_exit(void)
 266 {
 267         misc_deregister(&pnx833x_wdt_miscdev);
 268         unregister_reboot_notifier(&pnx833x_wdt_notifier);
 269 }
 270 
 271 module_init(watchdog_init);
 272 module_exit(watchdog_exit);
 273 
 274 MODULE_AUTHOR("Daniel Laird/Andre McCurdy");
 275 MODULE_DESCRIPTION("Hardware Watchdog Device for PNX833x");
 276 MODULE_LICENSE("GPL");