1ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 2ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Watchdog driver for Kendin/Micrel KS8695. 3ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * 4ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * (C) 2007 Andrew Victor 5ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * 6ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * This program is free software; you can redistribute it and/or modify 7ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * it under the terms of the GNU General Public License version 2 as 8ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * published by the Free Software Foundation. 9ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 10ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 1127c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1227c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches 131977f032722c27ee3730284582fd3991ad9ac81bJiri Slaby#include <linux/bitops.h> 14ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/errno.h> 15ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/fs.h> 16ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/init.h> 17ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/kernel.h> 18ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/miscdevice.h> 19ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/module.h> 20ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/moduleparam.h> 21ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/platform_device.h> 22ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/types.h> 23ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#include <linux/watchdog.h> 24f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox#include <linux/io.h> 25f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox#include <linux/uaccess.h> 26568dba66ac307532b6703331df71c17373c17a4aYegor Yefremov#include <mach/hardware.h> 27a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/regs-timer.h> 28ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 29ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#define WDT_DEFAULT_TIME 5 /* seconds */ 30ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#define WDT_MAX_TIME 171 /* seconds */ 31ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 32ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic int wdt_time = WDT_DEFAULT_TIME; 3386a1e1896c2710402e29a875d8d830244274244dWim Van Sebroeckstatic bool nowayout = WATCHDOG_NOWAYOUT; 34ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 35ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victormodule_param(wdt_time, int, 0); 36f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan CoxMODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default=" 37f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox __MODULE_STRING(WDT_DEFAULT_TIME) ")"); 38ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 39ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#ifdef CONFIG_WATCHDOG_NOWAYOUT 4086a1e1896c2710402e29a875d8d830244274244dWim Van Sebroeckmodule_param(nowayout, bool, 0); 41f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan CoxMODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 42f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 43ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#endif 44ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 45ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 46ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic unsigned long ks8695wdt_busy; 471334f32938e46fb321c67a652997d33583257249Axel Linstatic DEFINE_SPINLOCK(ks8695_lock); 48ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 49ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* ......................................................................... */ 50ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 51ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 52ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Disable the watchdog. 53ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 54f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Coxstatic inline void ks8695_wdt_stop(void) 55ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 56ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor unsigned long tmcon; 57ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 58f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox spin_lock(&ks8695_lock); 59ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor /* disable timer0 */ 60ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 61ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 62f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox spin_unlock(&ks8695_lock); 63ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 64ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 65ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 66ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Enable and reset the watchdog. 67ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 68f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Coxstatic inline void ks8695_wdt_start(void) 69ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 70ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor unsigned long tmcon; 710a51810aa058a0a4ac76dd6f87f4d10bee774e2eAndrew Victor unsigned long tval = wdt_time * KS8695_CLOCK_RATE; 72ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 73f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox spin_lock(&ks8695_lock); 74ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor /* disable timer0 */ 75ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 76ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 77ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 78ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor /* program timer0 */ 79ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor __raw_writel(tval | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC); 80ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 81ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor /* re-enable timer0 */ 82ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 83ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 84f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox spin_unlock(&ks8695_lock); 85ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 86ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 87ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 88ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Reload the watchdog timer. (ie, pat the watchdog) 89ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 90f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Coxstatic inline void ks8695_wdt_reload(void) 91ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 92ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor unsigned long tmcon; 93ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 94f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox spin_lock(&ks8695_lock); 95ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor /* disable, then re-enable timer0 */ 96ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); 97ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 98ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); 99f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox spin_unlock(&ks8695_lock); 100ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 101ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 102ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 103ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Change the watchdog time interval. 104ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 105ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic int ks8695_wdt_settimeout(int new_time) 106ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 107ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor /* 1080a51810aa058a0a4ac76dd6f87f4d10bee774e2eAndrew Victor * All counting occurs at KS8695_CLOCK_RATE / 128 = 0.256 Hz 109ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * 110ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Since WDV is a 16-bit counter, the maximum period is 111ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * 65536 / 0.256 = 256 seconds. 112ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 113ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) 114ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return -EINVAL; 115ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 116f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox /* Set new watchdog time. It will be used when 117f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox ks8695_wdt_start() is called. */ 118ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor wdt_time = new_time; 119ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return 0; 120ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 121ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 122ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* ......................................................................... */ 123ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 124ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 125ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Watchdog device is opened, and watchdog starts running. 126ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 127ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic int ks8695_wdt_open(struct inode *inode, struct file *file) 128ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 129ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if (test_and_set_bit(0, &ks8695wdt_busy)) 130ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return -EBUSY; 131ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 132ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695_wdt_start(); 133ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return nonseekable_open(inode, file); 134ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 135ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 136ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 137ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Close the watchdog device. 138ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also 139ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * disabled. 140ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 141ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic int ks8695_wdt_close(struct inode *inode, struct file *file) 142ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 143f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox /* Disable the watchdog when file is closed */ 144ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if (!nowayout) 145f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox ks8695_wdt_stop(); 146ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor clear_bit(0, &ks8695wdt_busy); 147ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return 0; 148ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 149ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 15042747d712de56cf2087b702d2ad90af114c53138Wim Van Sebroeckstatic const struct watchdog_info ks8695_wdt_info = { 151ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .identity = "ks8695 watchdog", 152ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 153ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor}; 154ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 155ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 156ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Handle commands from user-space. 157ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 158f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Coxstatic long ks8695_wdt_ioctl(struct file *file, unsigned int cmd, 159f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox unsigned long arg) 160ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 161ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor void __user *argp = (void __user *)arg; 162ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor int __user *p = argp; 163ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor int new_value; 164ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 165f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox switch (cmd) { 166f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox case WDIOC_GETSUPPORT: 167f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox return copy_to_user(argp, &ks8695_wdt_info, 168f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox sizeof(ks8695_wdt_info)) ? -EFAULT : 0; 169f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox case WDIOC_GETSTATUS: 170f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox case WDIOC_GETBOOTSTATUS: 171f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox return put_user(0, p); 172f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox case WDIOC_SETOPTIONS: 173f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox if (get_user(new_value, p)) 174f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox return -EFAULT; 175f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox if (new_value & WDIOS_DISABLECARD) 176f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox ks8695_wdt_stop(); 177f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox if (new_value & WDIOS_ENABLECARD) 178ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695_wdt_start(); 179f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox return 0; 1800c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck case WDIOC_KEEPALIVE: 1810c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck ks8695_wdt_reload(); /* pat the watchdog */ 1820c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck return 0; 1830c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck case WDIOC_SETTIMEOUT: 1840c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck if (get_user(new_value, p)) 1850c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck return -EFAULT; 1860c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck if (ks8695_wdt_settimeout(new_value)) 1870c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck return -EINVAL; 1880c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck /* Enable new time value */ 1890c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck ks8695_wdt_start(); 1900c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck /* Return current value */ 1910c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck return put_user(wdt_time, p); 1920c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck case WDIOC_GETTIMEOUT: 1930c06090c9472db0525cb6fe229c3bea33bbbbb3cWim Van Sebroeck return put_user(wdt_time, p); 194f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox default: 195f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox return -ENOTTY; 196ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor } 197ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 198ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 199ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* 200ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor * Pat the watchdog whenever device is written to. 201ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor */ 202f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Coxstatic ssize_t ks8695_wdt_write(struct file *file, const char *data, 203f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox size_t len, loff_t *ppos) 204ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 205ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695_wdt_reload(); /* pat the watchdog */ 206ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return len; 207ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 208ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 209ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor/* ......................................................................... */ 210ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 211ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic const struct file_operations ks8695wdt_fops = { 212ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .owner = THIS_MODULE, 213ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .llseek = no_llseek, 214f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox .unlocked_ioctl = ks8695_wdt_ioctl, 215ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .open = ks8695_wdt_open, 216ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .release = ks8695_wdt_close, 217ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .write = ks8695_wdt_write, 218ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor}; 219ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 220ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic struct miscdevice ks8695wdt_miscdev = { 221ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .minor = WATCHDOG_MINOR, 222ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .name = "watchdog", 223ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .fops = &ks8695wdt_fops, 224ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor}; 225ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 226c98d58e00d8562520c9a69e688f007b860faebaaUwe Kleine-Königstatic int __devinit ks8695wdt_probe(struct platform_device *pdev) 227ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 228ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor int res; 229ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 230ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if (ks8695wdt_miscdev.parent) 231ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return -EBUSY; 232ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695wdt_miscdev.parent = &pdev->dev; 233ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 234ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor res = misc_register(&ks8695wdt_miscdev); 235ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if (res) 236ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return res; 237ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 23827c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_info("KS8695 Watchdog Timer enabled (%d seconds%s)\n", 23927c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches wdt_time, nowayout ? ", nowayout" : ""); 240ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return 0; 241ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 242ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 243c98d58e00d8562520c9a69e688f007b860faebaaUwe Kleine-Königstatic int __devexit ks8695wdt_remove(struct platform_device *pdev) 244ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 245ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor int res; 246ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 247ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor res = misc_deregister(&ks8695wdt_miscdev); 248ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if (!res) 249ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695wdt_miscdev.parent = NULL; 250ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 251ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return res; 252ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 253ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 254ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic void ks8695wdt_shutdown(struct platform_device *pdev) 255ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 256ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695_wdt_stop(); 257ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 258ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 259ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#ifdef CONFIG_PM 260ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 261ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic int ks8695wdt_suspend(struct platform_device *pdev, pm_message_t message) 262ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 263ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695_wdt_stop(); 264ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return 0; 265ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 266ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 267ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic int ks8695wdt_resume(struct platform_device *pdev) 268ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 269ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if (ks8695wdt_busy) 270ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695_wdt_start(); 271ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return 0; 272ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 273ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 274ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#else 275ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#define ks8695wdt_suspend NULL 276ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#define ks8695wdt_resume NULL 277ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor#endif 278ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 279ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic struct platform_driver ks8695wdt_driver = { 280ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .probe = ks8695wdt_probe, 281c98d58e00d8562520c9a69e688f007b860faebaaUwe Kleine-König .remove = __devexit_p(ks8695wdt_remove), 282ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .shutdown = ks8695wdt_shutdown, 283ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .suspend = ks8695wdt_suspend, 284ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .resume = ks8695wdt_resume, 285ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .driver = { 286ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .name = "ks8695_wdt", 287ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor .owner = THIS_MODULE, 288ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor }, 289ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor}; 290ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 291ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic int __init ks8695_wdt_init(void) 292ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 293f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox /* Check that the heartbeat value is within range; 294f4fabce15bb9b547f934e2b6f0e5e01044108e4dAlan Cox if not reset to the default */ 295ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor if (ks8695_wdt_settimeout(wdt_time)) { 296ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor ks8695_wdt_settimeout(WDT_DEFAULT_TIME); 297a77dba7e444a6618cbb666d1b42b79842b9c0171Wim Van Sebroeck pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i" 298a77dba7e444a6618cbb666d1b42b79842b9c0171Wim Van Sebroeck ", using %d\n", wdt_time, WDT_MAX_TIME); 299ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor } 300ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor return platform_driver_register(&ks8695wdt_driver); 301ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 302ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 303ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victorstatic void __exit ks8695_wdt_exit(void) 304ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor{ 305ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor platform_driver_unregister(&ks8695wdt_driver); 306ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor} 307ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 308ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victormodule_init(ks8695_wdt_init); 309ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victormodule_exit(ks8695_wdt_exit); 310ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew Victor 311ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew VictorMODULE_AUTHOR("Andrew Victor"); 312ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew VictorMODULE_DESCRIPTION("Watchdog driver for KS8695"); 313ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew VictorMODULE_LICENSE("GPL"); 314ccb8f430ac4cfd1acd12ff591918b8b67d73c977Andrew VictorMODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 315f37d193c7c150c40059c7ce5de34e8b28a9cd4aeKay SieversMODULE_ALIAS("platform:ks8695_wdt"); 316