Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: Convert BookE watchdog driver to watchdog infrastructure

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>

authored by

Guenter Roeck and committed by
Wim Van Sebroeck
52e5cc4e 04ecc7dc

+76 -130
+1
drivers/watchdog/Kconfig
··· 1145 1145 config BOOKE_WDT 1146 1146 tristate "PowerPC Book-E Watchdog Timer" 1147 1147 depends on BOOKE || 4xx 1148 + select WATCHDOG_CORE 1148 1149 ---help--- 1149 1150 Watchdog driver for PowerPC Book-E chips, such as the Freescale 1150 1151 MPC85xx SOCs and the IBM PowerPC 440.
+75 -130
drivers/watchdog/booke_wdt.c
··· 15 15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 16 17 17 #include <linux/module.h> 18 - #include <linux/fs.h> 19 18 #include <linux/smp.h> 20 - #include <linux/miscdevice.h> 21 - #include <linux/notifier.h> 22 19 #include <linux/watchdog.h> 23 - #include <linux/uaccess.h> 24 20 25 21 #include <asm/reg_booke.h> 26 22 #include <asm/time.h> ··· 41 45 #define WDTP_MASK (TCR_WP_MASK) 42 46 #endif 43 47 44 - static DEFINE_SPINLOCK(booke_wdt_lock); 48 + #ifdef CONFIG_PPC_FSL_BOOK3E 45 49 46 50 /* For the specified period, determine the number of seconds 47 51 * corresponding to the reset time. There will be a watchdog ··· 82 86 return 0; 83 87 } 84 88 89 + #define MAX_WDT_TIMEOUT period_to_sec(1) 90 + 91 + #else /* CONFIG_PPC_FSL_BOOK3E */ 92 + 93 + static unsigned long long period_to_sec(unsigned int period) 94 + { 95 + return period; 96 + } 97 + 98 + static unsigned int sec_to_period(unsigned int secs) 99 + { 100 + return secs; 101 + } 102 + 103 + #define MAX_WDT_TIMEOUT 3 /* from Kconfig */ 104 + 105 + #endif /* !CONFIG_PPC_FSL_BOOK3E */ 106 + 85 107 static void __booke_wdt_set(void *data) 86 108 { 87 109 u32 val; ··· 121 107 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); 122 108 } 123 109 124 - static void booke_wdt_ping(void) 110 + static int booke_wdt_ping(struct watchdog_device *wdog) 125 111 { 126 112 on_each_cpu(__booke_wdt_ping, NULL, 0); 113 + 114 + return 0; 127 115 } 128 116 129 117 static void __booke_wdt_enable(void *data) ··· 162 146 163 147 } 164 148 165 - static ssize_t booke_wdt_write(struct file *file, const char __user *buf, 166 - size_t count, loff_t *ppos) 149 + static void __booke_wdt_start(struct watchdog_device *wdog) 167 150 { 168 - booke_wdt_ping(); 169 - return count; 151 + on_each_cpu(__booke_wdt_enable, NULL, 0); 152 + pr_debug("watchdog enabled (timeout = %u sec)\n", wdog->timeout); 170 153 } 171 154 172 - static struct watchdog_info ident = { 155 + static int booke_wdt_start(struct watchdog_device *wdog) 156 + { 157 + if (booke_wdt_enabled == 0) { 158 + booke_wdt_enabled = 1; 159 + __booke_wdt_start(wdog); 160 + } 161 + return 0; 162 + } 163 + 164 + static int booke_wdt_stop(struct watchdog_device *wdog) 165 + { 166 + on_each_cpu(__booke_wdt_disable, NULL, 0); 167 + booke_wdt_enabled = 0; 168 + pr_debug("watchdog disabled\n"); 169 + 170 + return 0; 171 + } 172 + 173 + static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev, 174 + unsigned int timeout) 175 + { 176 + if (timeout > MAX_WDT_TIMEOUT) 177 + return -EINVAL; 178 + booke_wdt_period = sec_to_period(timeout); 179 + wdt_dev->timeout = timeout; 180 + booke_wdt_set(); 181 + 182 + return 0; 183 + } 184 + 185 + static struct watchdog_info booke_wdt_info = { 173 186 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 174 187 .identity = "PowerPC Book-E Watchdog", 175 188 }; 176 189 177 - static long booke_wdt_ioctl(struct file *file, 178 - unsigned int cmd, unsigned long arg) 179 - { 180 - u32 tmp = 0; 181 - u32 __user *p = (u32 __user *)arg; 182 - 183 - switch (cmd) { 184 - case WDIOC_GETSUPPORT: 185 - return copy_to_user(p, &ident, sizeof(ident)) ? -EFAULT : 0; 186 - case WDIOC_GETSTATUS: 187 - return put_user(0, p); 188 - case WDIOC_GETBOOTSTATUS: 189 - /* XXX: something is clearing TSR */ 190 - tmp = mfspr(SPRN_TSR) & TSR_WRS(3); 191 - /* returns CARDRESET if last reset was caused by the WDT */ 192 - return put_user((tmp ? WDIOF_CARDRESET : 0), p); 193 - case WDIOC_SETOPTIONS: 194 - if (get_user(tmp, p)) 195 - return -EFAULT; 196 - if (tmp == WDIOS_ENABLECARD) { 197 - booke_wdt_ping(); 198 - break; 199 - } else 200 - return -EINVAL; 201 - return 0; 202 - case WDIOC_KEEPALIVE: 203 - booke_wdt_ping(); 204 - return 0; 205 - case WDIOC_SETTIMEOUT: 206 - if (get_user(tmp, p)) 207 - return -EFAULT; 208 - #ifdef CONFIG_PPC_FSL_BOOK3E 209 - /* period of 1 gives the largest possible timeout */ 210 - if (tmp > period_to_sec(1)) 211 - return -EINVAL; 212 - booke_wdt_period = sec_to_period(tmp); 213 - #else 214 - booke_wdt_period = tmp; 215 - #endif 216 - booke_wdt_set(); 217 - /* Fall */ 218 - case WDIOC_GETTIMEOUT: 219 - #ifdef CONFIG_FSL_BOOKE 220 - return put_user(period_to_sec(booke_wdt_period), p); 221 - #else 222 - return put_user(booke_wdt_period, p); 223 - #endif 224 - default: 225 - return -ENOTTY; 226 - } 227 - 228 - return 0; 229 - } 230 - 231 - /* wdt_is_active stores whether or not the /dev/watchdog device is opened */ 232 - static unsigned long wdt_is_active; 233 - 234 - static int booke_wdt_open(struct inode *inode, struct file *file) 235 - { 236 - /* /dev/watchdog can only be opened once */ 237 - if (test_and_set_bit(0, &wdt_is_active)) 238 - return -EBUSY; 239 - 240 - spin_lock(&booke_wdt_lock); 241 - if (booke_wdt_enabled == 0) { 242 - booke_wdt_enabled = 1; 243 - on_each_cpu(__booke_wdt_enable, NULL, 0); 244 - pr_debug("watchdog enabled (timeout = %llu sec)\n", 245 - period_to_sec(booke_wdt_period)); 246 - } 247 - spin_unlock(&booke_wdt_lock); 248 - 249 - return nonseekable_open(inode, file); 250 - } 251 - 252 - static int booke_wdt_release(struct inode *inode, struct file *file) 253 - { 254 - #ifndef CONFIG_WATCHDOG_NOWAYOUT 255 - /* Normally, the watchdog is disabled when /dev/watchdog is closed, but 256 - * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the 257 - * watchdog should remain enabled. So we disable it only if 258 - * CONFIG_WATCHDOG_NOWAYOUT is not defined. 259 - */ 260 - on_each_cpu(__booke_wdt_disable, NULL, 0); 261 - booke_wdt_enabled = 0; 262 - pr_debug("watchdog disabled\n"); 263 - #endif 264 - 265 - clear_bit(0, &wdt_is_active); 266 - 267 - return 0; 268 - } 269 - 270 - static const struct file_operations booke_wdt_fops = { 190 + static struct watchdog_ops booke_wdt_ops = { 271 191 .owner = THIS_MODULE, 272 - .llseek = no_llseek, 273 - .write = booke_wdt_write, 274 - .unlocked_ioctl = booke_wdt_ioctl, 275 - .open = booke_wdt_open, 276 - .release = booke_wdt_release, 192 + .start = booke_wdt_start, 193 + .stop = booke_wdt_stop, 194 + .ping = booke_wdt_ping, 195 + .set_timeout = booke_wdt_set_timeout, 277 196 }; 278 197 279 - static struct miscdevice booke_wdt_miscdev = { 280 - .minor = WATCHDOG_MINOR, 281 - .name = "watchdog", 282 - .fops = &booke_wdt_fops, 198 + static struct watchdog_device booke_wdt_dev = { 199 + .info = &booke_wdt_info, 200 + .ops = &booke_wdt_ops, 201 + .min_timeout = 1, 202 + .max_timeout = 0xFFFF 283 203 }; 284 204 285 205 static void __exit booke_wdt_exit(void) 286 206 { 287 - misc_deregister(&booke_wdt_miscdev); 207 + watchdog_unregister_device(&booke_wdt_dev); 288 208 } 289 209 290 210 static int __init booke_wdt_init(void) 291 211 { 292 212 int ret = 0; 213 + bool nowayout = WATCHDOG_NOWAYOUT; 293 214 294 215 pr_info("powerpc book-e watchdog driver loaded\n"); 295 - ident.firmware_version = cur_cpu_spec->pvr_value; 216 + booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value; 217 + booke_wdt_set_timeout(&booke_wdt_dev, 218 + period_to_sec(CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT)); 219 + watchdog_set_nowayout(&booke_wdt_dev, nowayout); 220 + if (booke_wdt_enabled) 221 + __booke_wdt_start(&booke_wdt_dev); 296 222 297 - ret = misc_register(&booke_wdt_miscdev); 298 - if (ret) { 299 - pr_err("cannot register device (minor=%u, ret=%i)\n", 300 - WATCHDOG_MINOR, ret); 301 - return ret; 302 - } 303 - 304 - spin_lock(&booke_wdt_lock); 305 - if (booke_wdt_enabled == 1) { 306 - pr_info("watchdog enabled (timeout = %llu sec)\n", 307 - period_to_sec(booke_wdt_period)); 308 - on_each_cpu(__booke_wdt_enable, NULL, 0); 309 - } 310 - spin_unlock(&booke_wdt_lock); 223 + ret = watchdog_register_device(&booke_wdt_dev); 311 224 312 225 return ret; 313 226 }